http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/ResponseResultSet.java ---------------------------------------------------------------------- diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/ResponseResultSet.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/ResponseResultSet.java deleted file mode 100644 index c42378b..0000000 --- a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/ResponseResultSet.java +++ /dev/null @@ -1,320 +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.atlas.lib.Lib.equal ; -import static org.apache.jena.fuseki.servlets.ServletBase.errorBadRequest ; -import static org.apache.jena.fuseki.servlets.ServletBase.errorOccurred ; -import static org.apache.jena.fuseki.servlets.ServletBase.log ; - -import java.io.IOException ; -import java.util.HashMap ; -import java.util.Map ; - -import javax.servlet.ServletOutputStream ; -import javax.servlet.http.HttpServletRequest ; -import javax.servlet.http.HttpServletResponse ; - -import org.apache.commons.lang.StringUtils ; -import org.apache.jena.atlas.web.AcceptList ; -import org.apache.jena.atlas.web.MediaType ; -import org.apache.jena.fuseki.DEF ; -import org.apache.jena.fuseki.FusekiException ; -import org.apache.jena.fuseki.conneg.ConNeg ; -import org.apache.jena.riot.ResultSetMgr ; -import org.apache.jena.riot.WebContent ; -import org.apache.jena.riot.resultset.ResultSetLang ; -import org.apache.jena.web.HttpSC ; -import org.slf4j.Logger ; -import org.slf4j.LoggerFactory ; - -import com.hp.hpl.jena.query.QueryCancelledException ; -import com.hp.hpl.jena.query.ResultSet ; -import com.hp.hpl.jena.query.ResultSetFormatter ; -import com.hp.hpl.jena.sparql.core.Prologue ; - -/** This is the content negotiation for each kind of SPARQL query result */ -public class ResponseResultSet -{ - private static Logger xlog = LoggerFactory.getLogger(ResponseResultSet.class) ; - private static Logger slog = ServletBase.log ; - - // Short names for "output=" - private static final String contentOutputJSON = "json" ; - private static final String contentOutputXML = "xml" ; - private static final String contentOutputSPARQL = "sparql" ; - private static final String contentOutputText = "text" ; - private static final String contentOutputCSV = "csv" ; - private static final String contentOutputTSV = "tsv" ; - private static final String contentOutputThrift = "thrift" ; - - public static Map<String,String> shortNamesResultSet = new HashMap<String, String>() ; - static { - // Some short names. keys are lowercase. - ResponseOps.put(shortNamesResultSet, contentOutputJSON, WebContent.contentTypeResultsJSON) ; - ResponseOps.put(shortNamesResultSet, contentOutputSPARQL, WebContent.contentTypeResultsXML) ; - ResponseOps.put(shortNamesResultSet, contentOutputXML, WebContent.contentTypeResultsXML) ; - ResponseOps.put(shortNamesResultSet, contentOutputText, WebContent.contentTypeTextPlain) ; - ResponseOps.put(shortNamesResultSet, contentOutputCSV, WebContent.contentTypeTextCSV) ; - ResponseOps.put(shortNamesResultSet, contentOutputTSV, WebContent.contentTypeTextTSV) ; - ResponseOps.put(shortNamesResultSet, contentOutputThrift, WebContent.contentTypeResultsThrift) ; - } - - interface OutputContent { void output(ServletOutputStream out) ; } - - public static void doResponseResultSet(HttpAction action, Boolean booleanResult) - { - doResponseResultSet$(action, null, booleanResult, null, DEF.rsOfferTable) ; - } - - public static void doResponseResultSet(HttpAction action, ResultSet resultSet, Prologue qPrologue) - { - doResponseResultSet$(action, resultSet, null, qPrologue, DEF.rsOfferTable) ; - } - - // If we refactor the conneg into a single function, we can split boolean and result set handling. - - // One or the other argument must be null - private static void doResponseResultSet$(HttpAction action, - ResultSet resultSet, Boolean booleanResult, - Prologue qPrologue, - AcceptList contentTypeOffer) - { - HttpServletRequest request = action.request ; - HttpServletResponse response = action.response ; - long id = action.id ; - - if ( resultSet == null && booleanResult == null ) - { - xlog.warn("doResponseResult: Both result set and boolean result are null") ; - throw new FusekiException("Both result set and boolean result are null") ; - } - - if ( resultSet != null && booleanResult != null ) - { - xlog.warn("doResponseResult: Both result set and boolean result are set") ; - throw new FusekiException("Both result set and boolean result are set") ; - } - - String mimeType = null ; - MediaType i = ConNeg.chooseContentType(request, contentTypeOffer, DEF.acceptRSXML) ; - if ( i != null ) - mimeType = i.getContentType() ; - - // Override content type - // Does &output= override? - // Requested output type by the web form or &output= in the request. - String outputField = ResponseOps.paramOutput(request, shortNamesResultSet) ; // Expands short names - if ( outputField != null ) - mimeType = outputField ; - - String serializationType = mimeType ; // Choose the serializer based on this. - String contentType = mimeType ; // Set the HTTP respose header to this. - - // Stylesheet - change to application/xml. - final String stylesheetURL = ResponseOps.paramStylesheet(request) ; - if ( stylesheetURL != null && equal(serializationType,WebContent.contentTypeResultsXML) ) - contentType = WebContent.contentTypeXML ; - - // Force to text/plain? - String forceAccept = ResponseOps.paramForceAccept(request) ; - if ( forceAccept != null ) - contentType = WebContent.contentTypeTextPlain ; - - // Better : dispatch on MediaType - // Fuseki2 uses the SPARQL parser/write registry. - if ( equal(serializationType, WebContent.contentTypeResultsXML) ) - sparqlXMLOutput(action, contentType, resultSet, stylesheetURL, booleanResult) ; - else if ( equal(serializationType, WebContent.contentTypeResultsJSON) ) - jsonOutput(action, contentType, resultSet, booleanResult) ; - else if ( equal(serializationType, WebContent.contentTypeTextPlain) ) - textOutput(action, contentType, resultSet, qPrologue, booleanResult) ; - else if ( equal(serializationType, WebContent.contentTypeTextCSV) ) - csvOutput(action, contentType, resultSet, booleanResult) ; - else if (equal(serializationType, WebContent.contentTypeTextTSV) ) - tsvOutput(action, contentType, resultSet, booleanResult) ; - else if (equal(serializationType, WebContent.contentTypeResultsThrift) ) - thriftOutput(action, contentType, resultSet, booleanResult) ; - else - errorBadRequest("Can't determine output serialization: "+serializationType) ; - } - - - public static void setHttpResponse(HttpServletRequest httpRequest, - HttpServletResponse httpResponse, - String contentType, String charset) - { - // ---- Set up HTTP Response - // Stop caching (not that ?queryString URLs are cached anyway) - if ( true ) - { - httpResponse.setHeader("Cache-Control", "no-cache") ; - httpResponse.setHeader("Pragma", "no-cache") ; - } - // See: http://www.w3.org/International/O-HTTP-charset.html - if ( contentType != null ) - { - if ( charset != null && ! isXML(contentType) ) - contentType = contentType+"; charset="+charset ; - log.trace("Content-Type for response: "+contentType) ; - httpResponse.setContentType(contentType) ; - } - } - - private static boolean isXML(String contentType) - { - return contentType.equals(WebContent.contentTypeRDFXML) - || contentType.equals(WebContent.contentTypeResultsXML) - || contentType.equals(WebContent.contentTypeXML) ; - } - - private static void sparqlXMLOutput(HttpAction action, String contentType, final ResultSet resultSet, final String stylesheetURL, final Boolean booleanResult) - { - OutputContent proc = - new OutputContent(){ - @Override - public void output(ServletOutputStream out) - { - if ( resultSet != null ) - ResultSetFormatter.outputAsXML(out, resultSet, stylesheetURL) ; - if ( booleanResult != null ) - ResultSetFormatter.outputAsXML(out, booleanResult, stylesheetURL) ; - }} ; - output(action, contentType, null, proc) ; - } - - private static void jsonOutput(HttpAction action, String contentType, final ResultSet resultSet, final Boolean booleanResult) - { - OutputContent proc = new OutputContent(){ - @Override - public void output(ServletOutputStream out) - { - if ( resultSet != null ) - ResultSetFormatter.outputAsJSON(out, resultSet) ; - if ( booleanResult != null ) - ResultSetFormatter.outputAsJSON(out, booleanResult ) ; - } - } ; - - try { - String callback = ResponseOps.paramCallback(action.request) ; - ServletOutputStream out = action.response.getOutputStream() ; - - if ( callback != null ) - { - callback = StringUtils.replaceChars(callback, "\r", "") ; - callback = StringUtils.replaceChars(callback, "\n", "") ; - out.print(callback) ; - out.println("(") ; - } - - output(action, contentType, WebContent.charsetUTF8, proc) ; - - if ( callback != null ) - out.println(")") ; - } catch (IOException ex) { errorOccurred(ex) ; } - } - - private static void textOutput(HttpAction action, String contentType, final ResultSet resultSet, final Prologue qPrologue, final Boolean booleanResult) - { - // Text is not streaming. - OutputContent proc = new OutputContent(){ - @Override - public void output(ServletOutputStream out) - { - if ( resultSet != null ) - ResultSetFormatter.out(out, resultSet, qPrologue) ; - if ( booleanResult != null ) - ResultSetFormatter.out(out, booleanResult ) ; - } - }; - - output(action, contentType, WebContent.charsetUTF8, proc) ; - } - - private static void csvOutput(HttpAction action, String contentType, final ResultSet resultSet, final Boolean booleanResult) { - OutputContent proc = new OutputContent(){ - @Override - public void output(ServletOutputStream out) - { - if ( resultSet != null ) - ResultSetFormatter.outputAsCSV(out, resultSet) ; - if ( booleanResult != null ) - ResultSetFormatter.outputAsCSV(out, booleanResult ) ; - } - } ; - output(action, contentType, WebContent.charsetUTF8, proc) ; - } - - private static void tsvOutput(HttpAction action, String contentType, final ResultSet resultSet, final Boolean booleanResult) { - OutputContent proc = new OutputContent(){ - @Override - public void output(ServletOutputStream out) - { - if ( resultSet != null ) - ResultSetFormatter.outputAsTSV(out, resultSet) ; - if ( booleanResult != null ) - ResultSetFormatter.outputAsTSV(out, booleanResult ) ; - } - } ; - output(action, contentType, WebContent.charsetUTF8, proc) ; - } - - private static void thriftOutput(HttpAction action, String contentType, final ResultSet resultSet, final Boolean booleanResult) { - OutputContent proc = new OutputContent(){ - @Override - public void output(ServletOutputStream out) - { - if ( resultSet != null ) - ResultSetMgr.write(out, resultSet, ResultSetLang.SPARQLResultSetThrift) ; - if ( booleanResult != null ) - slog.error("Can't write boolen result in thrift") ; - } - } ; - output(action, contentType, WebContent.charsetUTF8, proc) ; - } - - private static void output(HttpAction action, String contentType, String charset, OutputContent proc) - { - try { - setHttpResponse(action.request, action.response, contentType, charset) ; - action.response.setStatus(HttpSC.OK_200) ; - ServletOutputStream out = action.response.getOutputStream() ; - try - { - proc.output(out) ; - out.flush() ; - } catch (QueryCancelledException ex) { - // Bother. Status code 200 already sent. - slog.info(format("[%d] Query Cancelled - results truncated (but 200 already sent)", action.id)) ; - out.println() ; - out.println("## Query cancelled due to timeout during execution ##") ; - out.println("## **** Incomplete results **** ##") ; - out.flush() ; - // No point raising an exception - 200 was sent already. - //errorOccurred(ex) ; - } - // Includes client gone. - } catch (IOException ex) - { errorOccurred(ex) ; } - // Do not call httpResponse.flushBuffer(); here - Jetty closes the stream if it is a gzip stream - // then the JSON callback closing details can't be added. - } -}
http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Protocol.java ---------------------------------------------------------------------- diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Protocol.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Protocol.java deleted file mode 100644 index ed57a37..0000000 --- a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Protocol.java +++ /dev/null @@ -1,101 +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.paramDefaultGraphURI ; -import static org.apache.jena.fuseki.HttpNames.paramNamedGraphURI ; - -import java.util.Arrays ; -import java.util.Collections ; -import java.util.List ; - -import javax.servlet.http.HttpServletRequest ; - -import org.apache.jena.atlas.iterator.Filter ; -import org.apache.jena.atlas.iterator.Iter ; -import org.apache.jena.atlas.lib.Lib ; - -import com.hp.hpl.jena.query.Query ; -import com.hp.hpl.jena.query.QueryParseException ; -import com.hp.hpl.jena.sparql.core.DatasetDescription ; - -/** Support for the SPARQL protocol (SPARQL Query, SPARQL Update) - */ -public abstract class SPARQL_Protocol extends SPARQL_ServletBase -{ - protected SPARQL_Protocol() { super() ; } - - protected static String messageForQPE(QueryParseException ex) - { - if ( ex.getMessage() != null ) - return ex.getMessage() ; - if ( ex.getCause() != null ) - return Lib.classShortName(ex.getCause().getClass()) ; - return null ; - } - - protected static DatasetDescription getDatasetDescription(HttpAction action) - { - List<String> graphURLs = toStrList(action.request.getParameterValues(paramDefaultGraphURI)) ; - List<String> namedGraphs = toStrList(action.request.getParameterValues(paramNamedGraphURI)) ; - - graphURLs = removeEmptyValues(graphURLs) ; - namedGraphs = removeEmptyValues(namedGraphs) ; - - if ( graphURLs.size() == 0 && namedGraphs.size() == 0 ) - return null ; - return DatasetDescription.create(graphURLs, namedGraphs) ; - } - - protected static DatasetDescription getDatasetDescription(Query query) - { - return DatasetDescription.create(query) ; - } - - private static List<String> toStrList(String[] array) - { - if ( array == null ) - return Collections.emptyList() ; - return Arrays.asList(array) ; - } - - private static List<String> removeEmptyValues(List<String> list) - { - return Iter.iter(list).filter(acceptNonEmpty).toList() ; - } - - private static Filter<String> acceptNonEmpty = new Filter<String>(){ - @Override - public boolean accept(String item) - { - return item != null && item.length() != 0 ; - } - } ; - - protected static int countParamOccurences(HttpServletRequest request, String param) - { - String[] x = request.getParameterValues(param) ; - if ( x == null ) - return 0 ; - return x.length ; - } - - -} - http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java ---------------------------------------------------------------------- diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java deleted file mode 100644 index 27e76ac..0000000 --- a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java +++ /dev/null @@ -1,386 +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.HttpNames.* ; -import static org.apache.jena.fuseki.server.CounterName.QueryExecErrors ; -import static org.apache.jena.fuseki.server.CounterName.QueryTimeouts ; -import static org.apache.jena.fuseki.server.CounterName.RequestsBad ; - -import java.io.IOException ; -import java.io.InputStream ; -import java.util.* ; - -import javax.servlet.http.HttpServletRequest ; -import javax.servlet.http.HttpServletResponse ; - -import org.apache.jena.atlas.RuntimeIOException ; -import org.apache.jena.atlas.io.IO ; -import org.apache.jena.atlas.io.IndentedLineBuffer ; -import org.apache.jena.atlas.web.ContentType ; -import org.apache.jena.fuseki.FusekiException ; -import org.apache.jena.fuseki.FusekiLib ; -import org.apache.jena.fuseki.HttpNames ; -import org.apache.jena.riot.WebContent ; -import org.apache.jena.riot.web.HttpOp ; -import org.apache.jena.web.HttpSC ; - -import com.hp.hpl.jena.query.* ; -import com.hp.hpl.jena.rdf.model.Model ; -import com.hp.hpl.jena.sparql.core.Prologue ; -import com.hp.hpl.jena.sparql.resultset.SPARQLResult ; - -/** - * Handles SPARQL Query requests. - */ -public abstract class SPARQL_Query extends SPARQL_Protocol -{ - public SPARQL_Query() { super() ; } - - // Choose REST verbs to support. - - @Override - protected void doPost(HttpServletRequest request, HttpServletResponse response) - { doCommon(request, response) ; } - - @Override - protected void doGet(HttpServletRequest request, HttpServletResponse response) - { doCommon(request, response) ; } - - // HEAD - - @Override - protected void doOptions(HttpServletRequest request, HttpServletResponse response) - { - //response.setHeader(HttpNames.hAllow, "GET,HEAD,OPTIONS,POST"); - setCommonHeaders(response) ; - response.setHeader(HttpNames.hAllow, "GET,OPTIONS,POST"); - response.setHeader(HttpNames.hContentLengh, "0") ; - } - - @Override - protected final void perform(HttpAction action) - { - // GET - if ( action.request.getMethod().equals(HttpNames.METHOD_GET) ) - { - executeWithParameter(action) ; - return ; - } - - ContentType ct = FusekiLib.getContentType(action) ; - String incoming = ct.getContentType() ; - - // POST application/sparql-query - if (WebContent.contentTypeSPARQLQuery.equals(incoming)) - { - executeBody(action) ; - return ; - } - // POST application/x-www-form-url - if (WebContent.contentTypeHTMLForm.equals(incoming)) - { - executeWithParameter(action) ; - return ; - } - - error(HttpSC.UNSUPPORTED_MEDIA_TYPE_415, "Bad content type: "+incoming) ; - } - - // All the params we support - - protected static List<String> allParams = Arrays.asList(paramQuery, - paramDefaultGraphURI, paramNamedGraphURI, - paramQueryRef, - paramStyleSheet, - paramAccept, - paramOutput1, paramOutput2, - paramCallback, - paramForceAccept, - paramTimeout) ; - - @Override - protected void validate(HttpAction action) - { - String method = action.request.getMethod().toUpperCase(Locale.ROOT) ; - - if ( ! HttpNames.METHOD_POST.equals(method) && ! HttpNames.METHOD_GET.equals(method) ) - errorMethodNotAllowed("Not a GET or POST request") ; - - if ( HttpNames.METHOD_GET.equals(method) && action.request.getQueryString() == null ) - { - warning("Service Description / SPARQL Query / "+action.request.getRequestURI()) ; - errorNotFound("Service Description: "+action.request.getRequestURI()) ; - } - - // Use of the dataset describing parameters is check later. - try { - validateParams(action.request, allParams) ; - validateRequest(action) ; - } catch (ActionErrorException ex) { - throw ex ; - } - // Query not yet parsed. - } - - /** - * Validate the request after checking HTTP method and HTTP Parameters. - * @param action HTTP Action - */ - protected abstract void validateRequest(HttpAction action) ; - - /** - * Helper method for validating request. - * @param request HTTP request - * @param params parameters in a collection of Strings - */ - protected void validateParams(HttpServletRequest request, Collection<String> params) - { - ContentType ct = FusekiLib.getContentType(request) ; - boolean mustHaveQueryParam = true ; - if ( ct != null ) - { - String incoming = ct.getContentType() ; - - if ( WebContent.contentTypeSPARQLQuery.equals(incoming) ) - { - mustHaveQueryParam = false ; - //error(HttpSC.UNSUPPORTED_MEDIA_TYPE_415, "Unofficial "+WebContent.contentTypeSPARQLQuery+" not supported") ; - } - else if ( WebContent.contentTypeHTMLForm.equals(incoming) ) {} - else - error(HttpSC.UNSUPPORTED_MEDIA_TYPE_415, "Unsupported: "+incoming) ; - } - - // GET/POST of a form at this point. - - if ( mustHaveQueryParam ) - { - int N = countParamOccurences(request, paramQuery) ; - - if ( N == 0 ) errorBadRequest("SPARQL Query: No 'query=' parameter") ; - if ( N > 1 ) errorBadRequest("SPARQL Query: Multiple 'query=' parameters") ; - - // application/sparql-query does not use a query param. - String queryStr = request.getParameter(HttpNames.paramQuery) ; - - if ( queryStr == null ) - errorBadRequest("SPARQL Query: No query specified (no 'query=' found)") ; - if ( queryStr.isEmpty() ) - errorBadRequest("SPARQL Query: Empty query string") ; - } - - if ( params != null ) - { - Enumeration<String> en = request.getParameterNames() ; - for ( ; en.hasMoreElements() ; ) - { - String name = en.nextElement() ; - if ( ! params.contains(name) ) - warning("SPARQL Query: Unrecognize request parameter (ignored): "+name) ; - } - } - } - - private void executeWithParameter(HttpAction action) - { - String queryString = action.request.getParameter(paramQuery) ; - execute(queryString, action) ; - } - - private void executeBody(HttpAction action) - { - String queryString = null ; - try { - InputStream input = action.request.getInputStream() ; - queryString = IO.readWholeFileAsUTF8(input) ; - } - catch (IOException ex) { errorOccurred(ex) ; } - execute(queryString, action) ; - } - - private void execute(String queryString, HttpAction action) - { - String queryStringLog = formatForLog(queryString) ; - if ( action.verbose ) - log.info(format("[%d] Query = \n%s", action.id, queryString)); - else - log.info(format("[%d] Query = %s", action.id, queryStringLog)); - - Query query = null ; - try { - // NB syntax is ARQ (a superset of SPARQL) - query = QueryFactory.create(queryString, "http://example/query-base", Syntax.syntaxARQ) ; - queryStringLog = formatForLog(query) ; - validateQuery(action, query) ; - } catch (ActionErrorException ex) { - incCounter(action.srvRef, RequestsBad) ; - throw ex ; - } catch (QueryParseException ex) { - incCounter(action.srvRef, RequestsBad) ; - errorBadRequest("Parse error: \n" + queryString + "\n\r" + messageForQPE(ex)) ; - } catch (RuntimeIOException ex) { - errorBadRequest("Runtime IO Exception: \n" + queryString + "\n\r" + ex.getMessage()) ; - } - // Should not happen. - catch (QueryException ex) { - errorBadRequest("Error: \n" + queryString + "\n\r" + ex.getMessage()) ; - } - - // Assumes finished whole thing by end of sendResult. - action.beginRead() ; - try { - Dataset dataset = decideDataset(action, query, queryStringLog) ; - try(QueryExecution qExec = createQueryExecution(query, dataset)) { - SPARQLResult result = executeQuery(action, qExec, query, queryStringLog) ; - // Deals with exceptions itself. - sendResults(action, result, query.getPrologue()) ; - } - } catch (QueryCancelledException ex) { - // Additional counter information. - incCounter(action.srvRef, QueryTimeouts) ; - throw ex ; - } catch (RuntimeIOException ex) { - incCounter(action.srvRef, QueryExecErrors) ; - throw ex ; - } catch (QueryExecException ex) { - // Additional counter information. - incCounter(action.srvRef, QueryExecErrors) ; - throw ex ; - } finally { - action.endRead() ; - } - } - - /** - * Check the query, throwing ActionErrorException when not valid, or calling super#error. - * @param action HTTP Action - * @param query the Query - */ - protected abstract void validateQuery(HttpAction action, Query query) ; - - protected QueryExecution createQueryExecution(Query query, Dataset dataset) - { - return QueryExecutionFactory.create(query, dataset) ; - } - - protected SPARQLResult executeQuery(HttpAction action, QueryExecution qExec, Query query, String queryStringLog) - { - setAnyTimeouts(qExec, action); - - if ( query.isSelectType() ) - { - ResultSet rs = qExec.execSelect() ; - - // Force some query execution now. - // - // If the timeout-first-row goes off, the output stream has not - // been started so the HTTP error code is sent. - - rs.hasNext() ; - - // If we wanted perfect query time cancellation, we could consume the result now - // to see if the timeout-end-of-query goes off. - - //rs = ResultSetFactory.copyResults(rs) ; - - log.info(format("[%d] exec/select", action.id)) ; - return new SPARQLResult(rs) ; - } - - if ( query.isConstructType() ) - { - Model model = qExec.execConstruct() ; - log.info(format("[%d] exec/construct", action.id)) ; - return new SPARQLResult(model) ; - } - - if ( query.isDescribeType() ) - { - Model model = qExec.execDescribe() ; - log.info(format("[%d] exec/describe",action.id)) ; - return new SPARQLResult(model) ; - } - - if ( query.isAskType() ) - { - boolean b = qExec.execAsk() ; - log.info(format("[%d] exec/ask",action.id)) ; - return new SPARQLResult(b) ; - } - - errorBadRequest("Unknown query type - "+queryStringLog) ; - return null ; - } - - private void setAnyTimeouts(QueryExecution qexec, HttpAction action) { - if (!(action.getDatasetRef().allowTimeoutOverride)) - return; - - long desiredTimeout = Long.MAX_VALUE; - String timeoutHeader = action.request.getHeader("Timeout"); - String timeoutParameter = action.request.getParameter("timeout"); - if (timeoutHeader != null) { - try { - desiredTimeout = (int) Float.parseFloat(timeoutHeader) * 1000; - } catch (NumberFormatException e) { - throw new FusekiException("Timeout header must be a number", e); - } - } else if (timeoutParameter != null) { - try { - desiredTimeout = (int) Float.parseFloat(timeoutParameter) * 1000; - } catch (NumberFormatException e) { - throw new FusekiException("timeout parameter must be a number", e); - } - } - - desiredTimeout = Math.min(action.getDatasetRef().maximumTimeoutOverride, desiredTimeout); - if (desiredTimeout != Long.MAX_VALUE) - qexec.setTimeout(desiredTimeout); - } - - protected abstract Dataset decideDataset(HttpAction action, Query query, String queryStringLog) ; - - protected void sendResults(HttpAction action, SPARQLResult result, Prologue qPrologue) - { - if ( result.isResultSet() ) - ResponseResultSet.doResponseResultSet(action, result.getResultSet(), qPrologue) ; - else if ( result.isGraph() ) - ResponseModel.doResponseModel(action, result.getModel()) ; - else if ( result.isBoolean() ) - ResponseResultSet.doResponseResultSet(action, result.getBooleanResult()) ; - else - errorOccurred("Unknown or invalid result type") ; - } - - private String formatForLog(Query query) - { - IndentedLineBuffer out = new IndentedLineBuffer() ; - out.setFlatMode(true) ; - query.serialize(out) ; - return out.asString() ; - } - - private String getRemoteString(String queryURI) - { - return HttpOp.execHttpGetString(queryURI) ; - } - -} http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryDataset.java ---------------------------------------------------------------------- diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryDataset.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryDataset.java deleted file mode 100644 index 9e9df36..0000000 --- a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryDataset.java +++ /dev/null @@ -1,60 +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 com.hp.hpl.jena.query.Dataset ; -import com.hp.hpl.jena.query.DatasetFactory ; -import com.hp.hpl.jena.query.Query ; -import com.hp.hpl.jena.sparql.core.DatasetDescription ; -import com.hp.hpl.jena.sparql.core.DatasetGraph ; -import com.hp.hpl.jena.sparql.core.DynamicDatasets ; - -public class SPARQL_QueryDataset extends SPARQL_Query -{ - public SPARQL_QueryDataset(boolean verbose) { super() ; } - - public SPARQL_QueryDataset() - { this(false) ; } - - @Override - protected void validateRequest(HttpAction action) - { } - - @Override - protected void validateQuery(HttpAction action, Query query) - { } - - @Override - protected Dataset decideDataset(HttpAction action, Query query, String queryStringLog) - { - DatasetGraph dsg = action.getActiveDSG() ; - - // query.getDatasetDescription() ; - - // Protocol. - DatasetDescription dsDesc = getDatasetDescription(action) ; - if (dsDesc != null ) - { - //errorBadRequest("SPARQL Query: Dataset description in the protocol request") ; - dsg = DynamicDatasets.dynamicDataset(dsDesc, dsg, false) ; - } - - return DatasetFactory.create(dsg) ; - } -} http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryGeneral.java ---------------------------------------------------------------------- diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryGeneral.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryGeneral.java deleted file mode 100644 index a022e96..0000000 --- a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryGeneral.java +++ /dev/null @@ -1,143 +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 org.apache.jena.atlas.lib.InternalErrorException ; -import org.apache.jena.fuseki.migrate.GraphLoadUtils ; -import org.apache.jena.riot.RiotException ; - -import com.hp.hpl.jena.query.Dataset ; -import com.hp.hpl.jena.query.DatasetFactory ; -import com.hp.hpl.jena.query.Query ; -import com.hp.hpl.jena.rdf.model.Model ; -import com.hp.hpl.jena.rdf.model.ModelFactory ; -import com.hp.hpl.jena.sparql.core.DatasetDescription ; - -public class SPARQL_QueryGeneral extends SPARQL_Query -{ - final static int MaxTriples = 100*1000 ; - - public SPARQL_QueryGeneral() { super() ; } - - @Override - protected void validateRequest(HttpAction action) {} - - @Override - protected void validateQuery(HttpAction action, Query query) {} - - @Override - protected String mapRequestToDataset(String uri) - { return null ; } - - @Override - protected Dataset decideDataset(HttpAction action, Query query, String queryStringLog) - { - DatasetDescription datasetDesc = getDatasetDescription(action) ; - if ( datasetDesc == null ) - datasetDesc = getDatasetDescription(query) ; - if ( datasetDesc == null ) - errorBadRequest("No dataset description in protocol request or in the query string") ; - - return datasetFromDescription(action, datasetDesc) ; - } - - /** - * Construct a Dataset based on a dataset description. - */ - - protected static Dataset datasetFromDescription(HttpAction action, DatasetDescription datasetDesc) - { - try { - if ( datasetDesc == null ) - return null ; - if ( datasetDesc.isEmpty() ) - return null ; - - List<String> graphURLs = datasetDesc.getDefaultGraphURIs() ; - List<String> namedGraphs = datasetDesc.getNamedGraphURIs() ; - - if ( graphURLs.size() == 0 && namedGraphs.size() == 0 ) - return null ; - - Dataset dataset = DatasetFactory.createMem() ; - // Look in cache for loaded graphs!! - - // ---- Default graph - { - Model model = ModelFactory.createDefaultModel() ; - for ( String uri : graphURLs ) - { - if ( uri == null || uri.equals("") ) - throw new InternalErrorException("Default graph URI is null or the empty string") ; - - try { - //TODO Clearup - RIOT integration. - GraphLoadUtils.loadModel(model, uri, MaxTriples) ; - log.info(format("[%d] Load (default graph) %s", action.id, uri)) ; - } catch (RiotException ex) { - log.info(format("[%d] Parsing error loading %s: %s", action.id, uri, ex.getMessage())) ; - errorBadRequest("Failed to load URL (parse error) "+uri+" : "+ex.getMessage()) ; - } catch (Exception ex) - { - log.info(format("[%d] Failed to load (default) %s: %s", action.id, uri, ex.getMessage())) ; - errorBadRequest("Failed to load URL "+uri) ; - } - } - dataset.setDefaultModel(model) ; - } - // ---- Named graphs - if ( namedGraphs != null ) - { - for ( String uri : namedGraphs ) - { - if ( uri == null || uri.equals("") ) - throw new InternalErrorException("Named graph URI is null or the empty string") ; - - try { - Model model = ModelFactory.createDefaultModel() ; - GraphLoadUtils.loadModel(model, uri, MaxTriples) ; - log.info(format("[%d] Load (named graph) %s", action.id, uri)) ; - dataset.addNamedModel(uri, model) ; - } catch (RiotException ex) { - log.info(format("[%d] Parsing error loading %s: %s", action.id, uri, ex.getMessage())) ; - errorBadRequest("Failed to load URL (parse error) "+uri+" : "+ex.getMessage()) ; - } catch (Exception ex) - { - log.info(format("[%d] Failed to load (named graph) %s: %s", action.id, uri, ex.getMessage())) ; - errorBadRequest("Failed to load URL "+uri) ; - } - } - } - - return dataset ; - - } - catch (ActionErrorException ex) { throw ex ; } - catch (Exception ex) - { - log.info(format("[%d] SPARQL parameter error: "+ex.getMessage(),action.id, ex)) ; - errorBadRequest("Parameter error: "+ex.getMessage()); - return null ; - } - } -} http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/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/2fb788d3/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 3c5c926..0000000 --- a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_R.java +++ /dev/null @@ -1,125 +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() ; - - 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) - { - action.response.setHeader(HttpNames.hAllow, "GET,HEAD,OPTIONS") ; - action.response.setHeader(HttpNames.hContentLengh, "0") ; - success(action) ; - } - - @Override - protected void doHead(HttpAction action) - { - 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/2fb788d3/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 32a65e6..0000000 --- a/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_RW.java +++ /dev/null @@ -1,231 +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) - { - 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/2fb788d3/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 ; - } -}
