private void executeBody(HttpAction action) { InputStream input = null; try { input = action.request.getInputStream(); } catch (IOException ex) { ServletOps.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); } action.log.info(format("[%d] Update = %s", action.id, ServletOps.formatForLog(requestStr))); input = new ByteArrayInputStream(requestStr.getBytes()); requestStr = null; } execute(action, input); ServletOps.successNoContent(action); }
@Override protected void doGet(HttpAction action) { // Assume success - do the set up before grabbing the lock. // Sets content type. MediaType mediaType = ActionLib.contentNegotationRDF(action); ServletOutputStream output; try { output = action.response.getOutputStream(); } catch (IOException ex) { ServletOps.errorOccurred(ex); output = null; } TypedOutputStream out = new TypedOutputStream(output, mediaType); Lang lang = RDFLanguages.contentTypeToLang(mediaType.getContentType()); if (action.verbose) action.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 (action.log.isDebugEnabled()) action.log.debug("GET->" + target); boolean exists = target.exists(); if (!exists) ServletOps.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); try { RDFDataMgr.write(out, g, fmt); } catch (JenaException ex) { // Some RDF/XML data is unwritable. All we can do is pretend it's a bad // request (inappropriate content type). // Good news - this happens before any output for RDF/XML-ABBREV. if (fmt.getLang().equals(Lang.RDFXML)) ServletOps.errorBadRequest("Failed to write output in RDF/XML: " + ex.getMessage()); else ServletOps.errorOccurred("Failed to write output: " + ex.getMessage(), ex); } ServletOps.success(action); } finally { action.endRead(); } }
private void execute(HttpAction action, InputStream input) { // OPTIONS if (action.request.getMethod().equals(HttpNames.METHOD_OPTIONS)) { // Share with update via SPARQL_Protocol. doOptions(action); return; } 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) { ServletOps.errorBadRequest(ex.getMessage()); return; } catch (QueryParseException ex) { ServletOps.errorBadRequest(messageForQueryException(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.getEndpoint().getCounters(), UpdateExecErrors); ServletOps.errorOccurred(ex.getMessage()); } catch (QueryParseException | QueryBuildException ex) { action.abort(); // Counter inc'ed further out. ServletOps.errorBadRequest(messageForQueryException(ex)); } catch (Throwable ex) { if (!(ex instanceof ActionErrorException)) { try { action.abort(); } catch (Exception ex2) { } ServletOps.errorOccurred(ex.getMessage(), ex); } } finally { action.endWrite(); } }
@Override protected final void perform(HttpAction action) { // OPTIONS if (action.request.getMethod().equals(HttpNames.METHOD_OPTIONS)) { // Share with update via SPARQL_Protocol. doOptions(action); return; } // GET if (action.request.getMethod().equals(HttpNames.METHOD_GET)) { executeWithParameter(action); return; } ContentType ct = FusekiLib.getContentType(action); // POST application/x-www-form-url // POST ?query= and no Content-Type if (ct == null || isHtmlForm(ct)) { // validation checked that if no Content-type, then its a POST with ?query= executeWithParameter(action); return; } // POST application/sparql-query if (matchContentType(ct, ctSPARQLQuery)) { executeBody(action); return; } ServletOps.error(HttpSC.UNSUPPORTED_MEDIA_TYPE_415, "Bad content type: " + ct.getContentType()); }
@Override protected void doOptions(HttpAction action) { setCommonHeadersForOptions(action.response); action.response.setHeader(HttpNames.hAllow, "GET,HEAD,OPTIONS"); action.response.setHeader(HttpNames.hContentLengh, "0"); ServletOps.success(action); }
@Override protected void doHead(HttpAction action) { action.beginRead(); setCommonHeaders(action.response); try { Target target = determineTarget(action); if (action.log.isDebugEnabled()) action.log.debug("HEAD->" + target); if (!target.exists()) { ServletOps.successNotFound(action); return; } MediaType mediaType = ActionLib.contentNegotationRDF(action); ServletOps.success(action); } finally { action.endRead(); } }
private static Node createNode(String x) { try { IRI iri = resolver.resolve(x); return NodeFactory.createURI(iri.toString()); } catch (Exception ex) { ServletOps.errorBadRequest("SPARQL Update: bad IRI: " + x); return null; } }
protected void executeBody(HttpAction action) { String queryString = null; try { InputStream input = action.request.getInputStream(); queryString = IO.readWholeFileAsUTF8(input); } catch (IOException ex) { ServletOps.errorOccurred(ex); } execute(queryString, action); }
protected void execute(String queryString, HttpAction action) { String queryStringLog = ServletOps.formatForLog(queryString); if (action.verbose) action.log.info(format("[%d] Query = \n%s", action.id, queryString)); else action.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, QueryParseBase, Syntax.syntaxARQ); queryStringLog = formatForLog(query); validateQuery(action, query); } catch (ActionErrorException ex) { throw ex; } catch (QueryParseException ex) { ServletOps.errorBadRequest( "Parse error: \n" + queryString + "\n\r" + messageForQueryException(ex)); } // Should not happen. catch (QueryException ex) { ServletOps.errorBadRequest("Error: \n" + queryString + "\n\r" + ex.getMessage()); } // Assumes finished whole thing by end of sendResult. try { action.beginRead(); 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 (QueryParseException ex) { // Late stage static error (e.g. bad fixed Lucene query string). ServletOps.errorBadRequest( "Query parse error: \n" + queryString + "\n\r" + messageForQueryException(ex)); } catch (QueryCancelledException ex) { // Additional counter information. incCounter(action.getEndpoint().getCounters(), QueryTimeouts); throw ex; } finally { action.endRead(); } }
protected void validate(HttpAction action, Collection<String> params) { if (params != null) { Enumeration<String> en = action.request.getParameterNames(); for (; en.hasMoreElements(); ) { String name = en.nextElement(); if (!params.contains(name)) ServletOps.warning( action, "SPARQL Update: Unrecognized request parameter (ignored): " + name); } } }
/** * Ship the results to the remote caller. * * @param action * @param result * @param qPrologue */ protected void sendResults(HttpAction action, SPARQLResult result, Prologue qPrologue) { if (result.isResultSet()) ResponseResultSet.doResponseResultSet(action, result.getResultSet(), qPrologue); else if (result.isDataset()) // CONSTRUCT is processed as a extended CONSTRUCT - result is a dataset. ResponseDataset.doResponseDataset(action, result.getDataset()); else if (result.isModel()) // DESCRIBE results are models ResponseDataset.doResponseModel(action, result.getModel()); else if (result.isBoolean()) ResponseResultSet.doResponseResultSet(action, result.getBooleanResult()); else ServletOps.errorOccurred("Unknown or invalid result type"); }
/** * Validate the request, checking HTTP method and HTTP Parameters. * * @param action HTTP Action */ @Override protected void validate(HttpAction action) { String method = action.request.getMethod().toUpperCase(Locale.ROOT); if (HttpNames.METHOD_OPTIONS.equals(method)) return; if (!HttpNames.METHOD_POST.equals(method) && !HttpNames.METHOD_GET.equals(method)) ServletOps.errorMethodNotAllowed("Not a GET or POST request"); if (HttpNames.METHOD_GET.equals(method) && action.request.getQueryString() == null) { ServletOps.warning( action, "Service Description / SPARQL Query / " + action.request.getRequestURI()); ServletOps.errorNotFound("Service Description: " + action.request.getRequestURI()); } // Use of the dataset describing parameters is check later. try { validateParams(action, allParams); validateRequest(action); } catch (ActionErrorException ex) { throw ex; } // Query not yet parsed. }
private void executeForm(HttpAction action) { String requestStr = action.request.getParameter(paramUpdate); if (requestStr == null) requestStr = action.request.getParameter(paramRequest); if (action.verbose) action.log.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); ServletOps.successPage(action, "Update succeeded"); }
@Override protected void perform(HttpAction action) { ContentType ct = FusekiLib.getContentType(action); if (ct == null) ct = ctSPARQLUpdate; if (matchContentType(ctSPARQLUpdate, ct)) { executeBody(action); return; } if (isHtmlForm(ct)) { executeForm(action); return; } ServletOps.error( HttpSC.UNSUPPORTED_MEDIA_TYPE_415, "Bad content type: " + action.request.getContentType()); }
/** * Perform the {@link QueryExecution} once. * * @param action * @param queryExecution * @param query * @param queryStringLog Informational string created from the initial query. * @return */ protected SPARQLResult executeQuery( HttpAction action, QueryExecution queryExecution, Query query, String queryStringLog) { setAnyTimeouts(queryExecution, action); if (query.isSelectType()) { ResultSet rs = queryExecution.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) ; // action.log.info(format("[%d] exec/select", action.id)) ; return new SPARQLResult(rs); } if (query.isConstructType()) { Dataset dataset = queryExecution.execConstructDataset(); // action.log.info(format("[%d] exec/construct", action.id)); return new SPARQLResult(dataset); } if (query.isDescribeType()) { Model model = queryExecution.execDescribe(); // action.log.info(format("[%d] exec/describe", action.id)) ; return new SPARQLResult(model); } if (query.isAskType()) { boolean b = queryExecution.execAsk(); // action.log.info(format("[%d] exec/ask", action.id)) ; return new SPARQLResult(b); } ServletOps.errorBadRequest("Unknown query type - " + queryStringLog); return null; }
@Override protected void validate(HttpAction action) { HttpServletRequest request = action.request; if (HttpNames.METHOD_OPTIONS.equals(request.getMethod())) return; if (!HttpNames.METHOD_POST.equalsIgnoreCase(request.getMethod())) ServletOps.errorMethodNotAllowed("SPARQL Update : use POST"); ContentType ct = FusekiLib.getContentType(action); if (ct == null) ct = ctSPARQLUpdate; if (matchContentType(ctSPARQLUpdate, ct)) { String charset = request.getCharacterEncoding(); if (charset != null && !charset.equalsIgnoreCase(charsetUTF8)) ServletOps.errorBadRequest("Bad charset: " + charset); validate(action, paramsPOST); return; } if (isHtmlForm(ct)) { int x = countParamOccurences(request, paramUpdate) + countParamOccurences(request, paramRequest); if (x == 0) ServletOps.errorBadRequest("SPARQL Update: No 'update=' parameter"); if (x != 1) ServletOps.errorBadRequest("SPARQL Update: Multiple 'update=' parameters"); String requestStr = request.getParameter(paramUpdate); if (requestStr == null) requestStr = request.getParameter(paramRequest); if (requestStr == null) ServletOps.errorBadRequest("SPARQL Update: No update= in HTML form"); validate(action, paramsForm); return; } ServletOps.error( HttpSC.UNSUPPORTED_MEDIA_TYPE_415, "Must be " + contentTypeSPARQLUpdate + " or " + contentTypeHTMLForm + " (got " + ct.getContentType() + ")"); }
/** * Helper method for validating request. * * @param request HTTP request * @param params parameters in a collection of Strings */ protected void validateParams(HttpAction action, Collection<String> params) { HttpServletRequest request = action.request; ContentType ct = FusekiLib.getContentType(request); boolean mustHaveQueryParam = true; if (ct != null) { String incoming = ct.getContentType(); if (matchContentType(ctSPARQLQuery, ct)) { mustHaveQueryParam = false; // Drop through. } else if (matchContentType(ctHTMLForm, ct)) { // Nothing specific to do } else ServletOps.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) ServletOps.errorBadRequest("SPARQL Query: No 'query=' parameter"); if (N > 1) ServletOps.errorBadRequest("SPARQL Query: Multiple 'query=' parameters"); // application/sparql-query does not use a query param. String queryStr = request.getParameter(HttpNames.paramQuery); if (queryStr == null) ServletOps.errorBadRequest("SPARQL Query: No query specified (no 'query=' found)"); if (queryStr.isEmpty()) ServletOps.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)) ServletOps.warning( action, "SPARQL Query: Unrecognize request parameter (ignored): " + name); } } }
@Override protected void doPost(HttpAction action) { ServletOps.errorMethodNotAllowed("POST : Read-only"); }
@Override protected void doDelete(HttpAction action) { ServletOps.errorMethodNotAllowed("DELETE : Read-only"); }
@Override protected void doPatch(HttpAction action) { ServletOps.errorMethodNotAllowed("PATCH : Read-only"); }