Repository: jena Updated Branches: refs/heads/master af252a60c -> b56d50f75
JENA-1004: Dynamic dataset processing for all requests. Project: http://git-wip-us.apache.org/repos/asf/jena/repo Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/b56d50f7 Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/b56d50f7 Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/b56d50f7 Branch: refs/heads/master Commit: b56d50f75df22e15a66effeb2692c4f8b6b10675 Parents: af252a6 Author: Andy Seaborne <[email protected]> Authored: Sat Aug 1 19:23:07 2015 +0100 Committer: Andy Seaborne <[email protected]> Committed: Sat Aug 1 19:23:07 2015 +0100 ---------------------------------------------------------------------- .../jena/fuseki/servlets/SPARQL_Protocol.java | 68 ++++++---- .../jena/fuseki/servlets/SPARQL_Query.java | 2 +- .../fuseki/servlets/SPARQL_QueryDataset.java | 20 +-- .../fuseki/servlets/SPARQL_QueryGeneral.java | 100 +++++++------- .../java/org/apache/jena/fuseki/TestQuery.java | 134 ++++++++++++------- 5 files changed, 190 insertions(+), 134 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jena/blob/b56d50f7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Protocol.java ---------------------------------------------------------------------- diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Protocol.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Protocol.java index f605060..b9ab24b 100644 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Protocol.java +++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Protocol.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package org.apache.jena.fuseki.servlets; +package org.apache.jena.fuseki.servlets ; import static org.apache.jena.riot.web.HttpNames.paramDefaultGraphURI ; import static org.apache.jena.riot.web.HttpNames.paramNamedGraphURI ; @@ -34,60 +34,74 @@ import org.apache.jena.query.Query ; import org.apache.jena.query.QueryException ; import org.apache.jena.sparql.core.DatasetDescription ; -/** Support for the SPARQL protocol (SPARQL Query, SPARQL Update) +/** + * Support for the SPARQL protocol (SPARQL Query, SPARQL Update) */ -public abstract class SPARQL_Protocol extends ActionSPARQL -{ - protected SPARQL_Protocol() { super() ; } +public abstract class SPARQL_Protocol extends ActionSPARQL { + protected SPARQL_Protocol() { + super() ; + } - protected static String messageForQueryException(QueryException ex) - { if ( ex.getMessage() != null ) + protected static String messageForQueryException(QueryException 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) - { + + protected static DatasetDescription getProtocolDatasetDescription(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) - { + + protected static DatasetDescription getQueryDatasetDescription(Query query) { return DatasetDescription.create(query) ; } - - private static List<String> toStrList(String[] array) - { + + /** Given an action (protocol request) and a query, decide the DatasetDescription, if any. + * + * @param action Action details - may be null. + * @param query The query - may be null. + * @return DatasetDescription or null + */ + protected static DatasetDescription getDatasetDescription(HttpAction action, Query query) { + // Protocol overrides query, + DatasetDescription dsDesc = null ; + if ( action != null ) { + dsDesc = getProtocolDatasetDescription(action) ; + if (dsDesc != null ) + return dsDesc ; + } + if ( query != null ) + dsDesc = getQueryDatasetDescription(query) ; + return dsDesc ; + } + + 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) - { + private static List<String> removeEmptyValues(List<String> list) { return Iter.iter(list).filter(acceptNonEmpty).toList() ; } - - private static Predicate<String> acceptNonEmpty = item -> item != null && !item.isEmpty(); - - protected static int countParamOccurences(HttpServletRequest request, String param) - { + + private static Predicate<String> acceptNonEmpty = item -> item != null && !item.isEmpty() ; + + 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/b56d50f7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java ---------------------------------------------------------------------- diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java index c411989..ba4a61a 100644 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java +++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java @@ -364,7 +364,7 @@ public abstract class SPARQL_Query extends SPARQL_Protocol /** Choose the dataset for this SPARQL Query request. * @param action - * @param query + * @param query Query - this may be modified to remove a DatasetDescription. * @param queryStringLog * @return {@link Dataset} */ http://git-wip-us.apache.org/repos/asf/jena/blob/b56d50f7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryDataset.java ---------------------------------------------------------------------- diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryDataset.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryDataset.java index bb9ad5c..aa503da 100644 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryDataset.java +++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryDataset.java @@ -40,19 +40,19 @@ public class SPARQL_QueryDataset extends SPARQL_Query protected void validateQuery(HttpAction action, Query query) { } + /** Decide the datset - this modifies the query + * If the query has a dataset description. + */ @Override - protected Dataset decideDataset(HttpAction action, Query query, String queryStringLog) - { + 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") ; + DatasetDescription dsDesc = getDatasetDescription(action, query) ; + if ( dsDesc != null ) { dsg = DynamicDatasets.dynamicDataset(dsDesc, dsg, false) ; + if ( query.hasDatasetDescription() ) { + query.getGraphURIs().clear() ; + query.getNamedGraphURIs().clear() ; + } } return DatasetFactory.create(dsg) ; http://git-wip-us.apache.org/repos/asf/jena/blob/b56d50f7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryGeneral.java ---------------------------------------------------------------------- diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryGeneral.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryGeneral.java index df871ba..dc4e7b4 100644 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryGeneral.java +++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_QueryGeneral.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package org.apache.jena.fuseki.servlets; +package org.apache.jena.fuseki.servlets ; import static java.lang.String.format ; @@ -32,109 +32,107 @@ import org.apache.jena.rdf.model.ModelFactory ; import org.apache.jena.riot.RiotException ; import org.apache.jena.sparql.core.DatasetDescription ; -public class SPARQL_QueryGeneral extends SPARQL_Query -{ - final static int MaxTriples = 100*1000 ; - - public SPARQL_QueryGeneral() { super() ; } +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(HttpAction action) - { return null ; } - + protected String mapRequestToDataset(HttpAction action) { + return null ; + } + @Override - protected Dataset decideDataset(HttpAction action, Query query, String queryStringLog) - { - DatasetDescription datasetDesc = getDatasetDescription(action) ; - if ( datasetDesc == null ) - datasetDesc = getDatasetDescription(query) ; + protected Dataset decideDataset(HttpAction action, Query query, String queryStringLog) { + DatasetDescription datasetDesc = getDatasetDescription(action, query) ; if ( datasetDesc == null ) ServletOps.errorBadRequest("No dataset description in protocol request or in the query string") ; - - return datasetFromDescription(action, datasetDesc) ; + return datasetFromDescriptionWeb(action, datasetDesc) ; } /** - * Construct a Dataset based on a dataset description. + * Construct a Dataset based on a dataset description. Loads graph from the + * web. */ - - protected Dataset datasetFromDescription(HttpAction action, DatasetDescription datasetDesc) - { + + protected Dataset datasetFromDescriptionWeb(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 ; - + return null ; + Dataset dataset = DatasetFactory.createMem() ; // Look in cache for loaded graphs!! // ---- Default graph { Model model = ModelFactory.createDefaultModel() ; - for ( String uri : graphURLs ) - { + for ( String uri : graphURLs ) { if ( uri == null || uri.equals("") ) - throw new InternalErrorException("Default graph URI is null or the empty string") ; + throw new InternalErrorException("Default graph URI is null or the empty string") ; try { GraphLoadUtils.loadModel(model, uri, MaxTriples) ; action.log.info(format("[%d] Load (default graph) %s", action.id, uri)) ; - } catch (RiotException ex) { + } + catch (RiotException ex) { action.log.info(format("[%d] Parsing error loading %s: %s", action.id, uri, ex.getMessage())) ; - ServletOps.errorBadRequest("Failed to load URL (parse error) "+uri+" : "+ex.getMessage()) ; - } catch (Exception ex) - { + ServletOps.errorBadRequest("Failed to load URL (parse error) " + uri + " : " + ex.getMessage()) ; + } + catch (Exception ex) { action.log.info(format("[%d] Failed to load (default) %s: %s", action.id, uri, ex.getMessage())) ; - ServletOps.errorBadRequest("Failed to load URL "+uri) ; + ServletOps.errorBadRequest("Failed to load URL " + uri) ; } } dataset.setDefaultModel(model) ; } // ---- Named graphs - if ( namedGraphs != null ) - { - for ( String uri : namedGraphs ) - { + if ( namedGraphs != null ) { + for ( String uri : namedGraphs ) { if ( uri == null || uri.equals("") ) - throw new InternalErrorException("Named graph URI is null or the empty string") ; + throw new InternalErrorException("Named graph URI is null or the empty string") ; try { Model model = ModelFactory.createDefaultModel() ; GraphLoadUtils.loadModel(model, uri, MaxTriples) ; action.log.info(format("[%d] Load (named graph) %s", action.id, uri)) ; dataset.addNamedModel(uri, model) ; - } catch (RiotException ex) { + } + catch (RiotException ex) { action.log.info(format("[%d] Parsing error loading %s: %s", action.id, uri, ex.getMessage())) ; - ServletOps.errorBadRequest("Failed to load URL (parse error) "+uri+" : "+ex.getMessage()) ; - } catch (Exception ex) - { + ServletOps.errorBadRequest("Failed to load URL (parse error) " + uri + " : " + ex.getMessage()) ; + } + catch (Exception ex) { action.log.info(format("[%d] Failed to load (named graph) %s: %s", action.id, uri, ex.getMessage())) ; - ServletOps.errorBadRequest("Failed to load URL "+uri) ; + ServletOps.errorBadRequest("Failed to load URL " + uri) ; } } } - + return dataset ; - - } - catch (ActionErrorException ex) { throw ex ; } - catch (Exception ex) - { - action.log.info(format("[%d] SPARQL parameter error: "+ex.getMessage(),action.id, ex)) ; - ServletOps.errorBadRequest("Parameter error: "+ex.getMessage()); + + } + catch (ActionErrorException ex) { + throw ex ; + } + catch (Exception ex) { + action.log.info(format("[%d] SPARQL parameter error: " + ex.getMessage(), action.id, ex)) ; + ServletOps.errorBadRequest("Parameter error: " + ex.getMessage()) ; return null ; } } http://git-wip-us.apache.org/repos/asf/jena/blob/b56d50f7/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestQuery.java ---------------------------------------------------------------------- diff --git a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestQuery.java b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestQuery.java index f8742a5..2f4d73a 100644 --- a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestQuery.java +++ b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestQuery.java @@ -16,18 +16,21 @@ * limitations under the License. */ -package org.apache.jena.fuseki; +package org.apache.jena.fuseki ; + +import static org.apache.jena.fuseki.ServerTest.gn1 ; +import static org.apache.jena.fuseki.ServerTest.gn2 ; +import static org.apache.jena.fuseki.ServerTest.model1 ; +import static org.apache.jena.fuseki.ServerTest.model2 ; +import static org.apache.jena.fuseki.ServerTest.serviceQuery ; +import static org.apache.jena.fuseki.ServerTest.serviceREST ; import java.io.IOException ; import java.net.HttpURLConnection ; import java.net.URL ; -import static org.apache.jena.fuseki.ServerTest.* ; -import org.junit.AfterClass ; -import org.junit.Assert ; -import org.junit.BeforeClass ; -import org.junit.Test ; import org.apache.jena.atlas.junit.BaseTest ; +import org.apache.jena.graph.Node ; import org.apache.jena.query.* ; import org.apache.jena.sparql.core.Var ; import org.apache.jena.sparql.engine.binding.Binding ; @@ -36,76 +39,117 @@ import org.apache.jena.sparql.sse.Item ; import org.apache.jena.sparql.sse.SSE ; import org.apache.jena.sparql.sse.builders.BuilderResultSet ; import org.apache.jena.sparql.util.Convert ; +import org.junit.AfterClass ; +import org.junit.Assert ; +import org.junit.BeforeClass ; +import org.junit.Test ; -public class TestQuery extends BaseTest -{ - protected static ResultSet rs1 = null ; +public class TestQuery extends BaseTest { + protected static ResultSet rs1 = null ; static { Item item = SSE.parseItem("(resultset (?s ?p ?o) (row (?s <x>)(?p <p>)(?o 1)))") ; rs1 = BuilderResultSet.build(item) ; } - - @BeforeClass public static void beforeClass() - { + + @BeforeClass + public static void beforeClass() { ServerTest.allocServer() ; ServerTest.resetServer() ; DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ; du.putModel(model1) ; du.putModel(gn1, model2) ; } - - @AfterClass public static void afterClass() - { + + @AfterClass + public static void afterClass() { DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ; du.deleteDefault() ; ServerTest.freeServer() ; } - - @Test public void query_01() - { + + @Test + public void query_01() { execQuery("SELECT * {?s ?p ?o}", 1) ; } - - @Test public void query_recursive_01() - { - String query = "SELECT * WHERE { SERVICE <" + serviceQuery + "> { ?s ?p ?o . BIND(?o AS ?x) } }"; - try ( QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery, query) ) { - ResultSet rs = qExec.execSelect(); - Var x = Var.alloc("x"); + + @Test + public void query_recursive_01() { + String query = "SELECT * WHERE { SERVICE <" + serviceQuery + "> { ?s ?p ?o . BIND(?o AS ?x) } }" ; + try (QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery, query)) { + ResultSet rs = qExec.execSelect() ; + Var x = Var.alloc("x") ; while (rs.hasNext()) { - Binding b = rs.nextBinding(); - Assert.assertNotNull(b.get(x)); + Binding b = rs.nextBinding() ; + Assert.assertNotNull(b.get(x)) ; } } } - - @Test public void query_with_params_01() - { - String query = "ASK { }"; - try ( QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery + "?output=json", query) ) { - boolean result = qExec.execAsk(); - Assert.assertTrue(result); + + @Test + public void query_with_params_01() { + String query = "ASK { }" ; + try (QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery + "?output=json", query)) { + boolean result = qExec.execAsk() ; + Assert.assertTrue(result) ; } } - - @Test public void request_id_header_01() throws IOException - { + + @Test + public void request_id_header_01() throws IOException { String qs = Convert.encWWWForm("ASK{}") ; - URL u = new URL(serviceQuery+"?query="+qs); - HttpURLConnection conn = (HttpURLConnection) u.openConnection(); - Assert.assertTrue(conn.getHeaderField("Fuseki-Request-ID") != null); + URL u = new URL(serviceQuery + "?query=" + qs) ; + HttpURLConnection conn = (HttpURLConnection)u.openConnection() ; + Assert.assertTrue(conn.getHeaderField("Fuseki-Request-ID") != null) ; } - private void execQuery(String queryString, int exceptedRowCount) - { + @Test + public void query_dynamic_dataset_01() { + DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ; + du.putModel(model1); + du.putModel(gn1, model2); + { + String query = "SELECT * { ?s ?p ?o }" ; + try (QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery + "?output=json", query)) { + ResultSet rs = qExec.execSelect() ; + Node o = rs.next().getLiteral("o").asNode() ; + Node n = SSE.parseNode("1") ; + assertEquals(n, o) ; + } + } + { + + String query = "SELECT * FROM <" + gn1 + "> { ?s ?p ?o }" ; + try (QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery + "?output=json", query)) { + ResultSet rs = qExec.execSelect() ; + Node o = rs.next().getLiteral("o").asNode() ; + Node n = SSE.parseNode("2") ; + assertEquals(n, o) ; + } + } + } + + @Test + public void query_dynamic_dataset_02() { + DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ; + du.putModel(model1); + du.putModel(gn1, model1); + du.putModel(gn2, model2); + String query = "SELECT * FROM <"+gn1+"> FROM <"+gn2+"> { ?s ?p ?o }" ; + try (QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery + "?output=json", query)) { + ResultSet rs = qExec.execSelect() ; + int n = ResultSetFormatter.consume(rs) ; + assertEquals(2, n) ; + } + } + + private void execQuery(String queryString, int exceptedRowCount) { QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery, queryString) ; ResultSet rs = qExec.execSelect() ; int x = ResultSetFormatter.consume(rs) ; assertEquals(exceptedRowCount, x) ; } - - private void execQuery(String queryString, ResultSet expectedResultSet) - { + + private void execQuery(String queryString, ResultSet expectedResultSet) { QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery, queryString) ; ResultSet rs = qExec.execSelect() ; boolean b = ResultSetCompare.equalsByTerm(rs, expectedResultSet) ;
