You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2020/10/11 09:50:33 UTC
[jena] branch master updated: JENA-1979: Protect against complex
paths for $PATH
This is an automated email from the ASF dual-hosted git repository.
andy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jena.git
The following commit(s) were added to refs/heads/master by this push:
new 54b1f50 JENA-1979: Protect against complex paths for $PATH
new 7e98a8a Merge pull request #810 from afs/jena1979-shacl-path
54b1f50 is described below
commit 54b1f508498d172fe2f5d690a56eec525b681022
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Sat Oct 10 16:14:14 2020 +0100
JENA-1979: Protect against complex paths for $PATH
---
.../org/apache/jena/shacl/engine/ShaclPaths.java | 3 +-
.../jena/shacl/engine/SparqlConstraints.java | 53 ++++++++++++++++------
.../constraint/ConstraintComponentSPARQL.java | 4 +-
.../shacl/engine/constraint/SparqlValidation.java | 10 +++-
4 files changed, 50 insertions(+), 20 deletions(-)
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ShaclPaths.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ShaclPaths.java
index efdef05..f0266c0 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ShaclPaths.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ShaclPaths.java
@@ -204,8 +204,7 @@ public class ShaclPaths {
if ( n == null )
out.print(PathWriter.asString(path));
else
- nodeFmt.format(out, n);;
-
+ nodeFmt.format(out, n);
}
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/SparqlConstraints.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/SparqlConstraints.java
index a803675..5496027 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/SparqlConstraints.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/SparqlConstraints.java
@@ -18,6 +18,8 @@
package org.apache.jena.shacl.engine;
+import java.util.HashMap;
+import java.util.Map;
import java.util.StringJoiner;
import org.apache.jena.atlas.iterator.Iter;
@@ -49,15 +51,6 @@ public class SparqlConstraints {
// 5.3.1 Pre-bound Variables in SPARQL Constraints ($this, $shapesGraph, $currentShape)
// 5.3.2 Mapping of Solution Bindings to Result Properties
- private static String prefixesQueryString = StrUtils.strjoinNL
- ("PREFIX owl: <http://www.w3.org/2002/07/owl#>"
- ,"PREFIX sh: <http://www.w3.org/ns/shacl#>"
- ,"SELECT * { ?x sh:prefixes/owl:imports*/sh:declare [ sh:prefix ?prefix ; sh:namespace ?namespace ] }"
- );
- private static Query prefixesQuery = QueryFactory.create(prefixesQueryString);
- private static Var varPrefix = Var.alloc("prefix");
- private static Var varNamespace = Var.alloc("namespace");
-
public static Constraint parseSparqlConstraint(Graph shapesGraph, Node shape, Node p, Node sparqlConstraintNode) {
/*
sh:sparql [
@@ -86,15 +79,34 @@ public class SparqlConstraints {
String selectQuery = selectNode.getLiteralLexicalForm();
// If parse error - constraint failure.
String qs = prefixes+"\n"+selectQuery;
- try {
- Query query = QueryFactory.create(qs);
- String msg = (message != null && message.isLiteral() ? message.getLiteralLexicalForm() : null );
+ String msg = (message != null && message.isLiteral() ? message.getLiteralLexicalForm() : null );
+ try {
+ Query query = parseQueryString(qs);
return new SparqlConstraint(query, msg);
} catch (QueryParseException ex) {
+// Log.warn("SHACL", "SPARQL parse error: "+ex.getMessage()+"\n"+qs);
+// return new SparqlConstraint(new Query(), msg);
throw new ShaclParseException("SPARQL parse error: "+ex.getMessage()+"\n"+qs);
}
}
-
+
+ /**
+ * Parse a string to produce a {@link Query}.
+ * All {@link Query} should go through this function to allow of inserting default prefixes.
+ */
+ public static Query parseQueryString(String queryString) {
+ Query query = new Query();
+ // The SHACL spec does not define any default prefixes.
+ // But for identified practical reasons some may be added such as:
+// query.getPrefixMapping().setNsPrefix("owl", OWL.getURI());
+// query.getPrefixMapping().setNsPrefix("rdf", RDF.getURI());
+// query.getPrefixMapping().setNsPrefix("rdfs", RDFS.getURI());
+// query.getPrefixMapping().setNsPrefix("sh", SHACL.getURI());
+// query.getPrefixMapping().setNsPrefix("xsd", XSD.getURI());
+ QueryFactory.parse(query, queryString, null, Syntax.defaultQuerySyntax);
+ return query;
+ }
+
/**
* Test for zero or one occurrences of a tripel pattern that is expected to be
* Returns false for zero, true for one.
@@ -114,13 +126,21 @@ public class SparqlConstraints {
finally { iter.close(); }
}
-
+ private static String prefixesQueryString = StrUtils.strjoinNL
+ ("PREFIX owl: <http://www.w3.org/2002/07/owl#>"
+ ,"PREFIX sh: <http://www.w3.org/ns/shacl#>"
+ ,"SELECT * { ?x sh:prefixes/owl:imports*/sh:declare [ sh:prefix ?prefix ; sh:namespace ?namespace ] }"
+ );
+ private static Query prefixesQuery = QueryFactory.create(prefixesQueryString);
+ private static Var varPrefix = Var.alloc("prefix");
+ private static Var varNamespace = Var.alloc("namespace");
public static String prefixes(Graph shapesGraph, Node sparqlNode) {
// XXX Ignores sparqlNode ATM
StringJoiner prefixesSJ = new StringJoiner("\n");
QueryExecution qExec = QueryExecutionFactory.create(prefixesQuery, DatasetGraphFactory.wrap(shapesGraph));
ResultSet rs = qExec.execSelect();
+ Map<String, String> seen = new HashMap<>();
while(rs.hasNext()) {
Binding binding = rs.nextBinding();
@@ -128,7 +148,12 @@ public class SparqlConstraints {
Node nNamespace = binding.get(varNamespace);
String prefix = nPrefix.getLiteralLexicalForm();
String ns = nNamespace.getLiteralLexicalForm();
+ if ( seen.containsKey(prefix) ) {
+ if ( seen.get(prefix).equals(ns) )
+ continue;
+ }
prefixesSJ.add("PREFIX "+prefix+": <"+ns+">");
+ seen.put(prefix, ns);
}
return prefixesSJ.toString();
}
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ConstraintComponentSPARQL.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ConstraintComponentSPARQL.java
index 9060693..150d49e 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ConstraintComponentSPARQL.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ConstraintComponentSPARQL.java
@@ -26,10 +26,10 @@ import org.apache.jena.ext.com.google.common.collect.Multimap;
import org.apache.jena.graph.Graph;
import org.apache.jena.graph.Node;
import org.apache.jena.query.Query;
-import org.apache.jena.query.QueryFactory;
import org.apache.jena.query.QueryParseException;
import org.apache.jena.riot.out.NodeFormatter;
import org.apache.jena.shacl.engine.Parameter;
+import org.apache.jena.shacl.engine.SparqlConstraints;
import org.apache.jena.shacl.engine.ValidationContext;
import org.apache.jena.shacl.parser.Constraint;
import org.apache.jena.shacl.parser.ShaclParseException;
@@ -51,7 +51,7 @@ public class ConstraintComponentSPARQL implements Constraint {
String qs = sparqlConstraintComponent.getSparqlString();
try {
- this.query = QueryFactory.create(sparqlConstraintComponent.getSparqlString());
+ this.query = SparqlConstraints.parseQueryString(sparqlConstraintComponent.getSparqlString());
if ( !query.isAskType() && !query.isSelectType() )
throw new ShaclParseException("Not a SELECT or ASK query");
} catch (QueryParseException ex) {
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/SparqlValidation.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/SparqlValidation.java
index d0b9130..51b85e3 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/SparqlValidation.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/SparqlValidation.java
@@ -234,8 +234,14 @@ import org.apache.jena.sparql.util.ModelUtils;
}
qsm.add("this", ModelUtils.convertGraphNodeToRDFNode(thisNode, model));
if ( path != null ) {
- RDFNode z = ModelUtils.convertGraphNodeToRDFNode(ShaclPaths.pathNode(path), model);
- qsm.add("PATH" , z);
+ Node pn = ShaclPaths.pathNode(path);
+ // If 'path' can not be translated into a substituted form, then ignore
+ // PATH. This means that is the path is not a simple link, it could only be
+ // done by textually substitution of the SPARQL query string.
+ if ( pn != null ) {
+ RDFNode z = ModelUtils.convertGraphNodeToRDFNode(pn, model);
+ qsm.add("PATH", z);
+ }
}
return qsm;
}