Package org.apache.jena.fuseki.servlets

Source Code of org.apache.jena.fuseki.servlets.SPARQL_REST$Target

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.jena.fuseki.servlets;

import static java.lang.String.format ;
import static org.apache.jena.fuseki.HttpNames.* ;

import java.io.ByteArrayInputStream ;
import java.io.IOException ;
import java.io.InputStream ;
import java.util.Enumeration ;
import java.util.Locale ;

import javax.servlet.ServletException ;
import javax.servlet.http.HttpServletRequest ;
import javax.servlet.http.HttpServletResponse ;

import org.apache.jena.atlas.web.ContentType ;
import org.apache.jena.fuseki.FusekiLib ;
import org.apache.jena.fuseki.HttpNames ;
import org.apache.jena.fuseki.server.DatasetRef ;
import org.apache.jena.riot.Lang ;
import org.apache.jena.riot.RiotException ;
import org.apache.jena.riot.RiotReader ;
import org.apache.jena.riot.WebContent ;
import org.apache.jena.riot.lang.LangRIOT ;
import org.apache.jena.riot.system.* ;
import org.apache.jena.web.HttpSC ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;

import com.hp.hpl.jena.graph.Graph ;
import com.hp.hpl.jena.graph.Node ;
import com.hp.hpl.jena.graph.NodeFactory ;
import com.hp.hpl.jena.sparql.core.DatasetGraph ;
import com.hp.hpl.jena.sparql.core.DatasetGraphFactory ;
import com.hp.hpl.jena.sparql.graph.GraphFactory ;
import com.hp.hpl.jena.util.FileUtils ;

public abstract class SPARQL_REST extends SPARQL_ServletBase
{
    protected static Logger classLog = LoggerFactory.getLogger(SPARQL_REST.class) ;
   
    protected static ErrorHandler errorHandler = ErrorHandlerFactory.errorHandlerStd(log) ;

    protected static class HttpActionREST extends HttpAction
    {
        HttpActionREST(long id, DatasetRef desc, String absUri, HttpServletRequest request, HttpServletResponse response, boolean verbose)
        {
            super(id, desc, request, response, verbose) ;
            Node gn = NodeFactory.createURI(absUri) ;
            _target = Target.createNamed(desc.dataset, absUri, gn) ;
        }
       
        private Target _target = null ;
        protected HttpActionREST(long id, DatasetRef desc, HttpServletRequest request, HttpServletResponse response, boolean verbose)
        {
            super(id, desc, request, response, verbose) ;
        }

        protected final boolean hasTarget()
        {
            return true ;
//                request.getParameter(HttpNames.paramGraphDefault) == null &&
//                request.getParameter(HttpNames.paramGraph) == null ;
        }
       
        protected final Target getTarget()
        {
            // Delayed until inside a transaction.
            if ( _target == null )
            {
                if ( super.getActiveDSG() == null )
                    errorOccurred("Internal error : No action graph (not in a transaction?)") ;
                _target = targetGraph(request, super.getDatasetRef(), super.getActiveDSG() ) ;
            }
            return _target ;
        }
    }
   
    // struct for target
    protected static final class Target
    {
        final boolean isDefault ;
        final DatasetGraph dsg ;
        private Graph _graph ;
        final String name ;
        final Node graphName ;

        static Target createNamed(DatasetGraph dsg, String name, Node graphName)
        {
            return new Target(false, dsg, name, graphName) ;
        }

        static Target createDefault(DatasetGraph dsg)
        {
            return new Target(true, dsg, null, null) ;
        }

        private Target(boolean isDefault, DatasetGraph dsg, String name, Node graphName)
        {
            this.isDefault = isDefault ;
            this.dsg = dsg ;
            this._graph = null ;
            this.name  = name ;
            this.graphName = graphName ;

            if ( isDefault )
            {
                if ( name != null || graphName != null )
                    throw new IllegalArgumentException("Inconsistent: default and a graph name/node") ;      
            }
            else
            {
                if ( name == null || graphName == null )
                    throw new IllegalArgumentException("Inconsistent: not default and/or no graph name/node") ;
            }               
        }

        /** Get a graph for the action - this may create a graph in the dataset - this is not a test for graph existence */
        public Graph graph()
        {
            if ( ! isGraphSet() )
            {
                if ( isDefault )
                    _graph = dsg.getDefaultGraph() ;
                else
                    _graph = dsg.getGraph(graphName) ;
            }
            return _graph ;
        }

        public boolean exists()
        {
            if ( isDefault ) return true ;
            return dsg.containsGraph(graphName) ;
        }

        public boolean isGraphSet()
        {
            return _graph != null ;
        }

        @Override
        public String toString()
        {
            if ( isDefault ) return "default" ;
            return name ;
        }
    }

    public SPARQL_REST(boolean verbose)
    { super(verbose) ; }

    public SPARQL_REST()
    { this(false) ; }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        // Direct all verbs to our common framework.
        doCommon(request, response) ;
    }
   
    private void maybeSetLastModified(HttpServletResponse resp, long lastModified)
    {
        if (resp.containsHeader(HEADER_LASTMOD)) return ;
        if (lastModified >= 0) resp.setDateHeader(HEADER_LASTMOD, lastModified);
    }
   
    @Override
    protected void perform(long id, DatasetRef desc, HttpServletRequest request, HttpServletResponse response)
    {
        validate(request) ;
        HttpActionREST action = new HttpActionREST(id, desc, request, response, verbose_debug) ;
        dispatch(action) ;
    }

    private void dispatch(HttpActionREST action)
    {
        HttpServletRequest req = action.request ;
        HttpServletResponse resp = action.response ;
        String method = req.getMethod().toUpperCase(Locale.ENGLISH) ;

        // See HttpServlet.service.
        // We dispatch by REQUEST
       
        if (method.equals(METHOD_GET))
            doGet(action);
        else if (method.equals(METHOD_HEAD))
            doHead(action);
        else if (method.equals(METHOD_POST))
            doPost(action);
        else if (method.equals(METHOD_PATCH))
            doPatch(action) ;
        else if (method.equals(METHOD_OPTIONS))
            doOptions(action) ;
        else if (method.equals(METHOD_TRACE))
            //doTrace(action) ;
            errorMethodNotAllowed("TRACE") ;
        else if (method.equals(METHOD_PUT))
            doPut(action) ;  
        else if (method.equals(METHOD_DELETE))
            doDelete(action) ;
        else
            errorNotImplemented("Unknown method: "+method) ;
    }
       
    protected abstract void doGet(HttpActionREST action) ;
    protected abstract void doHead(HttpActionREST action) ;
    protected abstract void doPost(HttpActionREST action) ;
    protected abstract void doPatch(HttpActionREST action) ;
    protected abstract void doDelete(HttpActionREST action) ;
    protected abstract void doPut(HttpActionREST action) ;
    protected abstract void doOptions(HttpActionREST action) ;

    protected static void deleteGraph(HttpActionREST action)
    {
        if ( action.getTarget().isDefault )
            action.getTarget().graph().clear() ;
        else
            action.getActiveDSG().removeGraph(action.getTarget().graphName) ;
    }

    protected static void clearGraph(Target target)
    {
        if ( ! target.isGraphSet() )
        {
            Graph g = target.graph() ;
            g.clear() ;
        }
    }

    protected static void addDataInto(Graph data, HttpActionREST action)
    {  
        try
        {
            Target dest = action.getTarget() ;
            FusekiLib.addDataInto(data, dest.dsg, dest.graphName) ;
           
//            Graph g = dest.graph() ;
//           
//            if (g == null)
//            {
//                if (dest.isDefault) errorOccurred("Dataset does not have a default graph") ;
//                log.info(format("[%d] Creating in-memory graph for <%s>", action.id, dest.graphName)) ;
//                // Not default graph.
//                // Not an autocreate dataset - create something.
//                g = GraphFactory.createDefaultGraph() ;
//                dest.dsg.addGraph(dest.graphName, g) ;
//            }
//            GraphUtil.addInto(g, data) ;
        } catch (RuntimeException ex)
        {
            // If anything went wrong, try to backout.
            action.abort() ;
            errorOccurred(ex.getMessage()) ;
            return ;
        }
    }
   
    protected static DatasetGraph parseBody(HttpActionREST action)
    {
        String contentTypeHeader = action.request.getContentType() ;
       
        if ( contentTypeHeader == null )
            errorBadRequest("No content type: "+contentTypeHeader) ;
            // lang = Lang.guess(action.request.getRequestURI()) ;
       
        ContentType ct = ContentType.parse(contentTypeHeader) ;
       
        String base = wholeRequestURL(action.request) ;
       
        // Use WebContent names
        if ( WebContent.contentTypeMultiFormData.equalsIgnoreCase(ct.getContentType()) )
        {
//            //log.warn("multipart/form-data not supported (yet)") ;
//            error(HttpSC.UNSUPPORTED_MEDIA_TYPE_415, "multipart/form-data not supported") ;
            Graph graphTmp = SPARQL_Upload.upload(action.id,  action.getDatasetRef(), action.request, action.response, base) ;
            return DatasetGraphFactory.create(graphTmp) ;
        }
       
        if (WebContent.contentTypeMultiMixed.equals(ct.getContentType()) )
        {
            //log.warn("multipart/mixed not supported") ;
            error(HttpSC.UNSUPPORTED_MEDIA_TYPE_415, "multipart/mixed not supported") ;
            return null ;
        }

        int len = action.request.getContentLength() ;
        Lang lang = WebContent.contentTypeToLang(ct.getContentType()) ;
        if ( lang == null )
        {
            errorBadRequest("Unknown content type for triples: "+contentTypeHeader) ;
            return null ;
        }

        if ( action.verbose )
        {
            if ( len >= 0 )
                log.info(format("[%d]   Body: Content-Length=%d, Content-Type=%s, Charset=%s => %s",
                                      action.id, len, ct.getContentType(), ct.getCharset(), lang.getName())) ;
            else
                log.info(format("[%d]   Body: Content-Type=%s, Charset=%s => %s",
                                          action.id, ct.getContentType(), ct.getCharset(), lang.getName())) ;
        }
       
        try {
            InputStream input = action.request.getInputStream() ;
            boolean buffering = false ;
            if ( buffering )
            {
                // Slurp the input : can be helpful for debugging.
                if ( len >= 0 )
                {
                    byte b[] = new byte[len] ;
                    input.read(b) ;
                    input = new ByteArrayInputStream(b) ;
                }
                else
                {
                    // Without content length, reading to end of file is occassionaly fraught.
                    // Reason unknown - maybe some client mishandling of the stream.
                    String x = FileUtils.readWholeFileAsUTF8(input) ;
                    //System.out.println(x) ;
                    input = new ByteArrayInputStream(x.getBytes("UTF-8")) ;
                }
            }
           
            return parse(action, lang, base, input) ;
        } catch (IOException ex) { errorOccurred(ex) ; return null ; }
    }

    private static DatasetGraph parse(HttpActionREST action, Lang lang, String base, InputStream input)
    {
        Graph graphTmp = GraphFactory.createGraphMem() ;
       
        StreamRDF dest = StreamRDFLib.graph(graphTmp) ;
        LangRIOT parser = RiotReader.createParser(input, lang, base, dest) ;
        parser.getProfile().setHandler(errorHandler) ;
        try { parser.parse() ; }
        catch (RiotException ex) { errorBadRequest("Parse error: "+ex.getMessage()) ; }
        DatasetGraph dsgTmp = DatasetGraphFactory.create(graphTmp) ;
        return dsgTmp ;
    }
   
    @Override
    protected void validate(HttpServletRequest request)
    {
        // Direct naming.
        if ( request.getQueryString() == null )
            //errorBadRequest("No query string") ;
            return ;
       
        String g = request.getParameter(HttpNames.paramGraph) ;
        String d = request.getParameter(HttpNames.paramGraphDefault) ;
       
        if ( g != null && d !=null )
            errorBadRequest("Both ?default and ?graph in the query string of the request") ;
       
        if ( g == null && d == null )
            errorBadRequest("Neither ?default nor ?graph in the query string of the request") ;
       
        int x1 = SPARQL_Protocol.countParamOccurences(request, HttpNames.paramGraph) ;
        int x2 = SPARQL_Protocol.countParamOccurences(request, HttpNames.paramGraphDefault) ;
       
        if ( x1 > 1 )
            errorBadRequest("Multiple ?default in the query string of the request") ;
        if ( x2 > 1 )
            errorBadRequest("Multiple ?graph in the query string of the request") ;
       
        Enumeration<String> en = request.getParameterNames() ;
        for ( ; en.hasMoreElements() ; )
        {
            String h = en.nextElement() ;
            if ( ! HttpNames.paramGraph.equals(h) && ! HttpNames.paramGraphDefault.equals(h) )
                errorBadRequest("Unknown parameter '"+h+"'") ;
            // one of ?default and &graph
            if ( request.getParameterValues(h).length != 1 )
                errorBadRequest("Multiple parameters '"+h+"'") ;
        }
    }

    protected static Target targetGraph(HttpServletRequest request, DatasetRef desc, DatasetGraph dsg)
    {
        boolean dftGraph = getOneOnly(request, HttpNames.paramGraphDefault) != null ;
        String uri = getOneOnly(request, HttpNames.paramGraph) ;
       
        if ( !dftGraph && uri == null )
        {
            // Direct naming or error.
            uri = request.getRequestURL().toString() ;
            if ( request.getRequestURI().equals(desc.name) )
                // No name
                errorBadRequest("Neither default graph nor named graph specified; no direct name") ;
        }
       
        if ( dftGraph )
            return Target.createDefault(dsg) ;
       
        // Named graph
        if ( uri.equals(HttpNames.valueDefault ) )
            // But "named" default
            return Target.createDefault(dsg) ;
       
        // Strictly, a bit naughty on the URI resolution.  But more sensible.
        // Base is dataset.
        String base = request.getRequestURL().toString() ; //wholeRequestURL(request) ;
        // Make sure it ends in "/", ie. dataset as container.
        if ( request.getQueryString() != null && ! base.endsWith("/") )
            base = base + "/" ;
       
        String absUri = IRIResolver.resolveString(uri, base) ;
        Node gn = NodeFactory.createURI(absUri) ;
        return Target.createNamed(dsg, absUri, gn) ;
    }
   
    protected static String getOneOnly(HttpServletRequest request, String name)
    {
        String[] values = request.getParameterValues(name) ;
        if ( values == null )
            return null ;
        if ( values.length == 0 )
            return null ;
        if ( values.length > 1 )
            errorBadRequest("Multiple occurrences of '"+name+"'") ;
        return values[0] ;
    }
}
TOP

Related Classes of org.apache.jena.fuseki.servlets.SPARQL_REST$Target

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.