Merge pull request #787 from strangepleasures/JENA-1950
JENA-1950 Replace Nashorn with GraalVM-based JavaScript engine
diff --git a/jena-arq/src-examples/arq/examples/riot/Ex_WriteJsonLD.java b/jena-arq/src-examples/arq/examples/riot/Ex_WriteJsonLD.java
index 39eaefb..d66f592 100644
--- a/jena-arq/src-examples/arq/examples/riot/Ex_WriteJsonLD.java
+++ b/jena-arq/src-examples/arq/examples/riot/Ex_WriteJsonLD.java
@@ -200,7 +200,8 @@
DatasetGraph g = DatasetFactory.wrap(m).asDatasetGraph();
JsonLDWriteContext ctx = new JsonLDWriteContext();
- // The following should work, but unfortunately it doesn't (with JSONLD-java 0.8.3):
+ // The following should work for Uris returning JSON-LD,
+ // but unfortunately it doesn't for schema.org due to the following bug: https://github.com/jsonld-java/jsonld-java/issues/289:
ctx.setJsonLDContext("\"http://schema.org/\"");
System.out.println("\n--- Setting the context to a URI, WRONG WAY: it's slow, and the output is not JSON-LD. Sorry about that. ---");
write(g, RDFFormat.JSONLD_COMPACT_PRETTY, ctx);
@@ -214,7 +215,6 @@
// the output process must download the vocab before anything.
// (that's why the previous attempt was slow)
// -> that would not be an very efficient way to output your data.
- // -> it doesn't work, (with JSONLD-java 0.8.3), but no regret.
// To achieve the expected result,
// you have to do 2 things:
diff --git a/jena-arq/src/main/java/org/apache/jena/query/QueryFactory.java b/jena-arq/src/main/java/org/apache/jena/query/QueryFactory.java
index 0e84941..aa3564b 100644
--- a/jena-arq/src/main/java/org/apache/jena/query/QueryFactory.java
+++ b/jena-arq/src/main/java/org/apache/jena/query/QueryFactory.java
@@ -18,9 +18,12 @@
package org.apache.jena.query;
+import java.io.InputStream;
+
import org.apache.jena.atlas.io.IO;
import org.apache.jena.riot.system.IRIResolver ;
import org.apache.jena.riot.system.stream.StreamManager;
+import org.apache.jena.shared.NotFoundException;
import org.apache.jena.sparql.lang.ParserARQ ;
import org.apache.jena.sparql.lang.SPARQLParser ;
import org.apache.jena.sparql.lang.SPARQLParserRegistry ;
@@ -229,6 +232,9 @@
if ( filemanager == null )
filemanager = StreamManager.get() ;
+ InputStream in = filemanager.open(url);
+ if ( in == null )
+ throw new NotFoundException("Not found: "+url);
String qStr = IO.readWholeFileAsUTF8(filemanager.open(url));
if ( baseURI == null )
baseURI = url ;
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/JsonLDReadContext.java b/jena-arq/src/main/java/org/apache/jena/riot/JsonLDReadContext.java
new file mode 100644
index 0000000..22ffb34
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/riot/JsonLDReadContext.java
@@ -0,0 +1,74 @@
+/*
+ * 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.riot;
+
+import com.github.jsonldjava.core.JsonLdOptions;
+import org.apache.jena.atlas.web.ContentType;
+import org.apache.jena.riot.lang.JsonLDReader;
+import org.apache.jena.riot.system.StreamRDF;
+import org.apache.jena.sparql.util.Context;
+
+import java.io.InputStream;
+
+/**
+ * Set of parameters that can be used to control the reading of JSON-LD.
+ *
+ * This class provides setters to define a "Context" suitable to be passed as
+ * last argument to {@link ReaderRIOT#read(InputStream, String, ContentType, StreamRDF, Context)}
+ * when the ReaderRIOT has been created with one of the JSON-LD RDFFormat variants (that is, when it is
+ * an instance of {@link JsonLDReader})
+ *
+ * Parameters that are actually useful are ''documentLoader'' and ''produceGeneralizedRdf''.
+ *
+ */
+public class JsonLDReadContext extends Context {
+ /**
+ * Set the value of the JSON-LD "@context" node, used when reading a jsonld (overriding the actual @context in the jsonld). "Compact" and "Flattened" JSON-LD outputs.
+ *
+ * @param jsonLdContext the value of the "@context" node (a JSON value). Note that the use of an URI to pass an external context is not supported (as of JSONLD-java API 0.8.3)
+ *
+ * @see #setJsonLDContext(Object)
+ */
+ public void setJsonLDContext(String jsonLdContext) {
+ set(JsonLDReader.JSONLD_CONTEXT, jsonLdContext);
+ }
+
+ /**
+ * Set the value of the JSON-LD "@context" node, used when reading a jsonld (overriding the actual @context in the jsonld). "Compact" and "Flattened" JSON-LD outputs.
+ *
+ *
+ * @param jsonLdContext the context as expected by JSON-LD java API. As of JSON-LD java 0.8.3, a Map
+ * defining the properties and the prefixes is OK. Note that the use an URI to pass an external context is not supported (JSONLD-java RDF 0.8.3)
+ *
+ * @see #setJsonLDContext(String)
+ */
+ public void setJsonLDContext(Object jsonLdContext) {
+ set(JsonLDReader.JSONLD_CONTEXT, jsonLdContext);
+ }
+ /**
+ * Set the JSON-LD java API's options
+ *
+ * If not set, a default value is used.
+ *
+ * @param opts the options as defined by the JSON-LD java API
+ */
+ public void setOptions(JsonLdOptions opts) {
+ set(JsonLDReader.JSONLD_OPTIONS, opts);
+ }
+}
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/JsonLDWriteContext.java b/jena-arq/src/main/java/org/apache/jena/riot/JsonLDWriteContext.java
index d2e0b29..f40cc5d 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/JsonLDWriteContext.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/JsonLDWriteContext.java
@@ -15,6 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.apache.jena.riot;
import java.io.OutputStream;
@@ -59,7 +60,7 @@
* Only useful for "Compact" and "Flattened" JSON-LD outputs, and not required: if not set,
* a value for the "@Context" node is computed, based on the content of the dataset and its prefix mappings.
*
- * @param jsonLdContext the value of the "@context" node (a JSON value). Note that the use of an URI to pass an external context is not supported (as of JSONLD-java API 0.8.3)
+ * @param jsonLdContext the value of the "@context" node (a JSON value). Some remote contexts might not be resolved property.
* @see #setJsonLDContextSubstitution(String) for a way to overcome this problem.
*
* @see #setJsonLDContext(Object)
@@ -74,8 +75,7 @@
* Only useful for "Compact" and "Flattened" JSON-LD outputs, and not required: if not set,
* a value for the "@Context" node is computed, based on the content of the dataset and its prefix mappings.
*
- * @param jsonLdContext the context as expected by JSON-LD java API. As of JSON-LD java 0.8.3, a Map
- * defining the properties and the prefixes is OK. Note that the use an URI to pass an external context is not supported (JSONLD-java RDF 0.8.3)
+ * @param jsonLdContext the context as expected by JSON-LD java API. Some remote contexts might not be resolved property.
* @see #setJsonLDContextSubstitution(String) for a way to overcome this problem.
*
* @see #setJsonLDContext(String)
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/RDFParserRegistry.java b/jena-arq/src/main/java/org/apache/jena/riot/RDFParserRegistry.java
index 1bff3b0..c703f76 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/RDFParserRegistry.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/RDFParserRegistry.java
@@ -31,9 +31,11 @@
import org.apache.jena.atlas.lib.InternalErrorException ;
import org.apache.jena.atlas.web.ContentType ;
import org.apache.jena.riot.lang.* ;
+import org.apache.jena.riot.system.ErrorHandlerFactory;
import org.apache.jena.riot.system.ParserProfile;
import org.apache.jena.riot.system.StreamRDF;
import org.apache.jena.riot.thrift.BinRDF ;
+import org.apache.jena.riot.thrift.RiotThriftException;
import org.apache.jena.sparql.util.Context ;
/** The registry of languages and parsers.
@@ -206,14 +208,25 @@
private static class ReaderRIOTFactoryThrift implements ReaderRIOTFactory {
@Override
public ReaderRIOT create(Lang language, ParserProfile profile) {
- return new ReaderRDFThrift() ;
+ return new ReaderRDFThrift(profile) ;
}
}
private static class ReaderRDFThrift implements ReaderRIOT {
+ private final ParserProfile profile;
+ public ReaderRDFThrift(ParserProfile profile) { this.profile = profile; }
+
@Override
public void read(InputStream in, String baseURI, ContentType ct, StreamRDF output, Context context) {
- BinRDF.inputStreamToStream(in, output) ;
+ try {
+ BinRDF.inputStreamToStream(in, output);
+ } catch (RiotThriftException ex) {
+ if ( profile != null && profile.getErrorHandler() != null )
+ profile.getErrorHandler().error(ex.getMessage(), -1, -1);
+ else
+ ErrorHandlerFactory.errorHandlerStd.error(ex.getMessage(), -1 , -1);
+ throw ex;
+ }
}
@Override
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/RIOT.java b/jena-arq/src/main/java/org/apache/jena/riot/RIOT.java
index 6fcc439..39300ec 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/RIOT.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/RIOT.java
@@ -19,6 +19,7 @@
package org.apache.jena.riot ;
import org.apache.jena.query.ARQ ;
+import org.apache.jena.riot.lang.JsonLDReader;
import org.apache.jena.riot.resultset.ResultSetLang;
import org.apache.jena.sparql.SystemARQ ;
import org.apache.jena.sparql.mgt.SystemInfo ;
@@ -109,12 +110,9 @@
// ---- Symbols
- /**
- * Symbol to use to pass (in a Context object) the "@context" to be used when reading jsonld
- * (overriding the actual @context in the jsonld)
- * Expected value: the value of the "@context",
- * as expected by the JSONLD-java API (a Map) */
- public static final Symbol JSONLD_CONTEXT = Symbol.create("http://jena.apache.org/riot/jsonld#JSONLD_CONTEXT");
+ /** @deprecated Use {@link JsonLDReader#JSONLD_CONTEXT} */
+ @Deprecated
+ public static final Symbol JSONLD_CONTEXT = JsonLDReader.JSONLD_CONTEXT;
private static String TURTLE_SYMBOL_BASE = "http://jena.apache.org/riot/turtle#";
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/lang/JsonLDReader.java b/jena-arq/src/main/java/org/apache/jena/riot/lang/JsonLDReader.java
index 07a216b..305fe1e 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/lang/JsonLDReader.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/lang/JsonLDReader.java
@@ -26,6 +26,7 @@
import java.util.Map.Entry;
import java.util.Objects;
+import com.fasterxml.jackson.core.JsonParseException;
import org.apache.jena.atlas.io.IO ;
import org.apache.jena.atlas.lib.InternalErrorException ;
import org.apache.jena.atlas.web.ContentType ;
@@ -47,14 +48,42 @@
import com.github.jsonldjava.core.JsonLdTripleCallback;
import com.github.jsonldjava.core.RDFDataset;
import com.github.jsonldjava.utils.JsonUtils ;
+import org.apache.jena.sparql.util.Symbol;
/**
+ * One can pass a jsonld context using the (jena) Context mechanism, defining a (jena) Context
+ * (sorry for this clash of "contexts"), (cf. last argument in
+ * {@link ReaderRIOT#read(InputStream in, String baseURI, ContentType ct, StreamRDF output, Context context)})
+ * with:
+ * <pre>
+ * Context jenaContext = new Context()
+ * jenaCtx.set(JsonLdReader.JSONLD_CONTEXT, contextAsJsonString);
+ * </pre>
+ * where contextAsJsonString is a JSON string containing the value of the "@context".
+ *
+ * It is also possible to define the different options supported
+ * by JSONLD-java using the {@link #JSONLD_OPTIONS} Symbol
+ *
+ * The {@link JsonLDReadContext} is a convenience class that extends Context and
+ * provides methods to set the values of these different Symbols that are used in controlling the writing of JSON-LD.
* Note: it is possible to override jsonld's "@context" value by providing one,
- * using a {@link org.apache.jena.sparql.util.Context}, and setting the {@link RIOT#JSONLD_CONTEXT} Symbol's value
+ * using a {@link org.apache.jena.sparql.util.Context}, and setting the {@link JsonLDReader#JSONLD_CONTEXT} Symbol's value
* to the data expected by JSON-LD java API (a {@link Map}).
*/
public class JsonLDReader implements ReaderRIOT
{
+ private static final String SYMBOLS_NS = "http://jena.apache.org/riot/jsonld#" ;
+ private static Symbol createSymbol(String localName) {
+ return Symbol.create(SYMBOLS_NS + localName);
+ }
+ /**
+ * Symbol to use to pass (in a Context object) the "@context" to be used when reading jsonld
+ * (overriding the actual @context in the jsonld)
+ * Expected value: the value of the "@context",
+ * as expected by the JSONLD-java API (a Map) */
+ public static final Symbol JSONLD_CONTEXT = createSymbol("JSONLD_CONTEXT");
+ /** value: the option object expected by JsonLdProcessor (instance of JsonLdOptions) */
+ public static final Symbol JSONLD_OPTIONS = createSymbol("JSONLD_OPTIONS");
private /*final*/ ErrorHandler errorHandler = ErrorHandlerFactory.getDefaultErrorHandler() ;
private /*final*/ ParserProfile profile;
@@ -67,7 +96,26 @@
public void read(Reader reader, String baseURI, ContentType ct, StreamRDF output, Context context) {
try {
Object jsonObject = JsonUtils.fromReader(reader) ;
- read$(jsonObject, baseURI, ct, output, context) ;
+ readWithJsonLDCtxOptions(jsonObject, baseURI, output, context) ;
+ }
+ catch (JsonProcessingException ex) {
+ // includes JsonParseException
+ // The Jackson JSON parser, or addition JSON-level check, throws up something.
+ JsonLocation loc = ex.getLocation() ;
+ errorHandler.error(ex.getOriginalMessage(), loc.getLineNr(), loc.getColumnNr());
+ throw new RiotException(ex.getOriginalMessage()) ;
+ }
+ catch (IOException e) {
+ errorHandler.error(e.getMessage(), -1, -1);
+ IO.exception(e) ;
+ }
+ }
+
+ @Override
+ public void read(InputStream in, String baseURI, ContentType ct, StreamRDF output, Context context) {
+ try {
+ Object jsonObject = JsonUtils.fromInputStream(in) ;
+ readWithJsonLDCtxOptions(jsonObject, baseURI, output, context) ;
}
catch (JsonProcessingException ex) {
// includes JsonParseException
@@ -83,37 +131,20 @@
}
@SuppressWarnings({ "rawtypes", "unchecked" })
- @Override
- public void read(InputStream in, String baseURI, ContentType ct, StreamRDF output, Context context) {
- try {
- Object jsonObject = JsonUtils.fromInputStream(in) ;
-
- if (context != null) {
- Object jsonldCtx = context.get(RIOT.JSONLD_CONTEXT);
- if (jsonldCtx != null) {
- if (jsonObject instanceof Map) {
- ((Map) jsonObject).put("@context", jsonldCtx);
- } else {
- errorHandler.warning("Unexpected: not a Map; unable to set JsonLD's @context",-1,-1);
- }
- }
+ private void readWithJsonLDCtxOptions(Object jsonObject, String baseURI, final StreamRDF output, Context context) throws JsonParseException, IOException {
+ JsonLdOptions options = getJsonLdOptions(baseURI, context) ;
+ Object jsonldCtx = getJsonLdContext(context);
+ if (jsonldCtx != null) {
+ if (jsonObject instanceof Map) {
+ ((Map) jsonObject).put("@context", jsonldCtx);
+ } else {
+ errorHandler.warning("Unexpected: not a Map; unable to set JsonLD's @context",-1,-1);
}
- read$(jsonObject, baseURI, ct, output, context) ;
}
- catch (JsonProcessingException ex) {
- // includes JsonParseException
- // The Jackson JSON parser, or addition JSON-level check, throws up something.
- JsonLocation loc = ex.getLocation() ;
- errorHandler.error(ex.getOriginalMessage(), loc.getLineNr(), loc.getColumnNr());
- throw new RiotException(ex.getOriginalMessage()) ;
- }
- catch (IOException e) {
- errorHandler.error(e.getMessage(), -1, -1);
- IO.exception(e) ;
- }
+ read$(jsonObject, options, output);
}
-
- private void read$(Object jsonObject, String baseURI, ContentType ct, final StreamRDF output, Context context) {
+
+ private void read$(Object jsonObject, JsonLdOptions options, final StreamRDF output) {
output.start() ;
try {
JsonLdTripleCallback callback = new JsonLdTripleCallback() {
@@ -154,8 +185,6 @@
return null ;
}
} ;
- JsonLdOptions options = new JsonLdOptions(baseURI);
- options.useNamespaces = true;
JsonLdProcessor.toRDF(jsonObject, callback, options) ;
}
catch (JsonLdError e) {
@@ -165,6 +194,44 @@
output.finish() ;
}
+ /** Get the (jsonld) options from the jena context if exists or create default */
+ static private JsonLdOptions getJsonLdOptions(String baseURI, Context jenaContext) {
+ JsonLdOptions opts = null;
+ if (jenaContext != null) {
+ opts = (JsonLdOptions) jenaContext.get(JSONLD_OPTIONS);
+ }
+ if (opts == null) {
+ opts = defaultJsonLdOptions(baseURI);
+ }
+ return opts;
+ }
+
+ static private JsonLdOptions defaultJsonLdOptions(String baseURI) {
+ JsonLdOptions opts = new JsonLdOptions(baseURI);
+ opts.useNamespaces = true ; // this is NOT jsonld-java's default
+ return opts;
+ }
+
+ /** Get the (jsonld) context from the jena context if exists */
+ static private Object getJsonLdContext(Context jenaContext) throws JsonParseException, IOException {
+ Object ctx = null;
+ boolean isCtxDefined = false; // to allow jenaContext to set ctx to null. Useful?
+
+ if (jenaContext != null) {
+ if (jenaContext.isDefined(JSONLD_CONTEXT)) {
+ Object o = jenaContext.get(JSONLD_CONTEXT);
+ if (o != null) {
+ if (o instanceof String) { // supposed to be a json string
+ String jsonString = (String) o;
+ o = JsonUtils.fromString(jsonString);
+ }
+ ctx = o;
+ }
+ }
+ }
+ return ctx;
+ }
+
public static String LITERAL = "literal" ;
public static String BLANK_NODE = "blank node" ;
public static String IRI = "IRI" ;
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/JSONResultsKW.java b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/JSONResultsKW.java
index 2dbc9b6..aae25d1 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/JSONResultsKW.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/JSONResultsKW.java
@@ -45,6 +45,8 @@
// RDF* Triple terms
public static String kTriple = "triple" ;
+ // Alternative type for RDF* triple terms.
+ public static String kStatement = "statement" ;
public static String kSubject = "subject" ;
public static String kPredicate = "predicate" ;
public static String kProperty = "property" ;
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderJSON.java b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderJSON.java
index 95cc399..e614a4f 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderJSON.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultSetReaderJSON.java
@@ -199,7 +199,7 @@
String type = stringOrNull(term, kType);
- if ( kTriple.equals(type) ) {
+ if ( kTriple.equals(type) || kStatement.equals(type) ) {
JsonObject x = term.get(kValue).getAsObject();
return parseTripleTerm(x, labelMap);
}
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsStAX.java b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsStAX.java
index 6407f53..2471716 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsStAX.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/ResultsStAX.java
@@ -388,7 +388,7 @@
varName = parser.getAttributeValue(null, XMLResults.dfAttrVarName) ;
break ;
}
-
+
Node value = parseOneTerm(tag);
if ( value != null ) {
if ( varName == null )
@@ -440,14 +440,14 @@
if ( isTag(tag, XMLResults.dfUnbound) ) {
return null;
}
-
+
if ( isTag(tag, XMLResults.dfURI) ) {
String uri = parser.getElementText() ;
Node node = NodeFactory.createURI(uri) ;
return node;
}
-
- if ( isTag(tag, XMLResults.dfTriple) ) {
+
+ if ( isTag(tag, XMLResults.dfTriple) || isTag(tag, XMLResults.dfStatement) ) {
// <triple>
Node s = null;
Node p = null;
@@ -458,30 +458,30 @@
if ( event2 == XMLStreamConstants.END_ELEMENT ) {
// Early end.
String tagx = parser.getLocalName() ;
- if ( tagx.equals(XMLResults.dfTriple) )
+ if ( tagx.equals(XMLResults.dfTriple) || tagx.equals(XMLResults.dfStatement) )
staxError("Incomplete triple term");
else
staxError("Mismatched tag: "+tagx);
}
//XMLStreamConstants.START_ELEMENT
-
+
String tag2 = parser.getLocalName() ;
// <subject> <property> <object>
// One of subject, property, object (s,p,o)
-
+
if ( ! isOneOf(tag2, XMLResults.dfSubject, XMLResults.dfProperty, XMLResults.dfPredicate, XMLResults.dfObject,
XMLResults.dfSubjectAlt, XMLResults.dfPropertyAlt, XMLResults.dfObjectAlt) )
staxError("Unexpected tag in triple term: "+tag2);
-
+
int event3 = parser.nextTag() ;
String tag3 = parser.getLocalName() ;
Node x = parseOneTerm(tag3);
-
+
// Read end </subject> etc.
parser.nextTag() ;
// Check for double assignment.
- if ( isOneOf(tag2, XMLResults.dfSubject, XMLResults.dfSubjectAlt) )
+ if ( isOneOf(tag2, XMLResults.dfSubject, XMLResults.dfSubjectAlt) )
s = x ;
else if ( isOneOf(tag2, XMLResults.dfProperty, XMLResults.dfPredicate, XMLResults.dfPropertyAlt) )
p = x ;
@@ -493,13 +493,13 @@
if ( event4 == XMLStreamConstants.START_ELEMENT )
staxError("Too many terms for a triple");
// XMLStreamConstants.END_ELEMENT )
- if ( ! tagx.equals(XMLResults.dfTriple) )
+ if ( ! tagx.equals(XMLResults.dfTriple) && ! tagx.equals(XMLResults.dfStatement) )
staxError("Expecting </triple>: "+tagx);
// </triple>
break;
}
}
-
+
if ( s == null || p == null || o == null )
staxError("Bad <triple> term");
Node node = NodeFactory.createTripleNode(s, p, o);
@@ -515,7 +515,7 @@
}
return false;
}
-
+
static protected void addBinding(BindingMap binding, Var var, Node value) {
Node n = binding.get(var);
if ( n != null ) {
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/XMLResults.java b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/XMLResults.java
index ff7565f..0fd4c4d 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/XMLResults.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/resultset/rw/XMLResults.java
@@ -27,10 +27,10 @@
public static final String baseNamespace = ARQConstants.srxPrefix ;
public static final String xsBaseURI = ARQConstants.XML_SCHEMA_NS ;
-
+
public static final String dfAttrVarName = "name" ;
public static final String dfAttrDatatype = "datatype" ;
-
+
public static final String dfNamespace = baseNamespace ;
public static final String dfRootTag = "sparql" ;
public static final String dfHead = "head" ;
@@ -39,11 +39,12 @@
public static final String dfResults = "results" ;
public static final String dfSolution = "result" ;
public static final String dfBinding = "binding" ;
-
+
public static final String dfBNode = "bnode" ;
public static final String dfURI = "uri" ;
public static final String dfLiteral = "literal" ;
public static final String dfTriple = "triple" ;
+ public static final String dfStatement = "statement" ;
public static final String dfSubject = "subject" ;
public static final String dfProperty = "property" ;
public static final String dfObject = "object" ;
@@ -53,7 +54,7 @@
public static final String dfSubjectAlt = "s" ;
public static final String dfPropertyAlt = "p" ;
public static final String dfObjectAlt = "o" ;
-
+
public static final String dfUnbound = "unbound" ;
public static final String dfBoolean = "boolean" ;
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/thrift/BinRDF.java b/jena-arq/src/main/java/org/apache/jena/riot/thrift/BinRDF.java
index 52e6e92..47561af 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/thrift/BinRDF.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/thrift/BinRDF.java
@@ -157,8 +157,8 @@
final Thrift2StreamRDF s = new Thrift2StreamRDF(pmap, dest) ;
dest.start() ;
apply(protocol, z -> TRDF.visit(z, s)) ;
+ // Includes flushing the protocol.
dest.finish() ;
- // No need to flush - we read from the protocol ;
}
/**
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/thrift/Thrift2StreamRDF.java b/jena-arq/src/main/java/org/apache/jena/riot/thrift/Thrift2StreamRDF.java
index 3186bfc..30aa0b3 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/thrift/Thrift2StreamRDF.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/thrift/Thrift2StreamRDF.java
@@ -19,7 +19,6 @@
package org.apache.jena.riot.thrift;
import org.apache.jena.graph.Triple ;
-import org.apache.jena.riot.RiotException ;
import org.apache.jena.riot.system.PrefixMap ;
import org.apache.jena.riot.system.StreamRDF ;
import org.apache.jena.riot.thrift.wire.RDF_PrefixDecl ;
@@ -58,10 +57,7 @@
public void visit(RDF_PrefixDecl prefixDecl) {
String prefix = prefixDecl.getPrefix() ;
String iriStr = prefixDecl.getUri() ;
- try {
- pmap.add(prefix, iriStr) ;
- } catch (RiotException ex) {}
+ pmap.add(prefix, iriStr) ;
dest.prefix(prefix, iriStr) ;
}
-
}
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/writer/JsonLDWriter.java b/jena-arq/src/main/java/org/apache/jena/riot/writer/JsonLDWriter.java
index 3a70dfb..6a6f888 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/writer/JsonLDWriter.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/writer/JsonLDWriter.java
@@ -193,7 +193,6 @@
JsonLdOptions opts = getJsonLdOptions(baseURI, jenaContext) ;
// we can benefit from the fact we know that there are no duplicates in the jsonld RDFDataset that we create
- // (optimization in jsonld-java 0.8.3)
// see https://github.com/jsonld-java/jsonld-java/pull/173
// with this, we cannot call the json-ld fromRDF method that assumes no duplicates in RDFDataset
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/algebra/Algebra.java b/jena-arq/src/main/java/org/apache/jena/sparql/algebra/Algebra.java
index 32728ac..89e18ad 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/algebra/Algebra.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/algebra/Algebra.java
@@ -50,10 +50,10 @@
public class Algebra
{
// -------- Optimize
-
+
/** Apply static transformations to a query to optimize it */
public static Op optimize(Op op) { return optimize(op, null) ; }
-
+
/** Apply static transformations to a query to optimize it */
public static Op optimize(Op op, Context context)
{
@@ -63,10 +63,10 @@
if ( op == null )
return null ;
return Optimize.optimize(op, context) ;
- }
-
+ }
+
// -------- Compile
-
+
/** Compile a query - pattern and modifiers. */
public static Op compile(Query query)
{
@@ -88,21 +88,25 @@
{
return AlgebraQuad.quadize(op) ;
}
-
+
/** Turn an algebra expression into quadblock form */
public static Op toQuadBlockForm(Op op)
{
return AlgebraQuad.quadizeBlock(op) ;
}
-
- /** Transform an algebra expression so that default graph is union of the named graphs. */
+
+ /** Transform an algebra expression so that default graph is union of the named graphs.
+ * Does not work with property paths.
+ * @deprecated To be removed
+ */
+ @Deprecated
public static Op unionDefaultGraph(Op op)
{
return TransformUnionQuery.transform(op) ;
}
-
+
// -------- SSE uses these operations ...
-
+
static public Op read(String filename)
{
Item item = SSE.readFile(filename) ;
@@ -114,20 +118,20 @@
Item item = SSE.parse(string) ;
return parse(item) ;
}
-
+
static public Op parse(String string, PrefixMapping pmap)
{
Item item = SSE.parse(string, pmap) ;
return parse(item) ;
}
-
+
static public Op parse(Item item)
{
Op op = BuilderOp.build(item) ;
return op ;
}
-
+
// -------- Execute
static public QueryIterator exec(Op op, Dataset ds)
@@ -174,16 +178,16 @@
QueryEngineRef qe = new QueryEngineRef(op, dsg, ARQ.getContext().copy()) ;
return qe.getPlan().iterator() ;
}
-
- // This is the SPARQL merge rule.
+
+ // This is the SPARQL merge rule.
public static Binding merge(Binding bindingLeft, Binding bindingRight)
{
// Test to see if compatible: Iterate over variables in left
boolean matches = compatible(bindingLeft, bindingRight) ;
-
- if ( ! matches )
+
+ if ( ! matches )
return null ;
-
+
// If compatible, merge. Iterate over variables in right but not in left.
BindingMap b = BindingFactory.create(bindingLeft) ;
for ( Iterator<Var> vIter = bindingRight.vars() ; vIter.hasNext() ; )
@@ -195,28 +199,28 @@
}
return b ;
}
-
+
public static boolean compatible(Binding bindingLeft, Binding bindingRight)
{
// Test to see if compatible: Iterate over variables in left
for ( Iterator<Var> vIter = bindingLeft.vars() ; vIter.hasNext() ; )
{
Var v = vIter.next();
- Node nLeft = bindingLeft.get(v) ;
+ Node nLeft = bindingLeft.get(v) ;
Node nRight = bindingRight.get(v) ;
-
+
if ( nRight != null && ! nRight.equals(nLeft) )
return false ;
}
return true ;
}
-
+
public static boolean disjoint(Binding binding1, Binding binding2)
{
Iterator<Var> iterVar1 = binding1.vars() ;
for ( ; iterVar1.hasNext() ; )
{
- Var v = iterVar1.next() ;
+ Var v = iterVar1.next() ;
if ( binding2.contains(v) )
return false ;
}
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphOne.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphOne.java
index f7d5b77..1323c0a 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphOne.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphOne.java
@@ -35,9 +35,9 @@
/** DatasetGraph of a single graph as default graph.
* <p>
- * Fixed as one graph (the default) - named graphs can notbe added nor the default graph changed, only the contents modified.
+ * Fixed as one graph (the default) - named graphs can notbe added nor the default graph changed, only the contents modified.
* <p>
- * Ths dataset passes transactions down to a nominated backing {@link DatasetGraph}
+ * This dataset passes transactions down to a nominated backing {@link DatasetGraph}.
* <p>
* It is particular suitable for use with an interference graph.
*/
@@ -58,7 +58,7 @@
// Didn't find a GraphView so no backing DatasetGraph; work on the graph as given.
return new DatasetGraphOne(graph);
}
-
+
private static Graph unwrap(Graph graph) {
for (;;) {
if ( graph instanceof InfGraph ) {
@@ -71,26 +71,26 @@
graph = graph2;
}
}
-
+
private DatasetGraphOne(Graph graph, DatasetGraph backing) {
this.graph = graph;
backingDGS = backing;
supportsAbort = backing.supportsTransactionAbort();
txn = backing;
}
-
+
private DatasetGraphOne(Graph graph) {
- // Not GraphView which was handled in create(Graph).
+ // Not GraphView which was handled in create(Graph).
this.graph = graph;
txn = new TxnDataset2Graph(graph);
//txn = TransactionalLock.createMRSW();
backingDGS = null;
// Don't advertise the fact but TxnDataset2Graph tries to provide abort.
- // We can not guarantee it though because a plain, non-TIM,
+ // We can not guarantee it though because a plain, non-TIM,
// memory graph does not support abort.
supportsAbort = false;
}
-
+
@Override public void begin(TxnType txnType) { txn.begin(txnType); }
@Override public void begin(ReadWrite mode) { txn.begin(mode); }
@Override public void commit() { txn.commit(); }
@@ -102,7 +102,7 @@
@Override public TxnType transactionType() { return txn.transactionType(); }
@Override public boolean supportsTransactions() { return true; }
@Override public boolean supportsTransactionAbort() { return supportsAbort; }
-
+
@Override
public boolean containsGraph(Node graphNode) {
if ( isDefaultGraph(graphNode) )
@@ -114,7 +114,7 @@
public Graph getDefaultGraph() {
return graph;
}
-
+
@Override
public Graph getUnionGraph() {
return GraphZero.instance();
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/AssemblerUtils.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/AssemblerUtils.java
index 6c46af9..d63b279 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/AssemblerUtils.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/AssemblerUtils.java
@@ -41,32 +41,34 @@
public class AssemblerUtils
{
- // Wrappers for reading things form a file - assumes one of the thing per file.
+ // Wrappers for reading things form a file - assumes one of the thing per file.
public static PrefixMapping readPrefixMapping(String file)
{
PrefixMapping pm = (PrefixMapping)AssemblerUtils.build(file, JA.PrefixMapping) ;
return pm ;
}
-
- private static boolean initialized = false ;
-
- static { JenaSystem.init() ; }
-
+
+ private static boolean initialized = false ;
+
+ static { JenaSystem.init() ; }
+
static public void init()
{
if ( initialized )
return ;
initialized = true ;
- registerDataset(tDataset, new DatasetAssembler()) ;
- registerDataset(tDatasetOne, new DatasetOneAssembler()) ;
- registerDataset(tDatasetZero, new DatasetNullAssembler(tDatasetZero)) ;
- registerDataset(tDatasetSink, new DatasetNullAssembler(tDatasetSink)) ;
- registerDataset(tMemoryDataset, new InMemDatasetAssembler()) ;
- registerDataset(tDatasetTxnMem, new InMemDatasetAssembler()) ;
+ registerDataset(tDataset, new DatasetAssembler());
+ registerDataset(tDatasetOne, new DatasetOneAssembler());
+ registerDataset(tDatasetZero, new DatasetNullAssembler(tDatasetZero));
+ registerDataset(tDatasetSink, new DatasetNullAssembler(tDatasetSink));
+ registerDataset(tMemoryDataset, new InMemDatasetAssembler());
+ registerDataset(tDatasetTxnMem, new InMemDatasetAssembler());
+
+ registerModel(tViewGraph, new ViewGraphAssembler());
}
-
+
private static Model modelExtras = ModelFactory.createDefaultModel() ;
-
+
/** Register an assembler that creates a dataset */
static public void registerDataset(Resource r, Assembler a) {
register(ConstAssembler.general(), r, a, DatasetAssembler.getType()) ;
@@ -77,7 +79,7 @@
register(ConstAssembler.general(), r, a, JA.Model) ;
}
- /** Register an addition assembler */
+ /** Register an additional assembler */
static public void register(AssemblerGroup g, Resource r, Assembler a, Resource superType) {
registerAssembler(g, r, a) ;
if ( superType != null && ! superType.equals(r) ) {
@@ -86,8 +88,8 @@
modelExtras.add(r, RDFS.Init.subClassOf(), superType) ;
}
}
-
- /** register */
+
+ /** register */
public static void registerAssembler(AssemblerGroup group, Resource r, Assembler a) {
if ( group == null )
group = ConstAssembler.general();
@@ -104,7 +106,7 @@
addRegistered(spec);
return spec ;
}
-
+
/** Add any extra information to the model.
* Such information includes registration of datasets (e.g. TDB1, TDB2)
* done by {@link #register} ({@link #registerDataset}, {@link #registerModel}.
@@ -116,36 +118,36 @@
model.add(modelExtras) ;
return model ;
}
-
+
public static Object build(String assemblerFile, String typeURI) {
Resource type = ResourceFactory.createResource(typeURI) ;
- return build(assemblerFile, type) ;
+ return build(assemblerFile, type) ;
}
-
+
public static Object build(String assemblerFile, Resource type) {
if ( assemblerFile == null )
throw new ARQException("No assembler file") ;
Model spec = readAssemblerFile(assemblerFile) ;
-
+
Resource root = null ;
try {
root = GraphUtils.findRootByType(spec, type) ;
if ( root == null )
throw new ARQException("No such type: <"+type+">");
-
+
} catch (TypeNotUniqueException ex)
{ throw new ARQException("Multiple types for: "+tDataset) ; }
return Assembler.general.open(root) ;
}
-
- /** Look for and build context declarations.
+
+ /** Look for and build context declarations.
* e.g.
* <pre>
* root ... ;
* ja:context [ ja:cxtName "arq:queryTimeout" ; ja:cxtValue "10000" ] ;
* ...
* </pre>
- * Short name forms of context parameters can be used.
+ * Short name forms of context parameters can be used.
* Setting as string "undef" will remove the context setting.
* Returns null when there is no {@link JA#context} on the resource.
*/
@@ -157,20 +159,20 @@
mergeContext(r, context);
return context;
}
-
+
/** @deprecated Use {@link #mergeContext(Resource, Context)} */
public static void setContext(Resource r, Context context) {
mergeContext(r, context);
}
-
- /** Look for and merge in context declarations.
+
+ /** Look for and merge in context declarations.
* e.g.
* <pre>
* root ... ;
* ja:context [ ja:cxtName "arq:queryTimeout" ; ja:cxtValue "10000" ] ;
* ...
* </pre>
- * Short name forms of context parameters can be used.
+ * Short name forms of context parameters can be used.
* Setting as string "undef" will remove the context setting.
*/
public static void mergeContext(Resource r, Context context) {
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/DatasetAssemblerVocab.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/DatasetAssemblerVocab.java
index d55d7d1..0bdd0ed 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/DatasetAssemblerVocab.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/DatasetAssemblerVocab.java
@@ -27,7 +27,7 @@
{
public static final String NS = JA.getURI() ;
public static String getURI() { return NS ; }
-
+
// General dataset
public static final Resource tDataset = ResourceFactory.createResource(NS+"RDFDataset") ;
// Dataset to hold exactly one model.
@@ -35,23 +35,27 @@
// In-memory dataset
public static final Resource tDatasetTxnMem = ResourceFactory.createResource(NS+"DatasetTxnMem") ;
-
+
// Specialised datasets
public static final Resource tMemoryDataset = ResourceFactory.createResource(NS+"MemoryDataset") ;
public static final Resource tDatasetZero = ResourceFactory.createResource(NS+"RDFDatasetZero") ;
public static final Resource tDatasetSink = ResourceFactory.createResource(NS+"RDFDatasetSink") ;
-
+ public static final Resource tViewGraph = ResourceFactory.createResource(NS+"ViewGraph") ;
+
+ public static final Property pDataset = ResourceFactory.createProperty(NS, "dataset") ;
+
public static final Property pDefaultGraph = ResourceFactory.createProperty(NS, "defaultGraph") ;
+
public static final Property pNamedGraph = ResourceFactory.createProperty(NS, "namedGraph") ;
-
public static final Property pGraphName = ResourceFactory.createProperty(NS, "graphName") ;
+
public static final Property pGraph = ResourceFactory.createProperty(NS, "graph") ;
public static final Property pGraphAlt = ResourceFactory.createProperty(NS, "graphData") ;
public static final Property pIndex = ResourceFactory.createProperty(NS, "textIndex") ;
-
+
public static final Property pTransactional = ResourceFactory.createProperty(NS, "transactional") ;
-
+
public static final Property pContext = ResourceFactory.createProperty(NS, "context") ;
public static final Property pCxtName = ResourceFactory.createProperty(NS, "cxtName") ;
public static final Property pCxtValue = ResourceFactory.createProperty(NS, "cxtValue") ;
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/ViewGraphAssembler.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/ViewGraphAssembler.java
new file mode 100644
index 0000000..56af65c
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/ViewGraphAssembler.java
@@ -0,0 +1,68 @@
+/*
+ * 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.sparql.core.assembler;
+
+import static org.apache.jena.sparql.core.assembler.DatasetAssemblerVocab.pDataset;
+import static org.apache.jena.sparql.core.assembler.DatasetAssemblerVocab.pGraphName;
+import static org.apache.jena.sparql.core.assembler.DatasetAssemblerVocab.pNamedGraph;
+import static org.apache.jena.sparql.util.graph.GraphUtils.getAsStringValue;
+import static org.apache.jena.sparql.util.graph.GraphUtils.getResourceValue;
+
+import org.apache.jena.assembler.Assembler;
+import org.apache.jena.assembler.Mode;
+import org.apache.jena.assembler.assemblers.AssemblerBase;
+import org.apache.jena.assembler.exceptions.AssemblerException;
+import org.apache.jena.query.Dataset;
+import org.apache.jena.query.DatasetFactory;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.Resource;
+
+/** Assembler to project a model out of a dataset.
+ *
+ * <pre>
+ * <#graph> rdf:type ja:ViewGraph ;
+ * ja:graphName "..." ; # Optional: else default graph
+ * js:dataset <#dataset> ;
+ * .
+ * <#dataset> rdf:type ja:RDFDataset ; # Any subtype
+ * ...
+ * </pre>
+ *
+ */
+public class ViewGraphAssembler extends AssemblerBase implements Assembler {
+
+ @Override
+ public Model open(Assembler a, Resource root, Mode mode)
+ {
+ Resource dataset = getResourceValue(root, pDataset) ;
+ if ( dataset == null )
+ throw new AssemblerException(root, "Must give a dataset with ja:dataset") ;
+
+ String graphName = null ;
+ if ( root.hasProperty(pNamedGraph) )
+ graphName = getAsStringValue(root, pNamedGraph) ;
+ if ( root.hasProperty(pGraphName) )
+ graphName = getAsStringValue(root, pGraphName) ;
+
+ Dataset ds = DatasetFactory.assemble(dataset);
+ Model model = (graphName == null) ? ds.getDefaultModel() : ds.getNamedModel(graphName) ;
+ return model;
+ }
+}
+
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/RX.java b/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/RX.java
index 9e6184f..197fb56 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/RX.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/RX.java
@@ -72,7 +72,7 @@
VarAlloc varAlloc = VarAlloc.get(context, ARQConstants.sysVarAllocRDFStar);
if ( varAlloc == null ) {
varAlloc = new VarAlloc(ARQConstants.allocVarTripleTerm);
- context.set(ARQConstants.sysVarAllocRDFStar, varAlloc);
+ context.set(ARQConstants.sysVarAllocRDFStar, varAlloc);
}
return varAlloc;
}
@@ -118,14 +118,14 @@
Node o1 = null;
// Recurse.
- if ( s.isNodeTriple() && ! s.isConcrete() ) {
+ if ( s.isNodeTriple() ) {
Triple t2 = triple(s);
Var var = varAlloc(execCxt).allocVar();
Triple tripleTerm = Triple.create(t2.getSubject(), t2.getPredicate(), t2.getObject());
chain = matchTripleStar(chain, var, tripleTerm, execCxt);
s1 = var;
}
- if ( o.isNodeTriple() && ! o.isConcrete() ) {
+ if ( o.isNodeTriple() ) {
Triple t2 = triple(o);
Var var = varAlloc(execCxt).allocVar();
Triple tripleTerm = Triple.create(t2.getSubject(), t2.getPredicate(), t2.getObject());
@@ -134,8 +134,8 @@
}
// Because of the test in rdfStarTriple,
- // This code only happens when there is a a triple term.
-
+ // This code only happens when there is a a triple term.
+
// No triple term in this triple.
if ( s1 == null && o1 == null )
return Pair.create(chain, patternTriple);
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/function/js/EnvJavaScript.java b/jena-arq/src/main/java/org/apache/jena/sparql/function/js/EnvJavaScript.java
index 259ba83..3d1bfe3 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/function/js/EnvJavaScript.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/function/js/EnvJavaScript.java
@@ -52,7 +52,7 @@
return new EnvJavaScript(context);
}
- private static EnvJavaScript global = null;
+ private static volatile EnvJavaScript global = null;
/**
* Return the global {@code EnvJavaScript}.
@@ -61,9 +61,11 @@
public static EnvJavaScript get() {
if ( global == null ) {
synchronized(EnvJavaScript.class) {
- Context context = ARQ.getContext();
- if ( context.isDefined(symJavaScriptFunctions) || context.isDefined(symJavaScriptLibFile) )
- global = create(ARQ.getContext());
+ if ( global == null ) {
+ Context context = ARQ.getContext();
+ if ( context.isDefined(symJavaScriptFunctions) || context.isDefined(symJavaScriptLibFile) )
+ global = create(context);
+ }
}
}
return global ;
@@ -90,7 +92,7 @@
// For now, in combination with the implementation of JSEngine,
// we keep separate Nashorn script engines.
- private Pool<JSEngine> pool = PoolSync.create(new PoolBase<JSEngine>());
+ private final Pool<JSEngine> pool = PoolSync.create(new PoolBase<JSEngine>());
private EnvJavaScript(Context context) {
this.scriptLib = context.getAsString(symJavaScriptFunctions);
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/graph/PrefixMappingMem.java b/jena-arq/src/main/java/org/apache/jena/sparql/graph/PrefixMappingMem.java
index 80c927a..67908b1 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/graph/PrefixMappingMem.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/graph/PrefixMappingMem.java
@@ -50,7 +50,7 @@
/** See notes on reverse mappings in {@link PrefixMappingBase}.
* This is a complete implementation.
* <p>
- * Test {@lcode AbstractTestPrefixMapping.testSecondPrefixDeletedUncoversPreviousMap}.
+ * Test {@code AbstractTestPrefixMapping.testSecondPrefixDeletedUncoversPreviousMap}.
*/
@Override
protected void remove(String prefix) {
diff --git a/jena-arq/src/test/java/org/apache/jena/rdf_star/TestSPARQLStarExtra.java b/jena-arq/src/test/java/org/apache/jena/rdf_star/TestSPARQLStarExtra.java
index 7e39e22..3381623 100644
--- a/jena-arq/src/test/java/org/apache/jena/rdf_star/TestSPARQLStarExtra.java
+++ b/jena-arq/src/test/java/org/apache/jena/rdf_star/TestSPARQLStarExtra.java
@@ -23,17 +23,26 @@
import org.apache.jena.riot.resultset.rw.ResultsReader;
import org.junit.Test;
-/**
- * Odds and ends for SPARQL*.
+/**
+ * Odds and ends for SPARQL*.
*/
public class TestSPARQLStarExtra {
private static String FILES = "testing/ARQ/RDF-Star/Other/";
// RDF4J format JSON results.
- // It uses "s", "p" and "o" for the RDF term results.
- @Test public void parse_alt() {
- String x = FILES+"alternate-results.srj";
+ // It uses "s", "p" and "o" for the RDF term results.
+ @Test public void parse_alt_1() {
+ String x = FILES+"alternate-results-1.srj";
+ ResultSet rs = ResultsReader.create().read(x);
+ ResultSetFormatter.consume(rs);
+ }
+
+ // Believed Stardog format JSON results.
+ // It uses "s", "p" and "o" for the RDF term results.
+ // It uses "statement" for "triple".
+ @Test public void parse_alt_2() {
+ String x = FILES+"alternate-results-2.srj";
ResultSet rs = ResultsReader.create().read(x);
ResultSetFormatter.consume(rs);
}
diff --git a/jena-arq/src/test/java/org/apache/jena/riot/TestJsonLDReader.java b/jena-arq/src/test/java/org/apache/jena/riot/TestJsonLDReader.java
index 0ac52ef..80bb6ec 100644
--- a/jena-arq/src/test/java/org/apache/jena/riot/TestJsonLDReader.java
+++ b/jena-arq/src/test/java/org/apache/jena/riot/TestJsonLDReader.java
@@ -18,57 +18,50 @@
package org.apache.jena.riot;
-import static org.junit.Assert.assertTrue;
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.github.jsonldjava.core.DocumentLoader;
+import com.github.jsonldjava.core.JsonLdOptions;
+import com.github.jsonldjava.utils.JsonUtils;
+import org.apache.jena.query.Dataset;
+import org.apache.jena.query.DatasetFactory;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.riot.lang.JsonLDReader;
+import org.apache.jena.riot.system.ErrorHandlerFactory;
+import org.apache.jena.sparql.util.Context;
+import org.apache.jena.vocabulary.RDF;
+import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
-import com.fasterxml.jackson.core.JsonGenerationException;
-import com.github.jsonldjava.utils.JsonUtils;
-
-import org.apache.jena.query.Dataset;
-import org.apache.jena.query.DatasetFactory;
-import org.apache.jena.rdf.model.Model;
-import org.apache.jena.rdf.model.ModelFactory;
-import org.apache.jena.riot.system.ErrorHandlerFactory;
-import org.apache.jena.sparql.util.Context;
-import org.apache.jena.vocabulary.RDF;
-import org.junit.Test;
+import static org.junit.Assert.assertTrue;
public class TestJsonLDReader {
@Test
- public final void simpleReadTest() {
- try {
- String jsonld = someSchemaDorOrgJsonld();
- Model m = ModelFactory.createDefaultModel();
- RDFParser.create()
- .errorHandler(ErrorHandlerFactory.errorHandlerNoLogging)
- .fromString(jsonld)
- .lang(Lang.JSONLD)
- .parse(m);
- assertJohnDoeIsOK(m);
- } catch (RiotException e) {
- // cf. org.apache.jena.riot.RiotException: loading remote context failed: http://schema.org/
- // There's a line printed anyway
- // e.printStackTrace();
- }
+ public final void simpleReadTest() throws IOException {
+ String jsonld = someSchemaDorOrgJsonld();
+ Dataset ds = jsonld2dataset(jsonld, null);
+ assertJohnDoeIsOK(ds.getDefaultModel());
}
- /** Test using the jena Context mechanism to pass the jsonld "@context" */
- @Test public final void overrideAtContextTest() throws JsonGenerationException, IOException {
+ /**
+ * Test using the jena Context mechanism to pass the jsonld "@context"
+ */
+ @Test
+ public final void overrideAtContextTest() throws JsonGenerationException, IOException {
// some jsonld using schema.org's URI as "@context"
String jsonld = someSchemaDorOrgJsonld();
// a subset of schema.org that can be used as @context for jsonld
- String jsonldContext = "{\"name\":{\"@id\":\"http://schema.org/name\"},\"Person\": {\"@id\": \"http://schema.org/Person\"}}";
+ String jsonldContext = "{\"name\":{\"@id\":\"http://schema.org/name\", \"@type\": \"http://www.w3.org/2001/XMLSchema#other\"},\"Person\": {\"@id\": \"http://schema.org/Person\"}}";
// pass the jsonldContext to the read using a jena Context
Context jenaCtx = new Context();
Object jsonldContextAsMap = JsonUtils.fromInputStream(new ByteArrayInputStream(jsonldContext.getBytes(StandardCharsets.UTF_8)));
- jenaCtx.set(RIOT.JSONLD_CONTEXT, jsonldContextAsMap);
+ jenaCtx.set(JsonLDReader.JSONLD_CONTEXT, jsonldContextAsMap);
// read the jsonld, replacing its "@context"
Dataset ds = jsonld2dataset(jsonld, jenaCtx);
@@ -77,33 +70,33 @@
assertJohnDoeIsOK(ds.getDefaultModel());
}
- /** Not really useful, but one can replace the @context by a URI: in this case, this URI is used when expanding the json
- * (letting JSON-LD java API taking care of downloading the context. */
- // well, as of this writing, it doesn't work, as we get a "loading remote context failed"
- // But it is about the replacing URI, not the replaced one, showing that the mechanism does work
- @Test public final void overrideAtContextByURITest() throws JsonGenerationException, IOException {
+ /**
+ * Not really useful, but one can replace the @context by a URI: in this case, this URI is used when expanding the json
+ * (letting JSON-LD java API taking care of downloading the context.
+ */
+ @Test
+ public final void overrideJsonLdOptionsAndContextUri() throws JsonGenerationException, IOException {
// some jsonld using a (fake) pseudo.schema.org's URI as "@context"
String jsonld = "{\"@id\":\"_:b0\",\"@type\":\"Person\",\"name\":\"John Doe\",\"@context\":\"http://pseudo.schema.org/\"}";
// a subset of schema.org that can be used as @context for jsonld
String jsonldContext = "\"http://schema.org\"";
- // pass the jsonldContext to the read using a jena Context
- Context jenaCtx = new Context();
- Object jsonldContextAsObject = JsonUtils.fromInputStream(new ByteArrayInputStream(jsonldContext.getBytes(StandardCharsets.UTF_8)));
- jenaCtx.set(RIOT.JSONLD_CONTEXT, jsonldContextAsObject);
+ JsonLdOptions options = new JsonLdOptions();
+ DocumentLoader dl = new DocumentLoader();
+ dl.addInjectedDoc("http://schema.org", String.format("{%s}", schemaOrgContext()));
+ options.setDocumentLoader(dl);
- try {
- // read the jsonld, replacing its "@context"
- Dataset ds = jsonld2dataset(jsonld, jenaCtx);
+ // pass the jsonldContext and JsonLdOptions to the read using a jena Context
+ JsonLDReadContext jenaCtx = new JsonLDReadContext();
+ jenaCtx.setJsonLDContext(jsonldContext);
+ jenaCtx.setOptions(options);
- // check ds is correct
- assertJohnDoeIsOK(ds.getDefaultModel());
- } catch (RiotException e) {
- // cf. org.apache.jena.riot.RiotException: loading remote context failed: http://schema.org/
- // There's a line printed anyway
- // e.printStackTrace();
- }
+ // read the jsonld, replacing its "@context"
+ Dataset ds = jsonld2dataset(jsonld, jenaCtx);
+
+ // check ds is correct
+ assertJohnDoeIsOK(ds.getDefaultModel());
}
//
@@ -120,25 +113,34 @@
try (InputStream in = new ByteArrayInputStream(jsonld.getBytes(StandardCharsets.UTF_8))) {
RDFParser.create()
- .source(in)
- .errorHandler(ErrorHandlerFactory.errorHandlerNoLogging)
- .lang(Lang.JSONLD)
- .context(jenaCtx)
- .parse(ds.asDatasetGraph());
+ .source(in)
+ .errorHandler(ErrorHandlerFactory.errorHandlerNoLogging)
+ .lang(Lang.JSONLD)
+ .context(jenaCtx)
+ .parse(ds.asDatasetGraph());
}
return ds;
}
- /** Example data */
+ /**
+ * Example data
+ */
private String someSchemaDorOrgJsonld() {
- return "{\"@id\":\"_:b0\",\"@type\":\"Person\",\"name\":\"John Doe\",\"@context\":\"http://schema.org/\"}";
+ return String.format("{\"@id\": \"_:b0\", \"@type\": \"Person\", \"name\": \"John Doe\", %s }", schemaOrgContext());
}
- /** Checking that the data loaded from someSchemaDorOrgJsonld into a model, is OK */
+ private String schemaOrgContext() {
+ return "\"@context\": {\"@vocab\": \"http://schema.org/\", \"name\": {\"@type\": \"http://www.w3.org/2001/XMLSchema#other\"} }";
+ }
+
+ /**
+ * Checking that the data loaded from someSchemaDorOrgJsonld into a model, is OK
+ */
private void assertJohnDoeIsOK(Model m) {
assertTrue(m.contains(null, RDF.type, m.createResource("http://schema.org/Person")));
- assertTrue(m.contains(null, m.createProperty("http://schema.org/name"), "John Doe"));
+ assertTrue(m.contains(null, m.createProperty("http://schema.org/name"),
+ m.createTypedLiteral("John Doe", "http://www.w3.org/2001/XMLSchema#other")));
}
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/core/TestSpecialGraphNames.java b/jena-arq/src/test/java/org/apache/jena/sparql/core/TestSpecialGraphNames.java
index 66c97e7..998e721 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/core/TestSpecialGraphNames.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/core/TestSpecialGraphNames.java
@@ -84,6 +84,7 @@
Op op = op("(bgp (?s ?p ?o))", mode) ;
List<Binding> results = exec(op) ;
assertEquals(5, results.size()) ;
+ @SuppressWarnings("deprecation")
Op op2 = Algebra.unionDefaultGraph(op) ;
List<Binding> results2 = exec(op2) ;
assertEquals(4, results2.size()) ;
diff --git a/jena-arq/testing/ARQ/RDF-Star/Other/README b/jena-arq/testing/ARQ/RDF-Star/Other/README
new file mode 100644
index 0000000..218fb62
--- /dev/null
+++ b/jena-arq/testing/ARQ/RDF-Star/Other/README
@@ -0,0 +1,4 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+SPARQL* JSON Result forms from other systems.
+ARQ can read these variations.
diff --git a/jena-arq/testing/ARQ/RDF-Star/Other/alternate-results.srj b/jena-arq/testing/ARQ/RDF-Star/Other/alternate-results-1.srj
similarity index 100%
rename from jena-arq/testing/ARQ/RDF-Star/Other/alternate-results.srj
rename to jena-arq/testing/ARQ/RDF-Star/Other/alternate-results-1.srj
diff --git a/jena-arq/testing/ARQ/RDF-Star/Other/alternate-results-2.srj b/jena-arq/testing/ARQ/RDF-Star/Other/alternate-results-2.srj
new file mode 100644
index 0000000..f7affa9
--- /dev/null
+++ b/jena-arq/testing/ARQ/RDF-Star/Other/alternate-results-2.srj
@@ -0,0 +1,41 @@
+{
+ "head" : {
+ "vars" : [
+ "a",
+ "b",
+ "c"
+ ]
+ },
+ "results" : {
+ "bindings": [
+ { "a" : {
+ "type" : "statement",
+ "value" : {
+ "s" : {
+ "type" : "uri",
+ "value" : "http://example.org/bob"
+ },
+ "p" : {
+ "type" : "uri",
+ "value" : "http://xmlns.com/foaf/0.1/name"
+ },
+ "o" : {
+ "datatype" : "http://www.w3.org/2001/XMLSchema#integer",
+ "type" : "literal",
+ "value" : "23"
+ }
+ }
+ },
+ "b": {
+ "type": "uri",
+ "value": "http://example.org/certainty"
+ },
+ "c" : {
+ "datatype" : "http://www.w3.org/2001/XMLSchema#decimal",
+ "type" : "literal",
+ "value" : "0.9"
+ }
+ }
+ ]
+ }
+}
diff --git a/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/data4.ttl b/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/data4.ttl
new file mode 100644
index 0000000..ca7eae0
--- /dev/null
+++ b/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/data4.ttl
@@ -0,0 +1,12 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX : <http://example/>
+
+# One triple with base triple.
+:s :p :o .
+<<:s :p :o>> :q 123 .
+
+# One triple term without base triple.
+<<:x :p :z>> :q 456 .
diff --git a/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/manifest.ttl b/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/manifest.ttl
index e9eb664..03bd9a1 100644
--- a/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/manifest.ttl
+++ b/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/manifest.ttl
@@ -49,6 +49,9 @@
:sparql-star-pattern-6
:sparql-star-pattern-7
:sparql-star-pattern-8
+ :sparql-star-pattern-9
+
+ :sparql-star-pattern-arq-1
:sparql-star-find-1
@@ -236,6 +239,24 @@
mf:result <sparql-star-pattern-09.srj>
.
+## SPARQL* : ARQ specific.
+
+:sparql-star-pattern-arq-1
+ mf:name "SPARQL* - Base triple in data: ground triple term in query" ;
+ mf:action
+ [ qt:query <sparql-star-pattern-arq-01.arq> ;
+ qt:data <data4.ttl> ] ;
+ mf:result <sparql-star-pattern-arq-01.srj>
+.
+
+:sparql-star-pattern-arq-1
+ mf:name "SPARQL* - Base triple in data: pattern triple term in query" ;
+ mf:action
+ [ qt:query <sparql-star-pattern-arq-01.arq> ;
+ qt:data <data4.ttl> ] ;
+ mf:result <sparql-star-pattern-arq-01.srj>
+.
+
## SPARQL FIND*
:sparql-star-find-1
diff --git a/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/sparql-star-pattern-arq-01.arq b/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/sparql-star-pattern-arq-01.arq
new file mode 100644
index 0000000..b774c51
--- /dev/null
+++ b/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/sparql-star-pattern-arq-01.arq
@@ -0,0 +1,9 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX : <http://example/>
+
+SELECT * {
+ <<:x :p :z>> :q 456 .
+}
diff --git a/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/sparql-star-pattern-arq-01.srj b/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/sparql-star-pattern-arq-01.srj
new file mode 100644
index 0000000..3edf012
--- /dev/null
+++ b/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/sparql-star-pattern-arq-01.srj
@@ -0,0 +1,9 @@
+{ "head": {
+ "vars": [ ]
+ } ,
+ "results": {
+ "bindings": [
+
+ ]
+ }
+}
diff --git a/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/sparql-star-pattern-arq-02.arq b/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/sparql-star-pattern-arq-02.arq
new file mode 100644
index 0000000..3cb9af9
--- /dev/null
+++ b/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/sparql-star-pattern-arq-02.arq
@@ -0,0 +1,11 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX : <http://example/>
+
+SELECT * {
+ { <<:s :p ?o1 >> :q ?v1 . }
+ UNION
+ { <<:x :p ?o2 >> :q ?v2 . }
+}
diff --git a/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/sparql-star-pattern-arq-02.srj b/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/sparql-star-pattern-arq-02.srj
new file mode 100644
index 0000000..de25bbe
--- /dev/null
+++ b/jena-arq/testing/ARQ/RDF-Star/SPARQL-Star/sparql-star-pattern-arq-02.srj
@@ -0,0 +1,12 @@
+{ "head": {
+ "vars": [ "o1" , "v1" , "o2" , "v2" ]
+ } ,
+ "results": {
+ "bindings": [
+ {
+ "o1": { "type": "uri" , "value": "http://example/o" } ,
+ "v1": { "type": "literal" , "datatype": "http://www.w3.org/2001/XMLSchema#integer" , "value": "123" }
+ }
+ ]
+ }
+}
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/CollectionUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/CollectionUtils.java
index 9cbf807..7f63718 100644
--- a/jena-base/src/main/java/org/apache/jena/atlas/lib/CollectionUtils.java
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/CollectionUtils.java
@@ -19,18 +19,23 @@
package org.apache.jena.atlas.lib;
import java.util.Collection ;
+import java.util.List;
import org.apache.jena.atlas.iterator.Iter;
public class CollectionUtils
-{
- /** Test for same elements, regardless of cardinality */
+{
+ /** Test for same elements, regardless of cardinality */
public static <T> boolean sameElts(Collection<T> left, Collection<T> right) {
return right.containsAll(left) && left.containsAll(right) ;
}
- /** Return an element from a collection. */
+ /** Return an element from a collection. */
public static <T> T oneElt(Collection<T> collection) {
+ if ( collection == null || collection.isEmpty() )
+ return null;
+ if ( collection instanceof List<?> )
+ return ((List<T>)collection).get(0);
return Iter.first(collection.iterator());
}
}
diff --git a/jena-cmds/src/main/java/arq/cmdline/ModQueryIn.java b/jena-cmds/src/main/java/arq/cmdline/ModQueryIn.java
index 26e41e3..4ddaf12 100644
--- a/jena-cmds/src/main/java/arq/cmdline/ModQueryIn.java
+++ b/jena-cmds/src/main/java/arq/cmdline/ModQueryIn.java
@@ -20,17 +20,12 @@
import java.io.IOException ;
-import jena.cmd.ArgDecl;
-import jena.cmd.CmdArgModule;
-import jena.cmd.CmdException;
-import jena.cmd.CmdGeneral;
-import jena.cmd.ModBase;
-import jena.cmd.TerminationException;
-
+import jena.cmd.*;
import org.apache.jena.query.Query ;
import org.apache.jena.query.QueryFactory ;
import org.apache.jena.query.Syntax ;
import org.apache.jena.shared.JenaException ;
+import org.apache.jena.shared.NotFoundException;
import org.apache.jena.sparql.ARQInternalErrorException ;
import org.apache.jena.util.FileUtils ;
@@ -127,8 +122,12 @@
throw new CmdException("Error reading stdin", ex) ;
}
} else {
- query = QueryFactory.read(queryFilename, baseURI, getQuerySyntax()) ;
- return query ;
+ try {
+ query = QueryFactory.read(queryFilename, baseURI, getQuerySyntax()) ;
+ return query ;
+ } catch (NotFoundException ex) {
+ throw new JenaException("Failed to load Query: "+ex.getMessage());
+ }
}
}
diff --git a/jena-cmds/src/main/java/arq/query.java b/jena-cmds/src/main/java/arq/query.java
index 898513d..67562d7 100644
--- a/jena-cmds/src/main/java/arq/query.java
+++ b/jena-cmds/src/main/java/arq/query.java
@@ -30,6 +30,7 @@
import org.apache.jena.riot.RiotNotFoundException ;
import org.apache.jena.riot.SysRIOT ;
import org.apache.jena.shared.JenaException ;
+import org.apache.jena.shared.NotFoundException;
import org.apache.jena.sparql.ARQInternalErrorException ;
import org.apache.jena.sparql.core.Transactional ;
import org.apache.jena.sparql.core.TransactionalNull;
@@ -45,10 +46,10 @@
private ArgDecl argExplain = new ArgDecl(ArgDecl.NoValue, "explain") ;
private ArgDecl argOptimize = new ArgDecl(ArgDecl.HasValue, "opt", "optimize") ;
- protected int repeatCount = 1 ;
+ protected int repeatCount = 1 ;
protected int warmupCount = 0 ;
protected boolean queryOptimization = true ;
-
+
protected ModTime modTime = new ModTime() ;
protected ModQueryIn modQuery = null;
protected ModDataset modDataset = null ;
@@ -63,7 +64,7 @@
public query(String[] argv)
{
super(argv) ;
- modQuery = new ModQueryIn(getDefaultSyntax()) ;
+ modQuery = new ModQueryIn(getDefaultSyntax()) ;
modDataset = setModDataset() ;
super.addModule(modQuery) ;
@@ -86,7 +87,7 @@
* <li>Command default</li>
* <li>System default</li>
* </ul>
- *
+ *
*/
protected Syntax getDefaultSyntax() { return Syntax.defaultQuerySyntax ; }
@@ -97,7 +98,7 @@
if ( contains(argRepeat) )
{
String[] x = getValue(argRepeat).split(",") ;
- if ( x.length == 1 )
+ if ( x.length == 1 )
{
try { repeatCount = Integer.parseInt(x[0]) ; }
catch (NumberFormatException ex)
@@ -115,26 +116,26 @@
}
if ( isVerbose() )
ARQ.getContext().setTrue(ARQ.symLogExec) ;
-
+
if ( hasArg(argExplain) )
ARQ.setExecutionLogging(Explain.InfoLevel.ALL) ;
-
+
if ( hasArg(argOptimize) )
{
String x1 = getValue(argOptimize) ;
- if ( hasValueOfTrue(argOptimize) || x1.equalsIgnoreCase("on") || x1.equalsIgnoreCase("yes") )
+ if ( hasValueOfTrue(argOptimize) || x1.equalsIgnoreCase("on") || x1.equalsIgnoreCase("yes") )
queryOptimization = true ;
else if ( hasValueOfFalse(argOptimize) || x1.equalsIgnoreCase("off") || x1.equalsIgnoreCase("no") )
queryOptimization = false ;
else throw new CmdException("Optimization flag must be true/false/on/off/yes/no. Found: "+getValue(argOptimize)) ;
}
}
-
+
protected ModDataset setModDataset()
{
return new ModDatasetGeneralAssembler() ;
}
-
+
@Override
protected void exec()
{
@@ -142,16 +143,16 @@
ARQ.getContext().setFalse(ARQ.optimization) ;
if ( cmdStrictMode )
ARQ.getContext().setFalse(ARQ.optimization) ;
-
+
// Warm up.
for ( int i = 0 ; i < warmupCount ; i++ )
{
queryExec(false, ResultsFormat.FMT_NONE) ;
}
-
+
for ( int i = 0 ; i < repeatCount ; i++ )
queryExec(modTime.timingEnabled(), modResults.getResultsFormat()) ;
-
+
if ( modTime.timingEnabled() && repeatCount > 1 )
{
long avg = totalTime/repeatCount ;
@@ -162,16 +163,16 @@
@Override
protected String getCommandName() { return Lib.className(this) ; }
-
+
@Override
protected String getSummary() { return getCommandName()+" --data=<file> --query=<query>" ; }
-
+
/** Choose the dataset.
* <li> use the data as described on the command line
* <li> else use FROM/FROM NAMED if present (pass null to ARQ)
* <li> else provided an empty dataset and hope the query has VALUES/BIND
*/
- protected Dataset getDataset(Query query) {
+ protected Dataset getDataset(Query query) {
try {
Dataset ds = modDataset.getDataset();
if ( ds == null )
@@ -187,20 +188,29 @@
throw new TerminationException(1);
}
}
-
- // Policy for no command line dataset. null means "whatever" (use FROM)
+
+ protected Query getQuery() {
+ try {
+ return modQuery.getQuery() ;
+ } catch (NotFoundException ex) {
+ System.err.println("Failed to load query: "+ex.getMessage());
+ throw new TerminationException(1);
+ }
+ }
+
+ // Policy for no command line dataset. null means "whatever" (use FROM)
protected Dataset dealWithNoDataset(Query query) {
if ( query.hasDatasetDescription() )
return null;
return DatasetFactory.createTxnMem();
- //throw new CmdException("No dataset provided") ;
+ //throw new CmdException("No dataset provided") ;
}
-
+
protected long totalTime = 0 ;
protected void queryExec(boolean timed, ResultsFormat fmt)
{
try {
- Query query = modQuery.getQuery() ;
+ Query query = getQuery() ;
if ( isVerbose() ) {
IndentedWriter out = new IndentedWriter(System.err, true);
query.serialize(out);
@@ -208,7 +218,7 @@
out.println();
out.flush();
}
-
+
if ( isQuiet() )
LogCtl.setError(SysRIOT.riotLoggerName) ;
Dataset dataset = getDataset(query) ;
diff --git a/jena-core/src/main/java/org/apache/jena/assembler/JA.java b/jena-core/src/main/java/org/apache/jena/assembler/JA.java
index 3e65085..5e6947f 100644
--- a/jena-core/src/main/java/org/apache/jena/assembler/JA.java
+++ b/jena-core/src/main/java/org/apache/jena/assembler/JA.java
@@ -82,13 +82,13 @@
public static final Property data = property( "data" );
public static final Property content = property( "content" );
-
+
public static final Property context = property( "context" );
public static final Property cxtName = property( "cxtName" );
public static final Property cxtValue = property( "cxtValue" );
-
+
public static final Resource ExternalContent = resource( "ExternalContent" );
public static final Property externalContent = property( "externalContent" );
diff --git a/jena-core/src/main/java/org/apache/jena/graph/impl/LiteralLabelImpl.java b/jena-core/src/main/java/org/apache/jena/graph/impl/LiteralLabelImpl.java
index bc5423c..cfbb262 100644
--- a/jena-core/src/main/java/org/apache/jena/graph/impl/LiteralLabelImpl.java
+++ b/jena-core/src/main/java/org/apache/jena/graph/impl/LiteralLabelImpl.java
@@ -18,6 +18,7 @@
package org.apache.jena.graph.impl;
+import java.util.Arrays;
import java.util.Locale ;
import java.util.Objects ;
@@ -303,20 +304,64 @@
return lexicalForm;
}
- /**
- Answer the value used to index this literal
- TODO Consider pushing indexing decisions down to the datatype
- */
+ /**
+ * Answer an object used to index this literal. This object must provide
+ * {@link Object#equals} and {@link Object#hashCode} based on values, not object
+ * instance identity.
+ */
@Override
public Object getIndexingValue() {
- return
- isXML() ? this
- : !lang.equals( "" ) ? getLexicalForm() + "@" + lang.toLowerCase(Locale.ROOT)
- : wellformed ? getValue()
- : getLexicalForm()
- ;
+ if ( isXML() )
+ return this;
+ if ( !lang.equals("") )
+ return getLexicalForm() + "@" + lang.toLowerCase(Locale.ROOT);
+ if ( wellformed ) {
+ Object value = getValue();
+ // JENA-1936
+ // byte[] does not provide hashCode/equals based on the contents of the array.
+ if ( value instanceof byte[] )
+ return new ByteArray((byte[])value);
+ return value;
+ }
+ return getLexicalForm();
}
+ /**
+ * {@code byte[]} wrapper that provides {@code hashCode} and {@code equals} based
+ * on the value of the array. This assumes the {@code byte[]} is not changed
+ * (which is the case for literals with binary value).
+ */
+ static class ByteArray {
+ private int hashCode = 0 ;
+
+ private final byte[] bytes;
+ /*package*/ ByteArray(byte[] bytes) {
+ this.bytes = bytes;
+ }
+
+ @Override
+ public int hashCode() {
+ if ( hashCode == 0 ) {
+ final int prime = 31;
+ int result = 1;
+ hashCode = prime * result + Arrays.hashCode(bytes);
+ }
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ ByteArray other = (ByteArray)obj;
+ return Arrays.equals(bytes, other.bytes);
+ }
+ }
+
/**
Answer the language associated with this literal (the empty string if
there's no language).
diff --git a/jena-core/src/test/java/org/apache/jena/graph/test/TestNode.java b/jena-core/src/test/java/org/apache/jena/graph/test/TestNode.java
index 1d2907f..53ea93a 100644
--- a/jena-core/src/test/java/org/apache/jena/graph/test/TestNode.java
+++ b/jena-core/src/test/java/org/apache/jena/graph/test/TestNode.java
@@ -22,6 +22,7 @@
import junit.framework.TestSuite ;
import org.apache.jena.JenaRuntime ;
+import org.apache.jena.atlas.lib.Creator;
import org.apache.jena.datatypes.RDFDatatype ;
import org.apache.jena.datatypes.TypeMapper ;
import org.apache.jena.datatypes.xsd.XSDDatatype ;
@@ -606,17 +607,40 @@
}
public void testGetIndexingValuePlainString()
- { testIndexingValueLiteral( NodeCreateUtils.create( "'literally'" ) ); }
+ { testIndexingValueLiteral( ()->NodeCreateUtils.create( "'literally'" ) ); }
public void testGetIndexingValueLanguagedString()
- { testIndexingValueLiteral( NodeCreateUtils.create( "'chat'fr" ) ); }
+ { testIndexingValueLiteral( ()->NodeCreateUtils.create( "'chat'fr" ) ); }
public void testGetIndexingValueXSDString()
- { testIndexingValueLiteral( NodeCreateUtils.create( "'string'xsd:string" ) ); }
+ { testIndexingValueLiteral( ()->NodeCreateUtils.create( "'string'xsd:string" ) ); }
- private void testIndexingValueLiteral( Node s )
- { assertEquals( s.getLiteral().getIndexingValue(), s.getIndexingValue() ); }
+ // JENA-1936
+ public void testGetIndexingValueHexBinary1()
+ { testIndexingValueLiteral( ()->NodeCreateUtils.create( "''xsd:hexBinary" ) ); }
+ public void testGetIndexingValueHexBinary2()
+ { testIndexingValueLiteral( ()->NodeCreateUtils.create( "'ABCD'xsd:hexBinary" ) ); }
+
+ public void testGetIndexingValueBase64Binary1()
+ { testIndexingValueLiteral( ()->NodeCreateUtils.create( "''xsd:base64Binary" ) ); }
+
+ // "sure." encodes to "c3VyZS4="
+ public void testGetIndexingValueBase64Binary2()
+ { testIndexingValueLiteral( ()->NodeCreateUtils.create( "'c3VyZS4='xsd:base64Binary" ) ); }
+
+ private void testIndexingValueLiteral( Creator<Node> creator) {
+ Node n1 = creator.create();
+ Node n2 = creator.create();
+ testIndexingValueLiteral(n1,n2);
+ }
+
+ private void testIndexingValueLiteral(Node n1, Node n2) {
+ assertNotSame(n1, n2); // Test the test.
+ assertEquals(n1.getLiteral().getIndexingValue(), n2.getIndexingValue());
+ assertEquals(n1.getLiteral().getIndexingValue().hashCode(), n2.getIndexingValue().hashCode());
+ }
+
public void testGetLiteralValuePlainString()
{
Node s = NodeCreateUtils.create( "'aString'" );
diff --git a/jena-core/src/test/java/org/apache/jena/graph/test/TestNodeExt.java b/jena-core/src/test/java/org/apache/jena/graph/test/TestNodeExt.java
index 3698475..ac1e0d2 100644
--- a/jena-core/src/test/java/org/apache/jena/graph/test/TestNodeExt.java
+++ b/jena-core/src/test/java/org/apache/jena/graph/test/TestNodeExt.java
@@ -35,8 +35,12 @@
private static Triple triple9 = Triple.create(NodeFactory.createBlankNode(),p,o);
- @Test public void ext_triple_1() {
- Node_Triple nt = new Node_Triple(s,p,o);
+ private static Node_Triple newTripleTerm(Triple triple) { return new Node_Triple(triple); }
+
+ private static Node_Triple newTripleTerm(Node s, Node p , Node o) { return new Node_Triple(s,p,o); }
+
+ @Test public void ext_triple_1() {
+ Node_Triple nt = newTripleTerm(s,p,o);
assertNotNull(nt.get());
assertNotNull(Node_Triple.tripleOrNull(nt));
assertNotNull(Node_Triple.triple(nt));
@@ -48,8 +52,8 @@
}
@Test public void ext_triple_2() {
- Node_Triple nt1 = new Node_Triple(s,p,o);
- Node_Triple nt2 = new Node_Triple(s,p,o);
+ Node_Triple nt1 = newTripleTerm(s,p,o);
+ Node_Triple nt2 = newTripleTerm(s,p,o);
assertEquals(nt1, nt2);
assertEquals(nt1.hashCode(), nt2.hashCode());
@@ -57,8 +61,8 @@
}
@Test public void ext_triple_3() {
- Node_Triple nt1 = new Node_Triple(triple1);
- Node_Triple nt2 = new Node_Triple(triple2);
+ Node_Triple nt1 = newTripleTerm(triple1);
+ Node_Triple nt2 = newTripleTerm(triple2);
assertNotSame(nt1.get(), nt2.get());
assertNotSame(nt1, nt2);
assertEquals(nt1, nt2);
@@ -66,8 +70,8 @@
}
@Test public void ext_triple_4() {
- Node_Triple nt1 = new Node_Triple(triple1);
- Node_Triple nt9 = new Node_Triple(triple9);
+ Node_Triple nt1 = newTripleTerm(triple1);
+ Node_Triple nt9 = newTripleTerm(triple9);
assertNotSame(nt1.get(), nt9.get());
assertNotSame(nt1, nt9);
assertNotEquals(nt1, nt9);
@@ -90,6 +94,4 @@
Node n = NodeFactory.createLiteral("abc");
Node_Triple.triple(n);
}
-
-
}
diff --git a/jena-core/src/test/java/org/apache/jena/graph/test/TestTypedLiterals.java b/jena-core/src/test/java/org/apache/jena/graph/test/TestTypedLiterals.java
index 91350c3..a81cc33 100644
--- a/jena-core/src/test/java/org/apache/jena/graph/test/TestTypedLiterals.java
+++ b/jena-core/src/test/java/org/apache/jena/graph/test/TestTypedLiterals.java
@@ -954,6 +954,42 @@
Literal l = m.createTypedLiteral(data, XSDDatatype.XSDhexBinary);
assertEquals("hexBinary encoding", "0FB7", l.getLexicalForm());
}
+
+ public void testBinaryIndexing1() {
+ Literal x1 = m.createTypedLiteral("", XSDDatatype.XSDbase64Binary);
+ Literal x2 = m.createTypedLiteral("", XSDDatatype.XSDbase64Binary);
+ assertEquals("base64Binary indexing hashCode",
+ x1.asNode().getIndexingValue().hashCode(),
+ x2.asNode().getIndexingValue().hashCode());
+ assertEquals("base64Binary indexing", x1.asNode().getIndexingValue(), x2.asNode().getIndexingValue());
+ }
+
+ public void testBinaryIndexing2() {
+ Literal x1 = m.createTypedLiteral("GpM7", XSDDatatype.XSDbase64Binary);
+ Literal x2 = m.createTypedLiteral("GpM7", XSDDatatype.XSDbase64Binary);
+ assertEquals("base64Binary indexing hashCode",
+ x1.asNode().getIndexingValue().hashCode(),
+ x2.asNode().getIndexingValue().hashCode());
+ assertEquals("base64Binary indexing", x1.asNode().getIndexingValue(), x2.asNode().getIndexingValue());
+ }
+
+ public void testBinaryIndexing3() {
+ Literal x1 = m.createTypedLiteral("", XSDDatatype.XSDhexBinary);
+ Literal x2 = m.createTypedLiteral("", XSDDatatype.XSDhexBinary);
+ assertEquals("hexBinary indexing hashCode",
+ x1.asNode().getIndexingValue().hashCode(),
+ x2.asNode().getIndexingValue().hashCode());
+ assertEquals("hexBinary indexing", x1.asNode().getIndexingValue(), x2.asNode().getIndexingValue());
+ }
+
+ public void testBinaryIndexing4() {
+ Literal x1 = m.createTypedLiteral("AABB", XSDDatatype.XSDhexBinary);
+ Literal x2 = m.createTypedLiteral("AABB", XSDDatatype.XSDhexBinary);
+ assertEquals("hexBinary indexing hashCode",
+ x1.asNode().getIndexingValue().hashCode(),
+ x2.asNode().getIndexingValue().hashCode());
+ assertEquals("hexBinary indexing", x1.asNode().getIndexingValue(), x2.asNode().getIndexingValue());
+ }
/** Test that XSD anyURI is not sameValueAs XSD string (Xerces returns a string as the value for both) */
public void testXSDanyURI() {
diff --git a/jena-db/jena-dboe-storage/src/main/java/org/apache/jena/dboe/storage/prefixes/PrefixMapI.java b/jena-db/jena-dboe-storage/src/main/java/org/apache/jena/dboe/storage/prefixes/PrefixMapI.java
index 30ea998..1a71853 100644
--- a/jena-db/jena-dboe-storage/src/main/java/org/apache/jena/dboe/storage/prefixes/PrefixMapI.java
+++ b/jena-db/jena-dboe-storage/src/main/java/org/apache/jena/dboe/storage/prefixes/PrefixMapI.java
@@ -36,7 +36,7 @@
* The contract does not require an implementation to do any validation unlike the
* Jena Core {@link PrefixMapping} which requires validation of prefixes.
* </p>
- *
+ *
* @implNote The package {@code org.apache.jena.dboe.storage.prefixes} in module
* {@code jena-dboe-storage} provides implementations that work with
* {@code StoragePrefixes} which is dataset provision of prefixes on per-named
@@ -68,7 +68,7 @@
public default void putAll(PrefixMap pmap) {
pmap.forEach(this::add);
}
-
+
@Override
public default void putAll(PrefixMapping pmap) {
pmap.getNsPrefixMap().forEach(this::add);
diff --git a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/SolverRX.java b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/SolverRX.java
index f43d2aa..37a30f6 100644
--- a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/SolverRX.java
+++ b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/SolverRX.java
@@ -69,7 +69,7 @@
VarAlloc varAlloc = VarAlloc.get(context, ARQConstants.sysVarAllocRDFStar);
if ( varAlloc == null ) {
varAlloc = new VarAlloc(ARQConstants.allocVarTripleTerm);
- context.set(ARQConstants.sysVarAllocRDFStar, varAlloc);
+ context.set(ARQConstants.sysVarAllocRDFStar, varAlloc);
}
return varAlloc;
}
@@ -80,7 +80,7 @@
ExecutionContext execCxt) {
if ( ! tripleHasNodeTriple(pattern) )
SolverLib.solve(nodeTupleTable, pattern, anyGraph, chain, filter, execCxt);
-
+
Args args = new Args(nodeTupleTable, anyGraph, filter, execCxt);
return rdfStarTriple(chain, pattern, args);
}
@@ -92,7 +92,7 @@
* within {@link #rdfStarTriple} for nested triple term and a temporary allocated
* variable as well can for {@code FIND(<<...>> AS ?t)}.
*
- * @implNote
+ * @implNote
* Without RDF*, this would be a plain call of {@link #matchData} which
* is simply a call to {@link SolverLib#solve}.
*/
@@ -148,7 +148,7 @@
Node subject1 = null;
Node object1 = null;
- if ( subject.isNodeTriple() && ! subject.isConcrete() ) {
+ if ( subject.isNodeTriple() ) {
Triple tripleTerm = triple(subject);
Var var = args.varAlloc.allocVar();
patternTuple = createTuple(patternTuple, var, sIdx);
@@ -157,7 +157,7 @@
subject1 = var;
}
- if ( object.isNodeTriple() && ! object.isConcrete() ) {
+ if ( object.isNodeTriple() ) {
Triple tripleTerm = triple(object);
Var var = args.varAlloc.allocVar();
patternTuple = createTuple(patternTuple, var, oIdx);
@@ -221,7 +221,7 @@
return binding;
return null;
}
-
+
BindingNodeId b2 = new BindingNodeId(binding);
b2.put(var, tid);
return b2;
@@ -305,11 +305,11 @@
private static Tuple<Node> tuple(Tuple<Node> base, Triple triple) {
switch(base.len()){
- case 3:
- return TupleFactory.create3(triple.getSubject(), triple.getPredicate(), triple.getObject());
+ case 3:
+ return TupleFactory.create3(triple.getSubject(), triple.getPredicate(), triple.getObject());
case 4:
return TupleFactory.create4(base.get(0), triple.getSubject(), triple.getPredicate(), triple.getObject());
default:
- } throw new TDBException("Tuple not of length 3 or 4");
+ } throw new TDBException("Tuple not of length 3 or 4");
}
}
\ No newline at end of file
diff --git a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/nodetable/NodeTableInline.java b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/nodetable/NodeTableInline.java
index f7d7671..8c7fe0f 100644
--- a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/nodetable/NodeTableInline.java
+++ b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/nodetable/NodeTableInline.java
@@ -18,7 +18,6 @@
package org.apache.jena.tdb2.store.nodetable;
-
import org.apache.jena.graph.Node;
import org.apache.jena.tdb2.store.NodeId;
diff --git a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/StoreConnection.java b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/StoreConnection.java
index cb38cd2..249b2bc 100644
--- a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/StoreConnection.java
+++ b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/StoreConnection.java
@@ -82,7 +82,7 @@
if ( sConn == null ) {
ProcessFileLock lock = null;
// This is not duplicating DatabaseConnection.build.
- // This is a tdb.lock file in the storage database, not the switchable.
+ // This is a tdb.lock file in the storage database, not the switchable.
if (SystemTDB.DiskLocationMultiJvmUsagePrevention && ! location.isMem() ) {
lock = lockForLocation(location);
// Take the lock. This is atomic and non-reentrant.
diff --git a/jena-db/jena-tdb2/src/test/java/org/apache/jena/tdb2/sys/TestDatabaseOps.java b/jena-db/jena-tdb2/src/test/java/org/apache/jena/tdb2/sys/TestDatabaseOps.java
index 91c6bb7..0e7760b 100644
--- a/jena-db/jena-tdb2/src/test/java/org/apache/jena/tdb2/sys/TestDatabaseOps.java
+++ b/jena-db/jena-tdb2/src/test/java/org/apache/jena/tdb2/sys/TestDatabaseOps.java
@@ -126,11 +126,19 @@
@Test public void compact_prefixes_3() {
// 2020-04:
- // This test fails at "HERE" sometimes with an NPE at the marked line when run with Java14 on ASF Jenkins.
+ // This test fails at "HERE" in the test, with an NPEwith Java14 on ASF Jenkins.
+ // java.lang.NullPointerException
+ // at java.base/java.nio.file.Files.provider(Files.java:105)
+ // at java.base/java.nio.file.Files.isDirectory(Files.java:2308)
+ // at org.apache.jena.tdb2.sys.IOX.asLocation(IOX.java:151)
+ // at org.apache.jena.tdb2.sys.DatabaseOps.compact(DatabaseOps.java:176)
+ // at org.apache.jena.tdb2.DatabaseMgr.compact(DatabaseMgr.java:62)
+ // at org.apache.jena.tdb2.sys.TestDatabaseOps.compact_prefixes_3_test(TestDatabaseOps.java:157)
+ // at org.apache.jena.tdb2.sys.TestDatabaseOps.compact_prefixes_3(TestDatabaseOps.java:135)
+ // (and now JDK15).
// The NPE is from java.nio.file.Files.provider.
- // It does not fail anywhere else and it does not always fail.
- // This suggests it is an environmental issue with the JDK14 job.
- // Attempt to find out what is going on:
+ // It does not fail anywhere else ecept at ASF and it does not always fail.
+ // This seems to be on specific, maybe just on, Jenkins build node.
try {
compact_prefixes_3_test();
} catch (Throwable th) {
diff --git a/jena-fuseki2/examples/README.md b/jena-fuseki2/examples/README.md
new file mode 100644
index 0000000..197a368
--- /dev/null
+++ b/jena-fuseki2/examples/README.md
@@ -0,0 +1,55 @@
+---
+title: Fuseki: Configuration file examples.
+---
+
+This directory includes some examples - they will need to be adapted to
+local requirements.
+
+_Configuration: Named services_
+
+* [config-1-mem.ttl](config-1-mem.ttl)
+* [config-2-mem-old.ttl](config-2-mem-old.ttl)
+
+_Configuration: Unnamed services_
+
+* [config-3-dataset-endpoints.ttl](config-3-dataset-endpoints.ttl)
+
+_Single endpoint "sparql" with multiple operations
+
+* [config-4-endpoint-sparql.ttl](config-4-endpoint-sparql.ttl)
+
+_TDB examples_
+
+* [config-tdb1.ttl](config-tdb1.ttl)
+* [config-tdb2.ttl](config-tdb2.ttl)
+
+TDB with text index:
+
+* [config-text-tdb2.ttl](config-text-tdb2.ttl)
+
+Selecting one graph from a TDB dataset
+
+tdb2-select-graphs-alt.ttl
+tdb2-select-graphs.ttl
+
+_SHACL service_
+
+* [config-shacl.ttl](config-shacl.ttl)
+
+_Query timeout_
+
+* [config-timeout-dataset.ttl](config-timeout-dataset.ttl)
+* [config-timeout-endpoint.ttl](config-timeout-endpoint.ttl)
+* [config-timeout-server.ttl](config-timeout-server.ttl)
+
+_Inference examples_
+
+* [config-inference-1.ttl](config-inference-1.ttl)
+* [config-inference-2.ttl](config-inference-2.ttl)
+
+_Eclipse Jetty HTTPs setup._
+
+A Jetty XML configuration file for running Jetty with HTTPS.
+This file will require configuration and also installing a certificate
+
+* [fuseki-jetty-https.xml](fuseki-jetty-https.xml)
diff --git a/jena-fuseki2/examples/config-1-mem.ttl b/jena-fuseki2/examples/config-1-mem.ttl
new file mode 100644
index 0000000..84fa0d4
--- /dev/null
+++ b/jena-fuseki2/examples/config-1-mem.ttl
@@ -0,0 +1,54 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ :service
+ ) .
+
+## Service description for "/dataset" with all endpoints.
+## e.g.
+## GET /dataset/query?query=...
+## GET /dataset/get?default (SPARQL Graph Store Protocol)
+
+:service rdf:type fuseki:Service ;
+ fuseki:name "dataset" ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "sparql"
+ ];
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "query"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:update ;
+ fuseki:name "update"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-r ;
+ fuseki:name "get"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-rw ;
+ fuseki:name "data"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:upload ;
+ fuseki:name "upload"
+ ] ;
+ fuseki:dataset :dataset ;
+ .
+
+# Transactional in-memory dataset.
+:dataset rdf:type ja:MemoryDataset ;
+ ## Optional load with data on start-up
+ ## ja:data "data1.trig";
+ ## ja:data "data2.trig";
+ .
+
diff --git a/jena-fuseki2/examples/config-2-mem-old.ttl b/jena-fuseki2/examples/config-2-mem-old.ttl
new file mode 100644
index 0000000..971d345
--- /dev/null
+++ b/jena-fuseki2/examples/config-2-mem-old.ttl
@@ -0,0 +1,32 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ :service
+ ) .
+
+## Service description for "/dataset" with all endpoints.
+## Example of old, less flexible, syntax.
+
+:service rdf:type fuseki:Service;
+ fuseki:name "dataset";
+ fuseki:serviceQuery "query";
+ fuseki:serviceQuery "sparql";
+ fuseki:serviceUpdate "update";
+ fuseki:serviceUpload "upload" ;
+ fuseki:serviceReadWriteGraphStore "data" ;
+ fuseki:serviceReadGraphStore "get" ;
+ fuseki:dataset :dataset ;
+ .
+
+# Transactional in-memory dataset.
+:dataset rdf:type ja:MemoryDataset ;
+ ## Optional load with data on start-up
+ ## ja:data "data.trig";
+ .
diff --git a/jena-fuseki2/examples/config-3-dataset-endpoints.ttl b/jena-fuseki2/examples/config-3-dataset-endpoints.ttl
new file mode 100644
index 0000000..50c5462
--- /dev/null
+++ b/jena-fuseki2/examples/config-3-dataset-endpoints.ttl
@@ -0,0 +1,34 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ :service
+ ) .
+
+## Service description for "/dataset" with all endpoints.
+## Operations are on the dataset e.g. /dataset?query=
+
+
+:service rdf:type fuseki:Service ;
+ fuseki:name "dataset" ;
+## fuseki:endpoint [
+## fuseki:operation fuseki:query ;
+## fuseki:name "" # This is optional.
+## ] ;
+ fuseki:endpoint [ fuseki:operation fuseki:query ; ] ;
+ fuseki:endpoint [ fuseki:operation fuseki:update ; ] ;
+ fuseki:endpoint [ fuseki:operation fuseki:gsp-r ; ] ;
+ fuseki:endpoint [ fuseki:operation fuseki:gsp-rw ; ] ;
+ fuseki:endpoint [ fuseki:operation fuseki:upload ; ] ;
+ fuseki:dataset :dataset ;
+ .
+
+# Transactional in-memory dataset.
+:dataset rdf:type ja:MemoryDataset .
+
diff --git a/jena-fuseki2/examples/config-4-endpoint-sparql.ttl b/jena-fuseki2/examples/config-4-endpoint-sparql.ttl
new file mode 100644
index 0000000..526466c
--- /dev/null
+++ b/jena-fuseki2/examples/config-4-endpoint-sparql.ttl
@@ -0,0 +1,30 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ :service
+ ) .
+
+## Service description for "/dataset/sparql" with SPARQL query and update.
+## These can be the same fuseki:name or different.
+
+:service rdf:type fuseki:Service ;
+ fuseki:name "dataset" ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "sparql" ;
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:update ;
+ fuseki:name "sparql" ;
+ ] ;
+ fuseki:dataset :dataset ;
+ .
+
+:dataset rdf:type ja:MemoryDataset .
diff --git a/jena-fuseki2/examples/config-inference-1.ttl b/jena-fuseki2/examples/config-inference-1.ttl
new file mode 100644
index 0000000..aae05f8
--- /dev/null
+++ b/jena-fuseki2/examples/config-inference-1.ttl
@@ -0,0 +1,43 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+# Example of a data service with only SPARQL query on an
+# in-memory inference model. Data is taken from a file
+# when the data service is started.
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ :service
+ ) .
+
+# Service description for "/dataset" with all endpoints.
+:service rdf:type fuseki:Service ;
+ fuseki:name "dataset" ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "query"
+ ] ;
+ fuseki:dataset :dataset ;
+ .
+
+# Dataset with only the default graph.
+:dataset rdf:type ja:RDFDataset ;
+ ja:defaultGraph :model_inf ;
+ .
+
+# The inference model
+:model_inf a ja:InfModel ;
+ ja:baseModel :baseModel ;
+ ja:reasoner [
+ ja:reasonerURL <http://jena.hpl.hp.com/2003/OWLFBRuleReasoner>
+ ] .
+
+# The base data.
+:baseModel a ja:MemoryModel ;
+ ja:content [ja:externalContent <file:Data/data.ttl> ] ;
+ .
diff --git a/jena-fuseki2/examples/config-inference-2.ttl b/jena-fuseki2/examples/config-inference-2.ttl
new file mode 100644
index 0000000..e7436eb
--- /dev/null
+++ b/jena-fuseki2/examples/config-inference-2.ttl
@@ -0,0 +1,52 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+# Example of a data service with SPARQL query ahgrep and update on an
+# inference model. Data is taken from TDB.
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ :service
+ ) .
+
+# Service description for "/dataset" with all endpoints.
+:service rdf:type fuseki:Service ;
+ fuseki:name "dataset" ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "query"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:update ;
+ fuseki:name "update"
+ ] ;
+ fuseki:dataset :dataset ;
+ .
+
+## ---------------------------------------------------------------
+
+:dataset rdf:type ja:RDFDataset ;
+ ja:defaultGraph :model_inf ;
+ .
+
+:model_inf a ja:InfModel ;
+ ja:baseModel :tdbGraph ;
+ ja:reasoner [
+ ja:reasonerURL <http://jena.hpl.hp.com/2003/OWLFBRuleReasoner>
+ ] .
+
+:tdbGraph rdf:type tdb2:GraphTDB2 ;
+ tdb2:dataset :tdbDataset .
+
+## Base data in TDB.
+:tdbDataset rdf:type tdb2:DatasetTDB2 ;
+ tdb2:location "DB" ;
+ # If the unionDefaultGraph is used, then the "update" service should be removed.
+ # tdb:unionDefaultGraph true ;
+ .
diff --git a/jena-fuseki2/examples/config-shacl.ttl b/jena-fuseki2/examples/config-shacl.ttl
new file mode 100644
index 0000000..288db76
--- /dev/null
+++ b/jena-fuseki2/examples/config-shacl.ttl
@@ -0,0 +1,35 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ :service
+ ) .
+
+## Service description for "/dataset" with
+## a SHACL validation service on "/dataset/shacl"
+## See https://jena.apache.org/documentation/shacl/
+
+:service rdf:type fuseki:Service ;
+ fuseki:name "dataset" ;
+
+ fuseki:endpoint [ fuseki:operation fuseki:query ] ;
+
+ ## SPARQL Graph Store Protocol : PUT/POST data to /dataset.
+ fuseki:endpoint [ fuseki:operation fuseki:gsp-rw ] ;
+
+## SHACL service - see https://jena.apache.org/documentation/shacl/
+ ## /dataset/shacl
+ fuseki:endpoint [
+ fuseki:operation fuseki:shacl ;
+ fuseki:name "shacl"
+ ] ;
+ fuseki:dataset :dataset ;
+ .
+
+:dataset rdf:type ja:MemoryDataset .
diff --git a/jena-fuseki2/examples/config-tdb1.ttl b/jena-fuseki2/examples/config-tdb1.ttl
new file mode 100644
index 0000000..2dfe0cb
--- /dev/null
+++ b/jena-fuseki2/examples/config-tdb1.ttl
@@ -0,0 +1,51 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+PREFIX tdb1: <http://jena.hpl.hp.com/2008/tdb#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ :service
+ ) .
+
+## Service description for "/dataset"
+## with a TDB1 dataset
+
+:service rdf:type fuseki:Service ;
+ fuseki:name "dataset" ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "sparql"
+ ];
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "query"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:update ;
+ fuseki:name "update"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-r ;
+ fuseki:name "get"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-rw ;
+ fuseki:name "data"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:upload ;
+ fuseki:name "upload"
+ ] ;
+ fuseki:dataset :dataset ;
+ .
+
+:dataset_tdb1 rdf:type tdb1:DatasetTDB ;
+ tdb1:location "DB1" ;
+ ## Optional - with union default for query and update WHERE matching.
+ ## tdb2:unionDefaultGraph true ;
+ .
diff --git a/jena-fuseki2/examples/config-tdb2.ttl b/jena-fuseki2/examples/config-tdb2.ttl
new file mode 100644
index 0000000..98e6f10
--- /dev/null
+++ b/jena-fuseki2/examples/config-tdb2.ttl
@@ -0,0 +1,53 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ :service
+ ) .
+
+## Service description for "/dataset"
+## with a TDB2 dataset
+
+:service rdf:type fuseki:Service ;
+ fuseki:name "dataset" ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "sparql" ;
+ ## Set default-union-graph for this endpoint.
+ ja:context [ ja:cxtName "tdb:unionDefaultGraph" ; ja:cxtValue true ] ;
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "query"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:update ;
+ fuseki:name "update"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-r ;
+ fuseki:name "get"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-rw ;
+ fuseki:name "data"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:upload ;
+ fuseki:name "upload"
+ ] ;
+ fuseki:dataset :dataset_tdb2 ;
+ .
+
+:dataset_tdb2 rdf:type tdb2:DatasetTDB2 ;
+ tdb2:location "DB2" ;
+ ## Optional - with union default for query and update WHERE matching.
+ ## tdb2:unionDefaultGraph true ;
+ .
diff --git a/jena-fuseki2/examples/config-text-tdb2.ttl b/jena-fuseki2/examples/config-text-tdb2.ttl
new file mode 100644
index 0000000..225a36c
--- /dev/null
+++ b/jena-fuseki2/examples/config-text-tdb2.ttl
@@ -0,0 +1,80 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+
+PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
+PREFIX text: <http://jena.apache.org/text#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ :service
+ ) .
+
+## Service description for "/dataset"
+## with a TDB2 dataset and a text index.
+
+:service rdf:type fuseki:Service ;
+ fuseki:name "dataset" ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "sparql"
+ ];
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "query"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:update ;
+ fuseki:name "update"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-r ;
+ fuseki:name "get"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-rw ;
+ fuseki:name "data"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:upload ;
+ fuseki:name "upload"
+ ] ;
+ fuseki:dataset :text_dataset ;
+ .
+
+## ---------------------------------------------------------------
+## Confiure a dataset with a text index.
+## See
+## https://jena.apache.org/documentation/query/text-query.html
+## for details
+
+:text_dataset rdf:type text:TextDataset ;
+ text:dataset :base_dataset ;
+ text:index :indexLucene ;
+ .
+
+:base_dataset rdf:type tdb2:DatasetTDB2 ;
+ tdb2:location "DB2"
+ .
+
+:indexLucene a text:TextIndexLucene ;
+ # File location of index
+ text:directory <file:Lucene> ;
+ text:entityMap :entMap ;
+ .
+
+<#entMap> a text:EntityMap ;
+ text:entityField "uri" ;
+ ## Must be defined in the text:map
+ text:defaultField "text" ;
+ ## Enable deleting of text index entries.
+ text:uidField "uid" ;
+ text:map (
+ # rdfs:label
+ [ text:field "text" ; text:predicate rdfs:label ]
+ )
+ .
diff --git a/jena-fuseki2/examples/config-timeout-dataset.ttl b/jena-fuseki2/examples/config-timeout-dataset.ttl
new file mode 100644
index 0000000..846a3e0
--- /dev/null
+++ b/jena-fuseki2/examples/config-timeout-dataset.ttl
@@ -0,0 +1,51 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ :service
+ ) .
+
+## Service description for "/dataset"
+## with a TDB2 dataset with a query timeout.
+
+:service rdf:type fuseki:Service ;
+ fuseki:name "dataset" ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "sparql"
+ ];
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "query"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:update ;
+ fuseki:name "update"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-r ;
+ fuseki:name "get"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-rw ;
+ fuseki:name "data"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:upload ;
+ fuseki:name "upload"
+ ] ;
+ fuseki:dataset :dataset_tdb2 ;
+ .
+
+:dataset_tdb2 rdf:type tdb2:DatasetTDB2 ;
+ ## Set the timeout for the dataset
+ ja:context [ ja:cxtName "arq:queryTimeout" ; ja:cxtValue "10000,60000" ] ;
+ tdb2:location "DB2" ;
+ .
diff --git a/jena-fuseki2/examples/config-timeout-endpoint.ttl b/jena-fuseki2/examples/config-timeout-endpoint.ttl
new file mode 100644
index 0000000..094352e
--- /dev/null
+++ b/jena-fuseki2/examples/config-timeout-endpoint.ttl
@@ -0,0 +1,52 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ :service
+ ) .
+
+## Service description for "/dataset"
+## with a TDB2 dataset with a timeout on one endpoint.
+
+:service rdf:type fuseki:Service ;
+ fuseki:name "dataset" ;
+ fuseki:endpoint [
+ ja:context [ ja:cxtName "arq:queryTimeout" ; ja:cxtValue "10000,60000" ] ;
+ fuseki:operation fuseki:query ;
+ fuseki:name "sparql"
+ ];
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "query"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:update ;
+ fuseki:name "update"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-r ;
+ fuseki:name "get"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-rw ;
+ fuseki:name "data"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:upload ;
+ fuseki:name "upload"
+ ] ;
+ fuseki:dataset :dataset_tdb2 ;
+ .
+
+:dataset_tdb2 rdf:type tdb2:DatasetTDB2 ;
+ tdb2:location "DB2" ;
+ ## Optional - with union default for query and update WHERE matching.
+ ## tdb2:unionDefaultGraph true ;
+ .
diff --git a/jena-fuseki2/examples/config-timeout-server.ttl b/jena-fuseki2/examples/config-timeout-server.ttl
new file mode 100644
index 0000000..43aefc0
--- /dev/null
+++ b/jena-fuseki2/examples/config-timeout-server.ttl
@@ -0,0 +1,53 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
+
+## Server-wide timeout (all datasets).
+
+[] rdf:type fuseki:Server ;
+ # Format 1: "10000" -- 10 second timeout
+ # Format 2: "10000,60000" -- 10s timeout to first result,
+ # then 60s timeout to for rest of query.
+ # See javadoc for ARQ.queryTimeout
+ ja:context [ ja:cxtName "arq:queryTimeout" ; ja:cxtValue "10000" ] ;
+ fuseki:services (
+ :service
+ ) .
+
+:service rdf:type fuseki:Service ;
+ fuseki:name "dataset" ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "sparql"
+ ];
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "query"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:update ;
+ fuseki:name "update"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-r ;
+ fuseki:name "get"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-rw ;
+ fuseki:name "data"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:upload ;
+ fuseki:name "upload"
+ ] ;
+ fuseki:dataset :dataset_tdb2 ;
+ .
+
+:dataset_tdb2 rdf:type tdb2:DatasetTDB2 ;
+ tdb2:location "DB2"
+ .
diff --git a/jena-fuseki2/examples/fuseki-in-mem-txn.ttl b/jena-fuseki2/examples/fuseki-in-mem-txn.ttl
deleted file mode 100644
index 1229e98..0000000
--- a/jena-fuseki2/examples/fuseki-in-mem-txn.ttl
+++ /dev/null
@@ -1,24 +0,0 @@
-## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
-
-@prefix : <#> .
-@prefix fuseki: <http://jena.apache.org/fuseki#> .
-@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix ja: <http://jena.hpl.hp.com/2005/11/Assembler#> .
-@prefix tdb: <http://jena.hpl.hp.com/2008/tdb#> .
-
-<#serviceInMemory> rdf:type fuseki:Service;
- rdfs:label "In-memory, transactional dataset.";
- fuseki:name "ds";
- fuseki:serviceQuery "query";
- fuseki:serviceQuery "sparql";
- fuseki:serviceUpdate "update";
- fuseki:serviceUpload "upload" ;
- fuseki:serviceReadWriteGraphStore "data" ;
- fuseki:serviceReadGraphStore "get" ;
- fuseki:dataset <#dataset> ;
-.
-
-<#dataset> rdf:type ja:MemoryDataset;
- ja:data "data.trig";
-.
diff --git a/jena-fuseki2/examples/fuseki-jetty-https.xml b/jena-fuseki2/examples/fuseki-jetty-https.xml
index d922e19..d9cb774 100644
--- a/jena-fuseki2/examples/fuseki-jetty-https.xml
+++ b/jena-fuseki2/examples/fuseki-jetty-https.xml
@@ -269,8 +269,8 @@
<Call name="addIfAbsentConnectionFactory">
<Arg>
<New class="org.eclipse.jetty.server.SslConnectionFactory">
- <Arg name="next">http/1.1</Arg>
- <Arg name="sslContextFactory"><Ref refid="sslContextFactory"/></Arg>
+ <Arg name="next">http/1.1</Arg>
+ <Arg name="sslContextFactory"><Ref refid="sslContextFactory"/></Arg>
</New>
</Arg>
</Call>
@@ -278,11 +278,10 @@
<Call name="addConnectionFactory">
<Arg>
<New class="org.eclipse.jetty.server.HttpConnectionFactory">
- <Arg name="config"><Ref refid="sslHttpConfig" /></Arg>
+ <Arg name="config"><Ref refid="sslHttpConfig" /></Arg>
</New>
</Arg>
</Call>
</Ref>
-
</Configure>
diff --git a/jena-fuseki2/examples/fuseki-tdb2.ttl b/jena-fuseki2/examples/fuseki-tdb2.ttl
deleted file mode 100644
index 8000156..0000000
--- a/jena-fuseki2/examples/fuseki-tdb2.ttl
+++ /dev/null
@@ -1,33 +0,0 @@
-## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
-
-## Example of a Fuseki server configuration file with a TDB2 dataset
-
-PREFIX : <#>
-PREFIX fuseki: <http://jena.apache.org/fuseki#>
-PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
-PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
-
-[] rdf:type fuseki:Server ;
- fuseki:services (
- <#service_tdb2>
- ) .
-
-<#service_tdb2> rdf:type fuseki:Service ;
- rdfs:label "TDB2 Service (RW)" ;
- fuseki:name "tdb2-database" ;
- fuseki:serviceQuery "query" ;
- fuseki:serviceQuery "sparql" ;
- fuseki:serviceUpdate "update" ;
- fuseki:serviceUpload "upload" ;
- fuseki:serviceReadWriteGraphStore "data" ;
- fuseki:serviceReadGraphStore "get" ;
- fuseki:dataset <#tdb_dataset_readwrite> ;
- .
-
-<#tdb_dataset_readwrite> rdf:type tdb2:DatasetTDB2 ;
- tdb2:location "TDB2" ;
- ## tdb2:unionDefaultGraph true ;
- .
-
\ No newline at end of file
diff --git a/jena-fuseki2/examples/service-inference-1.ttl b/jena-fuseki2/examples/service-inference-1.ttl
deleted file mode 100644
index 5fe894b..0000000
--- a/jena-fuseki2/examples/service-inference-1.ttl
+++ /dev/null
@@ -1,39 +0,0 @@
-## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
-
-# Example of a data service with only SPARQL query on an
-# in-memory inference model. Data is taken from a file
-# when the data service is started.
-
-@prefix : <#> .
-@prefix fuseki: <http://jena.apache.org/fuseki#> .
-@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
-
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix tdb: <http://jena.hpl.hp.com/2008/tdb#> .
-@prefix ja: <http://jena.hpl.hp.com/2005/11/Assembler#> .
-
-## Service with only SPARQL query on an inference model.
-## Inference model bbase data in TDB.
-
-<#service1> rdf:type fuseki:Service ;
- fuseki:name "inf-mem" ;
- fuseki:serviceQuery "sparql" ; # SPARQL query service
- fuseki:dataset <#dataset> ;
- .
-
-# Dataset with only the default graph.
-<#dataset> rdf:type ja:RDFDataset ;
- ja:defaultGraph <#model_inf> ;
- .
-
-# The inference model
-<#model_inf> a ja:InfModel ;
- ja:baseModel <#baseModel> ;
- ja:reasoner [
- ja:reasonerURL <http://jena.hpl.hp.com/2003/OWLFBRuleReasoner>
- ] .
-
-# The base data.
-<#baseModel> a ja:MemoryModel ;
- ja:content [ja:externalContent <file:Data/data.ttl> ] ;
- .
diff --git a/jena-fuseki2/examples/service-inference-2.ttl b/jena-fuseki2/examples/service-inference-2.ttl
deleted file mode 100644
index b036fa6..0000000
--- a/jena-fuseki2/examples/service-inference-2.ttl
+++ /dev/null
@@ -1,43 +0,0 @@
-## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
-
-@prefix : <#> .
-@prefix fuseki: <http://jena.apache.org/fuseki#> .
-@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
-
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix tdb: <http://jena.hpl.hp.com/2008/tdb#> .
-@prefix ja: <http://jena.hpl.hp.com/2005/11/Assembler#> .
-
-# Example of a data service with SPARQL query abnd update on an
-# inference model. Data is taken from TDB.
-
-## ---------------------------------------------------------------
-## Service with only SPARQL query on an inference model.
-## Inference model base data is in TDB.
-
-<#service2> rdf:type fuseki:Service ;
- fuseki:name "inf" ; # http://host/inf
- fuseki:serviceQuery "sparql" ; # SPARQL query service
- fuseki:serviceUpdate "update" ;
- fuseki:dataset <#dataset> ;
- .
-
-<#dataset> rdf:type ja:RDFDataset ;
- ja:defaultGraph <#model_inf> ;
- .
-
-<#model_inf> a ja:InfModel ;
- ja:baseModel <#tdbGraph> ;
- ja:reasoner [
- ja:reasonerURL <http://jena.hpl.hp.com/2003/OWLFBRuleReasoner>
- ] .
-
-## Base data in TDB.
-<#tdbDataset> rdf:type tdb:DatasetTDB ;
- tdb:location "DB" ;
- # If the unionDefaultGraph is used, then the "update" service should be removed.
- # tdb:unionDefaultGraph true ;
- .
-
-<#tdbGraph> rdf:type tdb:GraphTDB ;
- tdb:dataset <#tdbDataset> .
diff --git a/jena-fuseki2/examples/service-tdb1-A.ttl b/jena-fuseki2/examples/service-tdb1-A.ttl
deleted file mode 100644
index 8f0c34a..0000000
--- a/jena-fuseki2/examples/service-tdb1-A.ttl
+++ /dev/null
@@ -1,29 +0,0 @@
-## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
-
-## Example of a TDB dataset published using Fuseki
-## Persistent storage.
-## read-only
-
-@prefix : <#> .
-@prefix fuseki: <http://jena.apache.org/fuseki#> .
-@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix tdb: <http://jena.hpl.hp.com/2008/tdb#> .
-@prefix ja: <http://jena.hpl.hp.com/2005/11/Assembler#> .
-
-## Read-only TDB dataset (only read services enabled).
-
-<#service_tdb_read_only> rdf:type fuseki:Service ;
- rdfs:label "TDB Service (R)" ;
- fuseki:name "ds" ;
- fuseki:serviceQuery "query" ;
- fuseki:serviceQuery "sparql" ;
- fuseki:serviceReadGraphStore "data" ;
- fuseki:serviceReadGraphStore "get" ;
- fuseki:dataset <#tdb_dataset_read> ;
- .
-
-<#tdb_dataset_read> rdf:type tdb:DatasetTDB ;
- tdb:location "DB1" ;
- tdb:unionDefaultGraph true ;
- .
diff --git a/jena-fuseki2/examples/service-tdb1-B.ttl b/jena-fuseki2/examples/service-tdb1-B.ttl
deleted file mode 100644
index c85963f..0000000
--- a/jena-fuseki2/examples/service-tdb1-B.ttl
+++ /dev/null
@@ -1,33 +0,0 @@
-## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
-
-## Example of a TDB dataset published using Fuseki
-## Persistent storage.
-## All services enabled.
-
-@prefix : <#> .
-@prefix fuseki: <http://jena.apache.org/fuseki#> .
-@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix tdb: <http://jena.hpl.hp.com/2008/tdb#> .
-@prefix ja: <http://jena.hpl.hp.com/2005/11/Assembler#> .
-
-<#service_tdb_all> rdf:type fuseki:Service ;
- rdfs:label "TDB Service (RW)" ;
- fuseki:name "data" ;
- fuseki:serviceQuery "query" ;
- fuseki:serviceQuery "sparql" ;
- fuseki:serviceUpdate "update" ;
- fuseki:serviceUpload "upload" ;
- fuseki:serviceReadWriteGraphStore "data" ;
- # A separate read-only graph store endpoint:
- fuseki:serviceReadGraphStore "get" ;
- fuseki:dataset <#tdb_dataset_readwrite> ;
- .
-
-<#tdb_dataset_readwrite> rdf:type tdb:DatasetTDB ;
- tdb:location "DB2" ;
-## # Query timeout on this dataset (milliseconds)
-## ja:context [ ja:cxtName "arq:queryTimeout" ; ja:cxtValue "1000" ] ;
-## # Default graph for query is the (read-only) union of all named graphs.
- tdb:unionDefaultGraph true ;
- .
diff --git a/jena-fuseki2/examples/service-tdb1-mem.ttl b/jena-fuseki2/examples/service-tdb1-mem.ttl
deleted file mode 100644
index 82a3fc2..0000000
--- a/jena-fuseki2/examples/service-tdb1-mem.ttl
+++ /dev/null
@@ -1,32 +0,0 @@
-## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
-
-## An in-memory TDB datasets - for testing.
-
-@prefix : <#> .
-@prefix fuseki: <http://jena.apache.org/fuseki#> .
-@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
-
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix tdb: <http://jena.hpl.hp.com/2008/tdb#> .
-@prefix ja: <http://jena.hpl.hp.com/2005/11/Assembler#> .
-
-<#service_tdb> rdf:type fuseki:Service ;
- rdfs:label "TDB(mem) Service" ;
- fuseki:name "MEM" ;
- fuseki:serviceQuery "query" ;
- fuseki:serviceQuery "sparql" ;
- fuseki:serviceUpdate "update" ;
- fuseki:serviceUpload "upload" ;
- fuseki:serviceReadWriteGraphStore "data" ;
- # A separate read-only graph store endpoint:
- fuseki:serviceReadGraphStore "get" ;
- fuseki:dataset <#tdb_dataset> ;
- .
-
-<#tdb_dataset> rdf:type tdb:DatasetTDB ;
- tdb:location "--mem--" ;
- ## Query timeout on this dataset (milliseconds)
- ja:context [ ja:cxtName "arq:queryTimeout" ; ja:cxtValue "1000" ] ;
- ## Default graph for query is the (read-only) union of all named graphs.
- tdb:unionDefaultGraph true ;
- .
diff --git a/jena-fuseki2/examples/service-tdb2-A.ttl b/jena-fuseki2/examples/service-tdb2-A.ttl
deleted file mode 100644
index 89b87ff..0000000
--- a/jena-fuseki2/examples/service-tdb2-A.ttl
+++ /dev/null
@@ -1,28 +0,0 @@
-## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
-
-## Example of a service configuration file with a TDB2 dataset
-
-PREFIX : <#>
-PREFIX fuseki: <http://jena.apache.org/fuseki#>
-PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
-PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
-
-<#service_tdb2> rdf:type fuseki:Service ;
- rdfs:label "TDB2 Service (RW)" ;
- fuseki:name "tdb2-database" ;
- fuseki:serviceQuery "query" ;
- fuseki:serviceQuery "sparql" ;
- fuseki:serviceUpdate "update" ;
- fuseki:serviceUpload "upload" ;
- fuseki:serviceReadWriteGraphStore "data" ;
- fuseki:serviceReadGraphStore "get" ;
- fuseki:dataset <#tdb_dataset_readwrite> ;
- .
-
-<#tdb_dataset_readwrite> rdf:type tdb2:DatasetTDB2 ;
- tdb2:location "TDB2" ;
- ## tdb2:unionDefaultGraph true ;
- .
-
\ No newline at end of file
diff --git a/jena-fuseki2/examples/shacl-example.ttl b/jena-fuseki2/examples/shacl-example.ttl
deleted file mode 100644
index cc8400a..0000000
--- a/jena-fuseki2/examples/shacl-example.ttl
+++ /dev/null
@@ -1,17 +0,0 @@
-## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
-
-PREFIX : <#>
-PREFIX fuseki: <http://jena.apache.org/fuseki#>
-PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
-
-<#serviceInMemoryShacl> rdf:type fuseki:Service;
- rdfs:label "Dataset with SHACL validation";
- fuseki:name "ds";
- fuseki:serviceReadWriteGraphStore "" ;
- fuseki:serviceShacl "shacl" ;
- fuseki:dataset <#dataset> ;
-.
-
-<#dataset> rdf:type ja:MemoryDataset .
diff --git a/jena-fuseki2/examples/tdb2-select-graphs-alt.ttl b/jena-fuseki2/examples/tdb2-select-graphs-alt.ttl
index 8f3a165..9a1746c 100644
--- a/jena-fuseki2/examples/tdb2-select-graphs-alt.ttl
+++ b/jena-fuseki2/examples/tdb2-select-graphs-alt.ttl
@@ -3,53 +3,72 @@
PREFIX : <#>
PREFIX fuseki: <http://jena.apache.org/fuseki#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
-
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
-<#service_tdb> rdf:type fuseki:Service ;
- rdfs:label "Selection of TDB2 graphs" ;
- fuseki:name "ds2" ;
- fuseki:serviceQuery "query" ;
- fuseki:serviceQuery "sparql" ;
- fuseki:serviceUpdate "update" ;
- fuseki:serviceUpload "upload" ;
- fuseki:serviceReadWriteGraphStore "data" ;
- # A separate read-only graph store endpoint:
- fuseki:serviceReadGraphStore "get" ;
- fuseki:dataset <#dataset> ;
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ :service
+ ) .
+
+:service rdf:type fuseki:Service ;
+ fuseki:name "dataset" ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "sparql"
+ ];
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "query"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:update ;
+ fuseki:name "update"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-r ;
+ fuseki:name "get"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-rw ;
+ fuseki:name "data"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:upload ;
+ fuseki:name "upload"
+ ] ;
+ fuseki:dataset :dataset ;
.
+## Datasets with some graphs from a TDB2 dataset.
+## Note: Prefer using "GRAPH" in a SPARQL query where possible.
-<#dataset> rdf:type ja:RDFDataset ;
- ja:defaultGraph <#graph> ;
+:dataset rdf:type ja:RDFDataset ;
+ ja:defaultGraph :graph ;
ja:namedGraph [
ja:graphName <https://example/ng1> ;
- ja:graph <#graph2>
+ ja:graph :graph2
];
ja:namedGraph [
ja:graphName <https://example/ng2> ;
- ja:graph <#graph3>
+ ja:graph :graph3
];
.
## Graphs out of DB2.
+## If the location is the same, it will be the same dataset.
-<#graph> rdf:type tdb2:GraphTDB2 ;
+:graph rdf:type tdb2:GraphTDB2 ;
tdb2:graphName "urn:x-arq:UnionGraph" ;
- tdb2:dataset <#DB2> ;
+ tdb2:location "DB2" ;
.
-<#graph2> rdf:type tdb2:GraphTDB2 ;
+:graph2 rdf:type tdb2:GraphTDB2 ;
tdb2:graphName "https://example/ng1" ;
- tdb2:dataset <#DB2> ;
+ tdb2:location "DB2" ;
.
-<#graph3> rdf:type tdb2:GraphTDB2 ;
+:graph3 rdf:type tdb2:GraphTDB2 ;
tdb2:graphName "https://example/ng" ;
- tdb2:dataset <#DB2> ;
- .
-
-<#DB2> rdf:type tdb2:DatasetTDB2 ;
tdb2:location "DB2" ;
.
diff --git a/jena-fuseki2/examples/tdb2-select-graphs.ttl b/jena-fuseki2/examples/tdb2-select-graphs.ttl
index 1e66b6d..3f3bae2 100644
--- a/jena-fuseki2/examples/tdb2-select-graphs.ttl
+++ b/jena-fuseki2/examples/tdb2-select-graphs.ttl
@@ -3,49 +3,77 @@
PREFIX : <#>
PREFIX fuseki: <http://jena.apache.org/fuseki#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
-
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
-<#service_tdb> rdf:type fuseki:Service ;
- rdfs:label "Selection of TDB2 graphs" ;
- fuseki:name "ds2" ;
- fuseki:serviceQuery "query" ;
- fuseki:serviceQuery "sparql" ;
- fuseki:serviceUpdate "update" ;
- fuseki:serviceUpload "upload" ;
- fuseki:serviceReadWriteGraphStore "data" ;
- # A separate read-only graph store endpoint:
- fuseki:serviceReadGraphStore "get" ;
- fuseki:dataset <#dataset> ;
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ :service
+ ) .
+
+:service rdf:type fuseki:Service ;
+ fuseki:name "dataset" ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "sparql"
+ ];
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "query"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:update ;
+ fuseki:name "update"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-r ;
+ fuseki:name "get"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:gsp-rw ;
+ fuseki:name "data"
+ ] ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:upload ;
+ fuseki:name "upload"
+ ] ;
+ fuseki:dataset :dataset ;
.
+## Datasets with some graphs from a TDB2 dataset.
+## Note: Prefer using "GRAPH" in a SPARQL query where possible.
-<#dataset> rdf:type ja:RDFDataset ;
- ja:defaultGraph <#graph> ;
+:dataset rdf:type ja:RDFDataset ;
+ ja:defaultGraph :graph ;
ja:namedGraph [
ja:graphName <https://example/ng1> ;
- ja:graph <#graph2>
+ ja:graph :graph2
];
ja:namedGraph [
ja:graphName <https://example/ng2> ;
- ja:graph <#graph3>
+ ja:graph :graph3
];
.
## Graphs out of DB2.
-<#graph> rdf:type tdb2:GraphTDB2 ;
+:graph rdf:type tdb2:GraphTDB2 ;
tdb2:graphName "urn:x-arq:UnionGraph" ;
- tdb2:location "DB2" ;
+ tdb2:dataset :dataset_tdb2 ;
.
-<#graph2> rdf:type tdb2:GraphTDB2 ;
+:graph2 rdf:type tdb2:GraphTDB2 ;
tdb2:graphName "https://example/ng1" ;
- tdb2:location "DB2" ;
+ tdb2:dataset :dataset_tdb2 ;
.
-<#graph3> rdf:type tdb2:GraphTDB2 ;
+:graph3 rdf:type tdb2:GraphTDB2 ;
tdb2:graphName "https://example/ng" ;
+ tdb2:dataset :dataset_tdb2 ;
+ .
+
+## The database
+
+:dataset_tdb2 rdf:type tdb2:DatasetTDB2 ;
tdb2:location "DB2" ;
.
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AccessCtl_AllowGET.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AccessCtl_AllowGET.java
index d822714..f03eca1 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AccessCtl_AllowGET.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AccessCtl_AllowGET.java
@@ -65,7 +65,8 @@
public void execAny(String methodName, HttpAction action) {
if ( label == null )
ServletOps.errorBadRequest("Not supported");
- ServletOps.errorBadRequest(label+" : not supported");
+ else
+ ServletOps.errorBadRequest(label+" : not supported");
throw new InternalErrorException("AccessCtl_AllowGET: "+ "didn't reject request");
}
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/DatasetDescriptionMap.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/DatasetDescriptionMap.java
index c814a8f..647aa94 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/DatasetDescriptionMap.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/DatasetDescriptionMap.java
@@ -34,17 +34,15 @@
* same dataset.
*/
public class DatasetDescriptionMap {
-
+
private Map<Resource, Dataset> map = new HashMap<>();
-
+
public DatasetDescriptionMap() {}
-
+
public void register(Resource node, Dataset ds) {
Dataset dsCurrent = map.get(node);
- if ( dsCurrent != null ) {
- if ( ! dsCurrent.equals(ds) )
- Log.warn(this.getClass(), "Replacing registered dataset for "+node);
- }
+ if ( dsCurrent != null && ! dsCurrent.equals(ds) )
+ Log.warn(this.getClass(), "Replacing registered dataset for "+node);
map.put(node, ds);
}
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java
index ba3b956..3988818 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java
@@ -46,6 +46,7 @@
import org.apache.jena.fuseki.FusekiConfigException;
import org.apache.jena.fuseki.auth.Auth;
import org.apache.jena.fuseki.auth.AuthPolicy;
+import org.apache.jena.fuseki.auth.AuthPolicyList;
import org.apache.jena.fuseki.server.*;
import org.apache.jena.fuseki.servlets.ActionService;
import org.apache.jena.graph.Node;
@@ -455,17 +456,62 @@
accEndpointOldStyle(endpoints1, Operation.GSP_R, fusekiService, pServiceReadGraphStoreEP);
accEndpointOldStyle(endpoints1, Operation.GSP_RW, fusekiService, pServiceReadWriteGraphStoreEP);
+ // ---- Legacy for old style: a request would also try the dataset (i.e. no endpoint name).
+ // If "sparql" then allow /dataset?query=
+ // Instead, for old style declarations, add new endpoints to put on the dataset
+ // Only complication is that authorization is the AND (all say "yes") of named service authorization.
+ {
+ Collection<Endpoint> endpointsCompat = oldStyleCompat(dataService, endpoints1);
+ endpointsCompat.forEach(dataService::addEndpoint);
+ }
+ // Explicit definition overrides implied by legacy compatibility.
+ // Should not happen.
+ endpoints1.forEach(dataService::addEndpoint);
+
// New (2019) style
// fuseki:endpoint [ fuseki:operation fuseki:query ; fuseki:name "" ; fuseki:allowedUsers (....) ] ;
// and more.
- accFusekiEndpoints(endpoints2, fusekiService, dsDescMap);
- endpoints1.forEach(dataService::addEndpoint);
+ accFusekiEndpoints(endpoints2, fusekiService, dsDescMap);
// This will overwrite old style entries of the same fuseki:name.
endpoints2.forEach(dataService::addEndpoint);
+
return dataService;
}
+ /**
+ * Old style compatibility.
+ * For each endpoint in "endpoints1", ensure there is an endpoint on the dataset (endpoint name "") itself.
+ * Combine the authentication as "AND" of named endpoints authentication.
+ */
+ private static Collection<Endpoint> oldStyleCompat(DataService dataService, Set<Endpoint> endpoints1) {
+ Map<Operation, Endpoint> endpoints3 = new HashMap<>();
+ endpoints1.forEach(ep->{
+ Operation operation = ep.getOperation();
+ AuthPolicy auth = ep.getAuthPolicy();
+
+ if ( ! StringUtils.isEmpty(ep.getName()) ) {
+ if ( endpoints3.containsKey(operation) ) {
+ Endpoint ep1 = endpoints3.get(operation);
+ // Accumulate Authorization.
+ auth = AuthPolicyList.merge(ep1.getAuthPolicy(), auth);
+ Endpoint ep2 = Endpoint.create(ep.getOperation(), "", auth);
+ endpoints3.put(operation, ep2);
+ } else {
+ Endpoint ep2 = Endpoint.create(operation, "", auth);
+ endpoints3.put(operation, ep2);
+ }
+ }
+ });
+ // Now, after making all legacy endpoints, remove any that are explicit defined in endpoints1.
+ // Given the small numbers involved, it is easier to do it this way than
+ // additional logic in the first pass over endpoints1.
+ endpoints1.stream()
+ .filter(ep->StringUtils.isEmpty(ep.getName()))
+ .forEach(ep->endpoints3.remove(ep.getOperation()));
+ return endpoints3.values();
+ }
+
/** Find and parse {@code fuseki:endpoint} descriptions. */
private
static void accFusekiEndpoints(Set<Endpoint> endpoints, Resource fusekiService, DatasetDescriptionMap dsDescMap) {
@@ -540,7 +586,6 @@
epName = epNameR.asLiteral().getLexicalForm();
}
-
Context cxt = parseContext(endpoint);
// Per-endpoint context.
@@ -587,11 +632,11 @@
RDFNode ep = soln.get("ep");
String endpointName = null;
if ( ep.isLiteral() )
+ // fuseki:serviceQuery "sparql"
endpointName = soln.getLiteral("ep").getLexicalForm();
else if ( ep.isResource() ) {
Resource r = (Resource)ep;
try {
- // Look for possible:
// [ fuseki:name ""; fuseki:allowedUsers ( "" "" ) ]
endpointName = r.getProperty(FusekiVocab.pEndpointName).getString();
List<RDFNode> x = GraphUtils.multiValue(r, FusekiVocab.pAllowedUsers);
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiExt.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiExt.java
index 9df6b02..79188d9 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiExt.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiExt.java
@@ -64,6 +64,12 @@
/** Make a new operation available. */
public static void registerOperation(Operation op, ActionService handler) {
+ // No Content-type registration
OperationRegistry.get().register(op, null, handler);
}
+
+ /** Remove an operation. */
+ public static void unregisterOperation(Operation op, ActionService handler) {
+ OperationRegistry.get().unregister(op);
+ }
}
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/FusekiErrorHandler.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/FusekiErrorHandler.java
index fd6bc03..b4b880e 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/FusekiErrorHandler.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/FusekiErrorHandler.java
@@ -20,66 +20,43 @@
import static java.lang.String.format;
-import java.io.*;
+import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.apache.jena.atlas.io.IO;
import org.apache.jena.fuseki.servlets.ServletOps;
import org.apache.jena.web.HttpSC;
import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.handler.ErrorHandler;
-/** The usual Fuseki error handler.
- * Outputs a plain text message.
+/**
+ * Fuseki error handler (used with ServletAPI HttpServletResponse.sendError).
+ * Typically ServletOps.responseSendError is used which directly send the error and a message.
*/
-
public class FusekiErrorHandler extends ErrorHandler
{
+ // Only used if ServletOps.responseSendError calls Servlet API response.sendError
+ // or a non-Fuseki error occurs.
public FusekiErrorHandler() {}
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException {
String method = request.getMethod();
- if ( !method.equals(HttpMethod.GET.asString())
- && !method.equals(HttpMethod.POST.asString())
- && !method.equals(HttpMethod.HEAD.asString()) )
+ if ( !method.equals(HttpMethod.GET.asString())
+ && !method.equals(HttpMethod.POST.asString())
+ && !method.equals(HttpMethod.HEAD.asString()) )
return;
-
- response.setContentType(MimeTypes.Type.TEXT_PLAIN_UTF_8.asString());
+
ServletOps.setNoCache(response);
-
- ByteArrayOutputStream bytes = new ByteArrayOutputStream(1024);
- try ( Writer writer = IO.asUTF8(bytes) ) {
- String reason = (response instanceof Response) ? ((Response)response).getReason() : null;
- handleErrorPage(request, writer, response.getStatus(), reason);
- writer.flush();
- response.setContentLength(bytes.size());
- response.getOutputStream().write(bytes.toByteArray());
- }
- }
-
- @Override
- protected void handleErrorPage(HttpServletRequest request, Writer writer, int code, String message) throws IOException {
+ int code = response.getStatus();
+ String message = (response instanceof Response) ? ((Response)response).getReason() : HttpSC.getMessage(code);
if ( message == null )
message = HttpSC.getMessage(code);
- writer.write(format("Error %d: %s\n", code, message));
-
- Throwable th = (Throwable)request.getAttribute("javax.servlet.error.exception");
- while (th != null) {
- writer.write("\n");
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- th.printStackTrace(pw);
- pw.flush();
- writer.write(sw.getBuffer().toString());
- writer.write("\n");
- th = th.getCause();
- }
+ String msg = format("Error %d: %s\n", code, message);
+ ServletOps.writeMessagePlainText(response, msg);
}
}
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/FusekiErrorHandler1.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/FusekiErrorHandler1.java
deleted file mode 100644
index 7210afc..0000000
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/FusekiErrorHandler1.java
+++ /dev/null
@@ -1,56 +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.jetty;
-
-import static java.lang.String.format;
-
-import java.io.IOException;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.jena.fuseki.servlets.ServletOps;
-import org.apache.jena.web.HttpSC;
-import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.http.MimeTypes;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.Response;
-import org.eclipse.jetty.server.handler.ErrorHandler;
-
-/** One line Fuseki error handler */
-public class FusekiErrorHandler1 extends ErrorHandler
-{
- public FusekiErrorHandler1() {}
-
- @Override
- public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException {
- String method = request.getMethod();
-
- if ( !method.equals(HttpMethod.GET.asString())
- && !method.equals(HttpMethod.POST.asString())
- && !method.equals(HttpMethod.HEAD.asString()) )
- return;
-
- response.setContentType(MimeTypes.Type.TEXT_PLAIN_UTF_8.asString());
- ServletOps.setNoCache(response);
- int code = response.getStatus();
- String message = (response instanceof Response) ? ((Response)response).getReason() : HttpSC.getMessage(code);
- response.getOutputStream().print(format("Error %d: %s\n", code, message));
- }
-}
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataAccessPointRegistry.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataAccessPointRegistry.java
index 09fd560..b8b1bc0 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataAccessPointRegistry.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataAccessPointRegistry.java
@@ -27,6 +27,10 @@
import org.apache.jena.fuseki.FusekiException;
import org.apache.jena.fuseki.metrics.FusekiRequestsMetrics;
+/**
+ * Registry of (dataset name, {@link DataAccessPoint}).
+ * In addition, registered {@link DataAccessPoint} are added to the metrics.
+ */
public class DataAccessPointRegistry extends Registry<String, DataAccessPoint>
{
private MeterRegistry meterRegistry;
@@ -60,6 +64,11 @@
}
// Debugging
+ public void print() {
+ print(null);
+ }
+
+ // Debugging
public void print(String string) {
System.out.flush();
if ( string == null )
@@ -69,7 +78,7 @@
System.out.printf(" (key=%s, ref=%s)\n", k, ref.getName());
ref.getDataService().getOperations().forEach((op)->{
ref.getDataService().getEndpoints(op).forEach(ep->{
- System.out.printf(" %s : %s\n", op, ep.getName());
+ System.out.printf(" %-10s @ \"%s\"\n", op, ep.getName());
});
});
});
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Dispatcher.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Dispatcher.java
index 285d9bf..5d3cd21 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Dispatcher.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Dispatcher.java
@@ -26,13 +26,10 @@
import static org.apache.jena.fuseki.server.Operation.Update;
import static org.apache.jena.fuseki.servlets.ActionExecLib.allocHttpAction;
-import java.util.Collection;
-import java.util.List;
-
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.apache.jena.atlas.lib.InternalErrorException;
+import org.apache.commons.lang3.StringUtils;
import org.apache.jena.fuseki.Fuseki;
import org.apache.jena.fuseki.auth.Auth;
import org.apache.jena.fuseki.servlets.*;
@@ -70,12 +67,10 @@
*
* This function is called by {@link FusekiFilter#doFilter}.
*
- * @param request
- * HttpServletRequest
- * @param response
- * HttpServletResponse
- * @return Returns {@code true} if the request has been handled, else false (no
- * response sent).
+ * Returns {@code true} if the request has been handled, including an error response sent,
+ * and returns false (no error or response sent) if the request has not been handled.
+ *
+ * This function does not throw exceptions.
*/
public static boolean dispatch(HttpServletRequest request, HttpServletResponse response) {
// Path component of the URI, without context path
@@ -101,6 +96,14 @@
return process(dap, request, response);
}
+ /**
+ * Map request to operation name.
+ * Returns the service name (the part after the "/" of the dataset part) or "".
+ */
+ private static String mapRequestToEndpointName(HttpAction action, DataAccessPoint dataAccessPoint) {
+ return ActionLib.mapRequestToEndpointName(action, dataAccessPoint);
+ }
+
/** Set up and handle a HTTP request for a dataset. */
private static boolean process(DataAccessPoint dap, HttpServletRequest request, HttpServletResponse response) {
HttpAction action = allocHttpAction(dap, Fuseki.actionLog, ActionCategory.ACTION, request, response);
@@ -111,7 +114,7 @@
* Determine and call the {@link ActionProcessor} to handle this
* {@link HttpAction}, including access control at the dataset and service levels.
*/
- public static boolean dispatchAction(HttpAction action) {
+ private static boolean dispatchAction(HttpAction action) {
return ActionExecLib.execAction(action, ()->chooseProcessor(action));
}
@@ -128,9 +131,8 @@
* <li> Endpoint to Operation (endpoint carries Operation).
* <li> target(action, operation) -> ActionProcess.
*
- * @param action
- * @return ActionProcessor or null if the request URI does not name a service or the dataset.
- *
+ * @return ActionProcessor or null if the request URI can not be dealt with.
+ * @throws ActionErrorException for dispatch errors
*/
private static ActionProcessor chooseProcessor(HttpAction action) {
// "return null" indicates that processing failed to find a ActionProcessor
@@ -144,19 +146,16 @@
// ---- Determine Endpoint.
String endpointName = mapRequestToEndpointName(action, dataAccessPoint);
+ // Main step of choosing the endpoint for the dispatch of the request.
+ // An endpoint is a (name, operation).
+ // There may be multiple operations for an endpointName of this data service.
Endpoint endpoint = chooseEndpoint(action, dataService, endpointName);
- if ( endpoint == null ) {
- if ( isEmpty(endpointName) )
- ServletOps.errorBadRequest("No operation for request: "+action.getActionURI());
- else {
- // No dispatch - the filter passes these through if the ActionProcessor is null.
- return null;
- // If this is used, resources (servlets, sttaic files) under "/dataset/" are not accessible.
- //ServletOps.errorNotFound("No endpoint: "+action.getActionURI());
- }
+ if ( endpoint == null )
+ // Includes named service, no such endpoint.
+ // Allows for resources under /dataset/
+ // The request will pass on down the filter/servlet chain.
return null;
- }
Operation operation = endpoint.getOperation();
if ( operation == null ) {
@@ -181,18 +180,6 @@
// -- Endpoint level authorization
// Make sure all contribute authentication.
Auth.allow(user, action.getEndpoint().getAuthPolicy(), ServletOps::errorForbidden);
- if ( isEmpty(endpointName) && ! endpoint.isUnnamed() ) {
- // [DISPATCH LEGACY]
- // If choice was by looking in all named endpoints for a unnamed endpoint
- // request, ensure all choices allow access.
- // There may be several endpoints for the operation.
- // Authorization is the AND of all endpoints.
- Collection<Endpoint> x = getEndpoints(dataService, operation);
- if ( x.isEmpty() )
- throw new InternalErrorException("Inconsistent: no endpoints for "+operation);
- x.forEach(ept->
- Auth.allow(user, ept.getAuthPolicy(), ServletOps::errorForbidden));
- }
// ---- Authorization checking.
// ---- Handler.
@@ -203,134 +190,72 @@
return processor;
}
- /**
- * Map request to operation name.
- * Returns the service name (the part after the "/" of the dataset part) or "".
- */
- protected static String mapRequestToEndpointName(HttpAction action, DataAccessPoint dataAccessPoint) {
- return ActionLib.mapRequestToEndpointName(action, dataAccessPoint);
- }
- // Find the endpoints for an operation.
- // This is GSP_R/GSP_RW aware.
- // If asked for GSP_R and there are no endpoints for GSP_R, try GSP_RW.
- private static Collection<Endpoint> getEndpoints(DataService dataService, Operation operation) {
- Collection<Endpoint> x = dataService.getEndpoints(operation);
- if ( x == null || x.isEmpty() ) {
- if ( operation == GSP_R )
- x = dataService.getEndpoints(GSP_RW);
- }
- return x;
- }
- /**
- * Choose an endpoint. This can be with or without endpointName.
- * If there is no endpoint and the action is on the data service itself (unnamed endpoint)
- * look for a named endpoint that supplies the operation.
- */
- private static Endpoint chooseEndpoint(HttpAction action, DataService dataService, String endpointName) {
- try {
- Endpoint ep = chooseEndpointNoLegacy(action, dataService, endpointName);
- if ( ep != null )
- return ep;
- // No dispatch so far.
-
- if ( ! isEmpty(endpointName) )
- return ep;
- // [DISPATCH LEGACY]
-
- // When it is a unnamed service request (operation on the dataset) and there
- // is no match, search the named services.
- Operation operation = chooseOperation(action);
- // Search for an endpoint that provides the operation.
- // No guarantee it has the access controls for the operation
- // but in this case, access control will validate against all possible endpoints.
- ep = findEndpointForOperation(action, dataService, operation, true);
- return ep;
- } catch (ActionErrorException ex) {
- throw ex;
- } catch (RuntimeException ex) {
- // Example: Jetty throws BadMessageException when it is an HTML form and it is too big.
- ServletOps.errorBadRequest(ex.getMessage());
- return null;
- }
- }
+// // Find the endpoints for an operation.
+// // This is GSP_R/GSP_RW aware.
+// // If asked for GSP_R and there are no endpoints for GSP_R, try GSP_RW.
+// private static Collection<Endpoint> getEndpoints(DataService dataService, Operation operation) {
+// Collection<Endpoint> x = dataService.getEndpoints(operation);
+// if ( x == null || x.isEmpty() ) {
+// if ( operation == GSP_R ) // [GSP Promote]
+// x = dataService.getEndpoints(GSP_RW);
+// }
+// return x;
+// }
/**
* Choose an endpoint.
+ * An endpoint is a name and an operation.
* <ul>
* <li>Look by service name to get the EndpointSet</li>
- * <li>If empty set, return null.</li>
+ * <li>If empty set, respond with error</li>
* <li>If there is only one choice, return that (may even be the wrong operation
- * - processor implmentations must be defensive).</li>
+ * - processor implementations must be defensive).</li>
* <li>If multiple choices, classify the operation
* (includes custom content-type) and look up by operation.</li>
- * <li>Return a match wit a r
+ * <li>If not suitable, respond with error
+ * <li>Return an endpoint.
* </ul>
+ * The endpoint chosen may not be suitable, the operation must do checking.
*/
- private static Endpoint chooseEndpointNoLegacy(HttpAction action, DataService dataService, String endpointName) {
+ private static Endpoint chooseEndpoint(HttpAction action, DataService dataService, String endpointName) {
EndpointSet epSet = isEmpty(endpointName) ? dataService.getEndpointSet() : dataService.getEndpointSet(endpointName);
-
- if ( epSet == null || epSet.isEmpty() )
+ if ( epSet == null || epSet.isEmpty() ) {
// No matches by name.
- return null;
+ if ( ! StringUtils.isAnyEmpty(endpointName) )
+ // There was a service name but it was not found.
+ // It may be a URL for static resource.
+ return null;
+ // Dataset URL - "exists" (even if no services) so 404 is wrong.
+ ServletOps.errorBadRequest("No endpoint for request");
+ return null; // Unreachable.
+ }
// If there is one endpoint, dispatch there directly.
Endpoint ep = epSet.getExactlyOne();
if ( ep != null )
+ // Single dispatch, may not be valid.
return ep;
// No single direct dispatch. Multiple choices (different operation, same endpoint name)
// Work out which operation we are looking for.
Operation operation = chooseOperation(action);
ep = epSet.get(operation);
- // This also happens in findEndpointForOperation
- // If a GSP-R request, try for GSP-RW
- if ( ep == null && Operation.GSP_R.equals(operation) )
- ep = epSet.get(Operation.GSP_RW);
- return ep;
- }
-
- /**
- * Find an endpoint for an operation.
- * This searches all endpoints of a {@link DataService} that provide the {@link Operation}.
- * This understands that GSP_RW can service GSP_R.
- * Used for legacy dispatch.
- */
- private static Endpoint findEndpointForOperation(HttpAction action, DataService dataService, Operation operation, boolean preferUnnamed) {
- Endpoint ep = findEndpointForOperationExact(dataService, operation, preferUnnamed);
- if ( ep != null )
- return ep;
- // Try to find "R" functionality from an RW.
- if ( GSP_R.equals(operation) )
- return findEndpointForOperationExact(dataService, GSP_RW, preferUnnamed);
- // Instead of 404, return 405 if asked for RW but only R available.
- if ( GSP_RW.equals(operation) && dataService.hasOperation(GSP_R) )
- ServletOps.errorMethodNotAllowed(action.getMethod());
- return null;
- }
-
- /** Find a matching endpoint for exactly this operation.
- * If multiple choices, prefer either named or unnamed according
- * to the flag {@code preferUnnamed}.
- */
- private static Endpoint findEndpointForOperationExact(DataService dataService, Operation operation, boolean preferUnnamed) {
- List<Endpoint> eps = dataService.getEndpoints(operation);
- if ( eps == null || eps.isEmpty() )
- return null;
- // ==== Legacy compatibility.
- // Find a named service, with preference for named/unnamed.
- Endpoint epAlt = null;
- for ( Endpoint ep : eps ) {
- if ( operation.equals(ep.getOperation()) ) {
- if ( ep.isUnnamed() && preferUnnamed )
- return ep;
- if ( ! ep.isUnnamed() && ! preferUnnamed )
- return ep;
- epAlt = ep;
+ if ( ep == null ) {
+ if ( GSP_R.equals(operation) )
+ // If asking for GSP_R, and GSP_RW available, pass that back.
+ ep = epSet.get(GSP_RW); // [GSP Promote]
+ else if ( GSP_RW.equals(operation) ) {
+ // If asking for GSP_RW, only GSP_R available -> 405.
+ if ( epSet.contains(GSP_R) )
+ ServletOps.errorMethodNotAllowed(action.getMethod());
}
}
- // Did not find a preferred one.
- return epAlt;
+
+ // There are multiple endpoints; if none are suitable, then 400.
+ if ( ep == null )
+ ServletOps.errorBadRequest("No operation for request: "+action.getActionURI());
+ return ep;
}
/**
@@ -338,16 +263,16 @@
* It is analysing the HTTP request using global configuration.
* The decision is based on
* <ul>
- * <li>Query parameters (URL query string or HTML form)</li>
- * <li>Content-Type header</li>
- * <li>Otherwise it is a plain REST (quads) operation.chooseOperation</li>
+ * <li>HTTP query string parameters (URL query string or HTML form)</li>
+ * <li>Registered Content-Type header</li>
+ * <li>Otherwise it is a plain REST (quads)</li>
* </ul>
* The HTTP Method is not considered.
* <p>
* The operation is not guaranteed to be supported on every {@link DataService}
* nor that access control will allow it to be performed.
*/
- public static Operation chooseOperation(HttpAction action) {
+ private static Operation chooseOperation(HttpAction action) {
HttpServletRequest request = action.getRequest();
// ---- Dispatch based on HttpParams : Query, Update, GSP.
@@ -401,7 +326,6 @@
ServletOps.errorBadRequest(HttpSC.getMessage(HttpSC.BAD_REQUEST_400));
}
-
// ---- No registered content type, no query parameters.
// Plain HTTP operation on the dataset handled as quads or rejected.
return quadsOperation(action, request);
@@ -411,11 +335,8 @@
* Determine the {@link Operation} for a SPARQL Graph Store Protocol (GSP) action.
* <p>
* Assumes, and does not check, that the action is a GSP action.
- *
- * @throws ActionErrorException
- * (which causes a servlet 4xx response) if the operaton is not permitted.
*/
- private static Operation gspOperation(HttpAction action, HttpServletRequest request) throws ActionErrorException {
+ private static Operation gspOperation(HttpAction action, HttpServletRequest request) {
// Check enabled.
if ( isReadMethod(request) )
return GSP_R;
@@ -428,11 +349,8 @@
* whole dataset).
* <p>
* Assumes, and does not check, that the action is a Quads action.
- *
- * @throws ActionErrorException
- * (which causes a servlet 405 response) if the operaton is not permitted.
*/
- private static Operation quadsOperation(HttpAction action, HttpServletRequest request) throws ActionErrorException {
+ private static Operation quadsOperation(HttpAction action, HttpServletRequest request) {
// Check enabled. Extends GSP.
if ( isReadMethod(request) )
return GSP_R;
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Endpoint.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Endpoint.java
index 74671b5..f4e0580 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Endpoint.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Endpoint.java
@@ -114,6 +114,12 @@
return counters.value(CounterName.RequestsBad);
}
+ public static boolean sameNameAndOperation(Endpoint ep1, Endpoint ep2) {
+ return
+ Objects.equals(ep1.getName(), ep2.getName()) &&
+ Objects.equals(ep1.getOperation(), ep2.getOperation()) ;
+ }
+
@Override
public String toString() {
return getName()+"["+operation+"]";
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/EndpointFactoryRegistry.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/EndpointFactoryRegistry.java
deleted file mode 100644
index 1552b01..0000000
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/EndpointFactoryRegistry.java
+++ /dev/null
@@ -1,26 +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.server;
-
-/**
- *
- */
-public class EndpointFactoryRegistry {
-
-}
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java
index 4c87213..7ab6ff7 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java
@@ -56,6 +56,7 @@
// Server endpoints.
public static final Property pServerPing = property("pingEP");
public static final Property pServerStats = property("statsEP");
+ public static final Property pServerMetrics = property("metricsEP");
// Endpoint description - old style.
public static final Property pServiceQueryEP = property("serviceQuery");
@@ -64,10 +65,11 @@
public static final Property pServiceShaclEP = property("serviceShacl");
public static final Property pServiceReadWriteGraphStoreEP = property("serviceReadWriteGraphStore");
public static final Property pServiceReadGraphStoreEP = property("serviceReadGraphStore");
- public static final Property pServiceReadWriteQuadsEP = property("serviceReadWriteQuads");
- public static final Property pServiceReadQuadsEP = property("serviceReadQuads");
+ // No longer used.
+// public static final Property pServiceReadWriteQuadsEP = property("serviceReadWriteQuads");
+// public static final Property pServiceReadQuadsEP = property("serviceReadQuads");
- // Operation names : the standard operations.
+ // Operation names : the standard operations.
// "alt" names are the same but using "_" not "_".
public static final Resource opQuery = resource("query");
public static final Resource opUpdate = resource("update");
@@ -79,7 +81,7 @@
public static final Resource opNoOp = resource("no-op");
public static final Resource opNoOp_alt = resource("no_op");
public static final Resource opShacl = resource("shacl");
-
+
// Internal
private static final String stateNameActive = DataServiceStatus.ACTIVE.name;
private static final String stateNameOffline = DataServiceStatus.OFFLINE.name;
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionErrorException.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionErrorException.java
index d3784cf..2cef6c3 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionErrorException.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionErrorException.java
@@ -21,7 +21,7 @@
public class ActionErrorException extends RuntimeException {
private final int rc;
- public ActionErrorException(Throwable ex, String message, int rc) {
+ public ActionErrorException(int rc, String message, Throwable ex) {
super(message, ex);
this.rc = rc;
}
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionExecLib.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionExecLib.java
index 6ce59dc..27735c9 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionExecLib.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionExecLib.java
@@ -111,7 +111,7 @@
// global -- cxt.get(ARQ.queryTimeout)
// dataset -- dataset.getContect(ARQ.queryTimeout)
// protocol -- SPARQL_Query.setAnyTimeouts
- String message = String.format("Query timed out");
+ String message = "Query timed out";
ServletOps.responseSendError(response, HttpSC.SERVICE_UNAVAILABLE_503, message);
} catch (ActionErrorException ex) {
if ( ex.getCause() != null )
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java
index fa0ea1c..81e7520 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java
@@ -430,6 +430,6 @@
@Override
public String toString() {
- return request.getRequestURL().toString();
+ return request.getMethod()+" "+request.getRequestURL().toString();
}
}
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQLQueryProcessor.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQLQueryProcessor.java
index 2efc50d..282892c 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQLQueryProcessor.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQLQueryProcessor.java
@@ -253,11 +253,11 @@
} catch (ActionErrorException ex) {
throw ex;
} catch (QueryParseException ex) {
- ServletOps.errorBadRequest("Parse error: \n" + queryString + "\n\r" + SPARQLProtocol.messageForException(ex));
+ ServletOps.errorBadRequest("Parse error: \n" + queryString + "\n" + SPARQLProtocol.messageForException(ex));
}
// Should not happen.
catch (QueryException ex) {
- ServletOps.errorBadRequest("Error: \n" + queryString + "\n\r" + ex.getMessage());
+ ServletOps.errorBadRequest("Error: \n" + queryString + "\n" + ex.getMessage());
}
// Assumes finished whole thing by end of sendResult.
@@ -277,7 +277,7 @@
}
catch (QueryParseException ex) {
// Late stage static error (e.g. bad fixed Lucene query string).
- ServletOps.errorBadRequest("Query parse error: \n" + queryString + "\n\r" + SPARQLProtocol.messageForException(ex));
+ ServletOps.errorBadRequest("Query parse error: \n" + queryString + "\n" + SPARQLProtocol.messageForException(ex));
}
catch (QueryCancelledException ex) {
// Additional counter information.
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ServletOps.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ServletOps.java
index 6bee2ee..21f6563 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ServletOps.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ServletOps.java
@@ -37,22 +37,50 @@
public class ServletOps {
+ /** Send an HTTP error response.
+ * Include an optional message in the body (as text/plain), if provided.
+ * Note that we do not set a custom Reason Phrase.
+ * <br/>
+ * HTTPS/2 does not have a "Reason Phrase".
+ *
+ * @param response
+ * @param statusCode
+ * @param message
+ */
public static void responseSendError(HttpServletResponse response, int statusCode, String message) {
+ response.setStatus(statusCode);
+ if ( message != null )
+ writeMessagePlainText(response, message);
+ //response.sendError(statusCode, message);
+ }
+
+ /** Send an HTTP response with no body */
+ public static void responseSendError(HttpServletResponse response, int statusCode) {
+ response.setStatus(statusCode);
+ }
+
+ /** Write a plain text body.
+ * <p>
+ * Use Content-Length so the connection is preserved.
+ */
+ public static void writeMessagePlainText(HttpServletResponse response, String message) {
+ if ( message == null )
+ return;
try {
- response.sendError(statusCode, message);
+ if ( ! message.endsWith("\n") )
+ message = message+"\n";
+ response.setContentLength(message.length());
+ response.setContentType(WebContent.contentTypeTextPlain);
+ response.setCharacterEncoding(WebContent.charsetUTF8);
+ ServletOps.setNoCache(response);
+ try(ServletOutputStream out = response.getOutputStream()){
+ out.print(message);
+ }
} catch (IOException ex) {
errorOccurred(ex);
} catch (IllegalStateException ex) {}
}
-
- public static void responseSendError(HttpServletResponse response, int statusCode) {
- try {
- response.sendError(statusCode);
- } catch (IOException ex) {
- errorOccurred(ex);
- }
- }
-
+
public static void successNoContent(HttpAction action) {
success(action, HttpSC.NO_CONTENT_204);
}
@@ -78,6 +106,7 @@
public static void successPage(HttpAction action, String message) {
try {
action.response.setContentType("text/html");
+ action.response.setCharacterEncoding(WebContent.charsetUTF8);
action.response.setStatus(HttpSC.OK_200);
PrintWriter out = action.response.getWriter();
out.println("<html>");
@@ -146,11 +175,11 @@
}
public static void error(int statusCode) {
- throw new ActionErrorException(null, null, statusCode);
+ throw new ActionErrorException(statusCode, null, null);
}
public static void error(int statusCode, String string) {
- throw new ActionErrorException(null, string, statusCode);
+ throw new ActionErrorException(statusCode, string, null);
}
public static void errorOccurred(String message) {
@@ -162,7 +191,7 @@
}
public static void errorOccurred(String message, Throwable ex) {
- throw new ActionErrorException(ex, message, HttpSC.INTERNAL_SERVER_ERROR_500);
+ throw new ActionErrorException(HttpSC.INTERNAL_SERVER_ERROR_500, message, ex);
}
public static String formatForLog(String string) {
diff --git a/jena-fuseki2/jena-fuseki-docker/Dockerfile b/jena-fuseki2/jena-fuseki-docker/Dockerfile
new file mode 100644
index 0000000..abe6d9c
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-docker/Dockerfile
@@ -0,0 +1,115 @@
+## 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.
+
+## Apache Jena Fuseki server Dockerfile.
+
+## This Dockefile builds a reduced footprint container.
+
+ARG OPENJDK_VERSION=14
+ARG ALPINE_VERSION=3.12.0
+ARG JENA_VERSION=""
+
+# Internal, passed between stages.
+ARG FUSEKI_DIR=/fuseki
+ARG FUSEKI_JAR=jena-fuseki-server-${JENA_VERSION}.jar
+ARG JAVA_MINIMAL=/opt/java-minimal
+
+## ---- Stage: Download and build java.
+FROM openjdk:${OPENJDK_VERSION}-alpine AS base
+
+ARG JAVA_MINIMAL
+ARG JENA_VERSION
+ARG FUSEKI_DIR
+ARG FUSEKI_JAR
+ARG REPO=https://repo1.maven.org/maven2
+ARG JAR_URL=${REPO}/org/apache/jena/jena-fuseki-server/${JENA_VERSION}/${FUSEKI_JAR}
+
+RUN [ "${JENA_VERSION}" != "" ] || { echo -e '\n**** Set JENA_VERSION ****\n' ; exit 1 ; }
+RUN echo && echo "==== Docker build for Apache Jena Fuseki ${JENA_VERSION} ====" && echo
+
+# Alpine: For objcopy used in jlink
+RUN apk add --no-cache curl binutils
+
+## -- Fuseki installed and runs in /fuseki.
+WORKDIR $FUSEKI_DIR
+
+## -- Download the jar file.
+COPY download.sh .
+RUN chmod a+x download.sh
+
+# Download, with check of the SHA1 checksum.
+RUN ./download.sh --chksum sha1 "$JAR_URL"
+
+## -- Alternatives to download : copy already downloaded.
+## COPY ${FUSEKI_JAR} .
+
+## Use Docker ADD - does not retry, does not check checksum, and may run every build.
+## ADD "$JAR_URL"
+
+## -- Make reduced Java JDK
+RUN \
+ JDEPS="$(jdeps --multi-release base --print-module-deps --ignore-missing-deps ${FUSEKI_JAR})" && \
+ jlink \
+ --compress 2 --strip-debug --no-header-files --no-man-pages \
+ --output "${JAVA_MINIMAL}" \
+ --add-modules "${JDEPS}"
+
+ADD entrypoint.sh .
+ADD log4j2.properties .
+
+# Run as this user
+# -H : no home directorry
+# -D : no password
+
+RUN adduser -H -D fuseki fuseki
+
+## ---- Stage: Build runtime
+FROM alpine:${ALPINE_VERSION}
+
+## Import ARGs
+ARG JENA_VERSION
+ARG JAVA_MINIMAL
+ARG FUSEKI_DIR
+ARG FUSEKI_JAR
+
+COPY --from=base /opt/java-minimal /opt/java-minimal
+COPY --from=base /fuseki /fuseki
+COPY --from=base /etc/passwd /etc/passwd
+
+WORKDIR $FUSEKI_DIR
+
+ARG LOGS=${FUSEKI_DIR}/logs
+ARG DATA=${FUSEKI_DIR}/databases
+
+RUN \
+ mkdir -p $LOGS && \
+ mkdir -p $DATA && \
+ chown -R fuseki ${FUSEKI_DIR} && \
+ chmod a+x entrypoint.sh
+
+## Default environment variables.
+ENV \
+ JAVA_HOME=${JAVA_MINIMAL} \
+ JAVA_OPTIONS="-Xmx2048m -Xms2048m" \
+ JENA_VERSION=${JENA_VERSION} \
+ FUSEKI_JAR="${FUSEKI_JAR}" \
+ FUSEKI_DIR="${FUSEKI_DIR}"
+
+USER fuseki
+
+EXPOSE 3030
+
+ENTRYPOINT ["./entrypoint.sh" ]
+CMD []
diff --git a/jena-fuseki2/jena-fuseki-docker/README.md b/jena-fuseki2/jena-fuseki-docker/README.md
new file mode 100644
index 0000000..eecdcb8
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-docker/README.md
@@ -0,0 +1,109 @@
+# Apache Jena Fuseki Docker Tools
+
+This package contains a Dockerfile, docker-compose file, and helper scripts to
+create a docker container for Apache Jena Fuseki.
+
+The docker container is based on
+[Fuseki main](https://jena.apache.org/documentation/fuseki2/fuseki-main)
+for running a SPARQL server.
+
+There is no UI - all configuration is by command line and all usage by via the
+network protocols.
+
+Databases can be mounted outside the docker container so they are preserved when
+the container terminates.
+
+This build system allows the user to customize the docker image.
+
+The docker build downloads the server binary from
+[Maven central](https://repo1.maven.org/maven2/org/apache/jena/jena-fuseki-server/),
+checking the download against the SHA1 checksum.
+
+## Database
+
+There is a volume mapping "./databases" in the current directory into the server.
+This can be used to contain databases outside, but accessible to, the container
+that do not get deleted when the container exits.
+
+See examples below.
+
+## Build
+
+Choose the version number of Apache Jena release you wish to use. This toolkit
+defaults to the version of the overall Jena release it was part of. It is best
+to use the release of this set of tools from the same release of the desired
+server.
+
+ docker-compose build --build-arg JENA_VERSION=3.16.0
+
+Note the build command must provide the version number.
+
+## Test Run
+
+`docker-compose run` cam be used to test the build from the previous section.
+
+Examples:
+
+Start Fuseki with an in-memory, updatable dataset at http://<i>host</i>:3030/ds
+
+ docker-compose run --rm --service-ports fuseki --mem /ds
+
+Load a TDB2 database, and expose, read-only, via docker:
+
+ mkdir -p databases/DB2
+ tdb2.tdbloader --loc databases/DB2 MyData.ttl
+ # Publish read-only
+ docker-compose run --rm --name MyServer --service-ports fuseki --tdb2 --loc databases/DB2 /ds
+
+To allow update on the database, add `--update`. Updates are persisted.
+
+ docker-compose run --rm --name MyServer --service-ports fuseki --tdb2 --update --loc databases/DB2 /ds
+
+See
+[fuseki-configuration](https://jena.apache.org/documentation/fuseki2/fuseki-configuration.html)
+for more information on command line arguments.
+
+To use `docker-compose up`, edit the `docker-compose.yaml` to set the Fuseki
+command line arguments appropriately.
+
+## Layout
+
+The default layout in the container is:
+
+| Path | Use |
+| ----- | --- |
+| /opt/java-minimal | A reduced size Java runtime |
+| /fuseki | The Fuseki installation |
+| /fuseki/log4j2.properties | Logging configuration |
+| /fuseki/databases/ | Directory for a volume for persistent databases |
+
+## Setting JVM arguments
+
+Use `JAVA_OPTIONS`:
+
+ docker-compose run --service-ports --rm -e JAVA_OPTIONS="-Xmx1048m -Xms1048m" --name MyServer fuseki --mem /ds
+
+## Docker Commands
+
+If you prefer to use `docker` directly:
+
+Build:
+
+ docker build --force-rm --build-arg JENA_VERSION=3.16.0 -t fuseki .
+
+Run:
+
+ docker run -i --rm -p "3030:3030" --name MyServer -t fuseki --mem /ds
+
+With databases on a bind mount to host filesystem directory:
+
+ MNT="--mount type=bind,src=$PWD/databases,dst=/fuseki/databases"
+ docker run -i --rm -p "3030:3030" $MNT --name MyServer -t fuseki --tdb2 --update --loc databases/DB2 /ds
+
+## Version specific notes:
+
+* Versions of Jena up to 3.14.0 use Log4j1 for logging. The docker will build will ignore
+ the log4j2.properties file
+* Version 3.15.0: When run, a warning will be emitted.
+ `WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.`
+ This can be ignored.
diff --git a/jena-fuseki2/jena-fuseki-docker/assembly-docker.xml b/jena-fuseki2/jena-fuseki-docker/assembly-docker.xml
new file mode 100644
index 0000000..b62113f
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-docker/assembly-docker.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+
+<!--
+ The docker tools distribution.
+-->
+
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+
+ <id>distribution</id>
+
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
+
+ <!-- If including the jar
+ <dependencySets>
+ <dependencySet>
+ <useProjectArtifact>false</useProjectArtifact>
+ <includes>
+ <include>org.apache.jena:jena-fuseki-server:jar</include>
+ </includes>
+ <outputFileNameMapping>fuseki-server.jar</outputFileNameMapping>
+ <outputFileNameMapping>jena-fuseki-server-${artifact.version}.jar</outputFileNameMapping>
+ </dependencySet>
+ </dependencySets>
+ -->
+
+ <files>
+ <file>
+ <source>dist/LICENSE</source>
+ <destName>LICENSE</destName>
+ </file>
+ <file>
+ <source>dist/NOTICE</source>
+ <destName>NOTICE</destName>
+ </file>
+ </files>
+
+ <fileSets>
+ <fileSet>
+ <outputDirectory></outputDirectory>
+ <includes>
+ <include>Dockerfile*</include>
+ <include>docker-compose.yaml</include>
+ <include>README*</include>
+ <include>log4j2.properties</include>
+ <include>entrypoint.sh</include>
+ <include>download.sh</include>
+ <include>.dockerignore</include>
+ </includes>
+ </fileSet>
+
+ </fileSets>
+</assembly>
diff --git a/jena-fuseki2/jena-fuseki-docker/dist/LICENSE b/jena-fuseki2/jena-fuseki-docker/dist/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-docker/dist/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed 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.
diff --git a/jena-fuseki2/jena-fuseki-docker/dist/NOTICE b/jena-fuseki2/jena-fuseki-docker/dist/NOTICE
new file mode 100644
index 0000000..5a33516
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-docker/dist/NOTICE
@@ -0,0 +1,5 @@
+Apache Jena - module Fuseki (Docker tools)
+Copyright - The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/jena-fuseki2/jena-fuseki-docker/docker-compose.yaml b/jena-fuseki2/jena-fuseki-docker/docker-compose.yaml
new file mode 100644
index 0000000..4433e9d
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-docker/docker-compose.yaml
@@ -0,0 +1,32 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.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.
+
+version: '3.0'
+services:
+ fuseki:
+ ## Example:
+ ## command: [ "--tdb2", "--update", "--loc", "databases/DB2", "/ds" ]
+ build:
+ context: .
+ dockerfile: Dockerfile
+ image: fuseki
+ ports:
+ - "3030:3030"
+ volumes:
+ - ./logs:/fuseki/logs
+ - ./databases:/fuseki/databases
+#volumes:
diff --git a/jena-fuseki2/jena-fuseki-docker/download.sh b/jena-fuseki2/jena-fuseki-docker/download.sh
new file mode 100755
index 0000000..bf4e2ae
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-docker/download.sh
@@ -0,0 +1,147 @@
+#!/bin/sh
+
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.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.
+
+# This is an ash/dash script (it uses "local"), not a bash script.
+# It can run in an Alpine image durign a docker build.
+#
+# The advantage over using docker ADD is that it checks
+# whether download file is already present and does not
+# download each time.
+#
+# Shell script to download URL and check the checksum
+
+USAGE="Usage: $(basename "$0") --chksum [sha1|sha512] URL"
+
+if [ $# -eq 0 ]
+then
+ echo "$USAGE" 2>&1
+ exit 1
+fi
+
+CHKSUM_TYPE='unset'
+
+while [ $# -gt 0 ] ; do
+ case "$1" in
+ --chksum|-chksum|-sha|--sha)
+ if [ $# -lt 2 ]
+ then
+ echo "$USAGE" 1>&2
+ exit 1
+ fi
+ CHKSUM_TYPE=$2
+ shift
+ shift
+ ;;
+ -h|--help)
+ echo "$USAGE" 1>&2
+ exit 0
+ ;;
+ -*)
+ echo "$USAGE" 1>&2
+ exit 1
+ ;;
+ *)
+ if [ $# -ne 1 ]
+ then
+ echo "$USAGE" 1>&2
+ exit 1
+ fi
+ URL="$1"
+ shift
+ ;;
+ esac
+done
+
+case "${CHKSUM_TYPE}" in
+ unset)
+ echo "$USAGE" 1>&2
+ exit 1
+ ;;
+ sha*|md5) ;;
+ *)
+ echo "Bad checksum type: '$CHKSUM_TYPE' (must start 'sha' or be 'md5')" 2>&1
+ exit 1
+ ;;
+esac
+
+## ---- Script starts ----
+
+ARTIFACT_URL="${URL}"
+ARTIFACT_NAME="$(basename "$ARTIFACT_URL")"
+
+# -------- Checksum details
+
+CHKSUM_EXT=".${CHKSUM_TYPE}"
+CHKSUM_URL="${ARTIFACT_URL}${CHKSUM_EXT}"
+CHKSUM_FILE="${ARTIFACT_NAME}${CHKSUM_EXT}"
+CHKSUMPROG="${CHKSUM_TYPE}sum"
+# --------
+
+CURL_FETCH_OPTS="-s -S --fail --location --max-redirs 3"
+if false
+then
+ echo "ARTIFACT_URL=$ARTIFACT_URL"
+ echo "CHKSUM_URL=$CHKSUM_URL"
+fi
+
+download() { # URL
+ local URL="$1"
+ local FN="$(basename "$URL")"
+ if [ ! -e "$FN" ]
+ then
+ echo "Fetching $URL"
+ curl $CURL_FETCH_OPTS "$URL" --output "$FN" \
+ || { echo "Bad download of $FN" 2>&1 ; return 1 ; }
+ else
+ echo "$FN already present"
+ fi
+ return 0
+}
+
+checkChksum() { # Filename checksum
+ local FN="$1"
+ local CHKSUM="$2"
+ if [ ! -e "$FN" ]
+ then
+ echo "No such file: '$FN'" 2>&1
+ exit 1
+ fi
+ # NB Two spaces required for busybox
+ echo "$CHKSUM $FN" | ${CHKSUMPROG} -c > /dev/null
+}
+
+download "$ARTIFACT_URL" || exit 1
+
+if [ -z "$CHKSUM" ]
+then
+ # Checksum not previously set.
+ # Extract from file, copes with variations in content (filename or not)
+ download "$CHKSUM_URL" || exit 1
+ CHKSUM="$(cut -d' ' -f1 "$CHKSUM_FILE")"
+fi
+
+checkChksum "${ARTIFACT_NAME}" "$CHKSUM"
+if [ $? = 0 ]
+then
+ echo "Good download: $ARTIFACT_NAME"
+else
+ echo "BAD download !!!! $ARTIFACT_NAME"
+ echo "To retry: delete downloaded files and try again"
+ exit 1
+fi
diff --git a/jena-fuseki2/jena-fuseki-docker/entrypoint.sh b/jena-fuseki2/jena-fuseki-docker/entrypoint.sh
new file mode 100755
index 0000000..a4ab8cd
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-docker/entrypoint.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+## env | sort
+exec "$JAVA_HOME/bin/java" $JAVA_OPTIONS -jar "${FUSEKI_DIR}/${FUSEKI_JAR}" "$@"
diff --git a/jena-fuseki2/jena-fuseki-docker/log4j2.properties b/jena-fuseki2/jena-fuseki-docker/log4j2.properties
new file mode 100644
index 0000000..9235085
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-docker/log4j2.properties
@@ -0,0 +1,70 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+status = error
+name = PropertiesConfig
+filters = threshold
+
+filter.threshold.type = ThresholdFilter
+filter.threshold.level = INFO
+
+appender.console.type = Console
+appender.console.name = OUT
+appender.console.target = SYSTEM_OUT
+appender.console.layout.type = PatternLayout
+## appender.console.layout.pattern = %d{HH:mm:ss} %-5p %-15c{1} :: %m%n
+## Include date.
+appender.console.layout.pattern = [%d{yyyy-MM-dd HH:mm:ss}] %-5p %-15c{1} :: %m%n
+
+## To a file.
+## appender.file.type = File
+## appender.file.name = FILE
+## appender.file.fileName=/fuseki/logs/log.fuseki
+## appender.file.layout.type=PatternLayout
+## appender.file.layout.pattern = [%d{yyyy-MM-dd HH:mm:ss}] %-5p %-15c{1} :: %m%n
+
+rootLogger.level = INFO
+rootLogger.appenderRef.stdout.ref = OUT
+
+logger.jena.name = org.apache.jena
+logger.jena.level = INFO
+
+logger.arq-exec.name = org.apache.jena.arq.exec
+logger.arq-exec.level = INFO
+
+logger.riot.name = org.apache.jena.riot
+logger.riot.level = INFO
+
+logger.fuseki.name = org.apache.jena.fuseki
+logger.fuseki.level = INFO
+
+logger.fuseki-fuseki.name = org.apache.jena.fuseki.Fuseki
+logger.fuseki-fuseki.level = INFO
+
+logger.fuseki-server.name = org.apache.jena.fuseki.Server
+logger.fuseki-server.level = INFO
+
+logger.fuseki-admin.name = org.apache.jena.fuseki.Admin
+logger.fuseki-admin.level = INFO
+
+logger.jetty.name = org.eclipse.jetty
+logger.jetty.level = WARN
+
+# May be useful to turn up to DEBUG if debugging HTTP communication issues
+logger.apache-http.name = org.apache.http
+logger.apache-http.level = WARN
+
+logger.shiro.name = org.apache.shiro
+logger.shiro.level = WARN
+# Hide bug in Shiro 1.5.x
+logger.shiro-realm.name = org.apache.shiro.realm.text.IniRealm
+logger.shiro-realm.level = ERROR
+
+# This goes out in NCSA format
+appender.plain.type = Console
+appender.plain.name = PLAIN
+appender.plain.layout.type = PatternLayout
+appender.plain.layout.pattern = %m%n
+
+logger.request-log.name = org.apache.jena.fuseki.Request
+logger.request-log.additivity = false
+logger.request-log.level = OFF
+logger.request-log.appenderRef.plain.ref = PLAIN
diff --git a/jena-fuseki2/jena-fuseki-docker/pom.xml b/jena-fuseki2/jena-fuseki-docker/pom.xml
new file mode 100644
index 0000000..b400e0e
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-docker/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <name>Apache Jena - Fuseki Docker Tools</name>
+ <artifactId>jena-fuseki-docker</artifactId>
+ <version>3.17.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <parent>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>jena-fuseki</artifactId>
+ <version>3.17.0-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <description>Fuseki Docker</description>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>create-zip-assembly</id>
+ <phase>package</phase>
+ <!--<phase />-->
+ <goals><goal>single</goal></goals>
+ <configuration>
+ <appendAssemblyId>false</appendAssemblyId>
+ <tarLongFileMode>posix</tarLongFileMode>
+ <descriptors>
+ <descriptor>assembly-docker.xml</descriptor>
+ </descriptors>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+
+ </build>
+
+</project>
diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
index 2b09b94..65438ca 100644
--- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
+++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
@@ -27,6 +27,8 @@
import javax.servlet.Filter;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import org.apache.jena.atlas.lib.Pair;
import org.apache.jena.atlas.logging.FmtLog;
@@ -38,9 +40,10 @@
import org.apache.jena.fuseki.auth.Auth;
import org.apache.jena.fuseki.auth.AuthPolicy;
import org.apache.jena.fuseki.build.FusekiConfig;
+import org.apache.jena.fuseki.ctl.ActionMetrics;
import org.apache.jena.fuseki.ctl.ActionPing;
import org.apache.jena.fuseki.ctl.ActionStats;
-import org.apache.jena.fuseki.jetty.FusekiErrorHandler1;
+import org.apache.jena.fuseki.jetty.FusekiErrorHandler;
import org.apache.jena.fuseki.jetty.JettyHttps;
import org.apache.jena.fuseki.jetty.JettyLib;
import org.apache.jena.fuseki.metrics.MetricsProviderRegistry;
@@ -242,8 +245,10 @@
private int serverHttpsPort = -1;
private boolean networkLoopback = false;
private boolean verbose = false;
- private boolean withStats = false;
private boolean withPing = false;
+ private boolean withMetrics = false;
+ private boolean withStats = false;
+
private Map<String, String> corsInitParams = null;
// Server wide authorization policy.
@@ -403,6 +408,14 @@
return this;
}
+ /** Add the "/$/ping" servlet that responds to HTTP very efficiently.
+ * This is useful for testing whether a server is alive, for example, from a load balancer.
+ */
+ public Builder enablePing(boolean withPing) {
+ this.withPing = withPing;
+ return this;
+ }
+
/** Add the "/$/stats" servlet that responds with stats about the server,
* including counts of all calls made.
*/
@@ -411,11 +424,9 @@
return this;
}
- /** Add the "/$/ping" servlet that responds to HTTP very efficiently.
- * This is useful for testing whether a server is alive, for example, from a load balancer.
- */
- public Builder enablePing(boolean withPing) {
- this.withPing = withPing;
+ /** Add the "/$/metrics" servlet that responds with Prometheus metrics about the server. */
+ public Builder enableMetrics(boolean withMetrics) {
+ this.withMetrics = withMetrics;
return this;
}
@@ -531,6 +542,7 @@
withPing = argBoolean(server, FusekiVocab.pServerPing, false);
withStats = argBoolean(server, FusekiVocab.pServerStats, false);
+ withMetrics = argBoolean(server, FusekiVocab.pServerMetrics, false);
// Extract settings - the server building is done in buildSecurityHandler,
// buildAccessControl. Dataset and graph level happen in assemblers.
@@ -972,7 +984,7 @@
contextPath = "/" + contextPath;
ServletContextHandler context = new ServletContextHandler();
context.setDisplayName(Fuseki.servletRequestLogName);
- context.setErrorHandler(new FusekiErrorHandler1());
+ context.setErrorHandler(new FusekiErrorHandler());
context.setContextPath(contextPath);
// SPARQL Update by HTML - not the best way but.
context.setMaxFormContentSize(1024*1024);
@@ -1003,10 +1015,12 @@
addFilter(context, "/*", ff);
// and then any additional servlets and filters.
- if ( withStats )
- addServlet(context, "/$/stats/*", new ActionStats());
if ( withPing )
addServlet(context, "/$/ping", new ActionPing());
+ if ( withStats )
+ addServlet(context, "/$/stats/*", new ActionStats());
+ if ( withMetrics )
+ addServlet(context, "/$/metrics", new ActionMetrics());
servlets.forEach(p-> addServlet(context, p.getLeft(), p.getRight()));
filters.forEach (p-> addFilter(context, p.getLeft(), p.getRight()));
@@ -1017,6 +1031,33 @@
ServletHolder staticContent = new ServletHolder(staticServlet);
staticContent.setInitParameter("resourceBase", staticContentDir);
context.addServlet(staticContent, "/");
+ } else {
+ // Backstop servlet
+ // Jetty default is 404 on GET and 405 otherwise
+ HttpServlet staticServlet = new Servlet404();
+ ServletHolder staticContent = new ServletHolder(staticServlet);
+ context.addServlet(staticContent, "/");
+ }
+ }
+
+ /** 404 for HEAD/GET/POST/PUT */
+ static class Servlet404 extends HttpServlet {
+ // service()?
+ @Override
+ protected void doHead(HttpServletRequest req, HttpServletResponse resp) { err404(req, resp); }
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) { err404(req, resp); }
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) { err404(req, resp); }
+ @Override
+ protected void doPut(HttpServletRequest req, HttpServletResponse resp) { err404(req, resp); }
+ //protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
+ //protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
+ //protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
+ private static void err404(HttpServletRequest req, HttpServletResponse response) {
+ try {
+ response.sendError(404, "NOT FOUND");
+ } catch (IOException ex) {}
}
}
diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiMain.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiMain.java
index d1aeb1e..5e4beae 100644
--- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiMain.java
+++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiMain.java
@@ -86,6 +86,7 @@
private static ArgDecl argCORS = new ArgDecl(ArgDecl.NoValue, "withCORS", "cors", "CORS");
private static ArgDecl argWithPing = new ArgDecl(ArgDecl.NoValue, "withPing", "ping");
private static ArgDecl argWithStats = new ArgDecl(ArgDecl.NoValue, "withStats", "stats");
+ private static ArgDecl argWithMetrics = new ArgDecl(ArgDecl.NoValue, "withMetrics", "metrics");
private static ArgDecl argAuth = new ArgDecl(ArgDecl.HasValue, "auth");
@@ -170,6 +171,7 @@
// add(argRealm, "--realm=REALM", "Realm name");
add(argWithPing, "--ping", "Enable /$/ping");
add(argWithStats, "--stats", "Enable /$/stats");
+ add(argWithMetrics, "--metrics", "Enable /$/metrics");
super.modVersion.addClass(Fuseki.class);
}
@@ -397,6 +399,7 @@
serverConfig.withCORS = contains(argCORS);
serverConfig.withPing = contains(argWithPing);
serverConfig.withStats = contains(argWithStats);
+ serverConfig.withMetrics = contains(argWithMetrics);
// if ( contains(argGZip) ) {
// if ( !hasValueOfTrue(argGZip) && !hasValueOfFalse(argGZip) )
@@ -507,6 +510,9 @@
if ( serverConfig.withStats )
builder.enableStats(true);
+ if ( serverConfig.withMetrics )
+ builder.enableMetrics(true);
+
return builder.build();
}
diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/ServerConfig.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/ServerConfig.java
index 73f8da0..8e83e61 100644
--- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/ServerConfig.java
+++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/ServerConfig.java
@@ -40,6 +40,7 @@
public boolean withCORS = false;
public boolean withPing = false;
public boolean withStats = false;
+ public boolean withMetrics = false;
// This is set ...
public DatasetGraph dsg = null;
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/FusekiTestLib.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/FusekiTestLib.java
index 89a9d1c..a0f47eb 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/FusekiTestLib.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/FusekiTestLib.java
@@ -30,7 +30,7 @@
public static void expect401(Runnable runnable) {
expectFail(runnable, HttpSC.Code.UNAUTHORIZED);
}
-
+
public static void expect403(Runnable runnable) {
expectFail(runnable, HttpSC.Code.FORBIDDEN);
}
@@ -38,13 +38,12 @@
public static void expect404(Runnable runnable) {
expectFail(runnable, HttpSC.Code.NOT_FOUND);
}
-
+
public static void expectFail(Runnable runnable, Code code) {
if ( code == null || ( 200 <= code.getCode() && code.getCode() < 300 ) ) {
runnable.run();
return;
}
-
try {
runnable.run();
fail("Failed: Got no exception: Expected HttpException "+code.getCode());
@@ -55,12 +54,23 @@
}
}
+ public static int expectFail(Runnable runnable) {
+ try {
+ runnable.run();
+ fail("Failed: Got no exception: Expected HttpException");
+ return -1;
+ } catch (HttpException ex) {
+ return ex.getStatusCode();
+ }
+ }
+
+
// Same - except a QueryExceptionHTTP.
-
+
public static void expectQuery401(Runnable runnable) {
expectQueryFail(HttpSC.Code.UNAUTHORIZED, runnable);
}
-
+
public static void expectQuery403(Runnable runnable) {
expectQueryFail(HttpSC.Code.FORBIDDEN, runnable);
}
@@ -68,13 +78,13 @@
public static void expectQuery404(Runnable runnable) {
expectQueryFail(HttpSC.Code.NOT_FOUND, runnable);
}
-
+
public static void expectQueryFail(Code code, Runnable runnable) {
if ( code == null || ( 200 <= code.getCode() && code.getCode() < 300 ) ) {
runnable.run();
return;
}
-
+
try {
runnable.run();
fail("Failed: Got no exception: Expected QueryExceptionHTTP "+code.getCode());
@@ -84,7 +94,7 @@
throw ex;
}
}
-
+
public static void expectOK(Runnable runnable) {
runnable.run();
}
@@ -92,7 +102,7 @@
public static void expectQueryOK(Runnable runnable) {
runnable.run();
}
-
+
public static void expectQueryAccessFail(Runnable runnable) {
try {
runnable.run();
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TS_FusekiMain.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TS_FusekiMain.java
index 408fa1b..6bdf2de 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TS_FusekiMain.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TS_FusekiMain.java
@@ -31,6 +31,8 @@
, TestFusekiCustomOperation.class
, TestFusekiMainCmd.class
, TestStdSetup.class
+ , TestConfigFile.class
+ , TestHTTP.class
, TestFusekiShaclValidation.class
})
public class TS_FusekiMain {}
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestConfigFile.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestConfigFile.java
index b271d60..4721f51 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestConfigFile.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestConfigFile.java
@@ -22,6 +22,7 @@
import static org.apache.jena.fuseki.test.FusekiTest.expect404;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.apache.jena.atlas.lib.StrUtils;
@@ -32,22 +33,23 @@
import org.apache.jena.rdfconnection.RDFConnectionFactory;
import org.apache.jena.rdfconnection.RDFConnectionRemote;
import org.apache.jena.rdfconnection.RDFConnectionRemoteBuilder;
+import org.apache.jena.riot.web.HttpOp;
import org.apache.jena.sparql.core.Var;
import org.junit.Test;
-/** Test server configuration by configuration file */
+/** Test server configuration by configuration file */
public class TestConfigFile {
private static final String DIR = "testing/Config/";
-
+
private static final String PREFIXES = StrUtils.strjoinNL
- ("PREFIX afn: <http://jena.apache.org/ARQ/function#>"
+ ("PREFIX afn: <http://jena.apache.org/ARQ/function#>"
,"PREFIX fuseki: <http://jena.apache.org/fuseki#>"
,"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>"
,"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>"
, ""
);
-
+
private static RDFConnection namedServices(String baseURL) {
return RDFConnectionRemote.create()
.destination(baseURL)
@@ -56,9 +58,9 @@
.gspEndpoint("data")
.build();
}
-
+
@Test public void basic () {
- int port = WebLib.choosePort();
+ int port = WebLib.choosePort();
FusekiServer server = server(port, "basic.ttl");
server.start();
try ( RDFConnection conn = RDFConnectionFactory.connect("http://localhost:"+port+"/ds") ) {
@@ -70,7 +72,7 @@
}
@Test public void context() {
- int port = WebLib.choosePort();
+ int port = WebLib.choosePort();
FusekiServer server = server(port, "context.ttl");
server.start();
try {
@@ -96,7 +98,7 @@
}
@Test public void stdServicesNamed () {
- int port = WebLib.choosePort();
+ int port = WebLib.choosePort();
FusekiServer server = server(port, "std-named.ttl");
String serverURL = "http://localhost:"+port+"/ds-named";
server.start();
@@ -108,7 +110,7 @@
Graph g = conn.fetch().getGraph();
assertEquals(1, g.size());
}
-
+
// These should not work because there is a blocking dataset service (no-op).
try ( RDFConnection conn = RDFConnectionFactory.connect(serverURL) ) {
expect400(()->conn.update("INSERT DATA { <x:s> <x:p> 123 }"));
@@ -120,37 +122,37 @@
server.stop();
}
}
-
- @Test public void stdServicesDirect () {
- int port = WebLib.choosePort();
+
+ @Test public void stdServicesDirect() {
+ int port = WebLib.choosePort();
FusekiServer server = server(port, "std-dataset.ttl");
String serverURL = "http://localhost:"+port+"/ds-direct";
server.start();
try {
- try ( RDFConnection conn = RDFConnectionFactory.connect(serverURL) ) {
- conn.update("INSERT DATA { <x:s> <x:p> 123 }");
- conn.queryAsk("ASK{}");
- Graph g = conn.fetch().getGraph();
- assertEquals(1, g.size());
- }
-
+// try ( RDFConnection conn = RDFConnectionFactory.connect(serverURL) ) {
+// conn.update("INSERT DATA { <x:s> <x:p> 123 }");
+// conn.queryAsk("ASK{}");
+// Graph g = conn.fetch().getGraph();
+// assertEquals(1, g.size());
+// }
+
// No named endpoints.
try ( RDFConnection conn = namedServices(serverURL) ) {
expect404(()->conn.update("INSERT DATA { <x:s> <x:p> 123 }"));
expect404(()->conn.queryAsk("ASK{}"));
expect404(()->conn.fetch());
}
-
+
} finally {
server.stop();
}
}
@Test public void stdServicesNoConfig() {
- int port = WebLib.choosePort();
+ int port = WebLib.choosePort();
FusekiServer server = server(port, "std-empty.ttl");
String serverURL = "http://localhost:"+port+"/ds-no-ep";
-
+
server.start();
try {
try ( RDFConnection conn = RDFConnectionFactory.connect(serverURL) ) {
@@ -170,51 +172,74 @@
server.stop();
}
}
-
- @Test public void stdServicesGeneral() {
- int port = WebLib.choosePort();
- FusekiServer server = server(port, "std-general.ttl");
- String serverURL = "http://localhost:"+port+"/ds";
-
+
+ // Named services mirrored onto the dataset
+ @Test public void stdServicesOldStyle() {
+ int port = WebLib.choosePort();
+ FusekiServer server = server(port, "std-old-style.ttl");
+ String serverURL = "http://localhost:"+port+"/ds0";
+
server.start();
try {
- // Either style.
-
- try ( RDFConnection conn = RDFConnectionFactory.connect(serverURL) ) {
- conn.update("INSERT DATA { <x:s> <x:p> 123 }");
- conn.queryAsk("ASK{}");
- Graph g = conn.fetch().getGraph();
- assertEquals(1, g.size());
- }
- RDFConnectionRemoteBuilder builder = RDFConnectionRemote.create()
+ RDFConnectionRemoteBuilder builderUnamedServices = RDFConnectionRemote.create()
+ .destination(serverURL)
+ .updateEndpoint("")
+ .queryEndpoint("");
+ RDFConnectionRemoteBuilder builderNamedServices = RDFConnectionRemote.create()
.destination(serverURL)
.queryEndpoint("sparql")
.updateEndpoint("update")
.gspEndpoint("data");
- try ( RDFConnection conn = builder.build() ) {
+
+ try ( RDFConnection conn = builderNamedServices.build() ) {
conn.update("INSERT DATA { <x:s> <x:p> 123 }");
+ Graph g = conn.fetch().getGraph();
+ assertEquals(1, g.size());
+ }
+
+ try ( RDFConnection conn = builderNamedServices.build() ) {
conn.queryAsk("ASK{}");
Graph g = conn.fetch().getGraph();
assertEquals(1, g.size());
}
-
+
+ try ( RDFConnection conn = builderUnamedServices.build() ) {
+ conn.update("INSERT DATA { <x:s> <x:p> 456 }");
+ conn.queryAsk("ASK{}");
+ Graph g = conn.fetch().getGraph();
+ assertEquals(2, g.size());
+ }
} finally {
server.stop();
}
}
- private static String NL = "\n";
-
+ @Test public void serverMisc() {
+ int port = WebLib.choosePort();
+ FusekiServer server = server(port, "server.ttl");
+ server.start();
+ try {
+ String x1 = HttpOp.execHttpGetString("http://localhost:"+port+"/$/ping");
+ assertNotNull(x1);
+ String x2 = HttpOp.execHttpGetString("http://localhost:"+port+"/$/stats");
+ assertNotNull(x2);
+ String x3 = HttpOp.execHttpGetString("http://localhost:"+port+"/$/metrics");
+ assertNotNull(x3);
+ } finally {
+ server.stop();
+ }
+ }
+
@Test public void unionGraph1() {
unionGraph("tdb1-endpoints.ttl","/ds-tdb1");
}
-
+
@Test public void unionGraph2() {
unionGraph("tdb2-endpoints.ttl","/ds-tdb2");
}
-
+
@Test public void setupOpsSameName() {
- int port = WebLib.choosePort();
+ int port = WebLib.choosePort();
FusekiServer server = server(port, "setup1.ttl");
String serverURL = "http://localhost:"+port+"/ds";
server.start();
@@ -228,9 +253,9 @@
server.stop();
}
}
-
+
@Test public void setupRootDataset() {
- int port = WebLib.choosePort();
+ int port = WebLib.choosePort();
FusekiServer server = server(port, "setup2.ttl");
String serverURL = "http://localhost:"+port+"/";
server.start();
@@ -245,12 +270,14 @@
}
}
+ private static String NL = "\n";
+
private void unionGraph(String fnConfig, String dbName) {
- int port = WebLib.choosePort();
+ int port = WebLib.choosePort();
FusekiServer server = server(port, fnConfig);
String serverURL = "http://localhost:"+port+dbName;
server.start();
-
+
try {
try ( RDFConnection conn = RDFConnectionFactory.connect(serverURL) ) {
conn.update("INSERT DATA {"+NL+
@@ -281,18 +308,18 @@
return x;
}
}
-
-
-
+
+
+
private static void assertCxtValue(RDFConnection conn, String contextSymbol, String value) {
- String actual =
+ String actual =
conn.query(PREFIXES+"SELECT ?V { BIND(afn:context('"+contextSymbol+"') AS ?V) }")
.execSelect()
.nextBinding().get(Var.alloc("V"))
.getLiteralLexicalForm();
assertEquals(value, actual);
}
-
+
private static void assertCxtValueNotNull(RDFConnection conn, String contextSymbol) {
boolean b = conn.queryAsk(PREFIXES+"ASK { FILTER (afn:context('"+contextSymbol+"') != '' ) }");
assertTrue(contextSymbol, b);
@@ -318,5 +345,5 @@
.port(port)
.build();
return server;
- }
+ }
}
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestEmbeddedFuseki.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestEmbeddedFuseki.java
index d2debf8..20f0780 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestEmbeddedFuseki.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestEmbeddedFuseki.java
@@ -164,7 +164,7 @@
} finally { server.stop(); }
}
- @Test public void embedded_05() {
+ @Test public void embedded_no_stats() {
DatasetGraph dsg = dataset();
int port = WebLib.choosePort();
FusekiServer server = FusekiServer.create()
@@ -173,13 +173,33 @@
.build();
server.start();
try {
- // No stats
- String x = HttpOp.execHttpGetString("http://localhost:"+port+"/$/stats");
- assertNull(x);
+ // No server services
+ String x1 = HttpOp.execHttpGetString("http://localhost:"+port+"/$/ping");
+ assertNull(x1);
+
+ String x2 = HttpOp.execHttpGetString("http://localhost:"+port+"/$/stats");
+ assertNull(x2);
+
+ String x3 = HttpOp.execHttpGetString("http://localhost:"+port+"/$/metrics");
+ assertNull(x3);
} finally { server.stop(); }
}
- @Test public void embedded_06() {
+ @Test public void embedded_ping() {
+ DatasetGraph dsg = dataset();
+ int port = WebLib.choosePort();
+ FusekiServer server = FusekiServer.create()
+ .port(port)
+ .add("/ds0", dsg)
+ .enablePing(true)
+ .build();
+ server.start();
+ String x = HttpOp.execHttpGetString("http://localhost:"+port+"/$/ping");
+ assertNotNull(x);
+ server.stop();
+ }
+
+ @Test public void embedded_stats() {
DatasetGraph dsg = dataset();
int port = WebLib.choosePort();
FusekiServer server = FusekiServer.create()
@@ -193,16 +213,16 @@
server.stop();
}
- @Test public void embedded_07() {
+ @Test public void embedded_metrics() {
DatasetGraph dsg = dataset();
int port = WebLib.choosePort();
FusekiServer server = FusekiServer.create()
.port(port)
.add("/ds0", dsg)
- .enablePing(true)
+ .enableMetrics(true)
.build();
server.start();
- String x = HttpOp.execHttpGetString("http://localhost:"+port+"/$/ping");
+ String x = HttpOp.execHttpGetString("http://localhost:"+port+"/$/metrics");
assertNotNull(x);
server.stop();
}
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestFusekiCustomOperation.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestFusekiCustomOperation.java
index a77d2b2..0afda07 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestFusekiCustomOperation.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestFusekiCustomOperation.java
@@ -1,4 +1,5 @@
-/*
+/*Multi
+ *
* 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
@@ -18,15 +19,16 @@
package org.apache.jena.fuseki.main;
+import static org.apache.jena.fuseki.main.FusekiTestLib.expectFail;
import static org.junit.Assert.*;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.jena.atlas.io.IO;
+import org.apache.jena.atlas.lib.Lib;
import org.apache.jena.atlas.web.HttpException;
import org.apache.jena.atlas.web.TypedInputStream;
import org.apache.jena.atlas.web.WebLib;
@@ -35,11 +37,9 @@
import org.apache.jena.fuseki.build.FusekiExt;
import org.apache.jena.fuseki.server.DataService;
import org.apache.jena.fuseki.server.Operation;
+import org.apache.jena.fuseki.server.OperationRegistry;
import org.apache.jena.fuseki.servlets.ActionService;
import org.apache.jena.fuseki.servlets.HttpAction;
-import org.apache.jena.query.QueryExecution;
-import org.apache.jena.rdfconnection.RDFConnection;
-import org.apache.jena.rdfconnection.RDFConnectionFactory;
import org.apache.jena.riot.WebContent;
import org.apache.jena.riot.web.HttpOp;
import org.apache.jena.sparql.core.DatasetGraph;
@@ -49,19 +49,21 @@
/** Test for adding a new operation */
public class TestFusekiCustomOperation {
- private static final Operation newOp = Operation.alloc("http://example/special", "special", "Custom operation");
- private static final String contentType = "application/special";
- private static final String endpointName = "special";
+ private static final Operation newOp = Operation.alloc("http://example/special", "special", "Custom operation");
+ private static final String contentType = "application/special";
+ private static final String endpointName = "special";
+ private static final String customHandlerBodyGet = " ** Hello world (GET) ** custom handler **";
+ private static final String customHandlerBodyPost = " ** Hello world (POST) ** custom handler **";
- private final ActionService customHandler = new CustomTestService() {
+ private final ActionService customHandler =
+ new CustomTestService() {
@Override
protected void doGet(HttpAction action) {
action.response.setStatus(HttpSC.OK_200);
try {
action.response.setContentType(WebContent.contentTypeTextPlain);
- action.response.getOutputStream().println(" ** Hello world (GET) **");
- }
- catch (IOException e) {
+ action.response.getOutputStream().print(customHandlerBodyGet);
+ } catch (IOException e) {
e.printStackTrace();
}
}
@@ -77,16 +79,16 @@
action.response.setStatus(HttpSC.OK_200);
try {
action.response.setContentType(WebContent.contentTypeTextPlain);
- action.response.getOutputStream().println(" ** Hello world (POST) **");
- }
- catch (IOException e) {
+ action.response.getOutputStream().print(customHandlerBodyPost);
+ } catch (IOException e) {
e.printStackTrace();
}
}
};
- private final int port = WebLib.choosePort();
- private final String url = "http://localhost:"+port;
+ private final int port = WebLib.choosePort();
+ // Without trailing "/"
+ private final String url = "http://localhost:" + port;
@Test
public void cfg_dataservice_named() {
@@ -95,16 +97,19 @@
DatasetGraph dsg = DatasetGraphFactory.createTxnMem();
DataService dataService = new DataService(dsg);
FusekiConfig.populateStdServices(dataService, true);
- FusekiExt.registerOperation(newOp, customHandler);
- FusekiConfig.addServiceEP(dataService, newOp, endpointName);
+ try {
+ FusekiExt.registerOperation(newOp, customHandler);
+ assertTrue(OperationRegistry.get().isRegistered(newOp));
- FusekiServer server =
- FusekiServer.create()
- .port(port)
- .registerOperation(newOp, contentType, customHandler)
- .add("/ds", dataService)
- .build();
- testServer(server, url, endpointName, true);
+ FusekiConfig.addServiceEP(dataService, newOp, endpointName);
+ FusekiServer server = FusekiServer.create().port(port).registerOperation(newOp, contentType, customHandler)
+ .add("/ds", dataService).build();
+ testServer(server, url, endpointName, true, false);
+ }
+ finally {
+ FusekiExt.unregisterOperation(newOp, customHandler);
+ }
+ assertFalse(OperationRegistry.get().isRegistered(newOp));
}
@Test
@@ -114,149 +119,136 @@
DatasetGraph dsg = DatasetGraphFactory.createTxnMem();
DataService dataService = new DataService(dsg);
FusekiConfig.populateStdServices(dataService, true);
- FusekiExt.registerOperation(newOp, customHandler);
- FusekiConfig.addServiceEP(dataService, newOp, null);
+ try {
+ FusekiExt.registerOperation(newOp, customHandler);
+ assertTrue(OperationRegistry.get().isRegistered(newOp));
- FusekiServer server =
- FusekiServer.create()
- .port(port)
- .registerOperation(newOp, contentType, customHandler)
- .add("/ds", dataService)
- .build();
- // No endpoint name dispatch - content-type required.
- testServer(server, url, null, true);
- }
-
- @Test
- public void cfg_builder_CT_named() {
- FusekiServer server =
- FusekiServer.create()
- .port(port)
- .registerOperation(newOp, contentType, customHandler)
- .add("/ds", DatasetGraphFactory.createTxnMem(), true)
- .addEndpoint("/ds", endpointName, newOp)
- .build();
- testServer(server, url, endpointName, true);
- }
-
- @Test
- public void cfg_builder_CT_noName() {
- FusekiServer server =
- FusekiServer.create()
- .port(port)
- .registerOperation(newOp, contentType, customHandler)
- .add("/ds", DatasetGraphFactory.createTxnMem(), true)
- .addEndpoint("/ds", "", newOp)
- .build();
- testServer(server, url, null, true);
+ FusekiConfig.addServiceEP(dataService, newOp, null);
+ FusekiServer server = FusekiServer.create().port(port).registerOperation(newOp, contentType, customHandler)
+ .add("/ds", dataService).build();
+ // No endpoint name dispatch - content-type required.
+ testServer(server, url, "", false, true);
+ }
+ finally {
+ FusekiExt.unregisterOperation(newOp, customHandler);
+ }
+ assertFalse(OperationRegistry.get().isRegistered(newOp));
}
@Test
public void cfg_builder_noCT() {
- FusekiServer server =
- FusekiServer.create()
- .port(port)
- .registerOperation(newOp, null, customHandler)
- .add("/ds", DatasetGraphFactory.createTxnMem(), true)
- .addEndpoint("/ds", endpointName, newOp)
- .build();
- testServer(server, url, endpointName, false);
+ // Register operation in the builder. Dispatch by-name. CT not required.
+ FusekiServer server = FusekiServer.create().port(port).registerOperation(newOp, null, customHandler)
+ .add("/ds", DatasetGraphFactory.createTxnMem(), true).addEndpoint("/ds", endpointName, newOp).build();
+ testServer(server, url, endpointName, true, false);
}
- @Test(expected=FusekiConfigException.class)
+ @Test
+ public void cfg_builder_CT_named() {
+ FusekiServer server = FusekiServer.create().port(port).registerOperation(newOp, contentType, customHandler)
+ .add("/ds", DatasetGraphFactory.createTxnMem(), true).addEndpoint("/ds", endpointName, newOp).build();
+ // Endpoint name dispatch - with content-type
+ testServer(server, url, endpointName, true, true);
+ }
+
+ @Test
+ public void cfg_builder_CT_noName() {
+ // Register operation in the builder. Dispatch by-content-type on "".
+ FusekiServer server = FusekiServer.create().port(port).registerOperation(newOp, contentType, customHandler)
+ .add("/ds", DatasetGraphFactory.createTxnMem(), true).addEndpoint("/ds", "", newOp).build();
+ testServer(server, url, "", false, true);
+ }
+
+ @Test(expected = FusekiConfigException.class)
public void cfg_bad_01() {
- FusekiServer.create()
- .port(port)
- .registerOperation(newOp, null, customHandler)
- .addEndpoint("/UNKNOWN", endpointName, newOp);
- //.build();
+ FusekiServer.create().port(port).registerOperation(newOp, null, customHandler).addEndpoint("/UNKNOWN", endpointName, newOp);
+ // .build();
}
- @Test(expected=FusekiConfigException.class)
+ @Test(expected = FusekiConfigException.class)
public void cfg_bad_02() {
- FusekiServer.create()
- .port(port)
- //.registerOperation(newOp, null, customHandler)
- .add("/ds", DatasetGraphFactory.createTxnMem(), true)
- // Unregistered.
- .addEndpoint("/ds", endpointName, newOp);
- //.build();
- }
-
- public void cfg_bad_ct_not_enabled_here() {
- FusekiServer server = FusekiServer.create()
- .port(port)
- .registerOperation(newOp, "app/special", customHandler)
+ FusekiServer.create().port(port)
+ // .registerOperation(newOp, null, customHandler)
.add("/ds", DatasetGraphFactory.createTxnMem(), true)
// Unregistered.
- .addEndpoint("/ds", endpointName, newOp)
- .build();
- testServer(server, url, null, false);
+ .addEndpoint("/ds", endpointName, newOp);
+ // .build();
}
+ // Bad test: no MIME type must match.
+ @Test
+ public void cfg_bad_ct_not_enabled_here_1() {
+ FusekiServer server = FusekiServer.create().port(port)
+ // Wrong MIME type.
+ .registerOperation(newOp, "app/special", customHandler).add("/ds", DatasetGraphFactory.createTxnMem(), true)
+ // Unregistered CT dispatch.
+ .addEndpoint("/ds", "", newOp).build();
- private static void testServer(FusekiServer server, String url, String epName, boolean withContentType) {
+ // CT dispatch.
+ expectFail(() -> testServer(server, url, "", false, true), HttpSC.Code.BAD_REQUEST);
+ }
+
+ /** Call the server to check that the endpoint can be contacted. */
+ private static void testServer(FusekiServer server, String url, String epName, boolean withoutContentType, boolean withContentType) {
try {
server.start();
- // Try query (no extension required)
- try(RDFConnection rconn = RDFConnectionFactory.connect(url+"/ds")) {
- try(QueryExecution qExec = rconn.query("ASK {}")) {
- qExec.execAsk();
- }
+ Lib.sleep(100);
+
+ String svcCall = StringUtils.isEmpty(epName) ? url + "/ds" : url + "/ds/" + epName;
+
+ if ( withoutContentType )
+ testServerNoCT(server, svcCall);
+
+ if ( withContentType )
+ testServerCT(server, svcCall);
+
+ // DELETE -> fails
+ int statusCode = expectFail(() -> HttpOp.execHttpDelete(svcCall));
+ switch (statusCode) {
+ // Acceptable.
+ case HttpSC.BAD_REQUEST_400 :
+ case HttpSC.METHOD_NOT_ALLOWED_405 :
+ break;
+ default :
+ // Wrong
+ fail("Status code = " + statusCode);
}
-
- if ( epName != null ) {
- if ( ! epName.isEmpty() ) {
- // Service endpoint name : GET
- String svcCall = url+"/ds/"+epName;
-
- String s1 = HttpOp.execHttpGetString(svcCall);
-
- // Service endpoint name : POST
- try ( TypedInputStream stream = HttpOp.execHttpPostStream(svcCall, "ignored", "", "text/plain") ) {
- assertNotNull(stream);
- String x = IOUtils.toString(stream, StandardCharsets.UTF_8);
- assertNotNull(x);
- } catch (IOException ex) {
- IO.exception(ex);
- }
- }
- } else {
- // No endpoint so we expect a 404.
- try {
- // Service endpoint name : GET
- HttpOp.execHttpGet(url+"/ds/"+endpointName);
- fail("Expected to fail HTTP GET");
- } catch (HttpException ex) {
- assertEquals(404, ex.getStatusCode());
- }
- }
-
- if ( withContentType ) {
- // Content-type
- try ( TypedInputStream stream = HttpOp.execHttpPostStream(url+"/ds", contentType, "", "text/plain") ) {
- assertNotNull(stream);
- String x = IOUtils.toString(stream, StandardCharsets.UTF_8);
- assertNotNull(x);
- } catch (IOException ex) {
- IO.exception(ex);
- }
- } else {
- // No Content-Type
- try ( TypedInputStream stream = HttpOp.execHttpPostStream(url+"/ds", contentType, "", "text/plain") ) {
- fail("Expected to fail HTTP POST using Content-Type");
- } catch (HttpException ex) {}
-
- // Service endpoint name. DELETE -> fails 405
- try {
- HttpOp.execHttpDelete(url+"/ds/"+endpointName);
- throw new IllegalStateException("DELETE succeeded");
- } catch (HttpException ex) {
- assertEquals(405, ex.getStatusCode());
- }
- }
- } finally {
+ }
+ finally {
server.stop();
}
}
+
+ private static void testServerCT(FusekiServer server, String svcCall) {
+ // Content-type
+ try (TypedInputStream stream = HttpOp.execHttpPostStream(svcCall, contentType, "", "text/plain")) {
+ assertNotNull(stream);
+ String x = IOUtils.toString(stream, StandardCharsets.UTF_8);
+ assertValidResponseBody(customHandlerBodyPost, x);
+ } catch (IOException ex) {
+ IO.exception(ex);
+ }
+ }
+
+ private static void testServerNoCT(FusekiServer server, String svcCall) {
+ // Service endpoint name : GET
+ String s1 = HttpOp.execHttpGetString(svcCall);
+ if ( s1 == null )
+ throw new HttpException(HttpSC.NOT_FOUND_404, "Not Found", "");
+ assertValidResponseBody(customHandlerBodyGet, s1);
+
+ // Service endpoint name : POST
+ try (TypedInputStream stream = HttpOp.execHttpPostStream(svcCall, "ignored", "", "text/plain")) {
+ assertNotNull(stream);
+ String x = IOUtils.toString(stream, StandardCharsets.UTF_8);
+ assertValidResponseBody(customHandlerBodyPost, x);
+ } catch (IOException ex) {
+ IO.exception(ex);
+ }
+ }
+
+ private static void assertValidResponseBody(String expectedResponseBody, String responseBody) {
+ assertNotNull(responseBody);
+ assertEquals(expectedResponseBody, responseBody);
+ }
}
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestFusekiMainCmd.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestFusekiMainCmd.java
index 1c0d4dd..dd958d8 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestFusekiMainCmd.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestFusekiMainCmd.java
@@ -82,4 +82,10 @@
assertNotNull(x);
JSON.parse(x);
}
+
+ @Test public void metrics_01() {
+ server("--mem", "--metrics", "/ds");
+ String x = HttpOp.execHttpGetString(serverURL+"/$/metrics");
+ assertNotNull(x);
+ }
}
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestHTTP.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestHTTP.java
index 5edf601..95ccf2a 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestHTTP.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestHTTP.java
@@ -181,7 +181,7 @@
// Servlet - mounted at /ds/myServlet, but not a service that Fuseki dispatches.
@Test public void plainServlet() {
String x = HttpOp.execHttpGetString(URL+"/myServlet");
- assertEquals(x, "SERVLET");
+ assertEquals("SERVLET",x);
}
// Files - a static file /ds/file.txt is visible.
diff --git a/jena-fuseki2/jena-fuseki-main/testing/Access/assem-security-shared.ttl b/jena-fuseki2/jena-fuseki-main/testing/Access/assem-security-shared.ttl
index 210ff9e..034ee31 100644
--- a/jena-fuseki2/jena-fuseki-main/testing/Access/assem-security-shared.ttl
+++ b/jena-fuseki2/jena-fuseki-main/testing/Access/assem-security-shared.ttl
@@ -71,7 +71,7 @@
## Shared database.
<#tdb_dataset_shared> rdf:type tdb2:DatasetTDB2 ;
- tdb2:location "--mem--/DB" ;
+ tdb2:location "--mem--" ;
tdb2:unionDefaultGraph true ;
.
diff --git a/jena-fuseki2/jena-fuseki-main/testing/Config/server.ttl b/jena-fuseki2/jena-fuseki-main/testing/Config/server.ttl
new file mode 100644
index 0000000..73de85c
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-main/testing/Config/server.ttl
@@ -0,0 +1,26 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:services ( <#service1> ) ;
+ fuseki:pingEP true ;
+ fuseki:statsEP true ;
+ fuseki:metricsEP true ;
+.
+
+<#service1> rdf:type fuseki:Service ;
+ fuseki:name "ds" ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:query;
+ fuseki:name "" ;
+ ] ;
+ fuseki:dataset <#emptyDataset> ;
+.
+
+<#emptyDataset> rdf:type ja:RDFDataset .
diff --git a/jena-fuseki2/jena-fuseki-main/testing/Config/setup2.ttl b/jena-fuseki2/jena-fuseki-main/testing/Config/setup2.ttl
index 19201d2..16171b1 100644
--- a/jena-fuseki2/jena-fuseki-main/testing/Config/setup2.ttl
+++ b/jena-fuseki2/jena-fuseki-main/testing/Config/setup2.ttl
@@ -15,7 +15,7 @@
## Same endpoint name, different operations available.
fuseki:endpoint [
fuseki:operation fuseki:query;
- ## Named service and root daatset not supported.
+ ## Named service and root dataset not supported.
#fuseki:name "sparql" ;
] ;
fuseki:endpoint [
diff --git a/jena-fuseki2/jena-fuseki-main/testing/Config/std-general.ttl b/jena-fuseki2/jena-fuseki-main/testing/Config/std-general.ttl
deleted file mode 100644
index a2cffef..0000000
--- a/jena-fuseki2/jena-fuseki-main/testing/Config/std-general.ttl
+++ /dev/null
@@ -1,24 +0,0 @@
-## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
-
-PREFIX : <#>
-PREFIX fuseki: <http://jena.apache.org/fuseki#>
-PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
-
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
-
-[] rdf:type fuseki:Server .
-
-<#service1> rdf:type fuseki:Service ;
- fuseki:name "ds" ;
- fuseki:endpoint [ fuseki:operation fuseki:query; fuseki:name "sparql" ] ;
- fuseki:endpoint [ fuseki:operation fuseki:query; fuseki:name "query" ] ;
- fuseki:endpoint [ fuseki:operation fuseki:update; fuseki:name "update" ] ;
- fuseki:endpoint [ fuseki:operation fuseki:gsp_r; fuseki:name "get" ] ;
- fuseki:endpoint [ fuseki:operation fuseki:gsp_rw; fuseki:name "data" ] ;
-
- ## No blocked on endpoint "".
- fuseki:dataset <#emptyDataset> ;
- .
-
-<#emptyDataset> rdf:type ja:RDFDataset .
diff --git a/jena-fuseki2/jena-fuseki-main/testing/Config/std-named.ttl b/jena-fuseki2/jena-fuseki-main/testing/Config/std-named.ttl
index a465abd..b36fe0b 100644
--- a/jena-fuseki2/jena-fuseki-main/testing/Config/std-named.ttl
+++ b/jena-fuseki2/jena-fuseki-main/testing/Config/std-named.ttl
@@ -18,10 +18,6 @@
fuseki:endpoint [ fuseki:operation fuseki:gsp_r; fuseki:name "get" ] ;
fuseki:endpoint [ fuseki:operation fuseki:gsp_rw; fuseki:name "data" ] ;
- ## Any explicit dataset level operation means that
- ## trying as named service does not happen.
- fuseki:endpoint [ fuseki:operation fuseki:no_op ] ;
-
fuseki:dataset <#emptyDataset> ;
.
diff --git a/jena-fuseki2/jena-fuseki-main/testing/Config/std-old-style.ttl b/jena-fuseki2/jena-fuseki-main/testing/Config/std-old-style.ttl
new file mode 100644
index 0000000..393f0d3
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-main/testing/Config/std-old-style.ttl
@@ -0,0 +1,23 @@
+## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+
+[] rdf:type fuseki:Server .
+
+<#service1> rdf:type fuseki:Service ;
+ fuseki:name "ds0" ;
+ fuseki:serviceQuery "query";
+ fuseki:serviceQuery "sparql";
+ fuseki:serviceUpdate "update";
+ ##fuseki:serviceUpload "upload" ;
+ fuseki:serviceReadWriteGraphStore "data" ;
+ fuseki:serviceReadGraphStore "get" ;
+ fuseki:dataset <#dataset> ;
+ .
+
+<#dataset> rdf:type ja:RDFDataset .
diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/cmd/JettyFusekiWebapp.java b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/cmd/JettyFusekiWebapp.java
index b1086a8..420d362 100644
--- a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/cmd/JettyFusekiWebapp.java
+++ b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/cmd/JettyFusekiWebapp.java
@@ -199,8 +199,8 @@
// which happens during server startup.
// This the name of the ServletContext logger as well
webapp.setDisplayName(Fuseki.servletRequestLogName);
- webapp.setParentLoaderPriority(true); // Normal Java classloader behaviour.
- webapp.setErrorHandler(new FusekiErrorHandler());
+ webapp.setParentLoaderPriority(true); // Normal Java classloader behaviour.
+ webapp.setErrorHandler(new FusekiErrorHandler()); // If used.
return webapp;
}
diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-mem b/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-mem
index 6ce86d0..6f42e59 100644
--- a/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-mem
+++ b/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-mem
@@ -22,8 +22,6 @@
fuseki:serviceUpload "upload" ;
fuseki:serviceReadWriteGraphStore "data" ;
fuseki:serviceReadGraphStore "get" ;
- fuseki:serviceReadQuads "" ;
- fuseki:serviceReadWriteQuads "" ;
fuseki:dataset <#dataset> ;
.
diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb b/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb
index a24655d..9b18588 100644
--- a/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb
+++ b/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb
@@ -22,8 +22,6 @@
fuseki:serviceReadWriteGraphStore "data" ;
# A separate read-only graph store endpoint:
fuseki:serviceReadGraphStore "get" ;
- fuseki:serviceReadQuads "";
- fuseki:serviceReadWriteQuads "";
fuseki:dataset <#tdb_dataset_readwrite> ;
.
diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb-dir b/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb-dir
index 338d7de..f22de07 100644
--- a/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb-dir
+++ b/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb-dir
@@ -21,8 +21,6 @@
fuseki:serviceUpload "upload" ;
fuseki:serviceReadWriteGraphStore "data" ;
fuseki:serviceReadGraphStore "get" ;
- fuseki:serviceReadQuads "" ;
- fuseki:serviceReadWriteQuads "" ;
fuseki:dataset <#tdb_dataset_readwrite> ;
.
diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb-mem b/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb-mem
index f751a69..6b9c656 100644
--- a/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb-mem
+++ b/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb-mem
@@ -21,8 +21,6 @@
fuseki:serviceUpload "upload" ;
fuseki:serviceReadWriteGraphStore "data" ;
fuseki:serviceReadGraphStore "get" ;
- fuseki:serviceReadQuads "" ;
- fuseki:serviceReadWriteQuads "" ;
fuseki:dataset <#tdb_dataset_readwrite> ;
.
diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb2 b/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb2
index c3412fc..3fa7c16 100644
--- a/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb2
+++ b/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb2
@@ -21,8 +21,6 @@
fuseki:serviceUpload "upload" ;
fuseki:serviceReadWriteGraphStore "data" ;
fuseki:serviceReadGraphStore "get" ;
- fuseki:serviceReadQuads "" ;
- fuseki:serviceReadWriteQuads "" ;
fuseki:dataset <#tdb_dataset_readwrite> ;
.
diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb2-dir b/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb2-dir
index 680d0a8..3312b93 100644
--- a/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb2-dir
+++ b/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb2-dir
@@ -21,8 +21,6 @@
fuseki:serviceUpload "upload" ;
fuseki:serviceReadWriteGraphStore "data" ;
fuseki:serviceReadGraphStore "get" ;
- fuseki:serviceReadQuads "" ;
- fuseki:serviceReadWriteQuads "" ;
fuseki:dataset <#tdb_dataset_readwrite> ;
.
diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb2-mem b/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb2-mem
index d9b21a8..de362d0 100644
--- a/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb2-mem
+++ b/jena-fuseki2/jena-fuseki-webapp/src/main/resources/org/apache/jena/fuseki/webapp/templates/config-tdb2-mem
@@ -21,8 +21,6 @@
fuseki:serviceUpload "upload" ;
fuseki:serviceReadWriteGraphStore "data" ;
fuseki:serviceReadGraphStore "get" ;
- fuseki:serviceReadQuads "" ;
- fuseki:serviceReadWriteQuads "" ;
fuseki:dataset <#tdb_dataset_readwrite> ;
.
diff --git a/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestServerReadOnly.java b/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestServerReadOnly.java
index 3bdf3d8..d61f026 100644
--- a/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestServerReadOnly.java
+++ b/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestServerReadOnly.java
@@ -25,6 +25,7 @@
import org.apache.http.HttpEntity;
import org.apache.http.entity.StringEntity;
+import org.apache.jena.atlas.web.TypedInputStream;
import org.apache.jena.fuseki.test.FusekiTest;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
@@ -99,6 +100,13 @@
}
@Test
+ public void dataset_readonly_GET() {
+ // Try to read
+ try ( TypedInputStream in = HttpOp.execHttpGet(ServerCtl.urlDataset()) ) {}
+ }
+
+
+ @Test
public void dataset_w_readonly_POST() {
// Try to write
FusekiTest.execWithHttpException(HttpSC.METHOD_NOT_ALLOWED_405, ()->{
diff --git a/jena-fuseki2/pom.xml b/jena-fuseki2/pom.xml
index 12bbea0..2af616e 100644
--- a/jena-fuseki2/pom.xml
+++ b/jena-fuseki2/pom.xml
@@ -65,6 +65,8 @@
<module>jena-fuseki-war</module>
<module>jena-fuseki-fulljar</module>
+ <module>jena-fuseki-docker</module>
+
<module>apache-jena-fuseki</module>
</modules>
diff --git a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/LibRDFConn.java b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/LibRDFConn.java
index b4a9b42..51780f1 100644
--- a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/LibRDFConn.java
+++ b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/LibRDFConn.java
@@ -43,6 +43,15 @@
return graphStoreProtocolService + queryStringForGraph(ch, graphName) ;
}
+ /**
+ * Service endpoint URL calculation.
+ * <ul>
+ * <li> If srvEndpoint is null, "destination"
+ * <li> If srvEndpoint is "", "destination"
+ * <li> If srvEndpoint is an absolute URL, "srvEndpoint"
+ * <li> "destination / srvEndpoint" (ensures the "/"), while preserving the query string
+ * </ul>
+ */
/*package*/ static String formServiceURL(String destination, String srvEndpoint) {
if ( srvEndpoint == null )
return null;
diff --git a/jena-shacl/shaclc/shaclc.jj b/jena-shacl/shaclc/shaclc.jj
index e81af72..cb1e041 100644
--- a/jena-shacl/shaclc/shaclc.jj
+++ b/jena-shacl/shaclc/shaclc.jj
@@ -140,7 +140,11 @@
void constraint() : { }
{
{ startConstraint(); }
- ( (nodeOr())+ | propertyShape() )
+ ( (nodeOr())+ | propertyShape()
+// <EXT>
+ | shapeRef(false)
+// </EXT>
+ )
{ finishConstraint() ; }
<DOT>
}
@@ -217,7 +221,7 @@
void propertyAtom() : { }
{
// Work on currentPropertyShape()
- propertyType() | nodeKind() | shapeRef() | propertyValue() |
+ propertyType() | nodeKind() | shapeRef(true) | propertyValue() |
( { startNestedPropertyAtom(); } nodeShapeBody() { finishNestedPropertyAtom(); })
}
@@ -249,7 +253,7 @@
{ rNodeKind(t.image); }
}
-void shapeRef() : { Token t; String iriStr; }
+void shapeRef(boolean inPropertyShape) : { Token t; String iriStr; }
{
// consistent WS handling.?
( t = <ATPNAME_LN>
@@ -258,8 +262,7 @@
{ iriStr = resolvePName(t.image.substring(1), t.beginLine, t.beginColumn) ; }
| <AT> iriStr= IRIREF()
)
- //<AT> iriStr = iri()
- { rShapeRef(iriStr); }
+ { rShapeRef(inPropertyShape, iriStr); }
}
void propertyValue() : { String s; Node n; List<Node> x; }
@@ -305,6 +308,11 @@
t = "equals" | t = "disjoint" | t = "lessThan" | t = "lessThanOrEquals" |
t = "qualifiedValueShape" | t = "qualifiedMinCount" | t = "qualifiedMaxCount" | t = "qualifiedValueShapesDisjoint" |
t = "closed" | t = "ignoredProperties" | t = "hasValue" | t = "in"
+// <EXT>
+ | t = "group" | t = "order"
+ | t = "name" | t = "description"
+ | t = "defaultValue"
+// </EXT>
)
{ return t.image; }
}
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/compact/reader/ShaclCompactParser.java b/jena-shacl/src/main/java/org/apache/jena/shacl/compact/reader/ShaclCompactParser.java
index 4e08482..11a05e1 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/compact/reader/ShaclCompactParser.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/compact/reader/ShaclCompactParser.java
@@ -426,9 +426,13 @@
// shapeRef: Produce a triple ?property sh:node ?node where ?node is the IRI
// derived from the substring of shapeRef after the '@' character using iri.
- protected void rShapeRef(String iriStr) {
+ protected void rShapeRef(boolean inPropertyShape, String iriStr) {
Node x = iri(iriStr);
- triple(currentTripleAcc(), currentPropertyShape(), SHACL.node, x);
+ if ( inPropertyShape )
+ triple(currentTripleAcc(), currentPropertyShape(), SHACL.node, x);
+ else
+ // Extension.
+ triple(currentTripleAcc(), currentNodeShape(), SHACL.node, x);
}
// propertyValue: Produce a triple ?property ?predicate ?object where ?predicate
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/compact/reader/parser/ShaclCompactParserJJ.java b/jena-shacl/src/main/java/org/apache/jena/shacl/compact/reader/parser/ShaclCompactParserJJ.java
index 1cce249..9ef855f 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/compact/reader/parser/ShaclCompactParserJJ.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/compact/reader/parser/ShaclCompactParserJJ.java
@@ -210,12 +210,15 @@
case 31:
case 32:
case 33:
+ case AT:
case CARAT:
case BANG:
case LPAREN:
case IRIref:
case PNAME_NS:
- case PNAME_LN:{
+ case PNAME_LN:
+ case ATPNAME_NS:
+ case ATPNAME_LN:{
;
break;
}
@@ -306,6 +309,12 @@
propertyShape();
break;
}
+ case AT:
+ case ATPNAME_NS:
+ case ATPNAME_LN:{
+ shapeRef(false);
+ break;
+ }
default:
jj_la1[9] = jj_gen;
jj_consume_token(-1);
@@ -563,7 +572,7 @@
case AT:
case ATPNAME_NS:
case ATPNAME_LN:{
- shapeRef();
+ shapeRef(true);
break;
}
case 9:
@@ -680,7 +689,7 @@
rNodeKind(t.image);
}
- final public void shapeRef() throws ParseException {Token t; String iriStr;
+ final public void shapeRef(boolean inPropertyShape) throws ParseException {Token t; String iriStr;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ATPNAME_LN:{
t = jj_consume_token(ATPNAME_LN);
@@ -702,7 +711,7 @@
jj_consume_token(-1);
throw new ParseException();
}
-rShapeRef(iriStr);
+rShapeRef(inPropertyShape, iriStr);
}
final public void propertyValue() throws ParseException {String s; Node n; List<Node> x;
@@ -968,6 +977,26 @@
t = jj_consume_token(33);
break;
}
+ case 41:{
+ t = jj_consume_token(41);
+ break;
+ }
+ case 42:{
+ t = jj_consume_token(42);
+ break;
+ }
+ case 43:{
+ t = jj_consume_token(43);
+ break;
+ }
+ case 44:{
+ t = jj_consume_token(44);
+ break;
+ }
+ case 45:{
+ t = jj_consume_token(45);
+ break;
+ }
default:
jj_la1[23] = jj_gen;
jj_consume_token(-1);
@@ -1284,7 +1313,7 @@
lex = string();
String lang = null ; String dt = null ;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
- case 41:
+ case 46:
case LANGTAG:{
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case LANGTAG:{
@@ -1292,8 +1321,8 @@
lang = stripChars(t.image, 1) ;
break;
}
- case 41:{
- jj_consume_token(41);
+ case 46:{
+ jj_consume_token(46);
dt = datatype();
break;
}
@@ -1421,13 +1450,13 @@
jj_la1_0 = new int[] {0x0,0x0,0x0,0x0,0x0,0x2,0x0,0xfffffe00,0xfffffe00,0xfffffe00,0x0,0x0,0x0,0xfffffff8,0xfffffff8,0x0,0x0,0xfffffff8,0x0,0x1f8,0x0,0x0,0xfffffe00,0xffffe000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,};
}
private static void jj_la1_init_1() {
- jj_la1_1 = new int[] {0x10000,0xe0000,0x300000,0x300000,0xe0000,0x0,0x0,0xa0000003,0x80000003,0xa0000003,0x8000000,0x80000000,0xc00000,0x90000003,0x90000003,0x8000000,0x80000000,0x10000003,0x0,0x0,0x10000000,0xc00000,0x3,0x1ff,0x8000000,0x0,0x2000000,0x20000000,0x2000000,0x0,0xc00000,0xc00000,0xc00000,0xc00000,0x0,0x200,0x200,0x0,0x0,0x0,};
+ jj_la1_1 = new int[] {0x200000,0x1c00000,0x6000000,0x6000000,0x1c00000,0x0,0x0,0x3,0x3,0x3,0x0,0x0,0x18000000,0x3,0x3,0x0,0x0,0x3,0x0,0x0,0x0,0x18000000,0x3,0x3fff,0x0,0x0,0x40000000,0x0,0x40000000,0x0,0x18000000,0x18000000,0x18000000,0x18000000,0x0,0x4000,0x4000,0x0,0x0,0x0,};
}
private static void jj_la1_init_2() {
- jj_la1_2 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x3810,0x0,0x3810,0x0,0x0,0x7783900,0xf940,0xf940,0x0,0x0,0xf840,0x1000004,0x0,0xc000,0x7783900,0x0,0x0,0x0,0x2,0x5,0x3810,0x5,0x3810,0x7783800,0x7783800,0x7780000,0x0,0x7000000,0x10000000,0x10000000,0x780000,0x3800,0x3000,};
+ jj_la1_2 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x70000,0x1f0216,0x10,0x1f0216,0x1,0x10,0xef072000,0x1f2812,0x1f2812,0x1,0x10,0x1f0802,0x20000080,0x0,0x180002,0xef072000,0x0,0x0,0x1,0x40,0xa0,0x70204,0xa0,0x70200,0xef070000,0xef070000,0xef000000,0x0,0xe0000000,0x0,0x0,0xf000000,0x70000,0x60000,};
}
private static void jj_la1_init_3() {
- jj_la1_3 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,};
+ jj_la1_3 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2,0x2,0x0,0x0,0x0,};
}
/** Constructor with InputStream. */
@@ -1544,7 +1573,7 @@
/** Generate ParseException. */
public ParseException generateParseException() {
jj_expentries.clear();
- boolean[] la1tokens = new boolean[105];
+ boolean[] la1tokens = new boolean[110];
if (jj_kind >= 0) {
la1tokens[jj_kind] = true;
jj_kind = -1;
@@ -1567,7 +1596,7 @@
}
}
}
- for (int i = 0; i < 105; i++) {
+ for (int i = 0; i < 110; i++) {
if (la1tokens[i]) {
jj_expentry = new int[1];
jj_expentry[0] = i;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/compact/reader/parser/ShaclCompactParserJJConstants.java b/jena-shacl/src/main/java/org/apache/jena/shacl/compact/reader/parser/ShaclCompactParserJJConstants.java
index 6cb2aa1..468f975 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/compact/reader/parser/ShaclCompactParserJJConstants.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/compact/reader/parser/ShaclCompactParserJJConstants.java
@@ -29,121 +29,121 @@
/** End of File. */
int EOF = 0;
/** RegularExpression Id. */
- int SINGLE_LINE_COMMENT = 47;
+ int SINGLE_LINE_COMMENT = 52;
/** RegularExpression Id. */
- int BOM = 48;
+ int BOM = 53;
/** RegularExpression Id. */
- int BASE = 49;
+ int BASE = 54;
/** RegularExpression Id. */
- int IMPORTS = 50;
+ int IMPORTS = 55;
/** RegularExpression Id. */
- int PREFIX = 51;
+ int PREFIX = 56;
/** RegularExpression Id. */
- int SHAPE_CLASS = 52;
+ int SHAPE_CLASS = 57;
/** RegularExpression Id. */
- int SHAPE = 53;
+ int SHAPE = 58;
/** RegularExpression Id. */
- int TRUE = 54;
+ int TRUE = 59;
/** RegularExpression Id. */
- int FALSE = 55;
+ int FALSE = 60;
/** RegularExpression Id. */
- int HEX = 56;
+ int HEX = 61;
/** RegularExpression Id. */
- int PLUS = 57;
+ int PLUS = 62;
/** RegularExpression Id. */
- int MINUS = 58;
+ int MINUS = 63;
/** RegularExpression Id. */
- int VBAR = 59;
+ int VBAR = 64;
/** RegularExpression Id. */
- int AT = 60;
+ int AT = 65;
/** RegularExpression Id. */
- int CARAT = 61;
+ int CARAT = 66;
/** RegularExpression Id. */
- int DOT = 62;
+ int DOT = 67;
/** RegularExpression Id. */
- int BANG = 63;
+ int BANG = 68;
/** RegularExpression Id. */
- int QMARK = 64;
+ int QMARK = 69;
/** RegularExpression Id. */
- int SLASH = 65;
+ int SLASH = 70;
/** RegularExpression Id. */
- int STAR = 66;
+ int STAR = 71;
/** RegularExpression Id. */
- int EQUALS = 67;
+ int EQUALS = 72;
/** RegularExpression Id. */
- int LPAREN = 68;
+ int LPAREN = 73;
/** RegularExpression Id. */
- int RPAREN = 69;
+ int RPAREN = 74;
/** RegularExpression Id. */
- int LBRACE = 70;
+ int LBRACE = 75;
/** RegularExpression Id. */
- int RBRACE = 71;
+ int RBRACE = 76;
/** RegularExpression Id. */
- int LBRACKET = 72;
+ int LBRACKET = 77;
/** RegularExpression Id. */
- int RBRACKET = 73;
+ int RBRACKET = 78;
/** RegularExpression Id. */
- int UCHAR = 74;
+ int UCHAR = 79;
/** RegularExpression Id. */
- int IRIref = 75;
+ int IRIref = 80;
/** RegularExpression Id. */
- int PNAME_NS = 76;
+ int PNAME_NS = 81;
/** RegularExpression Id. */
- int PNAME_LN = 77;
+ int PNAME_LN = 82;
/** RegularExpression Id. */
- int ATPNAME_NS = 78;
+ int ATPNAME_NS = 83;
/** RegularExpression Id. */
- int ATPNAME_LN = 79;
+ int ATPNAME_LN = 84;
/** RegularExpression Id. */
- int QUOTE_3D = 80;
+ int QUOTE_3D = 85;
/** RegularExpression Id. */
- int QUOTE_3S = 81;
+ int QUOTE_3S = 86;
/** RegularExpression Id. */
- int ECHAR = 82;
+ int ECHAR = 87;
/** RegularExpression Id. */
- int STRING_LITERAL1 = 83;
+ int STRING_LITERAL1 = 88;
/** RegularExpression Id. */
- int STRING_LITERAL2 = 84;
+ int STRING_LITERAL2 = 89;
/** RegularExpression Id. */
- int STRING_LITERAL_LONG1 = 85;
+ int STRING_LITERAL_LONG1 = 90;
/** RegularExpression Id. */
- int STRING_LITERAL_LONG2 = 86;
+ int STRING_LITERAL_LONG2 = 91;
/** RegularExpression Id. */
- int DIGITS = 87;
+ int DIGITS = 92;
/** RegularExpression Id. */
- int INTEGER = 88;
+ int INTEGER = 93;
/** RegularExpression Id. */
- int DECIMAL = 89;
+ int DECIMAL = 94;
/** RegularExpression Id. */
- int DOUBLE = 90;
+ int DOUBLE = 95;
/** RegularExpression Id. */
- int EXPONENT = 91;
+ int EXPONENT = 96;
/** RegularExpression Id. */
- int LANGTAG = 92;
+ int LANGTAG = 97;
/** RegularExpression Id. */
- int A2Z = 93;
+ int A2Z = 98;
/** RegularExpression Id. */
- int A2ZN = 94;
+ int A2ZN = 99;
/** RegularExpression Id. */
- int PN_CHARS_BASE = 95;
+ int PN_CHARS_BASE = 100;
/** RegularExpression Id. */
- int PN_CHARS_U = 96;
+ int PN_CHARS_U = 101;
/** RegularExpression Id. */
- int PN_CHARS = 97;
+ int PN_CHARS = 102;
/** RegularExpression Id. */
- int PN_PREFIX = 98;
+ int PN_PREFIX = 103;
/** RegularExpression Id. */
- int PN_LOCAL = 99;
+ int PN_LOCAL = 104;
/** RegularExpression Id. */
- int VARNAME = 100;
+ int VARNAME = 105;
/** RegularExpression Id. */
- int PN_LOCAL_ESC = 101;
+ int PN_LOCAL_ESC = 106;
/** RegularExpression Id. */
- int PLX = 102;
+ int PLX = 107;
/** RegularExpression Id. */
- int PERCENT = 103;
+ int PERCENT = 108;
/** RegularExpression Id. */
- int UNKNOWN = 104;
+ int UNKNOWN = 109;
/** Lexical state. */
int DEFAULT = 0;
@@ -191,6 +191,11 @@
"\"qualifiedMinCount\"",
"\"qualifiedMaxCount\"",
"\"qualifiedValueShapesDisjoint\"",
+ "\"group\"",
+ "\"order\"",
+ "\"name\"",
+ "\"description\"",
+ "\"defaultValue\"",
"\"^^\"",
"\" \"",
"\"\\t\"",
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/compact/reader/parser/ShaclCompactParserJJTokenManager.java b/jena-shacl/src/main/java/org/apache/jena/shacl/compact/reader/parser/ShaclCompactParserJJTokenManager.java
index 4b33b42..b524135 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/compact/reader/parser/ShaclCompactParserJJTokenManager.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/compact/reader/parser/ShaclCompactParserJJTokenManager.java
@@ -42,117 +42,121 @@
switch(curChar)
{
case 9:
- jjmatchedKind = 43;
+ jjmatchedKind = 48;
return jjMoveNfa_0(0, 0);
case 10:
- jjmatchedKind = 44;
+ jjmatchedKind = 49;
return jjMoveNfa_0(0, 0);
case 12:
- jjmatchedKind = 46;
+ jjmatchedKind = 51;
return jjMoveNfa_0(0, 0);
case 13:
- jjmatchedKind = 45;
+ jjmatchedKind = 50;
return jjMoveNfa_0(0, 0);
case 32:
- jjmatchedKind = 42;
+ jjmatchedKind = 47;
return jjMoveNfa_0(0, 0);
case 33:
- jjmatchedKind = 63;
- return jjMoveNfa_0(0, 0);
- case 40:
jjmatchedKind = 68;
return jjMoveNfa_0(0, 0);
+ case 40:
+ jjmatchedKind = 73;
+ return jjMoveNfa_0(0, 0);
case 41:
- jjmatchedKind = 69;
+ jjmatchedKind = 74;
return jjMoveNfa_0(0, 0);
case 42:
- jjmatchedKind = 66;
+ jjmatchedKind = 71;
return jjMoveNfa_0(0, 0);
case 43:
- jjmatchedKind = 57;
+ jjmatchedKind = 62;
return jjMoveNfa_0(0, 0);
case 45:
- jjmatchedKind = 58;
+ jjmatchedKind = 63;
return jjMoveStringLiteralDfa1_0(0x2L);
case 46:
- jjmatchedKind = 62;
+ jjmatchedKind = 67;
return jjMoveStringLiteralDfa1_0(0x4L);
case 47:
- jjmatchedKind = 65;
+ jjmatchedKind = 70;
return jjMoveNfa_0(0, 0);
case 61:
- jjmatchedKind = 67;
+ jjmatchedKind = 72;
return jjMoveNfa_0(0, 0);
case 63:
- jjmatchedKind = 64;
+ jjmatchedKind = 69;
return jjMoveNfa_0(0, 0);
case 64:
- jjmatchedKind = 60;
+ jjmatchedKind = 65;
return jjMoveNfa_0(0, 0);
case 66:
- return jjMoveStringLiteralDfa1_0(0x20000000000c8L);
+ return jjMoveStringLiteralDfa1_0(0x400000000000c8L);
case 70:
- return jjMoveStringLiteralDfa1_0(0x80000000000000L);
+ return jjMoveStringLiteralDfa1_0(0x1000000000000000L);
case 73:
- return jjMoveStringLiteralDfa1_0(0x4000000000110L);
+ return jjMoveStringLiteralDfa1_0(0x80000000000110L);
case 76:
return jjMoveStringLiteralDfa1_0(0x20L);
case 80:
- return jjMoveStringLiteralDfa1_0(0x8000000000000L);
+ return jjMoveStringLiteralDfa1_0(0x100000000000000L);
case 83:
- return jjMoveStringLiteralDfa1_0(0x30000000000000L);
+ return jjMoveStringLiteralDfa1_0(0x600000000000000L);
case 84:
- return jjMoveStringLiteralDfa1_0(0x40000000000000L);
+ return jjMoveStringLiteralDfa1_0(0x800000000000000L);
case 91:
- jjmatchedKind = 72;
+ jjmatchedKind = 77;
return jjMoveNfa_0(0, 0);
case 93:
- jjmatchedKind = 73;
+ jjmatchedKind = 78;
return jjMoveNfa_0(0, 0);
case 94:
- jjmatchedKind = 61;
- return jjMoveStringLiteralDfa1_0(0x20000000000L);
+ jjmatchedKind = 66;
+ return jjMoveStringLiteralDfa1_0(0x400000000000L);
case 98:
- return jjMoveStringLiteralDfa1_0(0x2000000000000L);
+ return jjMoveStringLiteralDfa1_0(0x40000000000000L);
case 99:
return jjMoveStringLiteralDfa1_0(0x40010000L);
case 100:
- return jjMoveStringLiteralDfa1_0(0x20022000L);
+ return jjMoveStringLiteralDfa1_0(0x300020022000L);
case 101:
return jjMoveStringLiteralDfa1_0(0x10000000L);
case 102:
- return jjMoveStringLiteralDfa1_0(0x80000004000000L);
+ return jjMoveStringLiteralDfa1_0(0x1000000004000000L);
+ case 103:
+ return jjMoveStringLiteralDfa1_0(0x20000000000L);
case 104:
return jjMoveStringLiteralDfa1_0(0x100000000L);
case 105:
- return jjMoveStringLiteralDfa1_0(0x4000280000000L);
+ return jjMoveStringLiteralDfa1_0(0x80000280000000L);
case 108:
return jjMoveStringLiteralDfa1_0(0x1808000000L);
case 109:
return jjMoveStringLiteralDfa1_0(0x1f88000L);
case 110:
- return jjMoveStringLiteralDfa1_0(0x40000L);
+ return jjMoveStringLiteralDfa1_0(0x80000040000L);
+ case 111:
+ return jjMoveStringLiteralDfa1_0(0x40000000000L);
case 112:
- return jjMoveStringLiteralDfa1_0(0x8000002000000L);
+ return jjMoveStringLiteralDfa1_0(0x100000002000000L);
case 113:
return jjMoveStringLiteralDfa1_0(0x1e000000000L);
case 115:
- return jjMoveStringLiteralDfa1_0(0x30000000004000L);
+ return jjMoveStringLiteralDfa1_0(0x600000000004000L);
case 116:
- return jjMoveStringLiteralDfa1_0(0x40000000001e00L);
+ return jjMoveStringLiteralDfa1_0(0x800000000001e00L);
case 117:
return jjMoveStringLiteralDfa1_0(0x400000000L);
case 123:
- jjmatchedKind = 70;
+ jjmatchedKind = 75;
return jjMoveNfa_0(0, 0);
case 124:
- jjmatchedKind = 59;
+ jjmatchedKind = 64;
return jjMoveNfa_0(0, 0);
case 125:
- jjmatchedKind = 71;
+ jjmatchedKind = 76;
return jjMoveNfa_0(0, 0);
case 65279:
- jjmatchedKind = 48;
+ jjmatchedKind = 53;
return jjMoveNfa_0(0, 0);
default :
return jjMoveNfa_0(0, 0);
@@ -180,34 +184,34 @@
}
break;
case 65:
- return jjMoveStringLiteralDfa2_0(active0, 0x82000000000000L);
+ return jjMoveStringLiteralDfa2_0(active0, 0x1040000000000000L);
case 72:
- return jjMoveStringLiteralDfa2_0(active0, 0x30000000000000L);
+ return jjMoveStringLiteralDfa2_0(active0, 0x600000000000000L);
case 77:
- return jjMoveStringLiteralDfa2_0(active0, 0x4000000000000L);
+ return jjMoveStringLiteralDfa2_0(active0, 0x80000000000000L);
case 82:
- return jjMoveStringLiteralDfa2_0(active0, 0x48000000000110L);
+ return jjMoveStringLiteralDfa2_0(active0, 0x900000000000110L);
case 94:
- if ((active0 & 0x20000000000L) != 0L)
+ if ((active0 & 0x400000000000L) != 0L)
{
- jjmatchedKind = 41;
+ jjmatchedKind = 46;
jjmatchedPos = 1;
}
break;
case 97:
- return jjMoveStringLiteralDfa2_0(active0, 0x8200010b621e00L);
+ return jjMoveStringLiteralDfa2_0(active0, 0x104008010b621e00L);
case 101:
- return jjMoveStringLiteralDfa2_0(active0, 0x180000e000L);
+ return jjMoveStringLiteralDfa2_0(active0, 0x30180000e000L);
case 103:
return jjMoveStringLiteralDfa2_0(active0, 0x80000000L);
case 104:
- return jjMoveStringLiteralDfa2_0(active0, 0x30000000000000L);
+ return jjMoveStringLiteralDfa2_0(active0, 0x600000000000000L);
case 105:
return jjMoveStringLiteralDfa2_0(active0, 0x20980020L);
case 108:
return jjMoveStringLiteralDfa2_0(active0, 0x440100c8L);
case 109:
- return jjMoveStringLiteralDfa2_0(active0, 0x4000000000000L);
+ return jjMoveStringLiteralDfa2_0(active0, 0x80000000000000L);
case 110:
if ((active0 & 0x200000000L) != 0L)
{
@@ -220,7 +224,7 @@
case 113:
return jjMoveStringLiteralDfa2_0(active0, 0x10000000L);
case 114:
- return jjMoveStringLiteralDfa2_0(active0, 0x48000000000000L);
+ return jjMoveStringLiteralDfa2_0(active0, 0x900060000000000L);
case 117:
return jjMoveStringLiteralDfa2_0(active0, 0x1e000000000L);
default :
@@ -238,9 +242,9 @@
switch(curChar)
{
case 65:
- return jjMoveStringLiteralDfa3_0(active0, 0x30000000000000L);
+ return jjMoveStringLiteralDfa3_0(active0, 0x600000000000000L);
case 69:
- return jjMoveStringLiteralDfa3_0(active0, 0x8000000000000L);
+ return jjMoveStringLiteralDfa3_0(active0, 0x100000000000000L);
case 73:
if ((active0 & 0x10L) != 0L)
{
@@ -249,37 +253,41 @@
}
return jjMoveStringLiteralDfa3_0(active0, 0x100L);
case 76:
- return jjMoveStringLiteralDfa3_0(active0, 0x80000000000000L);
+ return jjMoveStringLiteralDfa3_0(active0, 0x1000000000000000L);
case 80:
- return jjMoveStringLiteralDfa3_0(active0, 0x4000000000000L);
+ return jjMoveStringLiteralDfa3_0(active0, 0x80000000000000L);
case 83:
- return jjMoveStringLiteralDfa3_0(active0, 0x2000000000000L);
- case 85:
return jjMoveStringLiteralDfa3_0(active0, 0x40000000000000L);
+ case 85:
+ return jjMoveStringLiteralDfa3_0(active0, 0x800000000000000L);
case 97:
- return jjMoveStringLiteralDfa3_0(active0, 0x3001e0040120c8L);
+ return jjMoveStringLiteralDfa3_0(active0, 0x60001e0040120c8L);
case 100:
- return jjMoveStringLiteralDfa3_0(active0, 0x40000L);
+ return jjMoveStringLiteralDfa3_0(active0, 0x40000040000L);
case 101:
- return jjMoveStringLiteralDfa3_0(active0, 0x8000000000000L);
+ return jjMoveStringLiteralDfa3_0(active0, 0x100000000000000L);
+ case 102:
+ return jjMoveStringLiteralDfa3_0(active0, 0x200000000000L);
case 105:
return jjMoveStringLiteralDfa3_0(active0, 0x400000000L);
case 108:
- return jjMoveStringLiteralDfa3_0(active0, 0x80000000000000L);
+ return jjMoveStringLiteralDfa3_0(active0, 0x1000000000000000L);
+ case 109:
+ return jjMoveStringLiteralDfa3_0(active0, 0x80000000000L);
case 110:
return jjMoveStringLiteralDfa3_0(active0, 0x88980000L);
case 111:
- return jjMoveStringLiteralDfa3_0(active0, 0x40000000L);
+ return jjMoveStringLiteralDfa3_0(active0, 0x20040000000L);
case 112:
- return jjMoveStringLiteralDfa3_0(active0, 0x4000000000000L);
+ return jjMoveStringLiteralDfa3_0(active0, 0x80000000000000L);
case 114:
return jjMoveStringLiteralDfa3_0(active0, 0x1e00L);
case 115:
- return jjMoveStringLiteralDfa3_0(active0, 0x2001920008000L);
+ return jjMoveStringLiteralDfa3_0(active0, 0x40101920008000L);
case 116:
return jjMoveStringLiteralDfa3_0(active0, 0x2020020L);
case 117:
- return jjMoveStringLiteralDfa3_0(active0, 0x40000010000000L);
+ return jjMoveStringLiteralDfa3_0(active0, 0x800000010000000L);
case 118:
return jjMoveStringLiteralDfa3_0(active0, 0x4000L);
case 120:
@@ -299,39 +307,39 @@
switch(curChar)
{
case 69:
- if ((active0 & 0x2000000000000L) != 0L)
- {
- jjmatchedKind = 49;
- jjmatchedPos = 3;
- }
- else if ((active0 & 0x40000000000000L) != 0L)
+ if ((active0 & 0x40000000000000L) != 0L)
{
jjmatchedKind = 54;
jjmatchedPos = 3;
}
+ else if ((active0 & 0x800000000000000L) != 0L)
+ {
+ jjmatchedKind = 59;
+ jjmatchedPos = 3;
+ }
return jjMoveStringLiteralDfa4_0(active0, 0x280000L);
case 70:
- return jjMoveStringLiteralDfa4_0(active0, 0x8000000000000L);
+ return jjMoveStringLiteralDfa4_0(active0, 0x100000000000000L);
case 73:
return jjMoveStringLiteralDfa4_0(active0, 0x500000L);
case 76:
return jjMoveStringLiteralDfa4_0(active0, 0x1800000L);
case 79:
- return jjMoveStringLiteralDfa4_0(active0, 0x4000000000100L);
+ return jjMoveStringLiteralDfa4_0(active0, 0x80000000000100L);
case 80:
- return jjMoveStringLiteralDfa4_0(active0, 0x30000000000000L);
+ return jjMoveStringLiteralDfa4_0(active0, 0x600000000000000L);
case 83:
- return jjMoveStringLiteralDfa4_0(active0, 0x80000000000000L);
+ return jjMoveStringLiteralDfa4_0(active0, 0x1000000000000000L);
case 86:
return jjMoveStringLiteralDfa4_0(active0, 0x100000000L);
case 97:
- return jjMoveStringLiteralDfa4_0(active0, 0x10020000L);
+ return jjMoveStringLiteralDfa4_0(active0, 0x200010020000L);
case 99:
- return jjMoveStringLiteralDfa4_0(active0, 0x2000L);
+ return jjMoveStringLiteralDfa4_0(active0, 0x100000002000L);
case 101:
- if ((active0 & 0x2000000000000L) != 0L)
+ if ((active0 & 0x80000000000L) != 0L)
{
- jjmatchedKind = 49;
+ jjmatchedKind = 43;
jjmatchedPos = 3;
}
else if ((active0 & 0x40000000000000L) != 0L)
@@ -339,9 +347,14 @@
jjmatchedKind = 54;
jjmatchedPos = 3;
}
- return jjMoveStringLiteralDfa4_0(active0, 0x44020L);
+ else if ((active0 & 0x800000000000000L) != 0L)
+ {
+ jjmatchedKind = 59;
+ jjmatchedPos = 3;
+ }
+ return jjMoveStringLiteralDfa4_0(active0, 0x40000044020L);
case 102:
- return jjMoveStringLiteralDfa4_0(active0, 0x8000000000000L);
+ return jjMoveStringLiteralDfa4_0(active0, 0x100000000000000L);
case 103:
return jjMoveStringLiteralDfa4_0(active0, 0xc001e00L);
case 106:
@@ -351,15 +364,17 @@
case 110:
return jjMoveStringLiteralDfa4_0(active0, 0xc8L);
case 111:
- return jjMoveStringLiteralDfa4_0(active0, 0x4000080000000L);
+ return jjMoveStringLiteralDfa4_0(active0, 0x80000080000000L);
case 112:
- return jjMoveStringLiteralDfa4_0(active0, 0x30000000000000L);
+ return jjMoveStringLiteralDfa4_0(active0, 0x600000000000000L);
case 113:
return jjMoveStringLiteralDfa4_0(active0, 0x400000000L);
case 115:
- return jjMoveStringLiteralDfa4_0(active0, 0x80001840018000L);
+ return jjMoveStringLiteralDfa4_0(active0, 0x1000001840018000L);
case 116:
return jjMoveStringLiteralDfa4_0(active0, 0x2000000L);
+ case 117:
+ return jjMoveStringLiteralDfa4_0(active0, 0x20000000000L);
default :
break;
}
@@ -375,41 +390,41 @@
switch(curChar)
{
case 69:
- if ((active0 & 0x20000000000000L) != 0L)
+ if ((active0 & 0x400000000000000L) != 0L)
{
- jjmatchedKind = 53;
+ jjmatchedKind = 58;
jjmatchedPos = 4;
}
- else if ((active0 & 0x80000000000000L) != 0L)
+ else if ((active0 & 0x1000000000000000L) != 0L)
{
- jjmatchedKind = 55;
+ jjmatchedKind = 60;
jjmatchedPos = 4;
}
- return jjMoveStringLiteralDfa5_0(active0, 0x10000000000000L);
+ return jjMoveStringLiteralDfa5_0(active0, 0x200000000000000L);
case 73:
- return jjMoveStringLiteralDfa5_0(active0, 0x8000000000000L);
+ return jjMoveStringLiteralDfa5_0(active0, 0x100000000000000L);
case 75:
return jjMoveStringLiteralDfa5_0(active0, 0x40000L);
case 82:
- return jjMoveStringLiteralDfa5_0(active0, 0x4000000000000L);
+ return jjMoveStringLiteralDfa5_0(active0, 0x80000000000000L);
case 84:
return jjMoveStringLiteralDfa5_0(active0, 0x1800000000L);
case 97:
return jjMoveStringLiteralDfa5_0(active0, 0x100008000L);
case 101:
- if ((active0 & 0x20000000000000L) != 0L)
+ if ((active0 & 0x400000000000000L) != 0L)
{
- jjmatchedKind = 53;
+ jjmatchedKind = 58;
jjmatchedPos = 4;
}
- else if ((active0 & 0x80000000000000L) != 0L)
+ else if ((active0 & 0x1000000000000000L) != 0L)
{
- jjmatchedKind = 55;
+ jjmatchedKind = 60;
jjmatchedPos = 4;
}
- return jjMoveStringLiteralDfa5_0(active0, 0x10000043801e00L);
+ return jjMoveStringLiteralDfa5_0(active0, 0x200000043801e00L);
case 105:
- return jjMoveStringLiteralDfa5_0(active0, 0x801e000000000L);
+ return jjMoveStringLiteralDfa5_0(active0, 0x10001e000000000L);
case 107:
return jjMoveStringLiteralDfa5_0(active0, 0xc8L);
case 108:
@@ -418,8 +433,20 @@
return jjMoveStringLiteralDfa5_0(active0, 0x500000L);
case 111:
return jjMoveStringLiteralDfa5_0(active0, 0x20000000L);
+ case 112:
+ if ((active0 & 0x20000000000L) != 0L)
+ {
+ jjmatchedKind = 41;
+ jjmatchedPos = 4;
+ }
+ break;
case 114:
- return jjMoveStringLiteralDfa5_0(active0, 0x4000080004120L);
+ if ((active0 & 0x40000000000L) != 0L)
+ {
+ jjmatchedKind = 42;
+ jjmatchedPos = 4;
+ }
+ return jjMoveStringLiteralDfa5_0(active0, 0x80100080004120L);
case 115:
if ((active0 & 0x10000L) != 0L)
{
@@ -435,7 +462,7 @@
case 116:
return jjMoveStringLiteralDfa5_0(active0, 0x22000L);
case 117:
- return jjMoveStringLiteralDfa5_0(active0, 0x408000000L);
+ return jjMoveStringLiteralDfa5_0(active0, 0x200408000000L);
case 120:
return jjMoveStringLiteralDfa5_0(active0, 0x280000L);
default :
@@ -453,24 +480,24 @@
switch(curChar)
{
case 67:
- return jjMoveStringLiteralDfa6_0(active0, 0x10000000000000L);
+ return jjMoveStringLiteralDfa6_0(active0, 0x200000000000000L);
case 76:
return jjMoveStringLiteralDfa6_0(active0, 0x100L);
case 78:
return jjMoveStringLiteralDfa6_0(active0, 0xc8L);
case 84:
- return jjMoveStringLiteralDfa6_0(active0, 0x4000000000000L);
+ return jjMoveStringLiteralDfa6_0(active0, 0x80000000000000L);
case 88:
- if ((active0 & 0x8000000000000L) != 0L)
+ if ((active0 & 0x100000000000000L) != 0L)
{
- jjmatchedKind = 51;
+ jjmatchedKind = 56;
jjmatchedPos = 5;
}
break;
case 97:
return jjMoveStringLiteralDfa6_0(active0, 0x8000020L);
case 99:
- return jjMoveStringLiteralDfa6_0(active0, 0x10000000780000L);
+ return jjMoveStringLiteralDfa6_0(active0, 0x200000000780000L);
case 100:
if ((active0 & 0x40000000L) != 0L)
{
@@ -487,9 +514,9 @@
case 104:
return jjMoveStringLiteralDfa6_0(active0, 0x1800000000L);
case 105:
- return jjMoveStringLiteralDfa6_0(active0, 0x20046000L);
+ return jjMoveStringLiteralDfa6_0(active0, 0x100020046000L);
case 108:
- return jjMoveStringLiteralDfa6_0(active0, 0x100000000L);
+ return jjMoveStringLiteralDfa6_0(active0, 0x200100000000L);
case 110:
return jjMoveStringLiteralDfa6_0(active0, 0x1800000L);
case 114:
@@ -502,11 +529,11 @@
}
break;
case 116:
- return jjMoveStringLiteralDfa6_0(active0, 0x4000000001e00L);
+ return jjMoveStringLiteralDfa6_0(active0, 0x80000000001e00L);
case 120:
- if ((active0 & 0x8000000000000L) != 0L)
+ if ((active0 & 0x100000000000000L) != 0L)
{
- jjmatchedKind = 51;
+ jjmatchedKind = 56;
jjmatchedPos = 5;
}
break;
@@ -529,15 +556,15 @@
case 67:
return jjMoveStringLiteralDfa7_0(active0, 0x1000L);
case 76:
- return jjMoveStringLiteralDfa7_0(active0, 0x10000400000000L);
+ return jjMoveStringLiteralDfa7_0(active0, 0x200000400000000L);
case 78:
return jjMoveStringLiteralDfa7_0(active0, 0x200L);
case 79:
return jjMoveStringLiteralDfa7_0(active0, 0x400L);
case 83:
- if ((active0 & 0x4000000000000L) != 0L)
+ if ((active0 & 0x80000000000000L) != 0L)
{
- jjmatchedKind = 50;
+ jjmatchedKind = 55;
jjmatchedPos = 6;
}
return jjMoveStringLiteralDfa7_0(active0, 0x800L);
@@ -562,7 +589,7 @@
jjmatchedKind = 5;
jjmatchedPos = 6;
}
- return jjMoveStringLiteralDfa7_0(active0, 0x10000000780000L);
+ return jjMoveStringLiteralDfa7_0(active0, 0x200000000780000L);
case 110:
if ((active0 & 0x2000000L) != 0L)
{
@@ -573,16 +600,16 @@
case 111:
return jjMoveStringLiteralDfa7_0(active0, 0xc8L);
case 112:
- return jjMoveStringLiteralDfa7_0(active0, 0x20000L);
+ return jjMoveStringLiteralDfa7_0(active0, 0x100000020000L);
case 115:
- if ((active0 & 0x4000000000000L) != 0L)
+ if ((active0 & 0x80000000000000L) != 0L)
{
- jjmatchedKind = 50;
+ jjmatchedKind = 55;
jjmatchedPos = 6;
}
break;
case 116:
- return jjMoveStringLiteralDfa7_0(active0, 0x4000L);
+ return jjMoveStringLiteralDfa7_0(active0, 0x200000004000L);
case 117:
return jjMoveStringLiteralDfa7_0(active0, 0x100000000L);
case 118:
@@ -602,11 +629,13 @@
switch(curChar)
{
case 65:
- return jjMoveStringLiteralDfa8_0(active0, 0x10000000000000L);
+ return jjMoveStringLiteralDfa8_0(active0, 0x200000000000000L);
case 80:
return jjMoveStringLiteralDfa8_0(active0, 0x80000000L);
+ case 86:
+ return jjMoveStringLiteralDfa8_0(active0, 0x200000000000L);
case 97:
- return jjMoveStringLiteralDfa8_0(active0, 0x10000400002000L);
+ return jjMoveStringLiteralDfa8_0(active0, 0x200000400002000L);
case 98:
return jjMoveStringLiteralDfa8_0(active0, 0x400L);
case 100:
@@ -645,7 +674,7 @@
jjmatchedKind = 29;
jjmatchedPos = 7;
}
- return jjMoveStringLiteralDfa8_0(active0, 0x1800100L);
+ return jjMoveStringLiteralDfa8_0(active0, 0x100001800100L);
case 117:
return jjMoveStringLiteralDfa8_0(active0, 0x780800L);
case 121:
@@ -674,9 +703,9 @@
case 79:
return jjMoveStringLiteralDfa9_0(active0, 0x1000000000L);
case 83:
- return jjMoveStringLiteralDfa9_0(active0, 0x10000000000000L);
+ return jjMoveStringLiteralDfa9_0(active0, 0x200000000000000L);
case 97:
- return jjMoveStringLiteralDfa9_0(active0, 0x1000L);
+ return jjMoveStringLiteralDfa9_0(active0, 0x200000001000L);
case 98:
return jjMoveStringLiteralDfa9_0(active0, 0x800L);
case 100:
@@ -700,6 +729,8 @@
jjmatchedPos = 8;
}
break;
+ case 105:
+ return jjMoveStringLiteralDfa9_0(active0, 0x100000000000L);
case 106:
return jjMoveStringLiteralDfa9_0(active0, 0x400L);
case 110:
@@ -707,7 +738,7 @@
case 114:
return jjMoveStringLiteralDfa9_0(active0, 0x80000000L);
case 115:
- return jjMoveStringLiteralDfa9_0(active0, 0x10000000780000L);
+ return jjMoveStringLiteralDfa9_0(active0, 0x200000000780000L);
case 116:
return jjMoveStringLiteralDfa9_0(active0, 0x2000L);
default :
@@ -729,9 +760,9 @@
case 79:
return jjMoveStringLiteralDfa10_0(active0, 0xc0L);
case 83:
- if ((active0 & 0x10000000000000L) != 0L)
+ if ((active0 & 0x200000000000000L) != 0L)
{
- jjmatchedKind = 52;
+ jjmatchedKind = 57;
jjmatchedPos = 9;
}
break;
@@ -755,6 +786,8 @@
return jjMoveStringLiteralDfa10_0(active0, 0x780000L);
case 106:
return jjMoveStringLiteralDfa10_0(active0, 0x800L);
+ case 108:
+ return jjMoveStringLiteralDfa10_0(active0, 0x200000000000L);
case 110:
if ((active0 & 0x8000000L) != 0L)
{
@@ -763,13 +796,13 @@
}
break;
case 111:
- return jjMoveStringLiteralDfa10_0(active0, 0x80000000L);
+ return jjMoveStringLiteralDfa10_0(active0, 0x100080000000L);
case 114:
return jjMoveStringLiteralDfa10_0(active0, 0x1000000100L);
case 115:
- if ((active0 & 0x10000000000000L) != 0L)
+ if ((active0 & 0x200000000000000L) != 0L)
{
- jjmatchedKind = 52;
+ jjmatchedKind = 57;
jjmatchedPos = 9;
}
return jjMoveStringLiteralDfa10_0(active0, 0x1000L);
@@ -804,6 +837,13 @@
return jjMoveStringLiteralDfa11_0(active0, 0x800L);
case 105:
return jjMoveStringLiteralDfa11_0(active0, 0x4000000000L);
+ case 110:
+ if ((active0 & 0x100000000000L) != 0L)
+ {
+ jjmatchedKind = 44;
+ jjmatchedPos = 10;
+ }
+ break;
case 112:
return jjMoveStringLiteralDfa11_0(active0, 0x80000000L);
case 114:
@@ -815,6 +855,8 @@
jjmatchedPos = 10;
}
break;
+ case 117:
+ return jjMoveStringLiteralDfa11_0(active0, 0x200000000000L);
case 118:
return jjMoveStringLiteralDfa11_0(active0, 0x780000L);
default :
@@ -858,6 +900,11 @@
jjmatchedKind = 22;
jjmatchedPos = 11;
}
+ else if ((active0 & 0x200000000000L) != 0L)
+ {
+ jjmatchedKind = 45;
+ jjmatchedPos = 11;
+ }
return jjMoveStringLiteralDfa12_0(active0, 0x80000000L);
case 108:
if ((active0 & 0x100L) != 0L)
@@ -1301,8 +1348,8 @@
case 0:
if ((0x3ff000000000000L & l) != 0L)
{
- if (kind > 88)
- kind = 88;
+ if (kind > 93)
+ kind = 93;
{ jjCheckNAddStates(0, 6); }
}
else if ((0x280000000000L & l) != 0L)
@@ -1311,8 +1358,8 @@
{ jjCheckNAddTwoStates(164, 166); }
else if (curChar == 58)
{
- if (kind > 76)
- kind = 76;
+ if (kind > 81)
+ kind = 81;
{ jjCheckNAddStates(12, 14); }
}
else if (curChar == 34)
@@ -1323,8 +1370,8 @@
{ jjCheckNAddStates(15, 17); }
else if (curChar == 35)
{
- if (kind > 47)
- kind = 47;
+ if (kind > 52)
+ kind = 52;
{ jjCheckNAddStates(18, 20); }
}
if (curChar == 34)
@@ -1335,17 +1382,17 @@
case 1:
if ((0xffffffffffffdbffL & l) == 0L)
break;
- if (kind > 47)
- kind = 47;
+ if (kind > 52)
+ kind = 52;
{ jjCheckNAddStates(18, 20); }
break;
case 2:
- if ((0x2400L & l) != 0L && kind > 47)
- kind = 47;
+ if ((0x2400L & l) != 0L && kind > 52)
+ kind = 52;
break;
case 3:
- if (curChar == 10 && kind > 47)
- kind = 47;
+ if (curChar == 10 && kind > 52)
+ kind = 52;
break;
case 4:
if (curChar == 13)
@@ -1377,8 +1424,8 @@
{ jjCheckNAddStates(15, 17); }
break;
case 13:
- if (curChar == 62 && kind > 75)
- kind = 75;
+ if (curChar == 62 && kind > 80)
+ kind = 80;
break;
case 15:
if ((0x3ff000000000000L & l) != 0L)
@@ -1405,8 +1452,8 @@
jjstateSet[jjnewStateCnt++] = 21;
break;
case 23:
- if ((0x8400000000L & l) != 0L && kind > 82)
- kind = 82;
+ if ((0x8400000000L & l) != 0L && kind > 87)
+ kind = 87;
break;
case 24:
if (curChar == 39)
@@ -1417,8 +1464,8 @@
{ jjCheckNAddStates(24, 26); }
break;
case 26:
- if (curChar == 39 && kind > 83)
- kind = 83;
+ if (curChar == 39 && kind > 88)
+ kind = 88;
break;
case 28:
if ((0x8400000000L & l) != 0L)
@@ -1474,8 +1521,8 @@
{ jjCheckNAddStates(21, 23); }
break;
case 44:
- if (curChar == 34 && kind > 84)
- kind = 84;
+ if (curChar == 34 && kind > 89)
+ kind = 89;
break;
case 46:
if ((0x8400000000L & l) != 0L)
@@ -1585,8 +1632,8 @@
jjstateSet[jjnewStateCnt++] = 79;
break;
case 80:
- if (curChar == 39 && kind > 85)
- kind = 85;
+ if (curChar == 39 && kind > 90)
+ kind = 90;
break;
case 81:
if (curChar == 39)
@@ -1663,8 +1710,8 @@
jjstateSet[jjnewStateCnt++] = 103;
break;
case 104:
- if (curChar == 34 && kind > 86)
- kind = 86;
+ if (curChar == 34 && kind > 91)
+ kind = 91;
break;
case 105:
if (curChar == 34)
@@ -1687,8 +1734,8 @@
jjstateSet[jjnewStateCnt++] = 111;
break;
case 111:
- if (curChar == 58 && kind > 76)
- kind = 76;
+ if (curChar == 58 && kind > 81)
+ kind = 81;
break;
case 112:
if ((0x3ff600000000000L & l) != 0L)
@@ -1705,8 +1752,8 @@
case 115:
if ((0x7ff000000000000L & l) == 0L)
break;
- if (kind > 77)
- kind = 77;
+ if (kind > 82)
+ kind = 82;
{ jjCheckNAddStates(43, 46); }
break;
case 116:
@@ -1714,8 +1761,8 @@
{ jjCheckNAddStates(43, 46); }
break;
case 117:
- if ((0x7ff200000000000L & l) != 0L && kind > 77)
- kind = 77;
+ if ((0x7ff200000000000L & l) != 0L && kind > 82)
+ kind = 82;
break;
case 119:
if ((0xa800fffa00000000L & l) != 0L)
@@ -1738,18 +1785,18 @@
jjstateSet[jjnewStateCnt++] = 124;
break;
case 124:
- if ((0x3ff000000000000L & l) != 0L && kind > 77)
- kind = 77;
+ if ((0x3ff000000000000L & l) != 0L && kind > 82)
+ kind = 82;
break;
case 125:
- if ((0xa800fffa00000000L & l) != 0L && kind > 77)
- kind = 77;
+ if ((0xa800fffa00000000L & l) != 0L && kind > 82)
+ kind = 82;
break;
case 127:
if ((0xa800fffa00000000L & l) == 0L)
break;
- if (kind > 77)
- kind = 77;
+ if (kind > 82)
+ kind = 82;
{ jjCheckNAddStates(43, 46); }
break;
case 128:
@@ -1763,15 +1810,15 @@
case 130:
if ((0x3ff000000000000L & l) == 0L)
break;
- if (kind > 77)
- kind = 77;
+ if (kind > 82)
+ kind = 82;
{ jjCheckNAddStates(43, 46); }
break;
case 131:
if (curChar != 58)
break;
- if (kind > 76)
- kind = 76;
+ if (kind > 81)
+ kind = 81;
{ jjCheckNAddStates(12, 14); }
break;
case 134:
@@ -1783,8 +1830,8 @@
jjstateSet[jjnewStateCnt++] = 136;
break;
case 136:
- if (curChar == 58 && kind > 78)
- kind = 78;
+ if (curChar == 58 && kind > 83)
+ kind = 83;
break;
case 138:
if ((0x3ff600000000000L & l) != 0L)
@@ -1801,8 +1848,8 @@
case 141:
if ((0x7ff000000000000L & l) == 0L)
break;
- if (kind > 79)
- kind = 79;
+ if (kind > 84)
+ kind = 84;
{ jjCheckNAddStates(56, 59); }
break;
case 142:
@@ -1810,8 +1857,8 @@
{ jjCheckNAddStates(56, 59); }
break;
case 143:
- if ((0x7ff200000000000L & l) != 0L && kind > 79)
- kind = 79;
+ if ((0x7ff200000000000L & l) != 0L && kind > 84)
+ kind = 84;
break;
case 145:
if ((0xa800fffa00000000L & l) != 0L)
@@ -1834,18 +1881,18 @@
jjstateSet[jjnewStateCnt++] = 150;
break;
case 150:
- if ((0x3ff000000000000L & l) != 0L && kind > 79)
- kind = 79;
+ if ((0x3ff000000000000L & l) != 0L && kind > 84)
+ kind = 84;
break;
case 151:
- if ((0xa800fffa00000000L & l) != 0L && kind > 79)
- kind = 79;
+ if ((0xa800fffa00000000L & l) != 0L && kind > 84)
+ kind = 84;
break;
case 153:
if ((0xa800fffa00000000L & l) == 0L)
break;
- if (kind > 79)
- kind = 79;
+ if (kind > 84)
+ kind = 84;
{ jjCheckNAddStates(56, 59); }
break;
case 154:
@@ -1859,8 +1906,8 @@
case 156:
if ((0x3ff000000000000L & l) == 0L)
break;
- if (kind > 79)
- kind = 79;
+ if (kind > 84)
+ kind = 84;
{ jjCheckNAddStates(56, 59); }
break;
case 158:
@@ -1870,8 +1917,8 @@
case 159:
if ((0x3ff000000000000L & l) == 0L)
break;
- if (kind > 92)
- kind = 92;
+ if (kind > 97)
+ kind = 97;
{ jjCheckNAddTwoStates(158, 159); }
break;
case 160:
@@ -1881,8 +1928,8 @@
case 161:
if ((0x3ff000000000000L & l) == 0L)
break;
- if (kind > 88)
- kind = 88;
+ if (kind > 93)
+ kind = 93;
{ jjCheckNAdd(161); }
break;
case 162:
@@ -1896,8 +1943,8 @@
case 164:
if ((0x3ff000000000000L & l) == 0L)
break;
- if (kind > 89)
- kind = 89;
+ if (kind > 94)
+ kind = 94;
{ jjCheckNAdd(164); }
break;
case 165:
@@ -1915,8 +1962,8 @@
case 169:
if ((0x3ff000000000000L & l) == 0L)
break;
- if (kind > 90)
- kind = 90;
+ if (kind > 95)
+ kind = 95;
{ jjCheckNAdd(169); }
break;
case 170:
@@ -1942,8 +1989,8 @@
case 176:
if ((0x3ff000000000000L & l) == 0L)
break;
- if (kind > 90)
- kind = 90;
+ if (kind > 95)
+ kind = 95;
{ jjCheckNAdd(176); }
break;
case 177:
@@ -1957,15 +2004,15 @@
case 180:
if ((0x3ff000000000000L & l) == 0L)
break;
- if (kind > 90)
- kind = 90;
+ if (kind > 95)
+ kind = 95;
{ jjCheckNAdd(180); }
break;
case 181:
if ((0x3ff000000000000L & l) == 0L)
break;
- if (kind > 88)
- kind = 88;
+ if (kind > 93)
+ kind = 93;
{ jjCheckNAddStates(0, 6); }
break;
case 182:
@@ -1992,8 +2039,8 @@
jjstateSet[jjnewStateCnt++] = 23;
break;
case 1:
- if (kind > 47)
- kind = 47;
+ if (kind > 52)
+ kind = 52;
{ jjAddStates(18, 20); }
break;
case 6:
@@ -2058,8 +2105,8 @@
jjstateSet[jjnewStateCnt++] = 23;
break;
case 23:
- if ((0x14404410000000L & l) != 0L && kind > 82)
- kind = 82;
+ if ((0x14404410000000L & l) != 0L && kind > 87)
+ kind = 87;
break;
case 25:
if ((0xffffffffefffffffL & l) != 0L)
@@ -2328,8 +2375,8 @@
case 115:
if ((0x7fffffe87fffffeL & l) == 0L)
break;
- if (kind > 77)
- kind = 77;
+ if (kind > 82)
+ kind = 82;
{ jjCheckNAddStates(43, 46); }
break;
case 116:
@@ -2337,8 +2384,8 @@
{ jjCheckNAddStates(43, 46); }
break;
case 117:
- if ((0x7fffffe87fffffeL & l) != 0L && kind > 77)
- kind = 77;
+ if ((0x7fffffe87fffffeL & l) != 0L && kind > 82)
+ kind = 82;
break;
case 118:
if (curChar == 92)
@@ -2361,12 +2408,12 @@
jjstateSet[jjnewStateCnt++] = 124;
break;
case 124:
- if ((0x7e0000007eL & l) != 0L && kind > 77)
- kind = 77;
+ if ((0x7e0000007eL & l) != 0L && kind > 82)
+ kind = 82;
break;
case 125:
- if ((0x4000000080000001L & l) != 0L && kind > 77)
- kind = 77;
+ if ((0x4000000080000001L & l) != 0L && kind > 82)
+ kind = 82;
break;
case 126:
if (curChar == 92)
@@ -2375,8 +2422,8 @@
case 127:
if ((0x4000000080000001L & l) == 0L)
break;
- if (kind > 77)
- kind = 77;
+ if (kind > 82)
+ kind = 82;
{ jjCheckNAddStates(43, 46); }
break;
case 129:
@@ -2386,8 +2433,8 @@
case 130:
if ((0x7e0000007eL & l) == 0L)
break;
- if (kind > 77)
- kind = 77;
+ if (kind > 82)
+ kind = 82;
{ jjCheckNAddStates(43, 46); }
break;
case 132:
@@ -2421,8 +2468,8 @@
case 141:
if ((0x7fffffe87fffffeL & l) == 0L)
break;
- if (kind > 79)
- kind = 79;
+ if (kind > 84)
+ kind = 84;
{ jjCheckNAddStates(56, 59); }
break;
case 142:
@@ -2430,8 +2477,8 @@
{ jjCheckNAddStates(56, 59); }
break;
case 143:
- if ((0x7fffffe87fffffeL & l) != 0L && kind > 79)
- kind = 79;
+ if ((0x7fffffe87fffffeL & l) != 0L && kind > 84)
+ kind = 84;
break;
case 144:
if (curChar == 92)
@@ -2454,12 +2501,12 @@
jjstateSet[jjnewStateCnt++] = 150;
break;
case 150:
- if ((0x7e0000007eL & l) != 0L && kind > 79)
- kind = 79;
+ if ((0x7e0000007eL & l) != 0L && kind > 84)
+ kind = 84;
break;
case 151:
- if ((0x4000000080000001L & l) != 0L && kind > 79)
- kind = 79;
+ if ((0x4000000080000001L & l) != 0L && kind > 84)
+ kind = 84;
break;
case 152:
if (curChar == 92)
@@ -2468,8 +2515,8 @@
case 153:
if ((0x4000000080000001L & l) == 0L)
break;
- if (kind > 79)
- kind = 79;
+ if (kind > 84)
+ kind = 84;
{ jjCheckNAddStates(56, 59); }
break;
case 155:
@@ -2479,22 +2526,22 @@
case 156:
if ((0x7e0000007eL & l) == 0L)
break;
- if (kind > 79)
- kind = 79;
+ if (kind > 84)
+ kind = 84;
{ jjCheckNAddStates(56, 59); }
break;
case 157:
if ((0x7fffffe07fffffeL & l) == 0L)
break;
- if (kind > 92)
- kind = 92;
+ if (kind > 97)
+ kind = 97;
{ jjCheckNAddTwoStates(157, 158); }
break;
case 159:
if ((0x7fffffe07fffffeL & l) == 0L)
break;
- if (kind > 92)
- kind = 92;
+ if (kind > 97)
+ kind = 97;
{ jjCheckNAddTwoStates(158, 159); }
break;
case 167:
@@ -2531,8 +2578,8 @@
case 1:
if (!jjCanMove_0(hiByte, i1, i2, l1, l2))
break;
- if (kind > 47)
- kind = 47;
+ if (kind > 52)
+ kind = 52;
{ jjAddStates(18, 20); }
break;
case 6:
@@ -2574,8 +2621,8 @@
case 115:
if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
break;
- if (kind > 77)
- kind = 77;
+ if (kind > 82)
+ kind = 82;
{ jjCheckNAddStates(43, 46); }
break;
case 116:
@@ -2583,8 +2630,8 @@
{ jjCheckNAddStates(43, 46); }
break;
case 117:
- if (jjCanMove_2(hiByte, i1, i2, l1, l2) && kind > 77)
- kind = 77;
+ if (jjCanMove_2(hiByte, i1, i2, l1, l2) && kind > 82)
+ kind = 82;
break;
case 133:
if (jjCanMove_1(hiByte, i1, i2, l1, l2))
@@ -2613,8 +2660,8 @@
case 141:
if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
break;
- if (kind > 79)
- kind = 79;
+ if (kind > 84)
+ kind = 84;
{ jjCheckNAddStates(56, 59); }
break;
case 142:
@@ -2622,8 +2669,8 @@
{ jjCheckNAddStates(56, 59); }
break;
case 143:
- if (jjCanMove_2(hiByte, i1, i2, l1, l2) && kind > 79)
- kind = 79;
+ if (jjCanMove_2(hiByte, i1, i2, l1, l2) && kind > 84)
+ kind = 84;
break;
default : if (i1 == 0 || l1 == 0 || i2 == 0 || l2 == 0) break; else break;
}
@@ -2751,12 +2798,13 @@
"\154\145\163\163\124\150\141\156\117\162\105\161\165\141\154\163",
"\161\165\141\154\151\146\151\145\144\126\141\154\165\145\123\150\141\160\145", "\161\165\141\154\151\146\151\145\144\115\151\156\103\157\165\156\164",
"\161\165\141\154\151\146\151\145\144\115\141\170\103\157\165\156\164",
-"\161\165\141\154\151\146\151\145\144\126\141\154\165\145\123\150\141\160\145\163\104\151\163\152\157\151\156\164", "\136\136", null, null, null, null, null, null, "\ufeff", null, null, null,
-null, null, null, null, null, "\53", "\55", "\174", "\100", "\136", "\56", "\41",
-"\77", "\57", "\52", "\75", "\50", "\51", "\173", "\175", "\133", "\135", null, null,
+"\161\165\141\154\151\146\151\145\144\126\141\154\165\145\123\150\141\160\145\163\104\151\163\152\157\151\156\164", "\147\162\157\165\160", "\157\162\144\145\162", "\156\141\155\145",
+"\144\145\163\143\162\151\160\164\151\157\156", "\144\145\146\141\165\154\164\126\141\154\165\145", "\136\136", null, null,
+null, null, null, null, "\ufeff", null, null, null, null, null, null, null, null,
+"\53", "\55", "\174", "\100", "\136", "\56", "\41", "\77", "\57", "\52", "\75",
+"\50", "\51", "\173", "\175", "\133", "\135", null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-null, };
+null, null, null, null, null, null, null, null, null, null, null, };
protected Token jjFillToken()
{
final Token t;
@@ -2943,13 +2991,13 @@
"DEFAULT",
};
static final long[] jjtoToken = {
- 0xfeff03ffffffffffL, 0x177cfbffL,
+ 0xdfe07fffffffffffL, 0x2ef9f7fffL,
};
static final long[] jjtoSkip = {
- 0xfc0000000000L, 0x0L,
+ 0x1f800000000000L, 0x0L,
};
static final long[] jjtoSpecial = {
- 0x800000000000L, 0x0L,
+ 0x10000000000000L, 0x0L,
};
protected SimpleCharStream input_stream;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/CompactOut.java b/jena-shacl/src/main/java/org/apache/jena/shacl/compact/writer/CompactOut.java
similarity index 98%
rename from jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/CompactOut.java
rename to jena-shacl/src/main/java/org/apache/jena/shacl/compact/writer/CompactOut.java
index 3f7cbf0..ed6c0f9 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/CompactOut.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/compact/writer/CompactOut.java
@@ -16,7 +16,7 @@
* limitations under the License.
*/
-package org.apache.jena.shacl.engine.constraint;
+package org.apache.jena.shacl.compact.writer;
import java.util.Collection;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/compact/writer/CompactWriter.java b/jena-shacl/src/main/java/org/apache/jena/shacl/compact/writer/CompactWriter.java
index 83001e1..734b5e8 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/compact/writer/CompactWriter.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/compact/writer/CompactWriter.java
@@ -18,11 +18,13 @@
package org.apache.jena.shacl.compact.writer;
+import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.jena.atlas.io.IndentedLineBuffer;
import org.apache.jena.atlas.io.IndentedWriter;
+import org.apache.jena.atlas.lib.CollectionUtils;
import org.apache.jena.riot.out.NodeFormatter;
import org.apache.jena.riot.out.NodeFormatterTTL;
import org.apache.jena.riot.system.PrefixMap;
@@ -190,10 +192,10 @@
return null;
if ( ! other.getPropertyShapes().isEmpty() )
return null;
- List<Constraint> constraints = other.getConstraints();
+ Collection<Constraint> constraints = other.getConstraints();
if ( constraints.size() != 1 )
return null;
- return constraints.get(0);
+ return CollectionUtils.oneElt(constraints);
}
private static void notShaclc(String string) {
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/compact/writer/ShapeOutputVisitor.java b/jena-shacl/src/main/java/org/apache/jena/shacl/compact/writer/ShapeOutputVisitor.java
index c6d5129..818e646 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/compact/writer/ShapeOutputVisitor.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/compact/writer/ShapeOutputVisitor.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.compact.writer;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.*;
+import static org.apache.jena.shacl.compact.writer.CompactOut.*;
import org.apache.jena.atlas.io.IndentedWriter;
import org.apache.jena.riot.out.NodeFormatter;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ValidationContext.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ValidationContext.java
index 1e34f3e..7dbbc53 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ValidationContext.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ValidationContext.java
@@ -20,10 +20,12 @@
import org.apache.jena.graph.Graph;
import org.apache.jena.graph.Node;
+import org.apache.jena.riot.system.ErrorHandler;
import org.apache.jena.shacl.Shapes;
import org.apache.jena.shacl.ValidationReport;
import org.apache.jena.shacl.parser.Constraint;
import org.apache.jena.shacl.parser.Shape;
+import org.apache.jena.shacl.sys.ShaclSystem;
import org.apache.jena.shacl.validation.ReportItem;
import org.apache.jena.sparql.path.Path;
@@ -33,12 +35,19 @@
private final ValidationReport.Builder validationReportBuilder = ValidationReport.create();
private boolean verbose = false;
+ private boolean seenValidationReportEntry = false;
private final Shapes shapes;
private final Graph dataGraph;
private boolean strict = false;
+ private final ErrorHandler errorHandler;
+
public static ValidationContext create(Shapes shapes, Graph data) {
- ValidationContext vCxt = new ValidationContext(shapes, data);
+ return create(shapes, data, ShaclSystem.systemShaclErrorHandler);
+ }
+
+ public static ValidationContext create(Shapes shapes, Graph data, ErrorHandler errorHandler) {
+ ValidationContext vCxt = new ValidationContext(shapes, data, errorHandler);
vCxt.setVerbose(VERBOSE);
return vCxt;
}
@@ -52,11 +61,15 @@
this.dataGraph = vCxt.dataGraph;
this.verbose = vCxt.verbose;
this.strict = vCxt.strict;
+ this.errorHandler = vCxt.errorHandler;
}
- private ValidationContext(Shapes shapes, Graph data) {
+ private ValidationContext(Shapes shapes, Graph data, ErrorHandler errorHandler) {
this.shapes = shapes;
this.dataGraph = data;
+ if ( errorHandler == null )
+ errorHandler = ShaclSystem.systemShaclErrorHandler;
+ this.errorHandler = errorHandler;
validationReportBuilder.addPrefixes(data.getPrefixMapping());
validationReportBuilder.addPrefixes(shapes.getGraph().getPrefixMapping());
}
@@ -70,6 +83,7 @@
public void reportEntry(String message, Shape shape, Node focusNode, Path path, Node valueNode, Constraint constraint) {
if ( verbose )
System.out.println("Validation report entry");
+ seenValidationReportEntry = true;
validationReportBuilder.addReportEntry(message, shape, focusNode, path, valueNode, constraint);
}
@@ -77,6 +91,8 @@
return validationReportBuilder.build();
}
+ public boolean hasViolation() { return seenValidationReportEntry; }
+
public void setVerbose(boolean value) {
this.verbose = value;
}
@@ -103,4 +119,9 @@
public Graph getDataGraph() {
return dataGraph;
}
+
+ public ErrorHandler getErrorHandler() {
+ return errorHandler;
+ }
+
}
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ClassConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ClassConstraint.java
index e8f1a93..1d34754 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ClassConstraint.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ClassConstraint.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.engine.constraint;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.compact;
+import static org.apache.jena.shacl.compact.writer.CompactOut.compact;
import static org.apache.jena.shacl.lib.ShLib.displayStr;
import java.util.List;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ClosedConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ClosedConstraint.java
index d808604..6e0fbe3 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ClosedConstraint.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ClosedConstraint.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.engine.constraint;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.*;
+import static org.apache.jena.shacl.compact.writer.CompactOut.*;
import static org.apache.jena.shacl.lib.ShLib.displayStr;
import java.util.*;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/DatatypeConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/DatatypeConstraint.java
index 64d6d07..3285089 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/DatatypeConstraint.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/DatatypeConstraint.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.engine.constraint;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.compact;
+import static org.apache.jena.shacl.compact.writer.CompactOut.compact;
import static org.apache.jena.shacl.lib.ShLib.displayStr;
import java.util.Objects;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/DisjointConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/DisjointConstraint.java
index 14c02de..d2d7bec 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/DisjointConstraint.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/DisjointConstraint.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.engine.constraint;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.compactArrayNodes;
+import static org.apache.jena.shacl.compact.writer.CompactOut.compactArrayNodes;
import static org.apache.jena.shacl.lib.ShLib.displayStr;
import java.util.Objects;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/EqualsConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/EqualsConstraint.java
index 673d708..7a3072b 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/EqualsConstraint.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/EqualsConstraint.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.engine.constraint;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.compact;
+import static org.apache.jena.shacl.compact.writer.CompactOut.compact;
import static org.apache.jena.shacl.lib.ShLib.displayStr;
import java.util.Objects;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/HasValueConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/HasValueConstraint.java
index da50e37..8a18875 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/HasValueConstraint.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/HasValueConstraint.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.engine.constraint;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.compact;
+import static org.apache.jena.shacl.compact.writer.CompactOut.compact;
import static org.apache.jena.shacl.lib.ShLib.displayStr;
import java.util.Objects;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/InConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/InConstraint.java
index 910040c..cb9bdeb 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/InConstraint.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/InConstraint.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.engine.constraint;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.compactArrayNodes;
+import static org.apache.jena.shacl.compact.writer.CompactOut.compactArrayNodes;
import static org.apache.jena.shacl.lib.ShLib.displayStr;
import java.util.ArrayList;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/JLogConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/JLogConstraint.java
new file mode 100644
index 0000000..1a20b89
--- /dev/null
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/JLogConstraint.java
@@ -0,0 +1,73 @@
+/*
+ * 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.shacl.engine.constraint;
+
+import java.util.Objects;
+
+import org.apache.jena.graph.Node;
+import org.apache.jena.shacl.engine.ValidationContext;
+import org.apache.jena.shacl.lib.ShLib;
+import org.apache.jena.shacl.sys.ShaclSystem;
+import org.apache.jena.shacl.validation.ReportItem;
+import org.apache.jena.shacl.vocabulary.SHJ;
+
+/** A constraint that logs when touched but does not causes a violation */
+public class JLogConstraint extends ConstraintTerm {
+
+ private final String message;
+
+ public JLogConstraint(String message) {
+ this.message = message;
+ }
+
+ @Override
+ public Node getComponent() {
+ return SHJ.LogConstraintComponent;
+ }
+
+ @Override
+ public ReportItem validate(ValidationContext vCxt, Node n) {
+ String msg = String.format("%s[%s]", message, ShLib.displayStr(n));
+ ShaclSystem.systemShaclLogger.warn(msg);
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "Log["+message+"]";
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(message);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ JLogConstraint other = (JLogConstraint)obj;
+ return Objects.equals(message, other.message);
+ }
+}
+
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/JViolationConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/JViolationConstraint.java
new file mode 100644
index 0000000..4aac907
--- /dev/null
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/JViolationConstraint.java
@@ -0,0 +1,77 @@
+/*
+ * 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.shacl.engine.constraint;
+
+import org.apache.jena.atlas.io.IndentedWriter;
+import org.apache.jena.graph.Node;
+import org.apache.jena.riot.out.NodeFormatter;
+import org.apache.jena.shacl.compact.writer.CompactOut;
+import org.apache.jena.shacl.engine.ValidationContext;
+import org.apache.jena.shacl.validation.ReportItem;
+import org.apache.jena.shacl.vocabulary.SHJ;
+
+/** A constraint that causes a violation if it's object is "true" */
+public class JViolationConstraint extends ConstraintTerm {
+
+ private final boolean generateViolation;
+
+ public JViolationConstraint(boolean generateViolation) {
+ this.generateViolation = generateViolation;
+ }
+
+ @Override
+ public Node getComponent() {
+ return SHJ.ViolationConstraintComponent;
+ }
+
+ @Override
+ public ReportItem validate(ValidationContext vCxt, Node n) {
+ if ( ! generateViolation )
+ return null;
+ return new ReportItem("Violation");
+ }
+
+ @Override
+ public void printCompact(IndentedWriter out, NodeFormatter nodeFmt) {
+ CompactOut.compactUnquotedString(out, "violation", Boolean.toString(generateViolation));
+ }
+
+ @Override
+ public String toString() {
+ return "Violation["+generateViolation+"]";
+ }
+
+ @Override
+ public int hashCode() {
+ return 158+(generateViolation?1:2);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ JViolationConstraint other = (JViolationConstraint)obj;
+ return generateViolation == other.generateViolation;
+ }
+}
+
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/LessThanConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/LessThanConstraint.java
index 84ced0a..81a06fa 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/LessThanConstraint.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/LessThanConstraint.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.engine.constraint;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.compact;
+import static org.apache.jena.shacl.compact.writer.CompactOut.compact;
import static org.apache.jena.shacl.lib.ShLib.displayStr;
import java.util.Objects;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/LessThanOrEqualsConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/LessThanOrEqualsConstraint.java
index a625b6c..0a36e56 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/LessThanOrEqualsConstraint.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/LessThanOrEqualsConstraint.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.engine.constraint;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.compact;
+import static org.apache.jena.shacl.compact.writer.CompactOut.compact;
import static org.apache.jena.shacl.lib.ShLib.displayStr;
import java.util.Objects;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/PatternConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/PatternConstraint.java
index a2b3db3..c3fc4a5 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/PatternConstraint.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/PatternConstraint.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.engine.constraint;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.*;
+import static org.apache.jena.shacl.compact.writer.CompactOut.*;
import java.util.Objects;
import java.util.regex.Pattern;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/QualifiedValueShape.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/QualifiedValueShape.java
index 14199b4..9dc8ddc 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/QualifiedValueShape.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/QualifiedValueShape.java
@@ -26,6 +26,7 @@
import org.apache.jena.riot.out.NodeFormatter;
import org.apache.jena.shacl.ShaclException;
import org.apache.jena.shacl.ValidationReport;
+import org.apache.jena.shacl.compact.writer.CompactOut;
import org.apache.jena.shacl.compact.writer.CompactWriter;
import org.apache.jena.shacl.engine.ValidationContext;
import org.apache.jena.shacl.lib.G;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ReportConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ReportConstraint.java
index e728858..b5f0be2 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ReportConstraint.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ReportConstraint.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.engine.constraint;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.compactQuotedString;
+import static org.apache.jena.shacl.compact.writer.CompactOut.compactQuotedString;
import java.util.Set;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/StrLanguageIn.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/StrLanguageIn.java
index 72a28d7..fa9027e 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/StrLanguageIn.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/StrLanguageIn.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.engine.constraint;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.compactArrayString;
+import static org.apache.jena.shacl.compact.writer.CompactOut.compactArrayString;
import java.util.List;
import java.util.Objects;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/StrMaxLengthConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/StrMaxLengthConstraint.java
index 2eb8749..73ec972 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/StrMaxLengthConstraint.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/StrMaxLengthConstraint.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.engine.constraint;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.compact;
+import static org.apache.jena.shacl.compact.writer.CompactOut.compact;
import java.util.Objects;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/StrMinLengthConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/StrMinLengthConstraint.java
index e8eb511..4fdc1a0 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/StrMinLengthConstraint.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/StrMinLengthConstraint.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.engine.constraint;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.compact;
+import static org.apache.jena.shacl.compact.writer.CompactOut.compact;
import java.util.Objects;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/UniqueLangConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/UniqueLangConstraint.java
index 608ada5..494df61 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/UniqueLangConstraint.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/UniqueLangConstraint.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.engine.constraint;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.compactUnquotedString;
+import static org.apache.jena.shacl.compact.writer.CompactOut.compactUnquotedString;
import java.util.HashSet;
import java.util.Objects;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ValueRangeConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ValueRangeConstraint.java
index f5c2b62..fddd75c 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ValueRangeConstraint.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ValueRangeConstraint.java
@@ -18,7 +18,7 @@
package org.apache.jena.shacl.engine.constraint;
-import static org.apache.jena.shacl.engine.constraint.CompactOut.compact;
+import static org.apache.jena.shacl.compact.writer.CompactOut.compact;
import java.util.Objects;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Constraints.java b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Constraints.java
index 5a1929b..5d75798 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Constraints.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Constraints.java
@@ -84,35 +84,35 @@
dispatch.put( SHACL.nodeKind, (g, s, p, o) -> new NodeKindConstraint(o) );
dispatch.put( SHACL.minCount, (g, s, p, o) -> new MinCount(intValue(o)) );
dispatch.put( SHACL.maxCount, (g, s, p, o) -> new MaxCount(intValue(o)) );
-
+
dispatch.put( SHACL.minInclusive, (g, s, p, o) -> new ValueMinInclusiveConstraint(o) );
dispatch.put( SHACL.minExclusive, (g, s, p, o) -> new ValueMinExclusiveConstraint(o) );
dispatch.put( SHACL.maxInclusive, (g, s, p, o) -> new ValueMaxInclusiveConstraint(o) );
dispatch.put( SHACL.maxExclusive, (g, s, p, o) -> new ValueMaxExclusiveConstraint(o) );
-
+
dispatch.put( SHACL.minLength, (g, s, p, o) -> new StrMinLengthConstraint(intValue(o)) );
dispatch.put( SHACL.maxLength, (g, s, p, o) -> new StrMaxLengthConstraint(intValue(o)) );
// in parseConstraint
//dispatch.put( SHACL.pattern, (g, p, o) -> notImplemented(p) );
dispatch.put( SHACL.languageIn, (g, s, p, o) -> new StrLanguageIn(listString(g, o)) );
dispatch.put( SHACL.uniqueLang, (g, s, p, o) -> new UniqueLangConstraint(booleanValueStrict(o)) );
-
+
dispatch.put( SHACL.hasValue, (g, s, p, o) -> new HasValueConstraint(o) );
dispatch.put( SHACL.in, (g, s, p, o) -> new InConstraint(list(g,o)) );
dispatch.put( SHACL.closed, (g, s, p, o) -> new ClosedConstraint(g,s,booleanValue(o)) );
-
+
dispatch.put( SHACL.equals, (g, s, p, o) -> new EqualsConstraint(o) );
dispatch.put( SHACL.disjoint, (g, s, p, o) -> new DisjointConstraint(o) );
dispatch.put( SHACL.lessThan, (g, s, p, o) -> new LessThanConstraint(o) );
dispatch.put( SHACL.lessThanOrEquals, (g, s, p, o) -> new LessThanOrEqualsConstraint(o) );
-
+
// Below
//dispatch.put( SHACL.not, (g, s, p, o) -> notImplemented(p) );
//dispatch.put( SHACL.and, (g, s, p, o) -> notImplemented(p) );
//dispatch.put( SHACL.or, (g, s, p, o) -> notImplemented(p) );
//dispatch.put( SHACL.xone, (g, s, p, o) -> notImplemented(p) );
//dispatch.put( SHACL.node, (g, s, p, o) -> notImplemented(p) );
-
+
dispatch.put(SHACL.sparql, (g, s, p, o) -> SparqlConstraints.parseSparqlConstraint(g, s, p, o) );
}
@@ -144,7 +144,7 @@
* parser at when the constraint uses other shapes
* (sh:and/sh:or/sh:not/sh:xone.sh:node).
*/
- /*package*/ static List<Constraint> parseConstraints(Graph shapesGraph, Node shape, Map<Node, Shape> parsed) {
+ /*package*/ static List<Constraint> parseConstraints(Graph shapesGraph, Node shape, Map<Node, Shape> parsed, Set<Node> traversed) {
List<Constraint> constraints = new ArrayList<>();
Iterator<Triple> iter = G.find(shapesGraph, shape, null, null);
while(iter.hasNext()) {
@@ -157,18 +157,18 @@
continue;
Node s = t.getSubject();
Node o = t.getObject();
- Constraint c = parseConstraint(shapesGraph, s, p, o, parsed);
+ Constraint c = parseConstraint(shapesGraph, s, p, o, parsed, traversed);
if ( c != null )
constraints.add(c);
}
return constraints;
}
- /**
- * The translate of an RDF triple into a {@link Constraint}.
+ /**
+ * The translate of an RDF triple into a {@link Constraint}.
* Constraints require more that just the triple being inspected.
- */
- private static Constraint parseConstraint(Graph g, Node s, Node p, Node o, Map<Node, Shape> parsed) {
+ */
+ private static Constraint parseConstraint(Graph g, Node s, Node p, Node o, Map<Node, Shape> parsed, Set<Node> traversed) {
// Test for single triple constraints.
ConstraintMaker maker = dispatch.get(p);
@@ -177,35 +177,35 @@
// These require the "parsed" map.
if ( p.equals(SHACL.not) ) {
- Shape shape = ShapesParser.parseShapeStep(parsed, g, o);
+ Shape shape = ShapesParser.parseShapeStep(traversed, parsed, g, o);
return new ShNot(shape);
}
if ( p.equals(SHACL.or) ) {
List<Node> elts = list(g, o);
- List<Shape> shapes = elts.stream().map(x->ShapesParser.parseShapeStep(parsed, g, x)).collect(Collectors.toList());
+ List<Shape> shapes = elts.stream().map(x->ShapesParser.parseShapeStep(traversed, parsed, g, x)).collect(Collectors.toList());
return new ShOr(shapes);
}
if ( p.equals(SHACL.and) ) {
List<Node> elts = list(g, o);
- List<Shape> shapes = elts.stream().map(x->ShapesParser.parseShapeStep(parsed, g, x)).collect(Collectors.toList());
+ List<Shape> shapes = elts.stream().map(x->ShapesParser.parseShapeStep(traversed, parsed, g, x)).collect(Collectors.toList());
return new ShAnd(shapes);
}
if ( p.equals(SHACL.xone) ) {
List<Node> elts = list(g, o);
- List<Shape> shapes = elts.stream().map(x->ShapesParser.parseShapeStep(parsed, g, x)).collect(Collectors.toList());
+ List<Shape> shapes = elts.stream().map(x->ShapesParser.parseShapeStep(traversed, parsed, g, x)).collect(Collectors.toList());
return new ShXone(shapes);
}
if ( p.equals(SHACL.node) ) {
- Shape other = ShapesParser.parseShapeStep(parsed, g, o);
+ Shape other = ShapesParser.parseShapeStep(traversed, parsed, g, o);
if ( other instanceof PropertyShape )
throw new ShaclParseException("Object of sh:node must be a node shape, not a property shape");
return new ShNode(other);
}
- // sh:pattern is influenced by an adjacent sh:flags.
+ // sh:pattern is influenced by an adjacent sh:flags.
if ( p.equals(SHACL.pattern) ) {
Node pat = o;
if ( ! Util.isSimpleString(pat) )
@@ -221,7 +221,7 @@
return null;
if ( p.equals(SHACL.qualifiedValueShape) )
- return parseQualifiedValueShape(g, s, p, o, parsed);
+ return parseQualifiedValueShape(g, s, p, o, parsed, traversed);
// sh:qualifiedValueShape parameters.
if ( p.equals(SHACL.QualifiedMinCountConstraintComponent) ||
@@ -244,8 +244,8 @@
return null;
}
- private static Constraint parseQualifiedValueShape(Graph g, Node s, Node p, Node o, Map<Node, Shape> parsed) {
- Shape sub = ShapesParser.parseShapeStep(parsed, g, o);
+ private static Constraint parseQualifiedValueShape(Graph g, Node s, Node p, Node o, Map<Node, Shape> parsed, Set<Node> traversed) {
+ Shape sub = ShapesParser.parseShapeStep(traversed, parsed, g, o);
// [PARSE] Syntax check needed
Node qMin = G.getZeroOrOneSP(g, s, SHACL.qualifiedMinCount);
Node qMax = G.getZeroOrOneSP(g, s, SHACL.qualifiedMaxCount);
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/NodeShape.java b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/NodeShape.java
index 8cc7d30..e65629e 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/NodeShape.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/NodeShape.java
@@ -19,7 +19,6 @@
package org.apache.jena.shacl.parser;
import java.util.Collection;
-import java.util.List;
import org.apache.jena.atlas.io.IndentedWriter;
import org.apache.jena.graph.Graph;
@@ -31,8 +30,8 @@
public class NodeShape extends Shape {
public NodeShape(Graph shapeGraph, Node shapeNode, boolean deactivated,
- Severity severity, List<Node> messages, Collection<Target> targets,
- List<Constraint> constraints, List<PropertyShape> propertyShapes) {
+ Severity severity, Collection<Node> messages, Collection<Target> targets,
+ Collection<Constraint> constraints, Collection<PropertyShape> propertyShapes) {
super(shapeGraph, shapeNode, deactivated, severity, messages, targets, constraints, propertyShapes);
}
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/PropertyShape.java b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/PropertyShape.java
index f6c13f8..6259011 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/PropertyShape.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/PropertyShape.java
@@ -34,7 +34,7 @@
public class PropertyShape extends Shape {
private final Path path;
- public PropertyShape(Graph shapeGraph, Node shapeNode, boolean isDeactivated, Severity severity, List<Node> messages,
+ public PropertyShape(Graph shapeGraph, Node shapeNode, boolean isDeactivated, Severity severity, Collection<Node> messages,
Collection<Target> targets, Path path, List<Constraint> constraints, List<PropertyShape> propertyShapes) {
super(shapeGraph, shapeNode, isDeactivated, severity, messages, targets, constraints, propertyShapes);
this.path = Objects.requireNonNull(path, "path");
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Shape.java b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Shape.java
index 7d725fd..74c33d4 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Shape.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Shape.java
@@ -21,7 +21,6 @@
import java.io.BufferedOutputStream;
import java.io.OutputStream;
import java.util.Collection;
-import java.util.List;
import org.apache.jena.atlas.io.IndentedWriter;
import org.apache.jena.graph.Graph;
@@ -40,11 +39,11 @@
protected final Severity severity;
protected final Collection<Node> messages;
protected final Collection<Target> targets;
- protected final List<Constraint> constraints;
- protected final List<PropertyShape> propertyShapes;
+ protected final Collection<Constraint> constraints;
+ protected final Collection<PropertyShape> propertyShapes;
- public Shape(Graph shapeGraph, Node shapeNode, boolean deactivated, Severity severity, List<Node> messages,
- Collection<Target> targets, List<Constraint> constraints, List<PropertyShape> propertyShapes) {
+ protected Shape(Graph shapeGraph, Node shapeNode, boolean deactivated, Severity severity, Collection<Node> messages,
+ Collection<Target> targets, Collection<Constraint> constraints, Collection<PropertyShape> propertyShapes) {
super();
this.shapeGraph = shapeGraph;
this.shapeNode = shapeNode;
@@ -82,11 +81,11 @@
return ! targets.isEmpty();
}
- public List<Constraint> getConstraints() {
+ public Collection<Constraint> getConstraints() {
return constraints;
}
- public List<PropertyShape> getPropertyShapes() {
+ public Collection<PropertyShape> getPropertyShapes() {
return propertyShapes;
}
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/ShapesParser.java b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/ShapesParser.java
index c201159..ed8f49e 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/ShapesParser.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/ShapesParser.java
@@ -36,7 +36,10 @@
import org.apache.jena.shacl.engine.Target;
import org.apache.jena.shacl.engine.TargetType;
import org.apache.jena.shacl.engine.Targets;
+import org.apache.jena.shacl.engine.constraint.JLogConstraint;
import org.apache.jena.shacl.lib.G;
+import org.apache.jena.shacl.lib.ShLib;
+import org.apache.jena.shacl.sys.ShaclSystem;
import org.apache.jena.shacl.validation.Severity;
import org.apache.jena.shacl.vocabulary.SHACL;
import org.apache.jena.shared.JenaException;
@@ -58,7 +61,6 @@
private static final boolean DEBUG = false;
private static IndentedWriter OUT = IndentedWriter.stdout;
- //private static Logger LOG = LoggerFactory.getLogger(ShapesParser.class);
/**
* Parse, starting from the given targets.
@@ -67,6 +69,13 @@
* Applications should call functions in {@link Shapes} rather than call the parser directly.
*/
public static Collection<Shape> parseShapes(Graph shapesGraph, Targets targets, Map<Node, Shape> shapesMap) {
+ // Cycle detection.
+ Set<Node> cycles = new HashSet<>();
+ return parseShapes(shapesGraph, targets, shapesMap, cycles);
+ }
+
+ /*package*/ static Collection<Shape> parseShapes(Graph shapesGraph, Targets targets, Map<Node, Shape> shapesMap, Set<Node> cycles) {
+
Targets rootShapes = targets;
if ( DEBUG )
@@ -163,15 +172,17 @@
// ---- Main parser worker.
/**
- * Parse shape "shNode", updating the record of shapes already parsed.
+ * Parse one shape updating the record of shapes already parsed.
*
* @param shapesMap
* @param shapesGraph
* @param shNode
* @return Shape
*/
+
public static Shape parseShape(Map<Node, Shape> shapesMap, Graph shapesGraph, Node shNode) {
- Shape shape = parseShapeStep(shapesMap, shapesGraph, shNode);
+ Set<Node> traversed = new HashSet<>();
+ Shape shape = parseShapeStep(traversed, shapesMap, shapesGraph, shNode);
return shape;
}
@@ -218,22 +229,42 @@
| sh:path |
-------------------
*/
+
+ /** Do nothing placeholder shape. */
+ static Shape unshape(Graph shapesGraph, Node shapeNode) { return
+ new NodeShape(shapesGraph, shapeNode, false, Severity.Violation,
+ Collections.emptySet(), Collections.emptySet(),
+ Collections.singleton(new JLogConstraint("Cycle")),
+ Collections.emptySet());
+ }
+
/** parse a shape during a parsing process */
- /*package*/ static Shape parseShapeStep(Map<Node, Shape> parsed, Graph shapesGraph, Node shapeNode) {
+ /*package*/ static Shape parseShapeStep(Set<Node> traversed, Map<Node, Shape> parsed, Graph shapesGraph, Node shapeNode) {
// Called by Constraints
if ( parsed.containsKey(shapeNode) )
return parsed.get(shapeNode);
- Shape shape = parseShape$(parsed, shapesGraph, shapeNode);
+ // Loop detection. Do before parsing.
+ if ( traversed.contains(shapeNode) ) {
+// Log.error(ShapesParser.class, "Cycle detected : node "+ShLib.displayStr(shapeNode));
+// throw new ShaclParseException("Shapes cycle detected : node "+ShLib.displayStr(shapeNode));
+ ShaclSystem.systemShaclLogger.warn("Cycle detected : node "+ShLib.displayStr(shapeNode));
+ // Put in a substitute shape.
+ return unshape(shapesGraph, shapeNode);
+ }
+
+ traversed.add(shapeNode);
+ Shape shape = parseShape$(traversed, parsed, shapesGraph, shapeNode);
parsed.put(shapeNode, shape);
+ traversed.remove(shapeNode);
return shape;
}
- private static Shape parseShape$(Map<Node, Shape> parsed, Graph shapesGraph, Node shapeNode) {
+ private static Shape parseShape$(Set<Node> traversed, Map<Node, Shape> parsed, Graph shapesGraph, Node shapeNode) {
if ( DEBUG )
OUT.printf("Parse shape : %s\n", displayStr(shapeNode));
boolean isDeactivated = absentOrOne(shapesGraph, shapeNode, SHACL.deactivated, NodeConst.nodeTrue);
Collection<Target> targets = targets(shapesGraph, shapeNode);
- List<Constraint> constraints = Constraints.parseConstraints(shapesGraph, shapeNode, parsed);
+ List<Constraint> constraints = Constraints.parseConstraints(shapesGraph, shapeNode, parsed, traversed);
Severity severity = severity(shapesGraph, shapeNode);
List<Node> messages = listSP(shapesGraph, shapeNode, SHACL.message);
@@ -241,7 +272,7 @@
OUT.incIndent();
// sh:Property PropertyShapes from this shape.
// sh:node is treated as a constraint.
- List<PropertyShape> propertyShapes = findPropertyShapes(parsed, shapesGraph, shapeNode);
+ List<PropertyShape> propertyShapes = findPropertyShapes(traversed, parsed, shapesGraph, shapeNode);
if ( DEBUG )
OUT.decIndent();
@@ -303,7 +334,7 @@
return ShaclPaths.parsePath(shapesGraph, node);
}
- private static List<PropertyShape> findPropertyShapes(Map<Node, Shape> parsed, Graph shapesGraph, Node shapeNode) {
+ private static List<PropertyShape> findPropertyShapes(Set<Node> traversed, Map<Node, Shape> parsed, Graph shapesGraph, Node shapeNode) {
List<Triple> propertyTriples = G.find(shapesGraph, shapeNode, SHACL.property, null).toList();
List<PropertyShape> propertyShapes = new ArrayList<>();
for ( Triple t : propertyTriples) {
@@ -321,9 +352,9 @@
}
if ( x > 1 ) {
List<Node> paths = listSP(shapesGraph, propertyShape, SHACL.path);
- throw new ShaclParseException("Muiltiple sh:path on a property shape: "+displayStr(shapeNode)+" sh:property"+displayStr(propertyShape)+ " : "+paths);
+ throw new ShaclParseException("Multiple sh:path on a property shape: "+displayStr(shapeNode)+" sh:property"+displayStr(propertyShape)+ " : "+paths);
}
- PropertyShape ps = (PropertyShape)parseShapeStep(parsed, shapesGraph, propertyShape);
+ PropertyShape ps = (PropertyShape)parseShapeStep(traversed, parsed, shapesGraph, propertyShape);
propertyShapes.add(ps);
}
return propertyShapes;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/sys/ShaclSystem.java b/jena-shacl/src/main/java/org/apache/jena/shacl/sys/ShaclSystem.java
index 01ae3e9..73c32a8 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/sys/ShaclSystem.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/sys/ShaclSystem.java
@@ -18,10 +18,17 @@
package org.apache.jena.shacl.sys;
+import org.apache.jena.riot.system.ErrorHandler;
+import org.apache.jena.riot.system.ErrorHandlerFactory;
import org.apache.jena.shacl.ShaclValidator;
import org.apache.jena.shacl.validation.ShaclPlainValidator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class ShaclSystem {
+ public static Logger systemShaclLogger = LoggerFactory.getLogger("SHACL");
+ public static ErrorHandler systemShaclErrorHandler = ErrorHandlerFactory.errorHandlerStd(systemShaclLogger);
+
private static ShaclValidator globalDefault = new ShaclPlainValidator();
/** Set the current system-wide {@link ShaclValidator}. */
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/validation/VLib.java b/jena-shacl/src/main/java/org/apache/jena/shacl/validation/VLib.java
index 184382d..451fe35 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/validation/VLib.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/validation/VLib.java
@@ -121,7 +121,7 @@
out.println();
}
- static void validationPropertyShapes(ValidationContext vCxt, Graph data, List<PropertyShape> propertyShapes, Node focusNode) {
+ static void validationPropertyShapes(ValidationContext vCxt, Graph data, Collection<PropertyShape> propertyShapes, Node focusNode) {
if ( propertyShapes == null )
return;
for ( PropertyShape propertyShape : propertyShapes ) {
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/vocabulary/SHJ.java b/jena-shacl/src/main/java/org/apache/jena/shacl/vocabulary/SHJ.java
index 061db14..3033b67 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/vocabulary/SHJ.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/vocabulary/SHJ.java
@@ -18,17 +18,35 @@
package org.apache.jena.shacl.vocabulary;
+import java.util.Objects;
+
import org.apache.jena.graph.Node;
import org.apache.jena.graph.NodeFactory;
/** Vocabulary for Jena additions to SHACL */
public class SHJ {
- private static Node createResource(String localName) { return NodeFactory.createURI(NS+localName); }
- private static Node createProperty(String localName) { return NodeFactory.createURI(NS+localName); }
/** The namespace of the vocabulary as a string */
public static final String NS = "http://jena.apache.org/shacl#";
/** The namespace of the vocabulary as a string*/
public static String getURI() {return NS;}
+
+ /** Namespace */
+ public String ns() { return NS; }
+
+ private static String uri(String ns, String local) {
+ Objects.requireNonNull(ns);
+ Objects.requireNonNull(local);
+ return ns+local;
+ }
+
+ private static Node createResource(String ns, String localName) { return NodeFactory.createURI(uri(ns, localName)); }
+ private static Node createProperty(String ns, String localName) { return NodeFactory.createURI(uri(ns, localName)); }
+
+ public static final Node LogConstraintComponent = createResource(NS, "LogConstraintComponent");
+ public static final Node logConstraint = createProperty(NS, "log");
+
+ public static final Node ViolationConstraintComponent = createResource(NS, "ViolationConstraintComponent");
+ public static final Node violation = createProperty(NS, "violation");
}
diff --git a/jena-tdb/src/main/java/org/apache/jena/tdb/solver/SolverLib.java b/jena-tdb/src/main/java/org/apache/jena/tdb/solver/SolverLib.java
index 0539c12..45145fb 100644
--- a/jena-tdb/src/main/java/org/apache/jena/tdb/solver/SolverLib.java
+++ b/jena-tdb/src/main/java/org/apache/jena/tdb/solver/SolverLib.java
@@ -256,7 +256,7 @@
// Can occur with BindingProject
continue ;
- // Rely on the node table cache for efficency - we will likely be
+ // Rely on the node table cache for efficiency - we will likely be
// repeatedly looking up the same node in different bindings.
NodeId id = nodeTable.getNodeIdForNode(n) ;
// Optional: whether to put in "known missing"
@@ -312,7 +312,6 @@
final Var var = Var.alloc(graphNode) ;
Iterator<Binding> iterBinding = Iter.map(iter4, node -> BindingFactory.binding(var, node)) ;
- // Not abortable.
return new QueryIterTDB(iterBinding, killList, input, execCxt) ;
}
diff --git a/jena-tdb/src/main/java/org/apache/jena/tdb/solver/SolverRX.java b/jena-tdb/src/main/java/org/apache/jena/tdb/solver/SolverRX.java
index 7b661f6..93e62ad 100644
--- a/jena-tdb/src/main/java/org/apache/jena/tdb/solver/SolverRX.java
+++ b/jena-tdb/src/main/java/org/apache/jena/tdb/solver/SolverRX.java
@@ -69,7 +69,7 @@
VarAlloc varAlloc = VarAlloc.get(context, ARQConstants.sysVarAllocRDFStar);
if ( varAlloc == null ) {
varAlloc = new VarAlloc(ARQConstants.allocVarTripleTerm);
- context.set(ARQConstants.sysVarAllocRDFStar, varAlloc);
+ context.set(ARQConstants.sysVarAllocRDFStar, varAlloc);
}
return varAlloc;
}
@@ -80,7 +80,7 @@
ExecutionContext execCxt) {
if ( ! tripleHasNodeTriple(pattern) )
SolverLib.solve(nodeTupleTable, pattern, anyGraph, chain, filter, execCxt);
-
+
Args args = new Args(nodeTupleTable, anyGraph, filter, execCxt);
return rdfStarTriple(chain, pattern, args);
}
@@ -92,7 +92,7 @@
* within {@link #rdfStarTriple} for nested triple term and a temporary allocated
* variable as well can for {@code FIND(<<...>> AS ?t)}.
*
- * @implNote
+ * @implNote
* Without RDF*, this would be a plain call of {@link #matchData} which
* is simply a call to {@link SolverLib#solve}.
*/
@@ -148,7 +148,7 @@
Node subject1 = null;
Node object1 = null;
- if ( subject.isNodeTriple() && ! subject.isConcrete() ) {
+ if ( subject.isNodeTriple() ) {
Triple tripleTerm = triple(subject);
Var var = args.varAlloc.allocVar();
patternTuple = createTuple(patternTuple, var, sIdx);
@@ -157,7 +157,7 @@
subject1 = var;
}
- if ( object.isNodeTriple() && ! object.isConcrete() ) {
+ if ( object.isNodeTriple() ) {
Triple tripleTerm = triple(object);
Var var = args.varAlloc.allocVar();
patternTuple = createTuple(patternTuple, var, oIdx);
@@ -221,7 +221,7 @@
return binding;
return null;
}
-
+
BindingNodeId b2 = new BindingNodeId(binding);
b2.put(var, tid);
return b2;
@@ -305,11 +305,11 @@
private static Tuple<Node> tuple(Tuple<Node> base, Triple triple) {
switch(base.len()){
- case 3:
- return TupleFactory.create3(triple.getSubject(), triple.getPredicate(), triple.getObject());
+ case 3:
+ return TupleFactory.create3(triple.getSubject(), triple.getPredicate(), triple.getObject());
case 4:
return TupleFactory.create4(base.get(0), triple.getSubject(), triple.getPredicate(), triple.getObject());
default:
- } throw new TDBException("Tuple not of length 3 or 4");
+ } throw new TDBException("Tuple not of length 3 or 4");
}
}
diff --git a/pom.xml b/pom.xml
index 91074ce..2f28792 100644
--- a/pom.xml
+++ b/pom.xml
@@ -70,7 +70,7 @@
POM for the correct dependency versions
and use that or later.
-->
- <ver.jsonldjava>0.12.5</ver.jsonldjava>
+ <ver.jsonldjava>0.13.1</ver.jsonldjava>
<ver.jackson>2.10.1</ver.jackson>
<ver.jackson-databind>${ver.jackson}</ver.jackson-databind>