http://git-wip-us.apache.org/repos/asf/jena/blob/662cf71d/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST.java ---------------------------------------------------------------------- diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST.java deleted file mode 100644 index 4ab386b..0000000 --- a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST.java +++ /dev/null @@ -1,354 +0,0 @@ -/* - * 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 org.apache.jena.fuseki.HttpNames.* ; - -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.fuseki.HttpNames ; -import org.apache.jena.fuseki.server.CounterName ; -import org.apache.jena.riot.Lang ; -import org.apache.jena.riot.RDFDataMgr ; -import org.apache.jena.riot.ReaderRIOT ; -import org.apache.jena.riot.RiotException ; -import org.apache.jena.riot.system.ErrorHandler ; -import org.apache.jena.riot.system.ErrorHandlerFactory ; -import org.apache.jena.riot.system.IRIResolver ; -import org.apache.jena.riot.system.StreamRDF ; -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 ; - -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 final static Target determineTarget(HttpAction action) { - // Delayed until inside a transaction. - if ( action.getActiveDSG() == null ) - errorOccurred("Internal error : No action graph (not in a transaction?)") ; - - boolean dftGraph = getOneOnly(action.request, HttpNames.paramGraphDefault) != null ; - String uri = getOneOnly(action.request, HttpNames.paramGraph) ; - - if ( !dftGraph && uri == null ) { - // Direct naming or error. - uri = action.request.getRequestURL().toString() ; - if ( action.request.getRequestURI().equals(action.getDatasetRef().name) ) - // No name - errorBadRequest("Neither default graph nor named graph specified; no direct name") ; - } - - if ( dftGraph ) - return Target.createDefault(action.getActiveDSG()) ; - - // Named graph - if ( uri.equals(HttpNames.valueDefault ) ) - // But "named" default - return Target.createDefault(action.getActiveDSG()) ; - - // Strictly, a bit naughty on the URI resolution. But more sensible. - // Base is dataset. - String base = action.request.getRequestURL().toString() ; //wholeRequestURL(request) ; - // Make sure it ends in "/", ie. dataset as container. - if ( action.request.getQueryString() != null && ! base.endsWith("/") ) - base = base + "/" ; - - String absUri = IRIResolver.resolveString(uri, base) ; - Node gn = NodeFactory.createURI(absUri) ; - return Target.createNamed(action.getActiveDSG(), absUri, gn) ; - } - - - // 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() - { super() ; } - - @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(HttpAction action) { - dispatch(action) ; - } - - private void dispatch(HttpAction action) { - HttpServletRequest req = action.request ; - HttpServletResponse resp = action.response ; - String method = req.getMethod().toUpperCase(Locale.ROOT) ; - - 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) ; - } - - // Counter wrappers - - protected void doGet$(HttpAction action) { - incCounter(action.srvRef, CounterName.GSPget) ; - try { - doGet(action) ; - incCounter(action.srvRef, CounterName.GSPgetGood) ; - } catch ( ActionErrorException ex) { - incCounter(action.srvRef, CounterName.GSPgetBad) ; - throw ex ; - } - } - - protected void doHead$(HttpAction action) { - incCounter(action.srvRef, CounterName.GSPhead) ; - try { - doHead(action) ; - incCounter(action.srvRef, CounterName.GSPheadGood) ; - } catch ( ActionErrorException ex) { - incCounter(action.srvRef, CounterName.GSPheadBad) ; - throw ex ; - } - } - - protected void doPost$(HttpAction action) { - incCounter(action.srvRef, CounterName.GSPpost) ; - try { - doPost(action) ; - incCounter(action.srvRef, CounterName.GSPpostGood) ; - } catch ( ActionErrorException ex) { - incCounter(action.srvRef, CounterName.GSPpostBad) ; - throw ex ; - } - } - - protected void doPatch$(HttpAction action) { - incCounter(action.srvRef, CounterName.GSPpatch) ; - try { - doPatch(action) ; - incCounter(action.srvRef, CounterName.GSPpatchGood) ; - } catch ( ActionErrorException ex) { - incCounter(action.srvRef, CounterName.GSPpatchBad) ; - throw ex ; - } - } - - protected void doDelete$(HttpAction action) { - incCounter(action.srvRef, CounterName.GSPdelete) ; - try { - doDelete(action) ; - incCounter(action.srvRef, CounterName.GSPdeleteGood) ; - } catch ( ActionErrorException ex) { - incCounter(action.srvRef, CounterName.GSPdeleteBad) ; - throw ex ; - } - } - - protected void doPut$(HttpAction action) { - incCounter(action.srvRef, CounterName.GSPput) ; - try { - doPut(action) ; - incCounter(action.srvRef, CounterName.GSPputGood) ; - } catch ( ActionErrorException ex) { - incCounter(action.srvRef, CounterName.GSPputBad) ; - throw ex ; - } - } - - protected void doOptions$(HttpAction action) { - incCounter(action.srvRef, CounterName.GSPoptions) ; - try { - doOptions(action) ; - incCounter(action.srvRef, CounterName.GSPoptionsGood) ; - } catch ( ActionErrorException ex) { - incCounter(action.srvRef, CounterName.GSPoptionsBad) ; - throw ex ; - } - } - - protected abstract void doGet(HttpAction action) ; - protected abstract void doHead(HttpAction action) ; - protected abstract void doPost(HttpAction action) ; - protected abstract void doPatch(HttpAction action) ; - protected abstract void doDelete(HttpAction action) ; - protected abstract void doPut(HttpAction action) ; - protected abstract void doOptions(HttpAction action) ; - - // @@ Move to SPARQL_ServletBase - // Check for all RiotReader - public static void parse(HttpAction action, StreamRDF dest, InputStream input, Lang lang, String base) { - try { - ReaderRIOT r = RDFDataMgr.createReader(lang) ; - if ( r == null ) - errorBadRequest("No parser for language '"+lang.getName()+"'") ; - r.setErrorHandler(errorHandler); - r.read(input, base, null, dest, null) ; - } - catch (RiotException ex) { errorBadRequest("Parse error: "+ex.getMessage()) ; } - } - - @Override - protected void validate(HttpAction action) - { - HttpServletRequest request = action.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 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] ; - } -}
http://git-wip-us.apache.org/repos/asf/jena/blob/662cf71d/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_R.java ---------------------------------------------------------------------- diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_R.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_R.java deleted file mode 100644 index 0c02b51..0000000 --- a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_R.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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 java.io.IOException ; - -import javax.servlet.ServletOutputStream ; - -import org.apache.jena.atlas.web.MediaType ; -import org.apache.jena.atlas.web.TypedOutputStream ; -import org.apache.jena.fuseki.HttpNames ; -import org.apache.jena.riot.* ; - -import com.hp.hpl.jena.graph.Graph ; - -/** Only the READ operations */ -public class SPARQL_REST_R extends SPARQL_REST -{ - public SPARQL_REST_R() - { super() ; } - - - @Override - protected String mapRequestToDataset(String uri) { return mapRequestToDatasetLongest$(uri) ; } - - @Override - protected void doGet(HttpAction action) - { - // Assume success - do the set up before grabbing the lock. - // Sets content type. - MediaType mediaType = HttpAction.contentNegotationRDF(action) ; - - ServletOutputStream output ; - try { output = action.response.getOutputStream() ; } - catch (IOException ex) { errorOccurred(ex) ; output = null ; } - - TypedOutputStream out = new TypedOutputStream(output, mediaType) ; - Lang lang = RDFLanguages.contentTypeToLang(mediaType.getContentType()) ; - - if ( action.verbose ) - log.info(format("[%d] Get: Content-Type=%s, Charset=%s => %s", - action.id, mediaType.getContentType(), mediaType.getCharset(), lang.getName())) ; - - action.beginRead() ; - setCommonHeaders(action.response) ; - - try { - Target target = determineTarget(action) ; - if ( log.isDebugEnabled() ) - log.debug("GET->"+target) ; - boolean exists = target.exists() ; - if ( ! exists ) - errorNotFound("No such graph: <"+target.name+">") ; - // If we want to set the Content-Length, we need to buffer. - //response.setContentLength(??) ; - String ct = lang.getContentType().toHeaderString() ; - action.response.setContentType(ct) ; - Graph g = target.graph() ; - //Special case RDF/XML to be the plain (faster, less readable) form - RDFFormat fmt = - ( lang == Lang.RDFXML ) ? RDFFormat.RDFXML_PLAIN : RDFWriterRegistry.defaultSerialization(lang) ; - RDFDataMgr.write(out, g, fmt) ; - success(action) ; - } finally { action.endRead() ; } - } - - @Override - protected void doOptions(HttpAction action) - { - setCommonHeadersForOptions(action.response) ; - action.response.setHeader(HttpNames.hAllow, "GET,HEAD,OPTIONS") ; - action.response.setHeader(HttpNames.hContentLengh, "0") ; - success(action) ; - } - - @Override - protected void doHead(HttpAction action) - { - setCommonHeaders(action.response) ; - action.beginRead() ; - try { - Target target = determineTarget(action) ; - if ( log.isDebugEnabled() ) - log.debug("HEAD->"+target) ; - if ( ! target.exists() ) - { - successNotFound(action) ; - return ; - } - MediaType mediaType = HttpAction.contentNegotationRDF(action) ; - success(action) ; - } finally { action.endRead() ; } - } - - @Override - protected void doPost(HttpAction action) - { errorMethodNotAllowed("POST") ; } - - @Override - protected void doDelete(HttpAction action) - { errorMethodNotAllowed("DELETE") ; } - - @Override - protected void doPut(HttpAction action) - { errorMethodNotAllowed("PUT") ; } - - @Override - protected void doPatch(HttpAction action) - { errorMethodNotAllowed("PATCH") ; } -} http://git-wip-us.apache.org/repos/asf/jena/blob/662cf71d/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_RW.java ---------------------------------------------------------------------- diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_RW.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_RW.java deleted file mode 100644 index 712d543..0000000 --- a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_RW.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * 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 java.io.IOException ; -import java.io.InputStream ; -import java.util.Map ; -import java.util.Map.Entry ; - -import org.apache.jena.atlas.io.IO ; -import org.apache.jena.atlas.web.ContentType ; -import org.apache.jena.fuseki.FusekiLib ; -import org.apache.jena.fuseki.HttpNames ; -import org.apache.jena.riot.Lang ; -import org.apache.jena.riot.RDFLanguages ; -import org.apache.jena.riot.RiotException ; -import org.apache.jena.riot.WebContent ; -import org.apache.jena.riot.system.StreamRDF ; -import org.apache.jena.riot.system.StreamRDFLib ; -import org.apache.jena.web.HttpSC ; - -import com.hp.hpl.jena.graph.Graph ; -import com.hp.hpl.jena.sparql.graph.GraphFactory ; - -/** The WRITE operations added to the READ operations */ -public class SPARQL_REST_RW extends SPARQL_REST_R -{ - public SPARQL_REST_RW() - { super() ; } - - @Override - protected void doOptions(HttpAction action) - { - setCommonHeadersForOptions(action.response) ; - action.response.setHeader(HttpNames.hAllow, "GET,HEAD,OPTIONS,PUT,DELETE,POST"); - action.response.setHeader(HttpNames.hContentLengh, "0") ; - success(action) ; - } - - @Override - protected void doDelete(HttpAction action) - { - action.beginWrite() ; - try { - Target target = determineTarget(action) ; - if ( log.isDebugEnabled() ) - log.debug("DELETE->"+target) ; - boolean existedBefore = target.exists() ; - if ( ! existedBefore) - { - // commit, not abort, because locking "transactions" don't support abort. - action.commit() ; - errorNotFound("No such graph: "+target.name) ; - } - deleteGraph(action) ; - action.commit() ; - } - finally { action.endWrite() ; } - ServletBase.successNoContent(action) ; - } - - @Override - protected void doPut(HttpAction action) { doPutPost(action, true) ; } - - @Override - protected void doPost(HttpAction action) { doPutPost(action, false) ; } - - private void doPutPost(HttpAction action, boolean overwrite) { - ContentType ct = FusekiLib.getContentType(action) ; - if ( ct == null ) - errorBadRequest("No Content-Type:") ; - - // Helper case - if it's a possible HTTP file upload, pretend that's the action. - if ( WebContent.contentTypeMultipartFormData.equalsIgnoreCase(ct.getContentType()) ) { - String base = wholeRequestURL(action.request) ; - SPARQL_Upload.upload(action, base) ; - return ; - } - - if ( WebContent.matchContentType(WebContent.ctMultipartMixed, ct) ) - error(HttpSC.UNSUPPORTED_MEDIA_TYPE_415, "multipart/mixed not supported") ; - - boolean existedBefore = false ; - if ( action.isTransactional() ) - existedBefore = addDataIntoTxn(action, overwrite) ; - else - existedBefore = addDataIntoNonTxn(action, overwrite) ; - - if ( existedBefore ) - ServletBase.successNoContent(action) ; - else - ServletBase.successCreated(action) ; - } - - /** Directly add data in a transaction. - * Assumes recovery from parse errors by transaction abort. - * Return whether the target existed before. - * @param action - * @param cleanDest Whether to remove data first (true = PUT, false = POST) - * @return whether the target existed beforehand - */ - protected static boolean addDataIntoTxn(HttpAction action, boolean overwrite) { - action.beginWrite(); - Target target = determineTarget(action) ; - boolean existedBefore = false ; - try { - if ( log.isDebugEnabled() ) - log.debug(" ->"+target) ; - existedBefore = target.exists() ; - Graph g = target.graph() ; - if ( overwrite && existedBefore ) - clearGraph(target) ; - StreamRDF sink = StreamRDFLib.graph(g) ; - incomingData(action, sink); - action.commit() ; - return existedBefore ; - } catch (RiotException ex) { - // Parse error - action.abort() ; - errorBadRequest(ex.getMessage()) ; - return existedBefore ; - } catch (Exception ex) { - // Something else went wrong. Backout. - action.abort() ; - errorOccurred(ex.getMessage()) ; - return existedBefore ; - } finally { - action.endWrite() ; - } - } - - /** Add data where the destination does not support full transactions. - * In particular, with no abort, and actions probably going to the real storage - * parse errors can lead to partial updates. Instead, parse to a temporary - * graph, then insert that data. - * @param action - * @param cleanDest Whether to remove data first (true = PUT, false = POST) - * @return whether the target existed beforehand. - */ - - protected static boolean addDataIntoNonTxn(HttpAction action, boolean overwrite) { - Graph graphTmp = GraphFactory.createGraphMem() ; - StreamRDF dest = StreamRDFLib.graph(graphTmp) ; - - try { incomingData(action, dest); } - catch (RiotException ex) { - errorBadRequest(ex.getMessage()) ; - return false ; - } - // Now insert into dataset - action.beginWrite() ; - Target target = determineTarget(action) ; - boolean existedBefore = false ; - try { - if ( log.isDebugEnabled() ) - log.debug(" ->"+target) ; - existedBefore = target.exists() ; - if ( overwrite && existedBefore ) - clearGraph(target) ; - FusekiLib.addDataInto(graphTmp, target.dsg, target.graphName) ; - action.commit() ; - return existedBefore ; - } catch (Exception ex) { - // We parsed into a temporary graph so an exception at this point - // is not because of a parse error. - // We're in the non-transactional branch, this probably will not work - // but it might and there is no harm safely trying. - try { action.abort() ; } catch (Exception ex2) {} - errorOccurred(ex.getMessage()) ; - return existedBefore ; - } finally { action.endWrite() ; } - } - - private static void incomingData(HttpAction action, StreamRDF dest) { - String base = wholeRequestURL(action.request) ; - ContentType ct = FusekiLib.getContentType(action) ; - Lang lang = RDFLanguages.contentTypeToLang(ct.getContentType()) ; - if ( lang == null ) { - errorBadRequest("Unknown content type for triples: " + ct) ; - return ; - } - InputStream input = null ; - try { input = action.request.getInputStream() ; } - catch (IOException ex) { IO.exception(ex) ; } - - int len = action.request.getContentLength() ; - 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())) ; - } - - parse(action, dest, input, lang, base) ; - } - - protected static void deleteGraph(HttpAction action) { - Target target = determineTarget(action) ; - if ( target.isDefault ) - target.graph().clear() ; - else - action.getActiveDSG().removeGraph(target.graphName) ; - } - - protected static void clearGraph(Target target) { - Graph g = target.graph() ; - g.clear() ; - Map<String, String> pm = g.getPrefixMapping().getNsPrefixMap() ; - for ( Entry<String, String> e : pm.entrySet() ) - g.getPrefixMapping().removeNsPrefix(e.getKey()) ; - } -} http://git-wip-us.apache.org/repos/asf/jena/blob/662cf71d/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_ServletBase.java ---------------------------------------------------------------------- diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_ServletBase.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_ServletBase.java deleted file mode 100644 index a3d5271..0000000 --- a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_ServletBase.java +++ /dev/null @@ -1,458 +0,0 @@ -/* - * 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.server.CounterName.Requests ; -import static org.apache.jena.fuseki.server.CounterName.RequestsBad ; -import static org.apache.jena.fuseki.server.CounterName.RequestsGood ; - -import java.io.IOException ; -import java.util.Enumeration ; -import java.util.Map ; -import java.util.concurrent.atomic.AtomicLong ; - -import javax.servlet.ServletException ; -import javax.servlet.http.HttpServletRequest ; -import javax.servlet.http.HttpServletResponse ; - -import org.apache.jena.atlas.RuntimeIOException ; -import org.apache.jena.fuseki.Fuseki ; -import org.apache.jena.fuseki.HttpNames ; -import org.apache.jena.fuseki.server.* ; -import org.apache.jena.web.HttpSC ; - -import com.hp.hpl.jena.query.ARQ ; -import com.hp.hpl.jena.query.QueryCancelledException ; -import com.hp.hpl.jena.sparql.util.Context ; - -/** - * Base servlet for SPARQL requests. - */ -public abstract class SPARQL_ServletBase extends ServletBase -{ - /** - * Creates a new SPARQL base Servlet. - */ - protected SPARQL_ServletBase() { super() ; } - - // Common framework for handling HTTP requests - /** - * Handles GET and POST requests. - * @param request HTTP request - * @param response HTTP response - */ - protected void doCommon(HttpServletRequest request, HttpServletResponse response) - //throws ServletException, IOException - { - try { - long id = allocRequestId(request, response); - - // Lifecycle - HttpAction action = allocHttpAction(id, request, response) ; - // then add to doCommonWorker - // work with HttpServletResponseTracker - - printRequest(action) ; - action.setStartTime() ; - - response = action.response ; - initResponse(request, response) ; - Context cxt = ARQ.getContext() ; - - try { - execCommonWorker(action) ; - } catch (QueryCancelledException ex) { - // Also need the per query info ... - String message = String.format("The query timed out (restricted to %s ms)", cxt.get(ARQ.queryTimeout)); - // Possibility :: response.setHeader("Retry-after", "600") ; // 5 minutes - responseSendError(response, HttpSC.SERVICE_UNAVAILABLE_503, message); - } catch (ActionErrorException ex) { - if ( ex.exception != null ) - ex.exception.printStackTrace(System.err) ; - // Log message done by printResponse in a moment. - if ( ex.message != null ) - responseSendError(response, ex.rc, ex.message) ; - else - responseSendError(response, ex.rc) ; - } catch (RuntimeIOException ex) { - log.warn(format("[%d] Runtime IO Exception (client left?) RC = %d", id, HttpSC.INTERNAL_SERVER_ERROR_500)) ; - responseSendError(response, HttpSC.INTERNAL_SERVER_ERROR_500, ex.getMessage()) ; - } catch (Throwable ex) { - // This should not happen. - //ex.printStackTrace(System.err) ; - log.warn(format("[%d] RC = %d : %s", id, HttpSC.INTERNAL_SERVER_ERROR_500, ex.getMessage()), ex) ; - responseSendError(response, HttpSC.INTERNAL_SERVER_ERROR_500, ex.getMessage()) ; - } - - action.setFinishTime() ; - printResponse(action) ; - archiveHttpAction(action) ; - } catch (Throwable th) { - log.error("Internal error", th) ; - } - } - - // ---- Operation lifecycle - - /** - * Returns a fresh HTTP Action for this request. - * @param id the Request ID - * @param request HTTP request - * @param response HTTP response - * @return a new HTTP Action - */ - protected HttpAction allocHttpAction(long id, HttpServletRequest request, HttpServletResponse response) { - // Need a way to set verbose logging on a per servlet and per request basis. - return new HttpAction(id, request, response, verboseLogging) ; - } - - /** - * Validates a HTTP Action. - * @param action HTTP Action - */ - protected abstract void validate(HttpAction action) ; - - /** - * Performs the HTTP Action. - * @param action HTTP Action - */ - protected abstract void perform(HttpAction action) ; - - /** - * Default start step. - * @param action HTTP Action - */ - protected void startRequest(HttpAction action) { - } - - /** - * Default finish step. - * @param action HTTP Action - */ - protected void finishRequest(HttpAction action) { } - - /** - * Archives the HTTP Action. - * @param action HTTP Action - * @see HttpAction#minimize() - */ - private void archiveHttpAction(HttpAction action) - { - action.minimize() ; - } - - /** - * Executes common tasks, including mapping the request to the right dataset, setting the dataset into the HTTP - * action, and retrieving the service for the dataset requested. Finally, it calls the - * {@link #executeAction(HttpAction)} method, which executes the HTTP Action life cycle. - * @param action HTTP Action - */ - private void execCommonWorker(HttpAction action) - { - DatasetRef dsRef = null ; - String uri = action.request.getRequestURI() ; - - String datasetUri = mapRequestToDataset(uri) ; - - if ( datasetUri != null ) { - dsRef = DatasetRegistry.get().get(datasetUri) ; - if ( dsRef == null ) { - errorNotFound("No dataset for URI: "+datasetUri) ; - return ; - } - } else - dsRef = FusekiConfig.serviceOnlyDatasetRef() ; - - action.setDataset(dsRef) ; - String serviceName = mapRequestToService(dsRef, uri, datasetUri) ; - ServiceRef srvRef = dsRef.getServiceRef(serviceName) ; - action.setService(srvRef) ; - executeAction(action) ; - } - - /** - * Utility method, that increments and returns the AtomicLong value. - * @param x AtomicLong - */ - protected void inc(AtomicLong x) - { - x.incrementAndGet() ; - } - - /** - * Executes the HTTP Action. Serves as intercept point for the UberServlet. - * @param action HTTP Action - */ - protected void executeAction(HttpAction action) - { - executeLifecycle(action) ; - } - - /** - * Handles the service request lifecycle. Called directly by the UberServlet, - * which has not done any stats by this point. - * @param action {@link HttpAction} - * @see HttpAction - */ - protected void executeLifecycle(HttpAction action) - { - incCounter(action.dsRef, Requests) ; - incCounter(action.srvRef, Requests) ; - - startRequest(action) ; - try { - validate(action) ; - } catch (ActionErrorException ex) { - incCounter(action.dsRef,RequestsBad) ; - throw ex ; - } - - try { - perform(action) ; - // Success - incCounter(action.srvRef, RequestsGood) ; - incCounter(action.dsRef, RequestsGood) ; - } catch (ActionErrorException ex) { - incCounter(action.srvRef, RequestsBad) ; - incCounter(action.dsRef, RequestsBad) ; - throw ex ; - } catch (QueryCancelledException ex) { - incCounter(action.srvRef, RequestsBad) ; - incCounter(action.dsRef, RequestsBad) ; - throw ex ; - } finally { - finishRequest(action) ; - } - } - - /** - * Increments a counter. - * @param counters a {@link Counter} - * @param name a {@link CounterName} - */ - protected static void incCounter(Counters counters, CounterName name) { - try { - if ( counters.getCounters().contains(name) ) - counters.getCounters().inc(name) ; - } catch (Exception ex) { - Fuseki.serverLog.warn("Exception on counter inc", ex) ; - } - } - - /** - * Decrements a counter. - * @param counters a {@link Counter} - * @param name a {@link CounterName} - */ - protected static void decCounter(Counters counters, CounterName name) { - try { - if ( counters.getCounters().contains(name) ) - counters.getCounters().dec(name) ; - } catch (Exception ex) { - Fuseki.serverLog.warn("Exception on counter dec", ex) ; - } - } - - /** - * <p>Sends an <strong>error</strong> when the PATCH method is called.</p> - * <p>Throws ServletException or IOException as per overloaded method signature.</p> - * @param request HTTP request - * @param response HTTP response - * @throws ServletException from overloaded method signature - * @throws IOException from overloaded method signature - */ - protected void doPatch(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException - { - response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "HTTP PATCH not supported"); - } - - /** - * Prints the HTTP Action request to the program log, using the INFO level. - * @param action {@link HttpAction} - */ - private void printRequest(HttpAction action) - { - String url = wholeRequestURL(action.request) ; - String method = action.request.getMethod() ; - - log.info(format("[%d] %s %s", action.id, method, url)) ; - if ( action.verbose ) { - Enumeration<String> en = action.request.getHeaderNames() ; - for (; en.hasMoreElements();) { - String h = en.nextElement() ; - Enumeration<String> vals = action.request.getHeaders(h) ; - if (!vals.hasMoreElements()) - log.info(format("[%d] ", action.id, h)) ; - else { - for (; vals.hasMoreElements();) - log.info(format("[%d] %-20s %s", action.id, h, vals.nextElement())) ; - } - } - } - } - - /** - * Initiates the response, by setting common headers such as Access-Control-Allow-Origin and Server, and - * the Vary header if the request method used was a GET. - * @param request HTTP request - * @param response HTTP response - */ - private void initResponse(HttpServletRequest request, HttpServletResponse response) - { - setCommonHeaders(response) ; - String method = request.getMethod() ; - // All GET and HEAD operations are sensitive to conneg so ... - if ( HttpNames.METHOD_GET.equalsIgnoreCase(method) || HttpNames.METHOD_HEAD.equalsIgnoreCase(method) ) - setVaryHeader(response) ; - } - - /** - * Prints the HTTP Action response to the program log, using the INFO level. - * @param action {@link HttpAction} - */ - private void printResponse(HttpAction action) - { - long time = action.getTime() ; - - HttpServletResponseTracker response = action.response ; - if ( action.verbose ) - { - if ( action.contentType != null ) - log.info(format("[%d] %-20s %s", action.id, HttpNames.hContentType, action.contentType)) ; - if ( action.contentLength != -1 ) - log.info(format("[%d] %-20s %d", action.id, HttpNames.hContentLengh, action.contentLength)) ; - for ( Map.Entry<String, String> e: action.headers.entrySet() ) - log.info(format("[%d] %-20s %s", action.id, e.getKey(), e.getValue())) ; - } - - String timeStr = fmtMillis(time) ; - - if ( action.message == null ) - log.info(String.format("[%d] %d %s (%s) ", action.id, action.statusCode, HttpSC.getMessage(action.statusCode), timeStr)) ; - else - log.info(String.format("[%d] %d %s (%s) ", action.id, action.statusCode, action.message, timeStr)) ; - } - - /** - * <p>Given a time epoch, it will return the time in milli seconds if it is less than 1000, - * otherwise it will normalize it to display as second.</p> - * <p>It appends a 'ms' suffix when using milli seconds, and ditto <i>s</i> for seconds.</p> - * <p>For instance: </p> - * <ul> - * <li>10 emits 10 ms</li> - * <li>999 emits 999 ms</li> - * <li>1000 emits 1.000000 s</li> - * <li>10000 emits 10.000000 s</li> - * </ul> - * @param time the time epoch - * @return the time in milli seconds or in seconds - */ - private static String fmtMillis(long time) - { - // Millis only? seconds only? - if ( time < 1000 ) - return String.format("%,d ms", time) ; - return String.format("%,.3f s", time/1000.0) ; - } - - /** - * Map request to uri in the registry. null means no mapping done (passthrough). - * @param uri the URI - * @return the dataset - */ - protected String mapRequestToDataset(String uri) - { - return mapRequestToDataset$(uri) ; - } - - /** - * A possible implementation for mapRequestToDataset(String) that assumes the form /dataset/service. - * @param uri the URI - * @return the dataset - */ - protected static String mapRequestToDataset$(String uri) - { - // Chop off trailing part - the service selector - // e.g. /dataset/sparql => /dataset - int i = uri.lastIndexOf('/') ; - if ( i == -1 ) - return null ; - if ( i == 0 ) - { - // started with '/' - leave. - return uri ; - } - - return uri.substring(0, i) ; - } - - /** - * Maps a request to a service (e.g. Query, Update). - * @param dsRef a {@link DatasetRef} - * @param uri the URI - * @param datasetURI the dataset URI - * @return an empty String (i.e. "") if the DatasetRef is null, or if its name is longer than the URI's name. - * Otherwise will return the service name. - */ - protected String mapRequestToService(DatasetRef dsRef, String uri, String datasetURI) - { - if ( dsRef == null ) - return "" ; - if ( dsRef.name.length() >= uri.length() ) - return "" ; - return uri.substring(dsRef.name.length()+1) ; // Skip the separating "/" - - } - - /** - * Implementation of mapRequestToDataset(String) that looks for the longest match in the registry. - * This includes use in direct naming GSP. - * @param uri the URI - * @return <code>null</code> if the URI is null, otherwise will return the longest match in the registry. - */ - protected static String mapRequestToDatasetLongest$(String uri) - { - if ( uri == null ) - return null ; - - // This covers local, using the URI as a direct name for - // a graph, not just using the indirect ?graph= or ?default - // forms. - - String ds = null ; - for ( String ds2 : DatasetRegistry.get().keys() ) { - if ( ! uri.startsWith(ds2) ) - continue ; - - if ( ds == null ) - { - ds = ds2 ; - continue ; - } - if ( ds.length() < ds2.length() ) - { - ds = ds2 ; - continue ; - } - } - return ds ; - } -} http://git-wip-us.apache.org/repos/asf/jena/blob/662cf71d/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_UberServlet.java ---------------------------------------------------------------------- diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_UberServlet.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_UberServlet.java deleted file mode 100644 index 0c10cee..0000000 --- a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_UberServlet.java +++ /dev/null @@ -1,338 +0,0 @@ -/** - * 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 java.util.List ; - -import javax.servlet.http.HttpServletRequest ; -import javax.servlet.http.HttpServletResponse ; - -import org.apache.jena.atlas.web.MediaType ; -import org.apache.jena.fuseki.DEF ; -import org.apache.jena.fuseki.FusekiException ; -import org.apache.jena.fuseki.HttpNames ; -import org.apache.jena.fuseki.conneg.ConNeg ; -import org.apache.jena.fuseki.server.DatasetRef ; -import org.apache.jena.fuseki.server.ServiceRef ; -import org.apache.jena.riot.WebContent ; - -/** This servlet can be attached to a dataset location - * and acts as a router for all SPARQL operations - * (query, update, graph store, both direct and indirect naming). - */ -public abstract class SPARQL_UberServlet extends SPARQL_ServletBase -{ - protected abstract boolean allowQuery(HttpAction action) ; - protected abstract boolean allowUpdate(HttpAction action) ; - protected abstract boolean allowREST_R(HttpAction action) ; - protected abstract boolean allowREST_W(HttpAction action) ; - protected abstract boolean allowQuadsR(HttpAction action) ; - protected abstract boolean allowQuadsW(HttpAction action) ; - - public static class ReadOnly extends SPARQL_UberServlet - { - public ReadOnly() { super() ; } - @Override protected boolean allowQuery(HttpAction action) { return true ; } - @Override protected boolean allowUpdate(HttpAction action) { return false ; } - @Override protected boolean allowREST_R(HttpAction action) { return true ; } - @Override protected boolean allowREST_W(HttpAction action) { return false ; } - @Override protected boolean allowQuadsR(HttpAction action) { return true ; } - @Override protected boolean allowQuadsW(HttpAction action) { return false ; } - } - - public static class ReadWrite extends SPARQL_UberServlet - { - public ReadWrite() { super() ; } - @Override protected boolean allowQuery(HttpAction action) { return true ; } - @Override protected boolean allowUpdate(HttpAction action) { return true ; } - @Override protected boolean allowREST_R(HttpAction action) { return true ; } - @Override protected boolean allowREST_W(HttpAction action) { return true ; } - @Override protected boolean allowQuadsR(HttpAction action) { return true ; } - @Override protected boolean allowQuadsW(HttpAction action) { return true ; } - } - - public static class AccessByConfig extends SPARQL_UberServlet - { - public AccessByConfig() { super() ; } - @Override protected boolean allowQuery(HttpAction action) { return isEnabled(action.dsRef.query) ; } - @Override protected boolean allowUpdate(HttpAction action) { return isEnabled(action.dsRef.update) ; } - @Override protected boolean allowREST_R(HttpAction action) { return isEnabled(action.dsRef.readGraphStore) || allowREST_W(action); } - @Override protected boolean allowREST_W(HttpAction action) { return isEnabled(action.dsRef.readWriteGraphStore) ; } - // Quad operations tied to presence/absence of GSP. - @Override protected boolean allowQuadsR(HttpAction action) { return isEnabled(action.dsRef.readGraphStore) ; } - @Override protected boolean allowQuadsW(HttpAction action) { return isEnabled(action.dsRef.readWriteGraphStore) ; } - - private boolean isEnabled(ServiceRef service) { return service.isActive() ; } - } - - /* This can be used for a single servlet for everything (über-servlet) - * - * It can check for a request that looks like a service request and passes it on. - * This takes precedence over direct naming. - */ - - // Refactor? Extract the direct naming handling. - // To test: enable in SPARQLServer.configureOneDataset - - private final SPARQL_ServletBase queryServlet = new SPARQL_QueryDataset() ; - private final SPARQL_ServletBase updateServlet = new SPARQL_Update() ; - private final SPARQL_ServletBase uploadServlet = new SPARQL_Upload() ; - private final SPARQL_REST restServlet_RW = new SPARQL_REST_RW() ; - private final SPARQL_REST restServlet_R = new SPARQL_REST_R() ; - private final SPARQL_ServletBase restQuads = new REST_Quads() ; - - public SPARQL_UberServlet() { super(); } - - private String getEPName(String dsname, List<String> endpoints) - { - if (endpoints == null || endpoints.size() == 0) return null ; - String x = endpoints.get(0) ; - if ( ! dsname.endsWith("/") ) - x = dsname+"/"+x ; - else - x = dsname+x ; - return x ; - } - - // These calls should not happen because we hook in at executeAction - @Override protected void validate(HttpAction action) { throw new FusekiException("Call to SPARQL_UberServlet.validate") ; } - @Override protected void perform(HttpAction action) { throw new FusekiException("Call to SPARQL_UberServlet.perform") ; } - - /** Map request to uri in the registry. - * null means no mapping done - */ - @Override - protected String mapRequestToDataset(String uri) - { - return mapRequestToDatasetLongest$(uri) ; - } - - - /** Intercept the processing cycle at the point where the action has been set up, - * the dataset target decided but no validation or execution has been done, - * nor any stats have been done. - */ - @Override - protected void executeAction(HttpAction action) - { - long id = action.id ; - HttpServletRequest request = action.request ; - HttpServletResponse response = action.response ; - String uri = request.getRequestURI() ; - String method = request.getMethod() ; - DatasetRef desc = action.dsRef ; - - String trailing = findTrailing(uri, desc.name) ; - String qs = request.getQueryString() ; - - boolean hasParams = request.getParameterMap().size() > 0 ; - - // Test for parameters - includes HTML forms. - boolean hasParamQuery = request.getParameter(HttpNames.paramQuery) != null ; - // Include old name "request=" - boolean hasParamUpdate = request.getParameter(HttpNames.paramUpdate) != null || request.getParameter(HttpNames.paramRequest) != null ; - boolean hasParamGraph = request.getParameter(HttpNames.paramGraph) != null ; - boolean hasParamGraphDefault = request.getParameter(HttpNames.paramGraphDefault) != null ; - boolean isForm = WebContent.contentTypeHTMLForm.equalsIgnoreCase(request.getContentType()) ; - - String ct = request.getContentType() ; - String charset = request.getCharacterEncoding() ; - - MediaType mt = null ; - if ( ct != null ) - mt = MediaType.create(ct, charset) ; - - log.info(format("[%d] All: %s %s :: '%s' :: %s ? %s", id, method, desc.name, trailing, (mt==null?"<none>":mt), (qs==null?"":qs))) ; - - boolean hasTrailing = ( trailing.length() != 0 ) ; - - if ( ! hasTrailing && ! hasParams ) - { - restQuads.executeLifecycle(action) ; - return ; - } - - if ( ! hasTrailing ) - { - // Has params of some kind. - if ( hasParamQuery || WebContent.contentTypeSPARQLQuery.equalsIgnoreCase(ct) ) - { - // SPARQL Query - if ( ! allowQuery(action)) - errorForbidden("Forbidden: SPARQL query") ; - executeRequest(action, queryServlet, desc.query) ; - return ; - } - - if ( hasParamUpdate || WebContent.contentTypeSPARQLUpdate.equalsIgnoreCase(ct) ) - { - // SPARQL Update - if ( ! allowQuery(action)) - errorForbidden("Forbidden: SPARQL query") ; - executeRequest(action, updateServlet, desc.update) ; - return ; - } - - if ( hasParamGraph || hasParamGraphDefault ) - { - doGraphStoreProtocol(action) ; - return ; - } - - errorBadRequest("Malformed request") ; - errorForbidden("Forbidden: SPARQL Graph Store Protocol : Read operation : "+method) ; - } - - final boolean checkForPossibleService = true ; - if ( checkForPossibleService ) - { - // There is a trailing part. - // Check it's not the same name as a registered service. - // If so, dispatch to that service. - if ( serviceDispatch(action, desc.query, trailing, queryServlet) ) return ; - if ( serviceDispatch(action, desc.update, trailing, updateServlet) ) return ; - if ( serviceDispatch(action, desc.upload, trailing, uploadServlet) ) return ; - if ( serviceDispatch(action, desc.readGraphStore, trailing, restServlet_R) ) return ; - if ( serviceDispatch(action, desc.readWriteGraphStore, trailing, restServlet_RW) ) return ; - } - // There is a trailing part - params are illegal by this point. - if ( hasParams ) - // ?? Revisit to include query-on-one-graph - //errorBadRequest("Can't invoke a query-string service on a direct named graph") ; - errorNotFound("Not found: dataset='"+printName(desc.name)+"' service='"+printName(trailing)+"'"); - - // There is a trailing part - not a service, no params ==> GSP direct naming. - doGraphStoreProtocol(action) ; - } - - private String printName(String x) { - if ( x.startsWith("/") ) - return x.substring(1) ; - return x ; - } - - private void doGraphStoreProtocol(HttpAction action) - { - // The GSP servlets handle direct and indirect naming. - DatasetRef desc = action.dsRef ; - String method = action.request.getMethod() ; - - if ( HttpNames.METHOD_GET.equalsIgnoreCase(method) || - HttpNames.METHOD_HEAD.equalsIgnoreCase(method) ) - { - if ( ! allowREST_R(action)) - // Graphs Store Protocol, indirect naming, read - // Indirect naming. Prefer the R service if available. - if ( desc.readGraphStore.isActive() ) - executeRequest(action, restServlet_R, desc.readGraphStore) ; - else if ( desc.readWriteGraphStore.isActive() ) - executeRequest(action, restServlet_RW, desc.readWriteGraphStore) ; - else - errorMethodNotAllowed(method) ; - return ; - } - - // Graphs Store Protocol, indirect naming, write - if ( ! allowREST_W(action)) - errorForbidden("Forbidden: SPARQL Graph Store Protocol : Write operation : "+method) ; - executeRequest(action, restServlet_RW, desc.readWriteGraphStore) ; - return ; - } - - private void executeRequest(HttpAction action, SPARQL_ServletBase servlet, ServiceRef service) - { - if ( service.endpoints.size() == 0 ) - errorMethodNotAllowed(action.request.getMethod()) ; - servlet.executeLifecycle(action) ; - } - - private void executeRequest(HttpAction action,SPARQL_ServletBase servlet) - { - servlet.executeLifecycle(action) ; -// // Forwarded dispatch. -// try -// { -// String target = getEPName(desc.name, endpointList) ; -// if ( target == null ) -// errorMethodNotAllowed(request.getMethod()) ; -// // ** relative servlet forward -// request.getRequestDispatcher(target).forward(request, response) ; - - -// // ** absolute srvlet forward -// // getServletContext().getRequestDispatcher(target) ; -// } catch (Exception e) { errorOccurred(e) ; } - } - - protected static MediaType contentNegotationQuads(HttpAction action) - { - MediaType mt = ConNeg.chooseContentType(action.request, DEF.quadsOffer, DEF.acceptNQuads) ; - if ( mt == null ) - return null ; - if ( mt.getContentType() != null ) - action.response.setContentType(mt.getContentType()); - if ( mt.getCharset() != null ) - action.response.setCharacterEncoding(mt.getCharset()) ; - return mt ; - } - - /** return true if dispatched */ - private boolean serviceDispatch(HttpAction action, ServiceRef service, String srvName , SPARQL_ServletBase servlet) - { - if ( ! service.endpoints.contains(srvName) ) - return false ; - servlet.executeLifecycle(action) ; - return true ; - } - - /** Find the graph (direct naming) or service name */ - protected String findTrailing(String uri, String dsname) - { - if ( dsname.length() >= uri.length() ) - return "" ; - return uri.substring(dsname.length()+1) ; // Skip the separating "/" - } - - @Override - protected void doHead(HttpServletRequest request, HttpServletResponse response) - { doCommon(request, response) ; } - - @Override - protected void doGet(HttpServletRequest request, HttpServletResponse response) - { doCommon(request, response) ; } - - @Override - protected void doPost(HttpServletRequest request, HttpServletResponse response) - { doCommon(request, response) ; } - - @Override - protected void doOptions(HttpServletRequest request, HttpServletResponse response) - { doCommon(request, response) ; } - - @Override - protected void doPut(HttpServletRequest request, HttpServletResponse response) - { doCommon(request, response) ; } - - @Override - protected void doDelete(HttpServletRequest request, HttpServletResponse response) - { doCommon(request, response) ; } -} - http://git-wip-us.apache.org/repos/asf/jena/blob/662cf71d/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Update.java ---------------------------------------------------------------------- diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Update.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Update.java deleted file mode 100644 index f16f634..0000000 --- a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Update.java +++ /dev/null @@ -1,308 +0,0 @@ -/* - * 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.Fuseki.requestLog ; -import static org.apache.jena.fuseki.HttpNames.paramRequest ; -import static org.apache.jena.fuseki.HttpNames.paramUpdate ; -import static org.apache.jena.fuseki.HttpNames.paramUsingGraphURI ; -import static org.apache.jena.fuseki.HttpNames.paramUsingNamedGraphURI ; -import static org.apache.jena.fuseki.server.CounterName.UpdateExecErrors ; - -import java.io.ByteArrayInputStream ; -import java.io.IOException ; -import java.io.InputStream ; -import java.util.Arrays ; -import java.util.Collection ; -import java.util.Enumeration ; -import java.util.List ; - -import javax.servlet.ServletException ; -import javax.servlet.http.HttpServletRequest ; -import javax.servlet.http.HttpServletResponse ; - -import org.apache.jena.atlas.io.IO ; -import org.apache.jena.atlas.lib.StrUtils ; -import org.apache.jena.atlas.web.ContentType ; -import org.apache.jena.fuseki.FusekiLib ; -import org.apache.jena.fuseki.HttpNames ; -import org.apache.jena.iri.IRI ; -import org.apache.jena.riot.WebContent ; -import org.apache.jena.riot.system.IRIResolver ; -import org.apache.jena.web.HttpSC ; - -import com.hp.hpl.jena.graph.Node ; -import com.hp.hpl.jena.graph.NodeFactory ; -import com.hp.hpl.jena.query.QueryParseException ; -import com.hp.hpl.jena.query.Syntax ; -import com.hp.hpl.jena.sparql.modify.UsingList ; -import com.hp.hpl.jena.update.UpdateAction ; -import com.hp.hpl.jena.update.UpdateException ; -import com.hp.hpl.jena.update.UpdateFactory ; -import com.hp.hpl.jena.update.UpdateRequest ; - -public class SPARQL_Update extends SPARQL_Protocol -{ - // Base URI used to isolate parsing from the current directory of the server. - private static final String UpdateParseBase = "http://example/update-base/" ; - private static final IRIResolver resolver = IRIResolver.create(UpdateParseBase) ; - - public SPARQL_Update() - { super() ; } - - @Override - protected void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException - { - response.sendError(HttpSC.BAD_REQUEST_400, "Attempt to perform SPARQL update by GET. Use POST") ; - } - - @Override - protected void doPost(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException - { - doCommon(request, response) ; - } - - @Override - protected void doOptions(HttpServletRequest request, HttpServletResponse response) - { - setCommonHeadersForOptions(response) ; - response.setHeader(HttpNames.hAllow, "OPTIONS,POST"); - response.setHeader(HttpNames.hContentLengh, "0") ; - } - - @Override - protected void perform(HttpAction action) - { - // WebContent needs to migrate to using ContentType. - String ctStr ; - { - ContentType ct = FusekiLib.getContentType(action) ; - if ( ct == null ) - ctStr = WebContent.contentTypeSPARQLUpdate ; - else - ctStr = ct.getContentType() ; - } - - if (WebContent.contentTypeSPARQLUpdate.equals(ctStr)) - { - executeBody(action) ; - return ; - } - if (WebContent.contentTypeHTMLForm.equals(ctStr)) - { - executeForm(action) ; - return ; - } - error(HttpSC.UNSUPPORTED_MEDIA_TYPE_415, "Bad content type: " + action.request.getContentType()) ; - } - - protected static List<String> paramsForm = Arrays.asList(paramRequest, paramUpdate, - paramUsingGraphURI, paramUsingNamedGraphURI) ; - protected static List<String> paramsPOST = Arrays.asList(paramUsingGraphURI, paramUsingNamedGraphURI) ; - - @Override - protected void validate(HttpAction action) - { - HttpServletRequest request = action.request ; - - if ( ! HttpNames.METHOD_POST.equalsIgnoreCase(request.getMethod()) ) - errorMethodNotAllowed("SPARQL Update : use POST") ; - - ContentType incoming = FusekiLib.getContentType(action) ; - String ctStr = ( incoming == null ) ? WebContent.contentTypeSPARQLUpdate : incoming.getContentType() ; - // ---- - - if ( WebContent.contentTypeSPARQLUpdate.equals(ctStr) ) - { - String charset = request.getCharacterEncoding() ; - if ( charset != null && ! charset.equalsIgnoreCase(WebContent.charsetUTF8) ) - errorBadRequest("Bad charset: "+charset) ; - validate(request, paramsPOST) ; - return ; - } - - if ( WebContent.contentTypeHTMLForm.equals(ctStr) ) - { - int x = countParamOccurences(request, paramUpdate) + countParamOccurences(request, paramRequest) ; - if ( x == 0 ) - errorBadRequest("SPARQL Update: No 'update=' parameter") ; - if ( x != 1 ) - errorBadRequest("SPARQL Update: Multiple 'update=' parameters") ; - - String requestStr = request.getParameter(paramUpdate) ; - if ( requestStr == null ) - requestStr = request.getParameter(paramRequest) ; - if ( requestStr == null ) - errorBadRequest("SPARQL Update: No update= in HTML form") ; - validate(request, paramsForm) ; - return ; - } - - error(HttpSC.UNSUPPORTED_MEDIA_TYPE_415, "Must be "+WebContent.contentTypeSPARQLUpdate+" or "+WebContent.contentTypeHTMLForm+" (got "+ctStr+")") ; - } - - protected void validate(HttpServletRequest request, Collection<String> params) - { - if ( params != null ) - { - Enumeration<String> en = request.getParameterNames() ; - for ( ; en.hasMoreElements() ; ) - { - String name = en.nextElement() ; - if ( ! params.contains(name) ) - warning("SPARQL Update: Unrecognize request parameter (ignored): "+name) ; - } - } - } - - private void executeBody(HttpAction action) - { - InputStream input = null ; - try { input = action.request.getInputStream() ; } - catch (IOException ex) { errorOccurred(ex) ; } - - if ( action.verbose ) - { - // Verbose mode only .... capture request for logging (does not scale). - String requestStr = null ; - try { requestStr = IO.readWholeFileAsUTF8(input) ; } - catch (IOException ex) { IO.exception(ex) ; } - requestLog.info(format("[%d] Update = %s", action.id, formatForLog(requestStr))) ; - - input = new ByteArrayInputStream(requestStr.getBytes()); - requestStr = null; - } - - execute(action, input) ; - successNoContent(action) ; - } - - private void executeForm(HttpAction action) - { - String requestStr = action.request.getParameter(paramUpdate) ; - if ( requestStr == null ) - requestStr = action.request.getParameter(paramRequest) ; - - if ( action.verbose ) - //requestLog.info(format("[%d] Form update = %s", action.id, formatForLog(requestStr))) ; - requestLog.info(format("[%d] Form update = \n%s", action.id, requestStr)) ; - // A little ugly because we are taking a copy of the string, but hopefully shouldn't be too big if we are in this code-path - // If we didn't want this additional copy, we could make the parser take a Reader in addition to an InputStream - byte[] b = StrUtils.asUTF8bytes(requestStr) ; - ByteArrayInputStream input = new ByteArrayInputStream(b); - requestStr = null; // free it early at least - execute(action, input); - successPage(action,"Update succeeded") ; - } - - private void execute(HttpAction action, InputStream input) - { - UsingList usingList = processProtocol(action.request) ; - - // If the dsg is transactional, then we can parse and execute the update in a streaming fashion. - // If it isn't, we need to read the entire update request before performing any updates, because - // we have to attempt to make the request atomic in the face of malformed queries - UpdateRequest req = null ; - if (!action.isTransactional()) - { - try { - // TODO implement a spill-to-disk version of this - req = UpdateFactory.read(usingList, input, UpdateParseBase, Syntax.syntaxARQ); - } - catch (UpdateException ex) { errorBadRequest(ex.getMessage()) ; return ; } - catch (QueryParseException ex) { errorBadRequest(messageForQPE(ex)) ; return ; } - } - - action.beginWrite() ; - try { - if (req == null ) - UpdateAction.parseExecute(usingList, action.getActiveDSG(), input, UpdateParseBase, Syntax.syntaxARQ); - else - UpdateAction.execute(req, action.getActiveDSG()) ; - action.commit() ; - } catch (UpdateException ex) { - action.abort() ; - incCounter(action.srvRef, UpdateExecErrors) ; - errorOccurred(ex.getMessage()) ; - } catch (QueryParseException ex) { - action.abort() ; - // Counter inc'ed further out. - errorBadRequest(messageForQPE(ex)) ; - } catch (Throwable ex) { - if ( ! ( ex instanceof ActionErrorException ) ) - { - try { action.abort() ; } catch (Exception ex2) {} - errorOccurred(ex.getMessage(), ex) ; - } - } finally { action.endWrite(); } - } - - /* [It is an error to supply the using-graph-uri or using-named-graph-uri parameters - * when using this protocol to convey a SPARQL 1.1 Update request that contains an - * operation that uses the USING, USING NAMED, or WITH clause.] - * - * We will simply capture any using parameters here and pass them to the parser, which will be - * responsible for throwing an UpdateException if the query violates the above requirement, - * and will also be responsible for adding the using parameters to update queries that can - * accept them. - */ - private UsingList processProtocol(HttpServletRequest request) - { - UsingList toReturn = new UsingList(); - - String[] usingArgs = request.getParameterValues(paramUsingGraphURI) ; - String[] usingNamedArgs = request.getParameterValues(paramUsingNamedGraphURI) ; - if ( usingArgs == null && usingNamedArgs == null ) - return toReturn; - if ( usingArgs == null ) - usingArgs = new String[0] ; - if ( usingNamedArgs == null ) - usingNamedArgs = new String[0] ; - // Impossible. -// if ( usingArgs.length == 0 && usingNamedArgs.length == 0 ) -// return ; - - for (String nodeUri : usingArgs) - { - toReturn.addUsing(createNode(nodeUri)); - } - for (String nodeUri : usingNamedArgs) - { - toReturn.addUsingNamed(createNode(nodeUri)); - } - - return toReturn; - } - - private static Node createNode(String x) - { - try { - IRI iri = resolver.resolve(x) ; - return NodeFactory.createURI(iri.toString()) ; - } catch (Exception ex) - { - errorBadRequest("SPARQL Update: bad IRI: "+x) ; - return null ; - } - - } -} http://git-wip-us.apache.org/repos/asf/jena/blob/662cf71d/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Upload.java ---------------------------------------------------------------------- diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Upload.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Upload.java deleted file mode 100644 index d21855f..0000000 --- a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Upload.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * 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 java.io.IOException ; -import java.io.InputStream ; -import java.io.PrintWriter ; -import java.util.zip.GZIPInputStream ; - -import javax.servlet.ServletException ; -import javax.servlet.http.HttpServletRequest ; -import javax.servlet.http.HttpServletResponse ; - -import org.apache.commons.fileupload.FileItemIterator ; -import org.apache.commons.fileupload.FileItemStream ; -import org.apache.commons.fileupload.servlet.ServletFileUpload ; -import org.apache.commons.fileupload.util.Streams ; -import org.apache.jena.atlas.lib.Pair ; -import org.apache.jena.atlas.web.ContentType ; -import org.apache.jena.fuseki.FusekiLib ; -import org.apache.jena.fuseki.HttpNames ; -import org.apache.jena.iri.IRI ; -import org.apache.jena.riot.Lang ; -import org.apache.jena.riot.RDFLanguages ; -import org.apache.jena.riot.lang.StreamRDFCounting ; -import org.apache.jena.riot.system.* ; -import org.apache.jena.web.HttpSC ; - -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.Quad ; -import com.hp.hpl.jena.sparql.graph.GraphFactory ; - -public class SPARQL_Upload extends SPARQL_ServletBase -{ - private static ErrorHandler errorHandler = ErrorHandlerFactory.errorHandlerStd(log) ; - - public SPARQL_Upload() { - super() ; - } - - // Methods to respond to. - @Override - protected void doPost(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException - { - doCommon(request, response) ; - } - - @Override - protected void doOptions(HttpServletRequest request, HttpServletResponse response) - { - setCommonHeadersForOptions(response) ; - response.setHeader(HttpNames.hAllow, "OPTIONS,POST"); - response.setHeader(HttpNames.hContentLengh, "0") ; - } - - @Override - protected void perform(HttpAction action) - { - // Only allows one file in the upload. - boolean isMultipart = ServletFileUpload.isMultipartContent(action.request); - if ( ! isMultipart ) - error(HttpSC.BAD_REQUEST_400 , "Not a file upload") ; - long count = upload(action, "http://example/upload-base/") ; - try { - action.response.setContentType("text/html") ; - action.response.setStatus(HttpSC.OK_200); - PrintWriter out = action.response.getWriter() ; - out.println("<html>") ; - out.println("<head>") ; - out.println("</head>") ; - out.println("<body>") ; - out.println("<h1>Success</h1>"); - out.println("<p>") ; - out.println("Triples = "+count + "\n"); - out.println("<p>") ; - out.println("</p>") ; - out.println("<button onclick=\"timeFunction()\">Back to Fuseki</button>"); - out.println("</p>") ; - out.println("<script type=\"text/javascript\">"); - out.println("function timeFunction(){"); - out.println("window.location.href = \"/fuseki.html\";}"); - out.println("</script>"); - out.println("</body>") ; - out.println("</html>") ; - out.flush() ; - success(action) ; - } - catch (Exception ex) { errorOccurred(ex) ; } - } - - // Also used by SPARQL_REST - static public long upload(HttpAction action, String base) - { - if ( action.isTransactional() ) - return uploadTxn(action, base) ; - else - return uploadNonTxn(action, base) ; - } - - /** Non-transaction - buffer to a temporary graph so that parse errors - * are caught before inserting any data. - */ - private static long uploadNonTxn(HttpAction action, String base) { - Pair<String, Graph> p = uploadWorker(action, base) ; - String graphName = p.getLeft() ; - Graph graphTmp = p.getRight() ; - long tripleCount = graphTmp.size() ; - - log.info(format("[%d] Upload: Graph: %s (%d triple(s))", - action.id, graphName, tripleCount)) ; - - Node gn = graphName.equals(HttpNames.valueDefault) - ? Quad.defaultGraphNodeGenerated - : NodeFactory.createURI(graphName) ; - - action.beginWrite() ; - try { - FusekiLib.addDataInto(graphTmp, action.getActiveDSG(), gn) ; - action.commit() ; - return tripleCount ; - } catch (RuntimeException ex) - { - // If anything went wrong, try to backout. - try { action.abort() ; } catch (Exception ex2) {} - errorOccurred(ex.getMessage()) ; - return -1 ; - } - finally { action.endWrite() ; } - } - - /** Transactional - we'd like data to go straight to the destination, with an abort on parse error. - * But file upload with a name means that the name can be after the data - * (it is in the Fuseki default pages). - * Use Graph Store protocol for bulk uploads. - * (It would be possible to process the incoming stream and see the graph name first.) - */ - private static long uploadTxn(HttpAction action, String base) { - // We can't do better than the non-transaction approach. - return uploadNonTxn(action, base) ; - } - - /** process an HTTP upload of RDF. - * We can't stream straight into a dataset because the graph name can be after the data. - * @return graph name and count - */ - - static private Pair<String, Graph> uploadWorker(HttpAction action, String base) - { - Graph graphTmp = GraphFactory.createDefaultGraph() ; - ServletFileUpload upload = new ServletFileUpload(); - String graphName = null ; - long count = -1 ; - - String name = null ; - ContentType ct = null ; - Lang lang = null ; - - try { - FileItemIterator iter = upload.getItemIterator(action.request); - while (iter.hasNext()) { - FileItemStream item = iter.next(); - String fieldName = item.getFieldName(); - InputStream stream = item.openStream(); - if (item.isFormField()) - { - // Graph name. - String value = Streams.asString(stream, "UTF-8") ; - if ( fieldName.equals(HttpNames.paramGraph) ) - { - graphName = value ; - if ( graphName != null && ! graphName.equals("") && ! graphName.equals(HttpNames.valueDefault) ) - { - IRI iri = IRIResolver.parseIRI(value) ; - if ( iri.hasViolation(false) ) - errorBadRequest("Bad IRI: "+graphName) ; - if ( iri.getScheme() == null ) - errorBadRequest("Bad IRI: no IRI scheme name: "+graphName) ; - if ( iri.getScheme().equalsIgnoreCase("http") || iri.getScheme().equalsIgnoreCase("https")) - { - // Redundant?? - if ( iri.getRawHost() == null ) - errorBadRequest("Bad IRI: no host name: "+graphName) ; - if ( iri.getRawPath() == null || iri.getRawPath().length() == 0 ) - errorBadRequest("Bad IRI: no path: "+graphName) ; - if ( iri.getRawPath().charAt(0) != '/' ) - errorBadRequest("Bad IRI: Path does not start '/': "+graphName) ; - } - } - } - else if ( fieldName.equals(HttpNames.paramDefaultGraphURI) ) - graphName = null ; - else - // Add file type? - log.info(format("[%d] Upload: Field=%s ignored", action.id, fieldName)) ; - } else { - // Process the input stream - name = item.getName() ; - if ( name == null || name.equals("") || name.equals("UNSET FILE NAME") ) - errorBadRequest("No name for content - can't determine RDF syntax") ; - - String contentTypeHeader = item.getContentType() ; - ct = ContentType.create(contentTypeHeader) ; - - lang = RDFLanguages.contentTypeToLang(ct.getContentType()) ; - - if ( lang == null ) { - lang = RDFLanguages.filenameToLang(name) ; - - //JENA-600 filenameToLang() strips off certain extensions such as .gz and - //we need to ensure that if there was a .gz extension present we wrap the stream accordingly - if (name.endsWith(".gz")) - stream = new GZIPInputStream(stream); - } - if ( lang == null ) - // Desperate. - lang = RDFLanguages.RDFXML ; - - log.info(format("[%d] Upload: Filename: %s, Content-Type=%s, Charset=%s => %s", - action.id, name, ct.getContentType(), ct.getCharset(), lang.getName())) ; - - StreamRDF x = StreamRDFLib.graph(graphTmp) ; - StreamRDFCounting dest = StreamRDFLib.count(x) ; - SPARQL_REST.parse(action, dest, stream, lang, base); - count = dest.count() ; - } - } - - if ( graphName == null || graphName.equals("") ) - graphName = HttpNames.valueDefault ; - return Pair.create(graphName, graphTmp) ; - } - catch (ActionErrorException ex) { throw ex ; } - catch (Exception ex) { errorOccurred(ex) ; return null ; } - } - - @Override - protected void validate(HttpAction action) - {} -}
