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 2018/08/31 12:04:51 UTC
[01/27] jena git commit: JENA-1594: Initial machinery with SPARQL
Query filtering
Repository: jena
Updated Branches:
refs/heads/master 0a0b831b3 -> c8a31476d
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java
new file mode 100644
index 0000000..3c4ead4
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java
@@ -0,0 +1,320 @@
+/*
+ * 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.access;
+
+import static org.apache.jena.fuseki.access.GraphData.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+import org.apache.jena.atlas.iterator.Iter;
+import org.apache.jena.atlas.lib.Creator;
+import org.apache.jena.atlas.lib.SetUtils;
+import org.apache.jena.fuseki.access.DataAccessCtl;
+import org.apache.jena.fuseki.access.SecurityPolicy;
+import org.apache.jena.fuseki.access.SecurityRegistry;
+import org.apache.jena.graph.Graph;
+import org.apache.jena.graph.Node;
+import org.apache.jena.query.Dataset;
+import org.apache.jena.query.DatasetFactory;
+import org.apache.jena.query.QueryExecution;
+import org.apache.jena.query.QueryExecutionFactory;
+import org.apache.jena.query.QuerySolution;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.rdf.model.RDFNode;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.Quad;
+import org.apache.jena.system.Txn;
+import org.apache.jena.tdb.TDB;
+import org.apache.jena.tdb.TDBFactory;
+import org.apache.jena.tdb2.DatabaseMgr;
+import org.apache.jena.tdb2.TDB2;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class TestSecurityFilterLocal {
+ @Parameters(name = "{index}: {0}")
+ public static Iterable<Object[]> data() {
+ Creator<DatasetGraph> c1 = TDBFactory::createDatasetGraph;
+ Object[] obj1 = { "TDB", c1};
+ Creator<DatasetGraph> c2 = DatabaseMgr::createDatasetGraph;
+ Object[] obj2 = { "TDB2", c2 };
+ return Arrays.asList(obj1, obj2);
+ }
+
+ private DatasetGraph testdsg;
+ private SecurityRegistry reg = new SecurityRegistry();
+
+ public TestSecurityFilterLocal(String name, Creator<DatasetGraph> source) {
+ testdsg = source.create();
+ fill(testdsg);
+ reg.put("userNone", SecurityPolicy.NONE);
+ reg.put("userDft", SecurityPolicy.DFT_GRAPH);
+ reg.put("user0", new SecurityPolicy(Quad.defaultGraphIRI.getURI()));
+ reg.put("user1", new SecurityPolicy("http://test/g1", Quad.defaultGraphIRI.getURI()));
+ reg.put("user2", new SecurityPolicy("http://test/g1", "http://test/g2", "http://test/g3"));
+ DataAccessCtl.controlledDataset(testdsg, reg);
+ //testdsg = DataAccessCtl.wrapControlledDataset(testdsg, reg);
+ }
+
+ private static void assertSeen(Set<Node> visible, Node ... expected) {
+ Set<Node> expectedNodes = new HashSet<>(Arrays.asList(expected));
+ assertEquals(expectedNodes, visible);
+ }
+
+ private static String queryAll = "SELECT * { { ?s ?p ?o } UNION { GRAPH ?g { ?s ?p ?o } } }";
+ private static String queryDft = "SELECT * { ?s ?p ?o }";
+ private static String queryNamed = "SELECT * { GRAPH ?g { ?s ?p ?o } }";
+
+ private static String queryG2 = "SELECT * { GRAPH <http://test/graph2> { ?s ?p ?o } }";
+ private static String queryGraphNames = "SELECT * { GRAPH ?g { } }";
+
+ private Set<Node> subjects(DatasetGraph dsg, String queryString, Consumer<QueryExecution> modifier) {
+ Dataset ds = DatasetFactory.wrap(dsg);
+ return
+ Txn.calculateRead(ds, ()->{
+ try(QueryExecution qExec = QueryExecutionFactory.create(queryString, ds)) {
+ if ( modifier != null )
+ modifier.accept(qExec);
+ List<QuerySolution> results = Iter.toList(qExec.execSelect());
+ Stream<Node> stream = results.stream()
+ .map(qs->qs.get("s"))
+ .filter(Objects::nonNull)
+ .map(RDFNode::asNode);
+ return SetUtils.toSet(stream);
+ }
+ });
+ }
+
+ private Set<Node> graphs(DatasetGraph dsg, Consumer<QueryExecution> modifier) {
+ Dataset ds = DatasetFactory.wrap(dsg);
+ return
+ Txn.calculateRead(ds, ()->{
+ try(QueryExecution qExec = QueryExecutionFactory.create(queryGraphNames, ds)) {
+ if ( modifier != null )
+ modifier.accept(qExec);
+ List<QuerySolution> results = Iter.toList(qExec.execSelect());
+ Stream<Node> stream = results.stream().map(qs->qs.get("g")).filter(Objects::nonNull).map(RDFNode::asNode);
+ return SetUtils.toSet(stream);
+ }
+ });
+ }
+
+ @Test public void filter_setup() {
+ Set<Node> visible = subjects(testdsg, queryAll, null);
+ assertEquals(5, visible.size());
+ assertSeen(visible, s0, s1, s2, s3, s4);
+ }
+
+ private static Consumer<QueryExecution> qExecAddFiler(DatasetGraph dsg, SecurityPolicy sCxt) {
+ return qExec->sCxt.filterTDB(dsg, qExec);
+ }
+
+ // QueryExecution
+ private void filter_user(String user, Node ... expected) {
+ SecurityPolicy sCxt = reg.get(user);
+ Set<Node> visible = subjects(testdsg, queryAll, qExecAddFiler(testdsg, sCxt));
+ assertSeen(visible, expected);
+ }
+
+ @Test public void filter_userNone() {
+ filter_user("userNone");
+ }
+
+ @Test public void filter_userDft() {
+ filter_user("userDft", s0);
+ }
+
+ @Test public void filter_user0() {
+ filter_user("user0", s0);
+ }
+
+ @Test public void filter_user1() {
+ filter_user("user1", s0, s1);
+ }
+
+ @Test public void filter_user2() {
+ filter_user("user2", s1, s2, s3);
+ }
+
+ @Test public void filter_userX() {
+ filter_user("userX");
+ }
+
+ // "Access Denied"
+ @Test public void no_access_user1() {
+ SecurityPolicy sCxt = reg.get("user1");
+ Set<Node> visible = subjects(testdsg, queryG2, qExecAddFiler(testdsg, sCxt));
+ assertTrue(visible.isEmpty());
+ }
+
+ @Test public void graph_names_userNone() {
+ SecurityPolicy sCxt = reg.get("userNone");
+ Set<Node> visible = graphs(testdsg, qExecAddFiler(testdsg, sCxt));
+ assertSeen(visible);
+ }
+
+ @Test public void graph_names_userDft() {
+ SecurityPolicy sCxt = reg.get("userDft");
+ Set<Node> visible = graphs(testdsg, qExecAddFiler(testdsg, sCxt));
+ assertSeen(visible);
+ }
+
+ @Test public void graph_names_user0() {
+ SecurityPolicy sCxt = reg.get("user0");
+ Set<Node> visible = graphs(testdsg, qExecAddFiler(testdsg, sCxt));
+ assertSeen(visible);
+ }
+
+ @Test public void graph_names_user1() {
+ SecurityPolicy sCxt = reg.get("user1");
+ Set<Node> visible = graphs(testdsg, qExecAddFiler(testdsg, sCxt));
+ assertSeen(visible, g1);
+ }
+
+ @Test public void graph_names_user2() {
+ SecurityPolicy sCxt = reg.get("user2");
+ Set<Node> visible = graphs(testdsg, qExecAddFiler(testdsg, sCxt));
+ assertSeen(visible, g1, g2, g3);
+ }
+
+ @Test public void graph_names_userX() {
+ SecurityPolicy sCxt = reg.get("userX");
+ Set<Node> visible = graphs(testdsg, qExecAddFiler(testdsg, sCxt));
+ assertSeen(visible);
+ }
+
+ // QueryExecution w/ Union default graph
+ private void filter_union_user(String user, Node ... expected) {
+ SecurityPolicy sCxt = reg.get(user);
+ Consumer<QueryExecution> modifier = qExec-> {
+ qExec.getContext().set(TDB.symUnionDefaultGraph, true);
+ qExec.getContext().set(TDB2.symUnionDefaultGraph, true); // Not strictly necessary.
+ sCxt.filterTDB(testdsg, qExec);
+ };
+ Set<Node> visible = subjects(testdsg, queryDft, modifier);
+ assertSeen(visible, expected);
+ }
+
+ @Test public void filter_union_userNone() {
+ filter_union_user("userNone");
+ }
+
+ @Test public void filter_union_userDft() {
+ // Storage default graph not visible with a union query.
+ filter_union_user("userDft");
+ }
+
+ @Test public void filter_union_user0() {
+ // Storage default graph not visible with a union query.
+ filter_union_user("user0");
+ }
+
+ @Test public void filter_union_user1() {
+ filter_union_user("user1", s1);
+ }
+
+ @Test public void filter_union_user2() {
+ filter_union_user("user2", s1, s2, s3);
+ }
+
+ @Test public void filter_union_userX() {
+ filter_union_user("userX");
+ }
+
+ private Set<Node> subjects(Graph graph, String queryString, Consumer<QueryExecution> modifier) {
+ Model model = ModelFactory.createModelForGraph(graph);
+ return
+ Txn.calculateRead(testdsg, ()->{
+ try(QueryExecution qExec = QueryExecutionFactory.create(queryString, model)) {
+ if ( modifier != null )
+ modifier.accept(qExec);
+ List<QuerySolution> results = Iter.toList(qExec.execSelect());
+ Stream<Node> stream = results.stream().map(qs->qs.get("s")).filter(Objects::nonNull).map(RDFNode::asNode);
+ return SetUtils.toSet(stream);
+ }
+ });
+ }
+
+ // Graph/Model
+ @Test public void query_model_userNone() {
+ query_model_user(testdsg.getDefaultGraph(), "userNone");
+ }
+
+ @Test public void query_model_userDft() {
+ query_model_user(testdsg.getDefaultGraph(), "userDft", s0);
+ }
+
+ @Test public void query_model_user0() {
+ query_model_user(testdsg.getDefaultGraph(), "user0", s0);
+ }
+
+ @Test public void query_model_user1() {
+ query_model_user(testdsg.getDefaultGraph(), "user1", s0);
+ }
+
+ @Test public void query_model_user2() {
+ query_model_user(testdsg.getDefaultGraph(), "user2");
+ }
+
+ @Test public void query_model_ng_userNone() {
+ query_model_user(testdsg.getGraph(g1), "userNone");
+ }
+
+ @Test public void query_model_ng_user11() {
+ query_model_user(testdsg.getGraph(g1), "user1", s1);
+ }
+
+ @Test public void query_model_ng_user21() {
+ query_model_user(testdsg.getGraph(g1), "user2", s1);
+ }
+
+ @Test public void query_model_ng_user12() {
+ query_model_user(testdsg.getGraph(g2), "user1");
+ }
+
+ @Test public void query_model_ng_user22() {
+ query_model_user(testdsg.getGraph(g2), "user2", s2);
+ }
+
+ @Test public void query_model_userXa() {
+ query_model_user(testdsg.getDefaultGraph(), "userX");
+ }
+
+ @Test public void query_model_userXb() {
+ query_model_user(testdsg.getGraph(g1), "userX");
+ }
+
+ private void query_model_user(Graph g, String user, Node ... expected) {
+ SecurityPolicy sCxt = reg.get(user);
+ Set<Node> visible = subjects(g, queryDft, qExecAddFiler(testdsg, sCxt));
+ assertSeen(visible, expected);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/resources/log4j.properties b/jena-fuseki2/jena-fuseki-access/src/test/resources/log4j.properties
new file mode 100644
index 0000000..e84e60e
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/resources/log4j.properties
@@ -0,0 +1,40 @@
+# Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+# Plain output to stdout
+log4j.appender.jena.plainstdout=org.apache.log4j.ConsoleAppender
+log4j.appender.jena.plainstdout.target=System.out
+log4j.appender.jena.plainstdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.jena.plainstdout.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}] %-10c{1} %-5p %m%n
+## %d{ISO8601} -- includes "ss,sss"
+## log4j.appender.jena.plainstdout.layout.ConversionPattern=[%d{ISO8601}] %-10c{1} %-5p %m%n
+
+# Unadorned, for the NCSA requests log.
+log4j.appender.fuseki.plain=org.apache.log4j.ConsoleAppender
+log4j.appender.fuseki.plain.target=System.out
+log4j.appender.fuseki.plain.layout=org.apache.log4j.PatternLayout
+log4j.appender.fuseki.plain.layout.ConversionPattern=%m%n
+
+log4j.rootLogger=INFO, jena.plainstdout
+log4j.logger.org.apache.jena=WARN
+log4j.logger.org.apache.jena.fuseki=INFO
+
+# Others
+log4j.logger.org.eclipse.jetty=WARN
+log4j.logger.org.apache.shiro=WARN
+
+# Fuseki System logs.
+log4j.logger.org.apache.jena.fuseki.Server=INFO
+log4j.logger.org.apache.jena.fuseki.Fuseki=INFO
+log4j.logger.org.apache.jena.fuseki.Admin=INFO
+log4j.logger.org.apache.jena.fuseki.Validate=INFO
+log4j.logger.org.apache.jena.fuseki.Config=INFO
+
+# NCSA Request log.
+log4j.additivity.org.apache.jena.fuseki.Request=false
+log4j.logger.org.apache.jena.fuseki.Request=OFF, fuseki.plain
+
+# TDB
+log4j.logger.org.apache.jena.tdb.loader=INFO
+## Parser output
+log4j.additivity.org.apache.jena.riot=false
+log4j.logger.org.apache.jena.riot=INFO, jena.plainstdout
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/testing/Access/assem-security-shared.ttl
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/testing/Access/assem-security-shared.ttl b/jena-fuseki2/jena-fuseki-access/testing/Access/assem-security-shared.ttl
new file mode 100644
index 0000000..5372c81
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/testing/Access/assem-security-shared.ttl
@@ -0,0 +1,58 @@
+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 access: <http://jena.apache.org/access#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ <#service_tdb2>
+ <#service_plain>
+ ) .
+
+<#service_tdb2> rdf:type fuseki:Service ;
+ rdfs:label "Access controlled dataset" ;
+ fuseki:name "database" ;
+ ## Read-only operations.
+ fuseki:serviceQuery "query" ;
+ fuseki:serviceQuery "sparql" ;
+ fuseki:serviceReadGraphStore "get" ;
+ fuseki:dataset <#access_dataset>;
+ .
+
+## Dataset 1
+## Access control
+<#access_dataset> rdf:type access:AccessControlledDataset ;
+ access:registry <#securityRegistry> ;
+ access:dataset <#tdb_dataset_shared> ;
+ .
+
+<#securityRegistry> rdf:type access:SecurityRegistry ;
+ access:entry ("user1" <http://host/graphname1> <http://host/graphname2> ) ;
+ access:entry ("user1" <http://host/graphname3> ) ;
+ access:entry ("user2" <http://host/graphname9> ) ;
+ access:entry [ access:user "user3" ; access:graphs (<http://host/graphname3> <http://host/graphname4> ) ] ;
+ access:entry [ access:user "user3" ; access:graphs <http://host/graphname5> ] ;
+ access:entry [ access:user "userZ" ; access:graphs <http://host/graphnameZ> ] ;
+ .
+## Dataset 2
+## No data access control.
+<#service_plain> rdf:type fuseki:Service ;
+ fuseki:name "plain";
+ fuseki:serviceQuery "query";
+ fuseki:serviceQuery "sparql";
+ fuseki:serviceUpdate "update";
+ fuseki:serviceUpload "upload" ;
+ fuseki:serviceReadGraphStore "data" ;
+ fuseki:serviceReadGraphStore "get" ;
+ fuseki:dataset <#tdb_dataset_shared> ;
+ .
+
+## Shared database.
+<#tdb_dataset_shared> rdf:type tdb2:DatasetTDB2 ;
+ tdb2:location "--mem--/DB" ;
+ tdb2:unionDefaultGraph true ;
+ .
+
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/testing/Access/assem-security.ttl
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/testing/Access/assem-security.ttl b/jena-fuseki2/jena-fuseki-access/testing/Access/assem-security.ttl
new file mode 100644
index 0000000..8d04b8e
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/testing/Access/assem-security.ttl
@@ -0,0 +1,63 @@
+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 access: <http://jena.apache.org/access#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ <#service_tdb2>
+ <#service_plain>
+ ) .
+
+<#service_tdb2> rdf:type fuseki:Service ;
+ rdfs:label "Access controlled dataset" ;
+ fuseki:name "database" ;
+ ## Read-only operations.
+ fuseki:serviceQuery "query" ;
+ fuseki:serviceQuery "sparql" ;
+ fuseki:serviceReadGraphStore "get" ;
+ fuseki:dataset <#access_dataset>;
+ .
+
+## Dataset 1
+## Access control
+<#access_dataset> rdf:type access:AccessControlledDataset ;
+ access:registry <#securityRegistry> ;
+ access:dataset <#tdb_dataset_read> ;
+ .
+
+## Own database
+<#tdb_dataset_read> rdf:type tdb2:DatasetTDB2 ;
+ tdb2:location "--mem--" ;
+ tdb2:unionDefaultGraph true ;
+ .
+
+<#securityRegistry> rdf:type access:SecurityRegistry ;
+ access:entry ("user1" <http://host/graphname1> <http://host/graphname2> ) ;
+ access:entry ("user1" <http://host/graphname3> ) ;
+ access:entry ("user2" <http://host/graphname9> ) ;
+ access:entry [ access:user "user3" ; access:graphs (<http://host/graphname3> <http://host/graphname4> ) ] ;
+ access:entry [ access:user "user3" ; access:graphs <http://host/graphname5> ] ;
+ access:entry [ access:user "userZ" ; access:graphs <http://host/graphnameZ> ] ;
+ .
+
+## Dataset 2
+## No data access control.
+<#service_plain> rdf:type fuseki:Service ;
+ fuseki:name "plain";
+ fuseki:serviceQuery "query";
+ fuseki:serviceQuery "sparql";
+ fuseki:serviceUpdate "update";
+ fuseki:serviceUpload "upload" ;
+ fuseki:serviceReadGraphStore "data" ;
+ fuseki:serviceReadGraphStore "get" ;
+ fuseki:dataset <#tdb_dataset> ;
+ .
+
+<#tdb_dataset> rdf:type tdb2:DatasetTDB2 ;
+ tdb2:location "--mem--" ;
+ .
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-core/pom.xml
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/pom.xml b/jena-fuseki2/jena-fuseki-core/pom.xml
index fe62823..f49d4b5 100644
--- a/jena-fuseki2/jena-fuseki-core/pom.xml
+++ b/jena-fuseki2/jena-fuseki-core/pom.xml
@@ -106,11 +106,13 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
+ <optional>true</optional>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
+ <optional>true</optional>
</dependency>
<!-- Testing -->
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyLib.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyLib.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyLib.java
new file mode 100644
index 0000000..0d03ab4
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyLib.java
@@ -0,0 +1,169 @@
+/*
+ * 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 java.util.Objects;
+
+import org.apache.jena.riot.WebContent;
+import org.eclipse.jetty.http.MimeTypes;
+import org.eclipse.jetty.security.*;
+import org.eclipse.jetty.security.authentication.BasicAuthenticator;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.HandlerList;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.util.security.Constraint;
+import org.eclipse.jetty.util.security.Credential;
+import org.eclipse.jetty.util.security.Password;
+
+/** Helpers for working with Jetty.
+ * <p>
+ * <h3>SecurityHandler</h3>
+ * <pre>
+ * UserStore userStore = JettyLib.makeUserStore(...);
+ * SecurityHandler securityHandler = JettyLib.makeSecurityHandler(String pathSpec, String realm, UserStore userStore);
+ * </pre>
+ */
+public class JettyLib {
+
+ /** Create a Jetty {@link SecurityHandler} for basic authentication. */
+ public static SecurityHandler makeSecurityHandler(String pathSpec, String realm, UserStore userStore) {
+ return makeSecurityHandler(pathSpec, realm, userStore, "**");
+ }
+
+ /** Create a Jetty {@link SecurityHandler} for basic authentication. */
+ public static SecurityHandler makeSecurityHandler(String pathSpec, String realm, UserStore userStore, String role) {
+ // role can be "**" for any authenticated user.
+ Objects.requireNonNull(pathSpec);
+ Objects.requireNonNull(userStore);
+ Objects.requireNonNull(role);
+
+ Constraint constraint = new Constraint();
+ constraint.setName(Constraint.__BASIC_AUTH);
+ String[] roles = new String[]{role};
+ constraint.setRoles(roles);
+ constraint.setAuthenticate(true);
+
+ ConstraintMapping mapping = new ConstraintMapping();
+ mapping.setConstraint(constraint);
+ mapping.setPathSpec(pathSpec);
+
+ IdentityService identService = new DefaultIdentityService();
+ ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
+ securityHandler.addConstraintMapping(mapping);
+ securityHandler.setIdentityService(identService);
+
+ // ---- HashLoginService
+
+ HashLoginService loginService = new HashLoginService("Authentication");
+ loginService.setUserStore(userStore);
+ loginService.setIdentityService(identService);
+
+ // ----
+ securityHandler.setLoginService(loginService);
+ securityHandler.setAuthenticator(new BasicAuthenticator());
+ if ( realm != null )
+ securityHandler.setRealmName(realm);
+
+ return securityHandler;
+ }
+
+ /**
+ * Make a {@link UserStore} from a password file.
+ * {@link PropertyUserStore} for details.
+ */
+ public static UserStore makeUserStore(String passwordFile) {
+ PropertyUserStore propertyUserStore = new PropertyUserStore();
+ propertyUserStore.setConfig(passwordFile);
+ propertyUserStore.setHotReload(false);
+ try { propertyUserStore.start(); }
+ catch (Exception ex) { throw new RuntimeException("UserStore", ex); }
+ return propertyUserStore;
+ }
+
+ /** Make a {@link UserStore} for a single user,password in any role. */
+ public static UserStore makeUserStore(String user, String password) {
+ return makeUserStore(user, password, "**");
+ }
+
+ /** Make a {@link UserStore} for a sigle user,password,role*/
+ public static UserStore makeUserStore(String user, String password, String role) {
+ Objects.requireNonNull(user);
+ Objects.requireNonNull(password);
+ Objects.requireNonNull(role);
+ PropertyUserStore propertyUserStore = new PropertyUserStore();
+ String[] roles = role == null ? null : new String[]{role};
+ Credential cred = new Password(password);
+ propertyUserStore.addUser(user, cred, roles);
+
+ try { propertyUserStore.start(); }
+ catch (Exception ex) { throw new RuntimeException("UserStore", ex); }
+ return propertyUserStore;
+ }
+
+ /** Add or append a {@link Handler} to a Jetty {@link Server}. */
+ public static void addHandler(Server server, Handler handler) {
+ final Handler currentHandler = server.getHandler();
+ if (currentHandler == null) {
+ server.setHandler(handler);
+ } else {
+ if (currentHandler instanceof HandlerList) {
+ ((HandlerList) currentHandler).addHandler(handler);
+ } else {
+ // Singleton handler. Convert to list.
+ final HandlerList handlerList = new HandlerList();
+ handlerList.addHandler(currentHandler);
+ handlerList.addHandler(handler);
+ server.setHandler(handlerList);
+ }
+ }
+ }
+
+ /** Add the RDF MIME Type mappins */
+ public static void setMimeTypes(ServletContextHandler context) {
+ MimeTypes mimeTypes = new MimeTypes();
+ // RDF syntax
+ mimeTypes.addMimeMapping("nt", WebContent.contentTypeNTriples);
+ mimeTypes.addMimeMapping("nq", WebContent.contentTypeNQuads);
+ mimeTypes.addMimeMapping("ttl", WebContent.contentTypeTurtle+";charset=utf-8");
+ mimeTypes.addMimeMapping("trig", WebContent.contentTypeTriG+";charset=utf-8");
+ mimeTypes.addMimeMapping("rdf", WebContent.contentTypeRDFXML);
+ mimeTypes.addMimeMapping("jsonld", WebContent.contentTypeJSONLD);
+ mimeTypes.addMimeMapping("rj", WebContent.contentTypeRDFJSON);
+ mimeTypes.addMimeMapping("rt", WebContent.contentTypeRDFThrift);
+ mimeTypes.addMimeMapping("trdf", WebContent.contentTypeRDFThrift);
+
+ // SPARQL syntax
+ mimeTypes.addMimeMapping("rq", WebContent.contentTypeSPARQLQuery);
+ mimeTypes.addMimeMapping("ru", WebContent.contentTypeSPARQLUpdate);
+
+ // SPARQL Result set
+ mimeTypes.addMimeMapping("rsj", WebContent.contentTypeResultsJSON);
+ mimeTypes.addMimeMapping("rsx", WebContent.contentTypeResultsXML);
+ mimeTypes.addMimeMapping("srt", WebContent.contentTypeResultsThrift);
+
+ // Other
+ mimeTypes.addMimeMapping("txt", WebContent.contentTypeTextPlain);
+ mimeTypes.addMimeMapping("csv", WebContent.contentTypeTextCSV);
+ mimeTypes.addMimeMapping("tsv", WebContent.contentTypeTextTSV);
+ context.setMimeTypes(mimeTypes);
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Operation.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Operation.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Operation.java
index 06331df..7037f0d 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Operation.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Operation.java
@@ -29,7 +29,9 @@ public class Operation {
// Create intern'ed symbols.
static private NameMgr<Operation> mgr = new NameMgr<>();
- static public Operation register(String name, String description) { return mgr.register(name, (x)->new Operation(x, description)); }
+ static public Operation register(String name, String description) {
+ return mgr.register(name, (x)->new Operation(x, description));
+ }
public static final Operation Query = register("Query", "SPARQL Query");
public static final Operation Update = register("Update", "SPARQL Update");
@@ -39,7 +41,7 @@ public class Operation {
public static final Operation Quads_R = register("Quads_R", "HTTP Quads (Read)");
public static final Operation Quads_RW = register("Quads_RW", "HTTP Quads");
- // Plain REST operations on the datset URL
+ // Plain REST operations on the dataset URL
public static final Operation DatasetRequest_R = Quads_R;
public static final Operation DatasetRequest_RW = Quads_RW;
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionService.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionService.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionService.java
index a22b097..c8268e0 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionService.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionService.java
@@ -79,7 +79,7 @@ public abstract class ActionService extends ActionBase {
if ( !endpointName.isEmpty() ) {
operation = chooseOperation(action, dSrv, endpointName);
if ( operation == null )
- ServletOps.errorNotFound(format("dataset=%s, service=%s", dataAccessPoint.getName(), endpointName));
+ ServletOps.errorBadRequest(format("dataset=%s, service=%s", dataAccessPoint.getName(), endpointName));
} else {
operation = chooseOperation(action, dSrv);
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ServiceDispatchRegistry.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ServiceDispatchRegistry.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ServiceDispatchRegistry.java
index 198eb5c..4e66872 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ServiceDispatchRegistry.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ServiceDispatchRegistry.java
@@ -116,8 +116,16 @@ public class ServiceDispatchRegistry {
operationToHandler.put(operation, action);
}
+ /**
+ * Remove the registration for an operation.
+ */
+ public void unregister(Operation operation) {
+ Objects.requireNonNull(operation);
+ operationToHandler.remove(operation);
+ contentTypeToOperation.values().remove(operation);
+ }
+
// The server DataAccessPointRegistry is held in the ServletContext for the server.
-
public static ServiceDispatchRegistry get(ServletContext servletContext) {
ServiceDispatchRegistry registry = (ServiceDispatchRegistry)servletContext.getAttribute(Fuseki.attrServiceRegistry) ;
if ( registry == null )
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/FusekiServer.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/FusekiServer.java b/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/FusekiServer.java
index 2406e33..ef016f7 100644
--- a/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/FusekiServer.java
+++ b/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/FusekiServer.java
@@ -39,6 +39,7 @@ import org.apache.jena.fuseki.build.FusekiConfig;
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.JettyLib;
import org.apache.jena.fuseki.server.DataAccessPoint;
import org.apache.jena.fuseki.server.DataAccessPointRegistry;
import org.apache.jena.fuseki.server.DataService;
@@ -50,11 +51,9 @@ import org.apache.jena.fuseki.servlets.ServiceDispatchRegistry;
import org.apache.jena.query.Dataset;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Resource;
-import org.apache.jena.riot.WebContent;
import org.apache.jena.sparql.core.DatasetGraph;
import org.apache.jena.sparql.core.assembler.AssemblerUtils;
import org.apache.jena.sparql.util.graph.GraphUtils;
-import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
@@ -102,10 +101,21 @@ public class FusekiServer {
.build();
}
+ /** Return a builder, with the default choices of actions available. */
public static Builder create() {
return new Builder();
}
+ /**
+ * Return a builder, with a custom set of operation-action mappings. An endpoint must
+ * still be created for the server to be able to provide the action. An endpoint
+ * dispatches to an operation, and an operation maps to an implementation. This is a
+ * specialised operation - normal use is the operation {@link #create()}.
+ */
+ public static Builder create(ServiceDispatchRegistry serviceDispatchRegistry) {
+ return new Builder(serviceDispatchRegistry);
+ }
+
public final Server server;
private int port;
@@ -179,10 +189,10 @@ public class FusekiServer {
/** FusekiServer.Builder */
public static class Builder {
private DataAccessPointRegistry dataAccessPoints = new DataAccessPointRegistry();
- private ServiceDispatchRegistry serviceDispatch = new ServiceDispatchRegistry(true);
+ private final ServiceDispatchRegistry serviceDispatch;
// Default values.
- private int port = 3330;
- private boolean loopback = false;
+ private int serverPort = 3330;
+ private boolean networkLoopback = false;
private boolean verbose = false;
private boolean withStats = false;
private boolean withPing = false;
@@ -195,6 +205,17 @@ public class FusekiServer {
private SecurityHandler securityHandler = null;
private Map<String, Object> servletAttr = new HashMap<>();
+ // Builder with standard operation-action mapping.
+ Builder() {
+ this.serviceDispatch = new ServiceDispatchRegistry(true);
+ }
+
+ // Builder with provided operation-action mapping.
+ Builder(ServiceDispatchRegistry serviceDispatch) {
+ // Isolate.
+ this.serviceDispatch = new ServiceDispatchRegistry(serviceDispatch);
+ }
+
/** Set the port to run on.
* @deprecated Use {@link #port}.
*/
@@ -207,7 +228,7 @@ public class FusekiServer {
public Builder port(int port) {
if ( port < 0 )
throw new IllegalArgumentException("Illegal port="+port+" : Port must be greater than or equal to zero.");
- this.port = port;
+ this.serverPort = port;
return this;
}
@@ -230,7 +251,7 @@ public class FusekiServer {
}
/** Restrict the server to only responding to the localhost interface.
- * @deprecated Use {@link #loopback}.
+ * @deprecated Use {@link #networkLoopback}.
*/
@Deprecated
public Builder setLoopback(boolean loopback) {
@@ -239,7 +260,7 @@ public class FusekiServer {
/** Restrict the server to only responding to the localhost interface. */
public Builder loopback(boolean loopback) {
- this.loopback = loopback;
+ this.networkLoopback = loopback;
return this;
}
@@ -311,13 +332,21 @@ public class FusekiServer {
this.withPing = withPing;
return this;
}
- /** Add the dataset with given name and a default set of services including update */
+
+ /**
+ * Add the dataset with given name and a default set of services including update.
+ * This is equivalent to {@code add(name, dataset, true)}.
+ */
public Builder add(String name, Dataset dataset) {
requireNonNull(name, "name");
requireNonNull(dataset, "dataset");
return add(name, dataset.asDatasetGraph());
}
+ /**
+ * Add the {@link DatasetGraph} with given name and a default set of services including update.
+ * This is equivalent to {@code add(name, dataset, true)}.
+ */
/** Add the dataset with given name and a default set of services including update */
public Builder add(String name, DatasetGraph dataset) {
requireNonNull(name, "name");
@@ -325,14 +354,20 @@ public class FusekiServer {
return add(name, dataset, true);
}
- /** Add the dataset with given name and a default set of services. */
+ /**
+ * Add the dataset with given name and a default set of services and enabling
+ * update if allowUpdate=true.
+ */
public Builder add(String name, Dataset dataset, boolean allowUpdate) {
requireNonNull(name, "name");
requireNonNull(dataset, "dataset");
return add(name, dataset.asDatasetGraph(), allowUpdate);
}
- /** Add the dataset with given name and a default set of services. */
+ /**
+ * Add the dataset with given name and a default set of services and enabling
+ * update if allowUpdate=true.
+ */
public Builder add(String name, DatasetGraph dataset, boolean allowUpdate) {
requireNonNull(name, "name");
requireNonNull(dataset, "dataset");
@@ -358,11 +393,12 @@ public class FusekiServer {
return this;
}
- /** Read and parse a Fuseki services/datasets file.
- * <p>
- * The application is responsible for ensuring a correct classpath. For example,
- * including a dependency on {@code jena-text} if the configuration file
- * includes a text index.
+ /**
+ * Configure using a Fuseki services/datasets assembler file.
+ * <p>
+ * The application is responsible for ensuring a correct classpath. For example,
+ * including a dependency on {@code jena-text} if the configuration file includes
+ * a text index.
*/
public Builder parseConfigFile(String filename) {
requireNonNull(filename, "filename");
@@ -381,9 +417,10 @@ public class FusekiServer {
}
/**
- * Add the given servlet with the pathSpec. These are added so that they are
- * checked after the Fuseki filter for datasets and before the static content
- * handler (which is the last servlet) used for {@link #setStaticFileBase(String)}.
+ * Add the given servlet with the {@code pathSpec}. These servlets are added so
+ * that they are checked after the Fuseki filter for datasets and before the
+ * static content handler (which is the last servlet) used for
+ * {@link #setStaticFileBase(String)}.
*/
public Builder addServlet(String pathSpec, HttpServlet servlet) {
requireNonNull(pathSpec, "pathSpec");
@@ -395,7 +432,6 @@ public class FusekiServer {
/**
* Add a servlet attribute. Pass a value of null to remove any existing binding.
*/
-
public Builder addServletAttribute(String attrName, Object value) {
requireNonNull(attrName, "attrName");
if ( value != null )
@@ -406,7 +442,8 @@ public class FusekiServer {
}
/**
- * Add a filter with the pathSpec.
+ * Add a filter with the pathSpec. Note that Fuseki dispatch uses a servlet filter
+ * which is the last in the filter chain.
*/
public Builder addFilter(String pathSpec, Filter filter) {
requireNonNull(pathSpec, "pathSpec");
@@ -436,10 +473,10 @@ public class FusekiServer {
*/
public Builder registerOperation(Operation operation, String contentType, ActionService handler) {
Objects.requireNonNull(operation, "operation");
- Objects.requireNonNull(handler, "handler");
- if ( serviceDispatch.isRegistered(operation) )
- throw new FusekiConfigException("Handler for operation already registered: "+operation.getName());
- serviceDispatch.register(operation, contentType, handler);
+ if ( handler == null )
+ serviceDispatch.unregister(operation);
+ else
+ serviceDispatch.register(operation, contentType, handler);
return this;
}
@@ -470,9 +507,9 @@ public class FusekiServer {
public FusekiServer build() {
ServletContextHandler handler = buildFusekiContext();
// Use HandlerCollection for several ServletContextHandlers and thus several ServletContext.
- Server server = jettyServer(port, loopback);
+ Server server = jettyServer(serverPort, networkLoopback);
server.setHandler(handler);
- return new FusekiServer(port, server);
+ return new FusekiServer(serverPort, server);
}
/** Build one configured Fuseki in one unit - same ServletContext, same dispatch ContextPath */
@@ -484,8 +521,8 @@ public class FusekiServer {
// Clone to isolate from any future changes.
ServiceDispatchRegistry.set(cxt, new ServiceDispatchRegistry(serviceDispatch));
DataAccessPointRegistry.set(cxt, new DataAccessPointRegistry(dataAccessPoints));
- setMimeTypes(handler);
- servlets(handler);
+ JettyLib.setMimeTypes(handler);
+ servletsAndFilters(handler);
// Start services.
DataAccessPointRegistry.get(cxt).forEach((name, dap)->dap.getDataService().goActive());
return handler;
@@ -506,37 +543,8 @@ public class FusekiServer {
return context;
}
- private static void setMimeTypes(ServletContextHandler context) {
- MimeTypes mimeTypes = new MimeTypes();
- // RDF syntax
- mimeTypes.addMimeMapping("nt", WebContent.contentTypeNTriples);
- mimeTypes.addMimeMapping("nq", WebContent.contentTypeNQuads);
- mimeTypes.addMimeMapping("ttl", WebContent.contentTypeTurtle+";charset=utf-8");
- mimeTypes.addMimeMapping("trig", WebContent.contentTypeTriG+";charset=utf-8");
- mimeTypes.addMimeMapping("rdfxml", WebContent.contentTypeRDFXML);
- mimeTypes.addMimeMapping("jsonld", WebContent.contentTypeJSONLD);
- mimeTypes.addMimeMapping("rj", WebContent.contentTypeRDFJSON);
- mimeTypes.addMimeMapping("rt", WebContent.contentTypeRDFThrift);
- mimeTypes.addMimeMapping("trdf", WebContent.contentTypeRDFThrift);
-
- // SPARQL syntax
- mimeTypes.addMimeMapping("rq", WebContent.contentTypeSPARQLQuery);
- mimeTypes.addMimeMapping("ru", WebContent.contentTypeSPARQLUpdate);
-
- // SPARQL Result set
- mimeTypes.addMimeMapping("rsj", WebContent.contentTypeResultsJSON);
- mimeTypes.addMimeMapping("rsx", WebContent.contentTypeResultsXML);
- mimeTypes.addMimeMapping("srt", WebContent.contentTypeResultsThrift);
-
- // Other
- mimeTypes.addMimeMapping("txt", WebContent.contentTypeTextPlain);
- mimeTypes.addMimeMapping("csv", WebContent.contentTypeTextCSV);
- mimeTypes.addMimeMapping("tsv", WebContent.contentTypeTextTSV);
- context.setMimeTypes(mimeTypes);
- }
-
/** Add servlets and servlet filters, including the {@link FusekiFilter} */
- private void servlets(ServletContextHandler context) {
+ private void servletsAndFilters(ServletContextHandler context) {
// Fuseki dataset services filter
// This goes as the filter at the end of any filter chaining.
FusekiFilter ff = new FusekiFilter();
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/JettyServer.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/JettyServer.java b/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/JettyServer.java
new file mode 100644
index 0000000..704060c
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/JettyServer.java
@@ -0,0 +1,369 @@
+/*
+ * 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.embedded;
+
+import static java.lang.String.format;
+import static java.util.Objects.requireNonNull;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.fuseki.Fuseki;
+import org.apache.jena.fuseki.server.DataAccessPointRegistry;
+import org.apache.jena.fuseki.servlets.ActionBase;
+import org.apache.jena.fuseki.servlets.ServiceDispatchRegistry;
+import org.apache.jena.riot.web.HttpNames;
+import org.apache.jena.web.HttpSC;
+import org.eclipse.jetty.http.HttpMethod;
+import org.eclipse.jetty.http.MimeTypes;
+import org.eclipse.jetty.security.SecurityHandler;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Response;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.handler.ErrorHandler;
+import org.eclipse.jetty.servlet.DefaultServlet;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Jetty server for servlets, including being able to run Fuseki {@link ActionBase} derived servlets.
+ * Static RDF types by file extension can be enabled.
+ */
+public class JettyServer {
+ // Use this for the super class of FusekiServer or as implementation inheritance.
+ // Caution : there are small differences e.g. in building where order matters.
+
+ private static Logger LOG = LoggerFactory.getLogger("HTTP");
+
+ protected final Server server;
+ protected int port;
+
+ public static Builder create() {
+ return new Builder();
+ }
+
+ protected JettyServer(int port, Server server) {
+ this.server = server;
+ this.port = port;
+ }
+
+ /**
+ * Return the port begin used.
+ * This will be the give port, which defaults to 3330, or
+ * the one actually allocated if the port was 0 ("choose a free port").
+ */
+ public int getPort() {
+ return port;
+ }
+
+ /** Get the underlying Jetty server which has also been set up. */
+ public Server getJettyServer() {
+ return server;
+ }
+
+ /** Get the {@link ServletContext}.
+ * Adding new servlets is possible with care.
+ */
+ public ServletContext getServletContext() {
+ return ((ServletContextHandler)server.getHandler()).getServletContext();
+ }
+
+ /** Start the server - the server continues to run after this call returns.
+ * To synchronise with the server stopping, call {@link #join}.
+ */
+ public JettyServer start() {
+ try { server.start(); }
+ catch (Exception e) { throw new RuntimeException(e); }
+ if ( port == 0 )
+ port = ((ServerConnector)server.getConnectors()[0]).getLocalPort();
+ logStart();
+ return this;
+ }
+
+ protected void logStart() {
+ LOG.info("Start (port="+port+")");
+ }
+
+ /** Stop the server. */
+ public void stop() {
+ logStop();
+ try { server.stop(); }
+ catch (Exception e) { throw new RuntimeException(e); }
+ }
+
+ protected void logStop() {
+ LOG.info("Stop (port="+port+")");
+ }
+
+ /** Wait for the server to exit. This call is blocking. */
+ public void join() {
+ try { server.join(); }
+ catch (Exception e) { throw new RuntimeException(e); }
+ }
+
+ /** One line error handler */
+ public static class PlainErrorHandler extends ErrorHandler {
+ // c.f. FusekiErrorHandler1
+ public PlainErrorHandler() {}
+
+ @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()) ;
+ response.setHeader(HttpNames.hCacheControl, "must-revalidate,no-cache,no-store");
+ response.setHeader(HttpNames.hPragma, "no-cache");
+ 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)) ;
+ }
+ }
+
+ protected static class Builder {
+ private int port = -1;
+ private boolean loopback = false;
+ protected boolean verbose = false;
+ // Other servlets to add.
+ private List<Pair<String, HttpServlet>> servlets = new ArrayList<>();
+ private List<Pair<String, Filter>> filters = new ArrayList<>();
+
+ private String contextPath = "/";
+ private String servletContextName = "Jetty";
+ private String staticContentDir = null;
+ private SecurityHandler securityHandler = null;
+ private ErrorHandler errorHandler = new PlainErrorHandler();
+ private Map<String, Object> servletAttr = new HashMap<>();
+
+ /** Set the port to run on. */
+ public Builder port(int port) {
+ if ( port < 0 )
+ throw new IllegalArgumentException("Illegal port="+port+" : Port must be greater than or equal to zero.");
+ this.port = port;
+ return this;
+ }
+
+ /**
+ * Context path. If it's "/" then Server URL will look like
+ * "http://host:port/" else "http://host:port/path/"
+ * (or no port if :80).
+ */
+ public Builder contextPath(String path) {
+ requireNonNull(path, "path");
+ this.contextPath = path;
+ return this;
+ }
+
+ /**
+ * ServletContextName.
+ */
+ public Builder servletContextName(String name) {
+ requireNonNull(name, "name");
+ this.servletContextName = name;
+ return this;
+ }
+
+ /** Restrict the server to only responding to the localhost interface. */
+ public Builder loopback(boolean loopback) {
+ this.loopback = loopback;
+ return this;
+ }
+
+ /** Set the location (filing system directory) to serve static file from. */
+ public Builder staticFileBase(String directory) {
+ requireNonNull(directory, "directory");
+ this.staticContentDir = directory;
+ return this;
+ }
+
+ /** Set a Jetty SecurityHandler.
+ * <p>
+ * By default, the server runs with no security.
+ * This is more for using the basic server for testing.
+ * The full Fuseki server provides security with Apache Shiro
+ * and a defensive reverse proxy (e.g. Apache httpd) in front of the Jetty server
+ * can also be used, which provides a wide varity of proven security options.
+ */
+ public Builder securityHandler(SecurityHandler securityHandler) {
+ requireNonNull(securityHandler, "securityHandler");
+ this.securityHandler = securityHandler;
+ return this;
+ }
+
+ /** Set an {@link ErrorHandler}.
+ * <p>
+ * By default, the server runs with error handle that prints the code and message.
+ */
+ public Builder errorHandler(ErrorHandler errorHandler) {
+ requireNonNull(errorHandler, "securityHandler");
+ this.errorHandler = errorHandler;
+ return this;
+ }
+
+ /** Set verbose logging */
+ public Builder verbose(boolean verbose) {
+ this.verbose = verbose;
+ return this;
+ }
+
+ /**
+ * Add the given servlet with the pathSpec. These are added so that they are
+ * before the static content handler (which is the last servlet)
+ * used for {@link #staticFileBase(String)}.
+ */
+ public Builder addServlet(String pathSpec, HttpServlet servlet) {
+ requireNonNull(pathSpec, "pathSpec");
+ requireNonNull(servlet, "servlet");
+ servlets.add(Pair.create(pathSpec, servlet));
+ return this;
+ }
+
+ /**
+ * Add a servlet attribute. Pass a value of null to remove any existing binding.
+ */
+ public Builder addServletAttribute(String attrName, Object value) {
+ requireNonNull(attrName, "attrName");
+ if ( value != null )
+ servletAttr.put(attrName, value);
+ else
+ servletAttr.remove(attrName);
+ return this;
+ }
+
+ /**
+ * Add the given filter with the pathSpec.
+ * It is applied to all dispatch types.
+ */
+ public Builder addFilter(String pathSpec, Filter filter) {
+ requireNonNull(pathSpec, "pathSpec");
+ requireNonNull(filter, "filter");
+ filters.add(Pair.create(pathSpec, filter));
+ return this;
+ }
+
+ /**
+ * Build a server according to the current description.
+ */
+ public JettyServer build() {
+ ServletContextHandler handler = buildServletContext();
+ // Use HandlerCollection for several ServletContextHandlers and thus several ServletContext.
+ Server server = jettyServer(port, loopback);
+ server.setHandler(handler);
+ return new JettyServer(port, server);
+ }
+
+ /** Build a ServletContextHandler : one servlet context */
+ private ServletContextHandler buildServletContext() {
+ ServletContextHandler handler = buildServletContext(contextPath);
+ ServletContext cxt = handler.getServletContext();
+ adjustForFuseki(cxt);
+ servletAttr.forEach((n,v)->cxt.setAttribute(n, v));
+ servletsAndFilters(handler);
+ return handler;
+ }
+
+ private void adjustForFuseki(ServletContext cxt) {
+ // For Fuseki servlets added directly.
+ // This enables servlets inheriting from {@link ActionBase} to work in the
+ // plain Jetty server, e.g. to use Fuseki logging.
+ try {
+ Fuseki.setVerbose(cxt, verbose);
+ ServiceDispatchRegistry.set(cxt, new ServiceDispatchRegistry(false));
+ DataAccessPointRegistry.set(cxt, new DataAccessPointRegistry());
+ } catch (NoClassDefFoundError err) {
+ LOG.info("Fuseki classes not found");
+ }
+ }
+
+ /** Build a ServletContextHandler. */
+ private ServletContextHandler buildServletContext(String contextPath) {
+ if ( contextPath == null || contextPath.isEmpty() )
+ contextPath = "/";
+ else if ( !contextPath.startsWith("/") )
+ contextPath = "/" + contextPath;
+ ServletContextHandler context = new ServletContextHandler();
+ context.setDisplayName(servletContextName);
+ context.setErrorHandler(errorHandler);
+ context.setContextPath(contextPath);
+ if ( securityHandler != null )
+ context.setSecurityHandler(securityHandler);
+
+ return context;
+ }
+
+ /** Add servlets and servlet filters */
+ private void servletsAndFilters(ServletContextHandler context) {
+ servlets.forEach(p-> addServlet(context, p.getLeft(), p.getRight()) );
+ filters.forEach (p-> addFilter (context, p.getLeft(), p.getRight()) );
+
+ if ( staticContentDir != null ) {
+ DefaultServlet staticServlet = new DefaultServlet();
+ ServletHolder staticContent = new ServletHolder(staticServlet);
+ staticContent.setInitParameter("resourceBase", staticContentDir);
+ context.addServlet(staticContent, "/");
+ }
+ }
+
+ protected static void addServlet(ServletContextHandler context, String pathspec, HttpServlet httpServlet) {
+ ServletHolder sh = new ServletHolder(httpServlet);
+ context.addServlet(sh, pathspec);
+ }
+
+ protected void addFilter(ServletContextHandler context, String pathspec, Filter filter) {
+ FilterHolder h = new FilterHolder(filter);
+ context.addFilter(h, pathspec, null);
+ }
+
+ /** Jetty server */
+ private static Server jettyServer(int port, boolean loopback) {
+ Server server = new Server();
+ HttpConnectionFactory f1 = new HttpConnectionFactory();
+
+ //f1.getHttpConfiguration().setRequestHeaderSize(512 * 1024);
+ //f1.getHttpConfiguration().setOutputBufferSize(1024 * 1024);
+ f1.getHttpConfiguration().setSendServerVersion(false);
+ ServerConnector connector = new ServerConnector(server, f1);
+ connector.setPort(port);
+ server.addConnector(connector);
+ if ( loopback )
+ connector.setHost("localhost");
+ return server;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/pom.xml
----------------------------------------------------------------------
diff --git a/jena-fuseki2/pom.xml b/jena-fuseki2/pom.xml
index 1b13a9c..5a464d6 100644
--- a/jena-fuseki2/pom.xml
+++ b/jena-fuseki2/pom.xml
@@ -60,6 +60,7 @@
<modules>
<module>jena-fuseki-core</module>
<module>jena-fuseki-embedded</module>
+ <module>jena-fuseki-access</module>
<module>jena-fuseki-war</module>
<module>jena-fuseki-server</module>
<module>jena-fuseki-basic</module>
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionFactory.java
----------------------------------------------------------------------
diff --git a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionFactory.java b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionFactory.java
index 2091157..776817c 100644
--- a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionFactory.java
+++ b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionFactory.java
@@ -18,6 +18,12 @@
package org.apache.jena.rdfconnection;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.HttpClient;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.HttpClients;
import org.apache.jena.query.Dataset;
import org.apache.jena.sys.JenaSystem;
@@ -82,6 +88,25 @@ public class RDFConnectionFactory {
.gspEndpoint(graphStoreProtocolEndpoint)
.build();
}
+
+ /** Make a remote RDFConnection to the URL, with user and password for the client access using basic auth.
+ * Use with care. Basic auth over plain HTTP reveals the password on the network.
+ * @param URL
+ * @param user
+ * @param password
+ * @return RDFConnection
+ */
+ public static RDFConnection connectPW(String URL, String user, String password) {
+ BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
+ Credentials credentials = new UsernamePasswordCredentials(user, password);
+ credsProvider.setCredentials(AuthScope.ANY, credentials);
+ HttpClient client = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
+ return RDFConnectionRemote.create()
+ .destination(URL)
+ .httpClient(client)
+ .build();
+ }
+
/**
* Connect to a local (same JVM) dataset.
[26/27] jena git commit: JENA-1594: Interface AuthorizationService;
SecurityRegsitry is an impl
Posted by an...@apache.org.
JENA-1594: Interface AuthorizationService; SecurityRegsitry is an impl
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/3b01252f
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/3b01252f
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/3b01252f
Branch: refs/heads/master
Commit: 3b01252f9d767af3e3b119d3b34f3699a9017fdc
Parents: 20eb07c
Author: Andy Seaborne <an...@apache.org>
Authored: Tue Aug 28 16:17:03 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Tue Aug 28 16:17:03 2018 +0100
----------------------------------------------------------------------
.../sparql/core/DatasetGraphFilteredView.java | 2 +-
.../fuseki/access/AssemblerAccessDataset.java | 2 +-
.../access/AssemblerSecurityRegistry.java | 2 +-
.../fuseki/access/AuthorizationService.java | 30 ++++++++++++++++++++
.../jena/fuseki/access/DataAccessCtl.java | 22 +++++++-------
.../jena/fuseki/access/DataAccessLib.java | 21 ++++++++++----
.../access/DatasetGraphAccessControl.java | 10 +++----
.../jena/fuseki/access/SecurityRegistry.java | 15 ++--------
.../fuseki/access/TS_SecurityFiltering.java | 10 +++----
.../access/TestSecurityAssemblerBuild.java | 2 +-
.../java/org/apache/jena/fuseki/Fuseki.java | 2 +-
11 files changed, 74 insertions(+), 44 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/3b01252f/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
index 4c49bd1..be2cc38 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
@@ -70,7 +70,7 @@ public class DatasetGraphFilteredView extends DatasetGraphReadOnly implements Da
super(dsg);
this.quadFilter = filter;
if ( visibleGraphs.contains(Quad.defaultGraphIRI) || visibleGraphs.contains(Quad.defaultGraphNodeGenerated) ) {
- Log.warn(DatasetGraphFilteredView.class, "default graph Node in visibleGraphs colelction - fix up applied");
+ Log.warn(DatasetGraphFilteredView.class, "default graph Node in visibleGraphs collection - fix up applied");
visibleGraphs = new HashSet<>(visibleGraphs);
visibleGraphs.remove(Quad.defaultGraphIRI);
visibleGraphs.remove(Quad.defaultGraphNodeGenerated);
http://git-wip-us.apache.org/repos/asf/jena/blob/3b01252f/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerAccessDataset.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerAccessDataset.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerAccessDataset.java
index 75cb155..71a89db 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerAccessDataset.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerAccessDataset.java
@@ -47,7 +47,7 @@ public class AssemblerAccessDataset extends AssemblerBase {
RDFNode rnRegistry = root.getProperty(VocabSecurity.pSecurityRegistry).getObject();
RDFNode rnDataset = root.getProperty(VocabSecurity.pDataset).getObject();
- SecurityRegistry sr = (SecurityRegistry)a.open(rnRegistry.asResource()) ;
+ AuthorizationService sr = (AuthorizationService)a.open(rnRegistry.asResource()) ;
Dataset ds = (Dataset)a.open(rnDataset.asResource()) ;
DatasetGraph dsg = new DatasetGraphAccessControl(ds.asDatasetGraph(), sr);
http://git-wip-us.apache.org/repos/asf/jena/blob/3b01252f/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java
index dc66768..00c27b9 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java
@@ -52,7 +52,7 @@ public class AssemblerSecurityRegistry extends AssemblerBase {
*/
@Override
- public SecurityRegistry open(Assembler a, Resource root, Mode mode) {
+ public AuthorizationService open(Assembler a, Resource root, Mode mode) {
SecurityRegistry registry = new SecurityRegistry();
// Java walking gives better error messages.
StmtIterator sIter = root.listProperties(VocabSecurity.pEntry);
http://git-wip-us.apache.org/repos/asf/jena/blob/3b01252f/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AuthorizationService.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AuthorizationService.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AuthorizationService.java
new file mode 100644
index 0000000..dd8e7c6
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AuthorizationService.java
@@ -0,0 +1,30 @@
+/*
+ * 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.access;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * A {@link AuthorizationService} implemented with a {@link ConcurrentHashMap}.
+ */
+public interface AuthorizationService {
+
+ /** Return the security context for a geiven actor (user) */
+ public SecurityContext get(String actor);
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/3b01252f/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
index f1bf7d3..f1399f2 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
@@ -38,7 +38,7 @@ import org.apache.jena.sparql.util.Symbol;
import org.apache.jena.sys.JenaSystem;
import org.eclipse.jetty.security.SecurityHandler;
-/** A library of operations related to data acess sexurity for Fuseki */
+/** A library of operations related to data access security for Fuseki */
public class DataAccessCtl {
static { JenaSystem.init(); }
@@ -46,14 +46,14 @@ public class DataAccessCtl {
* Flag for whether this is data access controlled or not - boolean false or undef for "not
* controlled". This is an alternative to {@link DatasetGraphAccessControl}.
*/
- public static final Symbol symControlledAccess = Symbol.create(VocabSecurity.getURI() + "controlled");
+ public static final Symbol symControlledAccess = Symbol.create(VocabSecurity.getURI() + "controlled");
/**
- * Symbol for the {@link SecurityRegistry}. Must be present if
+ * Symbol for the {@link AuthorizationService}. Must be present if
* {@link #symControlledAccess} indicates data access control.
* This is an alternative to {@link DatasetGraphAccessControl}.
*/
- public static final Symbol symSecurityRegistry = Symbol.create(VocabSecurity.getURI() + "registry");
+ public static final Symbol symAuthorizationService = Symbol.create(VocabSecurity.getURI() + "authService");
/** Get the user from the servlet context via {@link HttpServletRequest#getRemoteUser} */
public static final Function<HttpAction, String> requestUserServlet = (action)->action.request.getRemoteUser();
@@ -68,16 +68,16 @@ public class DataAccessCtl {
* Add data access control information on a {@link DatasetGraph}. This modifies the
* {@link DatasetGraph}'s {@link Context}.
*/
- private static void addSecurityRegistry(DatasetGraph dsg, SecurityRegistry reg) {
+ private static void addAuthorizatonService(DatasetGraph dsg, AuthorizationService authService) {
dsg.getContext().set(symControlledAccess, true);
- dsg.getContext().set(symSecurityRegistry, reg);
+ dsg.getContext().set(symAuthorizationService, authService);
}
/**
* Return a {@link DatasetGraph} with added data access control.
* Use of the original {@code DatasetGraph} is not controlled.
*/
- public static Dataset controlledDataset(Dataset dsBase, SecurityRegistry reg) {
+ public static Dataset controlledDataset(Dataset dsBase, AuthorizationService reg) {
DatasetGraph dsg = controlledDataset(dsBase.asDatasetGraph(), reg);
return DatasetFactory.wrap(dsg);
}
@@ -86,12 +86,12 @@ public class DataAccessCtl {
* Return a {@link DatasetGraph} with added data access control. Use of the original
* {@code DatasetGraph} is not controlled.
*/
- public static DatasetGraph controlledDataset(DatasetGraph dsgBase, SecurityRegistry reg) {
+ public static DatasetGraph controlledDataset(DatasetGraph dsgBase, AuthorizationService reg) {
if ( dsgBase instanceof DatasetGraphAccessControl ) {
DatasetGraphAccessControl dsgx = (DatasetGraphAccessControl)dsgBase;
- if ( reg == dsgx.getRegistry() )
+ if ( reg == dsgx.getAuthService() )
return dsgx;
- throw new IllegalArgumentException("DatasetGraph is alerady wrapped on a DatasetGraphAccessControl with a different SecurityRegistry");
+ throw new IllegalArgumentException("DatasetGraph is alerady wrapped on a DatasetGraphAccessControl with a different AuthorizationService");
}
DatasetGraphAccessControl dsg1 = new DatasetGraphAccessControl(dsgBase, reg);
@@ -149,7 +149,7 @@ public class DataAccessCtl {
return true;
if ( dsg.getContext().isDefined(DataAccessCtl.symControlledAccess) )
return true;
- if ( dsg.getContext().isDefined(DataAccessCtl.symSecurityRegistry) )
+ if ( dsg.getContext().isDefined(DataAccessCtl.symAuthorizationService) )
return true;
return false;
}
http://git-wip-us.apache.org/repos/asf/jena/blob/3b01252f/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java
index c9b98bf..9b99f27 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java
@@ -20,6 +20,9 @@ package org.apache.jena.fuseki.access;
import java.util.function.Function;
+import javax.servlet.ServletContext;
+
+import org.apache.jena.fuseki.Fuseki;
import org.apache.jena.fuseki.servlets.HttpAction;
import org.apache.jena.fuseki.servlets.ServletOps;
import org.apache.jena.sparql.core.DatasetGraph;
@@ -29,7 +32,7 @@ class DataAccessLib {
/** Determine the {@link SecurityContext} for this request */
static SecurityContext getSecurityContext(HttpAction action, DatasetGraph dataset, Function<HttpAction, String> requestUser) {
- SecurityRegistry registry = getSecurityRegistry(action, dataset);
+ AuthorizationService registry = getAuthorizationService(action, dataset);
if ( registry == null )
ServletOps.errorOccurred("Internal Server Error");
@@ -41,11 +44,11 @@ class DataAccessLib {
return sCxt;
}
- /** Get the {@link SecurityRegistry} for an action/query/dataset */
- static SecurityRegistry getSecurityRegistry(HttpAction action, DatasetGraph dsg) {
+ /** Get the {@link AuthorizationService} for an action/query/dataset */
+ static AuthorizationService getAuthorizationService(HttpAction action, DatasetGraph dsg) {
if ( dsg instanceof DatasetGraphAccessControl )
- return ((DatasetGraphAccessControl)dsg).getRegistry();
- return dsg.getContext().get(DataAccessCtl.symSecurityRegistry);
+ return ((DatasetGraphAccessControl)dsg).getAuthService();
+ return dsg.getContext().get(DataAccessCtl.symAuthorizationService);
}
static SecurityContext noSecurityPolicy() {
@@ -66,5 +69,13 @@ class DataAccessLib {
dsg = DataAccessCtl.filteredDataset(dsg, sCxt);
return dsg;
}
+
+ static void set(ServletContext cxt, AuthorizationService authorizationService) {
+ cxt.setAttribute(Fuseki.attrAuthorizationService, authorizationService);
+ }
+
+ static AuthorizationService get(ServletContext cxt) {
+ return (AuthorizationService)cxt.getAttribute(Fuseki.attrAuthorizationService);
+ }
}
http://git-wip-us.apache.org/repos/asf/jena/blob/3b01252f/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphAccessControl.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphAccessControl.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphAccessControl.java
index f58bdcd..a518f75 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphAccessControl.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphAccessControl.java
@@ -23,17 +23,17 @@ import java.util.Objects;
import org.apache.jena.sparql.core.DatasetGraph;
import org.apache.jena.sparql.core.DatasetGraphWrapper;
-/** DatasetGraph layer that carries a SecurityRegistry. */
+/** DatasetGraph layer that carries an {@link AuthorizationService}. */
class DatasetGraphAccessControl extends DatasetGraphWrapper {
- private SecurityRegistry registry = null;
+ private AuthorizationService registry = null;
- public DatasetGraphAccessControl(DatasetGraph dsg, SecurityRegistry registry) {
+ public DatasetGraphAccessControl(DatasetGraph dsg, AuthorizationService authService) {
super(Objects.requireNonNull(dsg));
- this.registry = Objects.requireNonNull(registry);
+ this.registry = Objects.requireNonNull(authService);
}
- public SecurityRegistry getRegistry() {
+ public AuthorizationService getAuthService() {
return registry;
}
http://git-wip-us.apache.org/repos/asf/jena/blob/3b01252f/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java
index 10b9a08..7629cd2 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java
@@ -20,26 +20,15 @@ package org.apache.jena.fuseki.access;
import java.util.StringJoiner;
-import javax.servlet.ServletContext;
-
import org.apache.jena.atlas.lib.Registry;
-import org.apache.jena.fuseki.Fuseki;
/**
- * A {@link SecurityRegistry} is mapping from a string (typically a user name or role
+ * Am {@link AuthorizationService} implements as a mapping from a string (typically a user name or role
* name) to a {@link SecurityContext}, where the {@link SecurityContext}
* is the access control operations for the user/role.
*/
-public class SecurityRegistry extends Registry<String, SecurityContext>{
-
- public static SecurityRegistry get(ServletContext cxt) {
- return (SecurityRegistry)cxt.getAttribute(Fuseki.attrSecurityRegistry);
- }
+public class SecurityRegistry extends Registry<String, SecurityContext> implements AuthorizationService {
- public static void set(ServletContext cxt, SecurityRegistry securityRegistry) {
- cxt.setAttribute(Fuseki.attrSecurityRegistry, securityRegistry);
- }
-
public SecurityRegistry() {}
@Override
http://git-wip-us.apache.org/repos/asf/jena/blob/3b01252f/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java
index 981a205..715054d 100644
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java
@@ -35,10 +35,10 @@ import org.junit.runners.Suite;
public class TS_SecurityFiltering {
@BeforeClass public static void setupForFusekiServer() {
- LogCtl.setLevel(Fuseki.serverLogName, "WARN");
- LogCtl.setLevel(Fuseki.actionLogName, "WARN");
- LogCtl.setLevel(Fuseki.requestLogName, "WARN");
- LogCtl.setLevel(Fuseki.adminLogName, "WARN");
- LogCtl.setLevel("org.eclipse.jetty", "WARN");
+ LogCtl.setLevel(Fuseki.serverLogName, "WARN");
+ LogCtl.setLevel(Fuseki.actionLogName, "WARN");
+ LogCtl.setLevel(Fuseki.requestLogName, "WARN");
+ LogCtl.setLevel(Fuseki.adminLogName, "WARN");
+ LogCtl.setLevel("org.eclipse.jetty", "WARN");
}
}
http://git-wip-us.apache.org/repos/asf/jena/blob/3b01252f/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssemblerBuild.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssemblerBuild.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssemblerBuild.java
index 14610b1..54cab0d 100644
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssemblerBuild.java
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssemblerBuild.java
@@ -40,7 +40,7 @@ public class TestSecurityAssemblerBuild {
private void assemblerFile(String assemblerFile) {
Dataset ds = (Dataset)AssemblerUtils.build(assemblerFile, VocabSecurity.tAccessControlledDataset);
DatasetGraphAccessControl dsg = (DatasetGraphAccessControl)ds.asDatasetGraph();
- SecurityRegistry securityRegistry = dsg.getRegistry();
+ AuthorizationService securityRegistry = dsg.getAuthService();
assertNotNull(securityRegistry);
}
}
http://git-wip-us.apache.org/repos/asf/jena/blob/3b01252f/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/Fuseki.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/Fuseki.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/Fuseki.java
index ec1126a..4e5f1ac 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/Fuseki.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/Fuseki.java
@@ -189,7 +189,7 @@ public class Fuseki {
public static final String attrVerbose = "org.apache.jena.fuseki:verbose";
public static final String attrNameRegistry = "org.apache.jena.fuseki:DataAccessPointRegistry";
public static final String attrServiceRegistry = "org.apache.jena.fuseki:ServiceDispatchRegistry";
- public static final String attrSecurityRegistry = "org.apache.jena.fuseki:SecurityRegistry";
+ public static final String attrAuthorizationService = "org.apache.jena.fuseki:AuthorizationService";
public static void setVerbose(ServletContext cxt, boolean verbose) {
cxt.setAttribute(attrVerbose, Boolean.valueOf(verbose));
[05/27] jena git commit: JENA-1585: Refactoring webapp code to
separate from the core server.
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/webapp/WEB-INF/web.xml b/jena-fuseki2/jena-fuseki-core/src/main/webapp/WEB-INF/web.xml
index 48e49e8..b9f1ff1 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/webapp/WEB-INF/web.xml
+++ b/jena-fuseki2/jena-fuseki-core/src/main/webapp/WEB-INF/web.xml
@@ -185,12 +185,12 @@
<servlet>
<servlet-name>ActionBackup</servlet-name>
- <servlet-class>org.apache.jena.fuseki.ctl.ActionBackup</servlet-class>
+ <servlet-class>org.apache.jena.fuseki.mgt.ActionBackup</servlet-class>
</servlet>
<servlet>
<servlet-name>BackupListServlet</servlet-name>
- <servlet-class>org.apache.jena.fuseki.ctl.ActionBackupList</servlet-class>
+ <servlet-class>org.apache.jena.fuseki.mgt.ActionBackupList</servlet-class>
</servlet>
<!-- An action that only creates a background task that sleeps. -->
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/webapp/js/app/controllers/.svnkeep
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/webapp/js/app/controllers/.svnkeep b/jena-fuseki2/jena-fuseki-core/src/main/webapp/js/app/controllers/.svnkeep
deleted file mode 100644
index e69de29..0000000
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/webapp/js/app/layouts/.svnkeep
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/webapp/js/app/layouts/.svnkeep b/jena-fuseki2/jena-fuseki-core/src/main/webapp/js/app/layouts/.svnkeep
deleted file mode 100644
index e69de29..0000000
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/webapp/js/app/routers/.svnkeep
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/webapp/js/app/routers/.svnkeep b/jena-fuseki2/jena-fuseki-core/src/main/webapp/js/app/routers/.svnkeep
deleted file mode 100644
index e69de29..0000000
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/webapp/js/app/views/.svnkeep
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/webapp/js/app/views/.svnkeep b/jena-fuseki2/jena-fuseki-core/src/main/webapp/js/app/views/.svnkeep
deleted file mode 100644
index e69de29..0000000
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/ServerCtl.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/ServerCtl.java b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/ServerCtl.java
index 048ecf0..8fc4513 100644
--- a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/ServerCtl.java
+++ b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/ServerCtl.java
@@ -30,7 +30,7 @@ import org.apache.http.client.HttpClient ;
import org.apache.http.impl.client.CloseableHttpClient ;
import org.apache.jena.atlas.io.IO ;
import org.apache.jena.atlas.lib.FileOps ;
-import org.apache.jena.fuseki.jetty.JettyFuseki ;
+import org.apache.jena.fuseki.cmd.JettyFuseki;
import org.apache.jena.fuseki.jetty.JettyServerConfig ;
import org.apache.jena.fuseki.server.* ;
import org.apache.jena.fuseki.webapp.FusekiEnv;
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestAdmin.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestAdmin.java b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestAdmin.java
index cf9e192..8ce0947 100644
--- a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestAdmin.java
+++ b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestAdmin.java
@@ -18,11 +18,11 @@
package org.apache.jena.fuseki;
-import static org.apache.jena.fuseki.mgt.MgtConst.opDatasets ;
-import static org.apache.jena.fuseki.mgt.MgtConst.opListBackups ;
-import static org.apache.jena.fuseki.mgt.MgtConst.opPing ;
-import static org.apache.jena.fuseki.mgt.MgtConst.opServer ;
-import static org.apache.jena.fuseki.mgt.MgtConst.opStats ;
+import static org.apache.jena.fuseki.mgt.ServerMgtConst.opDatasets ;
+import static org.apache.jena.fuseki.mgt.ServerMgtConst.opListBackups ;
+import static org.apache.jena.fuseki.mgt.ServerMgtConst.opServer ;
+import static org.apache.jena.fuseki.server.ServerConst.opPing;
+import static org.apache.jena.fuseki.server.ServerConst.opStats;
import static org.apache.jena.riot.web.HttpOp.execHttpDelete ;
import static org.apache.jena.riot.web.HttpOp.execHttpGet ;
import static org.apache.jena.riot.web.HttpOp.execHttpPost ;
@@ -41,7 +41,8 @@ import org.apache.jena.atlas.json.JsonValue ;
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.fuseki.mgt.MgtConst;
+import org.apache.jena.fuseki.mgt.ServerMgtConst;
+import org.apache.jena.fuseki.server.ServerConst;
import org.apache.jena.riot.WebContent ;
import org.apache.jena.riot.web.HttpOp ;
import org.apache.jena.riot.web.HttpResponseHandler ;
@@ -71,9 +72,9 @@ public class TestAdmin extends AbstractFusekiTest {
JsonValue jv = httpGetJson(ServerCtl.urlRoot()+"$/"+opServer) ;
JsonObject obj = jv.getAsObject() ;
// Now optional : assertTrue(obj.hasKey(JsonConst.admin)) ;
- assertTrue(obj.hasKey(MgtConst.datasets)) ;
- assertTrue(obj.hasKey(MgtConst.uptime)) ;
- assertTrue(obj.hasKey(MgtConst.startDT)) ;
+ assertTrue(obj.hasKey(ServerConst.datasets)) ;
+ assertTrue(obj.hasKey(ServerMgtConst.uptime)) ;
+ assertTrue(obj.hasKey(ServerMgtConst.startDT)) ;
}
@Test public void server_2() {
[14/27] jena git commit: JENA-1594: GSP and Quads filtered access.
Tests.
Posted by an...@apache.org.
JENA-1594: GSP and Quads filtered access. Tests.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/689c4cf8
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/689c4cf8
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/689c4cf8
Branch: refs/heads/master
Commit: 689c4cf886facae3eec26208de059905db40408e
Parents: aa65883
Author: Andy Seaborne <an...@apache.org>
Authored: Fri Aug 24 17:38:42 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Fri Aug 24 17:38:42 2018 +0100
----------------------------------------------------------------------
.../fuseki/access/DatasetGraphFiltered.java | 144 ++++++++
.../fuseki/access/Filtered_REST_Quads_R.java | 40 ++-
.../fuseki/access/Filtered_SPARQL_GSP_R.java | 47 +--
.../access/Filtered_SPARQL_QueryDataset.java | 2 +
.../jena/fuseki/access/SecurityPolicy.java | 17 +
.../jena/fuseki/access/SecurityRegistry.java | 6 +-
.../access/AbstractTestSecurityAssembler.java | 331 +++++++++++++++++++
.../fuseki/access/TS_SecurityFiltering.java | 4 +-
.../fuseki/access/TestAssemblerSeparate.java | 26 ++
.../jena/fuseki/access/TestAssemblerShared.java | 26 ++
.../fuseki/access/TestSecurityAssembler.java | 193 -----------
.../access/TestSecurityAssemblerBuild.java | 46 +++
.../fuseki/access/TestSecurityFilterFuseki.java | 138 +++++++-
.../apache/jena/fuseki/build/FusekiBuilder.java | 3 +
.../org/apache/jena/fuseki/jetty/JettyLib.java | 2 +-
.../jena/fuseki/servlets/REST_Quads_R.java | 10 +-
.../apache/jena/fuseki/servlets/SPARQL_GSP.java | 19 +-
.../jena/fuseki/servlets/SPARQL_GSP_R.java | 16 +-
.../jena/fuseki/servlets/SPARQL_Query.java | 10 +-
19 files changed, 818 insertions(+), 262 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphFiltered.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphFiltered.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphFiltered.java
new file mode 100644
index 0000000..a7842ba
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphFiltered.java
@@ -0,0 +1,144 @@
+/*
+ * 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.access;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.function.Predicate;
+
+import org.apache.jena.atlas.iterator.Iter;
+import org.apache.jena.graph.Graph;
+import org.apache.jena.graph.Node;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.DatasetGraphReadOnly;
+import org.apache.jena.sparql.core.GraphView;
+import org.apache.jena.sparql.core.Quad;
+import org.apache.jena.sparql.graph.GraphReadOnly;
+import org.apache.jena.sparql.graph.GraphUnionRead;
+
+/**
+ * A read-only {@link DatasetGraph} that applies a filter testing all triples and quads
+ * returned by accessing the data. Only quads where the filter tests for "true" are exposed.
+ *
+ */
+public class DatasetGraphFiltered extends DatasetGraphReadOnly {
+
+ // Or DatasetGraphTriplesQuads
+
+ // Core operations at the triple/quad level.
+ // This would work for TDB where the root access is triples/quads
+ // but not for graph-style root access.
+ /*
+ Write operations
+ add(Quad)
+ delete(Quad)
+ add(Node, Node, Node, Node)
+ delete(Node, Node, Node, Node)
+ deleteAny(Node, Node, Node, Node)
+ clear()
+
+ Read operations
+ listGraphNodes()
+ isEmpty()
+ find()
+ find(Quad)
+ find(Node, Node, Node, Node)
+ findNG(Node, Node, Node, Node)
+ contains(Quad)
+ contains(Node, Node, Node, Node)
+ size()
+ toString()
+ */
+ /*
+ getGraph(Node)
+ getDefaultGraph()
+ containsGraph(Node)
+ */
+
+ private final Predicate<Quad> quadFilter;
+ private final Collection<Node> visibleGraphs;
+
+ public DatasetGraphFiltered(DatasetGraph dsg, Predicate<Quad> filter, Collection<Node> visibleGraphs) {
+ super(dsg);
+ this.quadFilter = filter;
+ this.visibleGraphs = visibleGraphs;
+ }
+
+ private boolean filter(Quad quad) {
+ return quadFilter.test(quad);
+ }
+
+ private Iterator<Quad> filter(Iterator<Quad> iter) {
+ return Iter.filter(iter, this::filter);
+ }
+
+ // Need to intercept these because otherwise that are a GraphView of the wrapped "dsg", not this one.
+
+ @Override
+ public Graph getDefaultGraph()
+ {
+ Graph g = GraphView.createDefaultGraph(this);
+ return new GraphReadOnly(g);
+ }
+
+ @Override
+ public Graph getGraph(Node graphNode) {
+ if ( Quad.isUnionGraph(graphNode))
+ return getUnionGraph();
+ Graph g = GraphView.createNamedGraph(this, graphNode);
+ return new GraphReadOnly(g);
+ }
+
+ @Override
+ public Graph getUnionGraph() {
+ return new GraphUnionRead(get(), visibleGraphs);
+ }
+
+ @Override
+ public Iterator<Quad> find() {
+ return filter(super.find());
+ }
+
+ @Override public Iterator<Quad> find(Node g, Node s, Node p, Node o) {
+ // Need union handling if for general API use.
+ return filter(super.find(g, s, p, o));
+ }
+
+ @Override public Iterator<Quad> find(Quad quad) {
+ // union
+ return filter(super.find(quad));
+ }
+
+ @Override public Iterator<Quad> findNG(Node g, Node s, Node p , Node o) {
+ // union
+ return filter(super.findNG(g, s, p, o));
+ }
+
+ @Override public boolean contains(Node g, Node s, Node p , Node o) {
+ return filter(super.find(g, s, p, o)).hasNext();
+ }
+
+ @Override public boolean contains(Quad quad) {
+ return filter(super.find(quad)).hasNext();
+ }
+
+ @Override public boolean isEmpty() {
+ return ! this.find().hasNext();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_R.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_R.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_R.java
index d698ecb..9a7fdd0 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_R.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_R.java
@@ -19,33 +19,43 @@
package org.apache.jena.fuseki.access;
import java.util.function.Function;
+import java.util.function.Predicate;
import org.apache.jena.fuseki.servlets.HttpAction;
import org.apache.jena.fuseki.servlets.REST_Quads_R;
import org.apache.jena.sparql.core.DatasetGraph;
-import org.apache.jena.sparql.core.DatasetGraphWrapper;
-import org.apache.jena.sparql.util.Context;
+import org.apache.jena.sparql.core.Quad;
+/**
+ * Filter for {@link REST_Quads_R} that inserts a security filter on read-access to the
+ * {@link DatasetGraph}.
+ */
public class Filtered_REST_Quads_R extends REST_Quads_R {
- public Filtered_REST_Quads_R(Function<HttpAction, String> determineUser) {}
+
+ private final Function<HttpAction, String> requestUser;
+
+ public Filtered_REST_Quads_R(Function<HttpAction, String> determineUser) {
+ this.requestUser = determineUser;
+ }
@Override
protected void validate(HttpAction action) {
super.validate(action);
}
+ // Where? REST_Quads_R < REST_Quads < ActionREST < ActionService
@Override
- protected void doGet(HttpAction action) {
-
- DatasetGraph dsg0 = action.getActiveDSG();
- DatasetGraph dsg = new DatasetGraphWrapper(dsg0) {
- @Override public Context getContext() { return super.getContext(); }
- };
- // Replace datasetGraph
- // XXX Implement access control for REST_Quads_R
-
- HttpAction action2 = action;
-
- super.doGet(action2);
+ protected DatasetGraph actOn(HttpAction action) {
+ DatasetGraph dsg = action.getDataset();
+ if ( dsg == null )
+ return dsg;//super.actOn(action);
+ if ( ! DataAccessCtl.isAccessControlled(dsg) )
+ // Not access controlled.
+ return dsg;//super.actOn(action);
+ SecurityPolicy sCxt = DataAccessLib.getSecurityPolicy(action, dsg, requestUser);
+ dsg = DatasetGraphAccessControl.unwrap(dsg);
+ Predicate<Quad> filter = sCxt.predicateQuad();
+ dsg = new DatasetGraphFiltered(dsg, filter, sCxt.visibleGraphs());
+ return dsg;
}
}
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_R.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_R.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_R.java
index 1eae1d1..d2803cc 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_R.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_R.java
@@ -19,47 +19,34 @@
package org.apache.jena.fuseki.access;
import java.util.function.Function;
+import java.util.function.Predicate;
import org.apache.jena.fuseki.servlets.HttpAction;
import org.apache.jena.fuseki.servlets.SPARQL_GSP_R;
-import org.apache.jena.sparql.util.Context;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.Quad;
public class Filtered_SPARQL_GSP_R extends SPARQL_GSP_R {
private final Function<HttpAction, String> requestUser;
public Filtered_SPARQL_GSP_R(Function<HttpAction, String> determineUser) {
- this.requestUser = determineUser;
+ this.requestUser = determineUser;
}
+ // Where? SPARQL_GSP_R < SPARQL_GSP < ActionREST < ActionService
@Override
- protected void doGet(HttpAction action) {
- // For this, mask on target.
-
- // Avoid doing twice?
- Target target = determineTarget(action);
-
-// Node gn = target.graphName;
-// boolean dftGraph = target.isDefault;
- // Yes/no based on graph.
-
- // 1:: DatsetGraphWrapper and modify action.activeDGS;
- // 2:: action.getContext().set(...
-
-
- DataAccessLib.getSecurityPolicy(action, action.getActiveDSG(), requestUser);
-
- Context context = action.getActiveDSG().getContext();
- //action.getContext(); // Is this the DGS? No. copied.
- action.getContext().set(DataAccessCtl.symControlledAccess, true);
- // XXX Implement access control for GSP_R
- SecurityRegistry securityRegistry = null;
- String user = requestUser.apply(action);
-
-
-
- action.getContext().set(DataAccessCtl.symSecurityRegistry, securityRegistry);
- super.doGet(action);
+ protected DatasetGraph actOn(HttpAction action) {
+ DatasetGraph dsg = action.getDataset();
+ if ( dsg == null )
+ return dsg;//super.actOn(action);
+ if ( ! DataAccessCtl.isAccessControlled(dsg) )
+ // Not access controlled.
+ return dsg;//super.actOn(action);
+ SecurityPolicy sCxt = DataAccessLib.getSecurityPolicy(action, dsg, requestUser);
+ dsg = DatasetGraphAccessControl.unwrap(dsg);
+ Predicate<Quad> filter = sCxt.predicateQuad();
+ dsg = new DatasetGraphFiltered(dsg, filter, sCxt.visibleGraphs());
+ return dsg;
}
-
}
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
index cc260f2..596bef1 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
@@ -41,6 +41,7 @@ public class Filtered_SPARQL_QueryDataset extends SPARQL_QueryDataset {
@Override
protected QueryExecution createQueryExecution(HttpAction action, Query query, Dataset dataset) {
// Server database, not the possibly dynamically built "dataset"
+ // ---- XXX DRY
DatasetGraph dsg = action.getDataset();
if ( dsg == null )
return super.createQueryExecution(action, query, dataset);
@@ -54,6 +55,7 @@ public class Filtered_SPARQL_QueryDataset extends SPARQL_QueryDataset {
// Add back the Dataset for the createQueryExecution call.
dataset = DatasetFactory.wrap(dsg);
}
+ // ----
QueryExecution qExec = super.createQueryExecution(action, query, dataset);
if ( sCxt != null )
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
index 808e980..8d59911 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
@@ -20,6 +20,7 @@ package org.apache.jena.fuseki.access;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
@@ -65,6 +66,10 @@ public class SecurityPolicy {
this.matchDefaultGraph = graphNames.stream().anyMatch(Quad::isDefaultGraph);
}
+ public Collection<Node> visibleGraphs() {
+ return Collections.unmodifiableCollection(graphNames);
+ }
+
/**
* Apply a filter suitable for the TDB-backed {@link DatasetGraph}, to the {@link Context} of the
* {@link QueryExecution}. This does not modify the {@link DatasetGraph}
@@ -85,6 +90,18 @@ public class SecurityPolicy {
return "dft:"+matchDefaultGraph+" / "+graphNames.toString();
}
+ public Predicate<Quad> predicateQuad() {
+ return quad -> {
+ if ( quad.isDefaultGraph() )
+ return matchDefaultGraph;
+ if ( quad.isUnionGraph() )
+ // XXX What to do here.
+ // Need special union graph?
+ return true;
+ return graphNames.contains(quad.getGraph());
+ };
+ }
+
/**
* Create a GraphFilter for a TDB backed dataset.
*
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java
index 1ad4098..490a785 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java
@@ -54,8 +54,10 @@ public class SecurityRegistry extends Registry<String, SecurityPolicy>{
@Override
public String toString() {
- if ( true )
- return "SecurityRegistry"+keys();
+ return "SecurityRegistry"+keys();
+ }
+
+ public String toLongString() {
// Long form.
StringJoiner sj1 = new StringJoiner("\n", "{ SecurityRegistry\n", "\n}");
super.keys().forEach(u->{
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestSecurityAssembler.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestSecurityAssembler.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestSecurityAssembler.java
new file mode 100644
index 0000000..c062012
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestSecurityAssembler.java
@@ -0,0 +1,331 @@
+/*
+ * 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.access;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.jena.atlas.iterator.Iter;
+import org.apache.jena.atlas.lib.SetUtils;
+import org.apache.jena.atlas.lib.StrUtils;
+import org.apache.jena.atlas.web.HttpException;
+import org.apache.jena.fuseki.FusekiLib;
+import org.apache.jena.fuseki.embedded.FusekiServer;
+import org.apache.jena.graph.Node;
+import org.apache.jena.query.Dataset;
+import org.apache.jena.query.QuerySolution;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.RDFNode;
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.rdfconnection.RDFConnection;
+import org.apache.jena.rdfconnection.RDFConnectionFactory;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.Quad;
+import org.apache.jena.sparql.sse.SSE;
+import org.apache.jena.sys.JenaSystem;
+import org.apache.jena.system.Txn;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test on the assembler for data access control.
+ * <ul>
+ * <li>assem-security.ttl - two services "/database" and "/plain" each with their own dataset.
+ * <li>assem-security-shared.ttl - two services "/database" and "/plain" with a shared dataset.
+ * </ul>
+ *
+ * @see TestSecurityFilterFuseki TestSecurityFilterFuseki for other HTTP tests.
+ */
+
+public abstract class AbstractTestSecurityAssembler {
+ static { JenaSystem.init(); }
+ static final String DIR = "testing/Access/";
+
+// @Parameters(name = "{index}: {0}")
+// public static Iterable<Object[]> data() {
+// Object[] obj1 = { DIR+"assem-security.ttl" , false };
+// Object[] obj2 = { DIR+"assem-security-shared.ttl" , true };
+// return Arrays.asList(obj1, obj2);
+// }
+
+ private final String assemblerFile;
+ private static AtomicReference<String> user = new AtomicReference<>();
+
+ private boolean sharedDatabase;
+
+ // Parameterized tests don't provide a convenient way to run code at the start and end of each parameter run and access the parameters.
+ private static FusekiServer server;
+ private FusekiServer getServer() {
+ if ( server == null )
+ server = setup(assemblerFile, false);
+ return server;
+ }
+ @AfterClass public static void afterClass() {
+ server.stop();
+ server = null;
+ user.set(null);
+ }
+
+ @Before
+ public void before() {
+ user.set(null);
+ }
+
+ private String getURL() {
+ getServer();
+ int port = server.getPort();
+ return "http://localhost:"+port+"/database";
+ }
+
+ private static FusekiServer setup(String assembler, boolean sharedDatabase) {
+ int port = FusekiLib.choosePort();
+ FusekiServer server = DataAccessCtl.fusekiBuilder((a)->user.get())
+ .port(port)
+ .parseConfigFile(assembler)
+ .build();
+ server.start();
+
+ if ( sharedDatabase ) {
+ String data = StrUtils.strjoinNL
+ ("PREFIX : <http://example/>"
+ ,"INSERT DATA {"
+ ," :s0 :p :o ."
+ ," GRAPH <http://host/graphname1> {:s1 :p :o}"
+ ," GRAPH <http://host/graphname3> {:s3 :p :o}"
+ ," GRAPH <http://host/graphname9> {:s9 :p :o}"
+ ,"}"
+ );
+ String plainUrl = "http://localhost:"+server.getPort()+"/plain";
+ try(RDFConnection conn = RDFConnectionFactory.connect(plainUrl)) {
+ conn.update(data);
+ }
+ } else {
+ DatasetGraph dsg = server.getDataAccessPointRegistry().get("/database").getDataService().getDataset();
+ Txn.executeWrite(dsg, ()->{
+ dsg.add(SSE.parseQuad("(<http://host/graphname1> :s1 :p :o)"));
+ dsg.add(SSE.parseQuad("(<http://host/graphname3> :s3 :p :o)"));
+ dsg.add(SSE.parseQuad("(<http://host/graphname9> :s9 :p :o)"));
+ });
+ }
+ return server;
+ }
+
+ protected AbstractTestSecurityAssembler(String assemberFile, boolean sharedDatabase) {
+ this.assemblerFile = assemberFile;
+ this.sharedDatabase = sharedDatabase ;
+ }
+
+ private static Node s1 = SSE.parseNode(":s1");
+ private static Node s2 = SSE.parseNode(":s2");
+ private static Node s3 = SSE.parseNode(":s3");
+ private static Node s9 = SSE.parseNode(":s9");
+
+ // The access controlled dataset.
+
+// { SecurityRegistry
+// user1 -> dft:false / [http://host/graphname2, http://host/graphname1, http://host/graphname3]
+// user2 -> dft:false / [http://host/graphname9]
+// userZ -> dft:false / [http://host/graphnameZ]
+// user3 -> dft:false / [http://host/graphname4, http://host/graphname3, http://host/graphname5]
+// }
+
+
+ @Test public void query_user1() {
+ user.set("user1");
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
+ assertSeen(visible, s1, s3);
+ }
+ }
+
+ @Test public void query_userX() {
+ user.set("userX"); // No such user in the registry
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
+ assertSeen(visible);
+ }
+ }
+
+ @Test public void query_no_user() {
+ user.set(null); // No user.
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
+ assertSeen(visible);
+ }
+ }
+
+ @Test public void query_user2() {
+ user.set("user2");
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
+ assertSeen(visible, s9);
+ }
+ }
+
+ @Test public void query_userZ() {
+ user.set("userZ"); // No graphs with data.
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
+ assertSeen(visible);
+ }
+ }
+
+ // GSP. "http://host/graphname1"
+ @Test public void gsp_dft_user1() {
+ user.set("user1");
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ Set<Node> visible = gsp(conn, null);
+ assertSeen(visible);
+ }
+ }
+
+ @Test public void gsp_ng_user1() {
+ user.set("user1");
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ Set<Node> visible = gsp(conn, "http://host/graphname1");
+ assertSeen(visible, s1);
+ }
+ }
+
+ @Test public void gsp_dft_user2() {
+ user.set("user2");
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ gsp404(conn, null);
+ }
+ }
+
+ @Test public void gsp_ng_user2() {
+ user.set("user2");
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ gsp404(conn, "http://host/graphname1");
+ }
+ }
+
+ @Test public void gsp_dft_userX() {
+ user.set("userX");
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ gsp404(conn, null);
+ }
+ }
+
+ @Test public void gsp_ng_userX() {
+ user.set("userX");
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ gsp404(conn, "http://host/graphname1");
+ }
+ }
+
+ @Test public void gsp_dft_user_null() {
+ user.set(null);
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ gsp404(conn, null);
+ }
+ }
+
+ @Test public void gsp_ng_user_null() {
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ gsp404(conn, "http://host/graphname1");
+ }
+ }
+
+// // Quads
+// user.set("user1");
+// try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+// Set<Node> visible = dataset(conn);
+// assertSeen(visible, s1, s3);
+// }
+// user.set("user2");
+// try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+// Set<Node> visible = dataset(conn);
+// assertSeen(visible, s9);
+// }
+// user.set("userX");
+// try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+// Set<Node> visible = dataset(conn);
+// assertSeen(visible);
+// }
+// user.set(null);
+// try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+// Set<Node> visible = dataset(conn);
+// assertSeen(visible);
+// }
+
+
+ private Set<Node> gsp(RDFConnection conn, String graphName) {
+ Set<Node> results = new HashSet<>();
+ Model model = graphName == null ? conn.fetch() : conn.fetch(graphName);
+ // Extract subjects.
+ Set<Node> seen =
+ SetUtils.toSet(
+ Iter.asStream(model.listSubjects())
+ .map(Resource::asNode)
+ );
+ return seen;
+ }
+
+ private void gsp404(RDFConnection conn, String graphName) {
+ gspHttp(conn, 404, graphName);
+ }
+
+ private void gspHttp(RDFConnection conn, int statusCode, String graphName) {
+ try {
+ gsp(conn, graphName);
+ if ( statusCode < 200 && statusCode > 299 )
+ fail("Should have responded with "+statusCode);
+ } catch (HttpException ex) {
+ assertEquals(statusCode, ex.getResponseCode());
+ }
+ }
+
+ private Set<Node> dataset(RDFConnection conn) {
+ Dataset ds = conn.fetchDataset();
+ Set<Node> seen =
+ SetUtils.toSet(
+ Iter.asStream(ds.asDatasetGraph().find())
+ .map(Quad::getSubject)
+ );
+ return seen;
+ }
+
+ private Set<Node> query(RDFConnection conn, String queryString) {
+ Set<Node> results = new HashSet<>();
+ conn.queryResultSet(queryString, rs->{
+ List<QuerySolution> list = Iter.toList(rs);
+ list.stream()
+ .map(qs->qs.get("s"))
+ .filter(Objects::nonNull)
+ .map(RDFNode::asNode)
+ .forEach(n->results.add(n));
+ });
+ return results;
+ }
+
+ private static void assertSeen(Set<Node> visible, Node ... expected) {
+ Set<Node> expectedNodes = new HashSet<>(Arrays.asList(expected));
+ assertEquals(expectedNodes, visible);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java
index 35cb7ed..981a205 100644
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java
@@ -28,7 +28,9 @@ import org.junit.runners.Suite;
@Suite.SuiteClasses( {
TestSecurityFilterLocal.class
, TestSecurityFilterFuseki.class
- , TestSecurityAssembler.class
+ , TestSecurityAssemblerBuild.class
+ , TestAssemblerSeparate.class
+ , TestAssemblerShared.class
})
public class TS_SecurityFiltering {
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAssemblerSeparate.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAssemblerSeparate.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAssemblerSeparate.java
new file mode 100644
index 0000000..78281f1
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAssemblerSeparate.java
@@ -0,0 +1,26 @@
+/*
+ * 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.access;
+
+public class TestAssemblerSeparate extends AbstractTestSecurityAssembler {
+
+ public TestAssemblerSeparate() {
+ super(DIR+"assem-security.ttl", false);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAssemblerShared.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAssemblerShared.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAssemblerShared.java
new file mode 100644
index 0000000..32d182b
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAssemblerShared.java
@@ -0,0 +1,26 @@
+/*
+ * 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.access;
+
+public class TestAssemblerShared extends AbstractTestSecurityAssembler {
+
+ public TestAssemblerShared() {
+ super(DIR+"assem-security-shared.ttl", true);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssembler.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssembler.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssembler.java
deleted file mode 100644
index eefdcd7..0000000
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssembler.java
+++ /dev/null
@@ -1,193 +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.access;
-
-import static org.junit.Assert.assertEquals;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.apache.jena.atlas.iterator.Iter;
-import org.apache.jena.atlas.lib.StrUtils;
-import org.apache.jena.fuseki.FusekiLib;
-import org.apache.jena.fuseki.embedded.FusekiServer;
-import org.apache.jena.graph.Node;
-import org.apache.jena.query.Dataset;
-import org.apache.jena.query.QuerySolution;
-import org.apache.jena.query.ResultSetFormatter;
-import org.apache.jena.rdf.model.RDFNode;
-import org.apache.jena.rdfconnection.RDFConnection;
-import org.apache.jena.rdfconnection.RDFConnectionFactory;
-import org.apache.jena.sparql.core.DatasetGraph;
-import org.apache.jena.sparql.core.assembler.AssemblerUtils;
-import org.apache.jena.sparql.sse.SSE;
-import org.apache.jena.system.Txn;
-import org.junit.Test;
-
-/**
- * Test on the assembler for data access control.
- * <ul>
- * <li>assem-security.ttl - two services "/database" and "/plain" each with their own dataset.
- * <li>assem-security-shared.ttl - two services "/database" and "/plain" with a shared dataset.
- * </ul>
- */
-public class TestSecurityAssembler {
- static final String DIR = "testing/Access/";
-
- // Check the main test inputs.
- @Test public void assembler1() {
- Dataset ds = (Dataset)AssemblerUtils.build(DIR+"assem-security.ttl", VocabSecurity.tAccessControlledDataset);
- }
-
- @Test public void assembler2() {
- Dataset ds = (Dataset)AssemblerUtils.build(DIR+"assem-security-shared.ttl", VocabSecurity.tAccessControlledDataset);
- SecurityRegistry securityRegistry = ds.getContext().get(DataAccessCtl.symSecurityRegistry);
- }
-
- private static FusekiServer setup(String assembler, AtomicReference<String> user) {
- int port = FusekiLib.choosePort();
- FusekiServer server = DataAccessCtl.fusekiBuilder((a)->user.get())
- .port(port)
- .parseConfigFile(assembler)
- .build();
-
- return server;
- }
-
- // Two separate datasets
- @Test public void assembler3() {
- AtomicReference<String> user = new AtomicReference<>();
- FusekiServer server = setup(DIR+"assem-security.ttl", user);
- // Add data directly to the datasets.
- DatasetGraph dsg = server.getDataAccessPointRegistry().get("/database").getDataService().getDataset();
- //System.out.println(dsg.getContext());
- Txn.executeWrite(dsg, ()->{
- dsg.add(SSE.parseQuad("(<http://host/graphname1> :s1 :p :o)"));
- dsg.add(SSE.parseQuad("(<http://host/graphname3> :s3 :p :o)"));
- dsg.add(SSE.parseQuad("(<http://host/graphname9> :s9 :p :o)"));
- });
- server.start();
- try {
- testAssembler(server.getPort(), user);
-
- // Access the uncontrolled dataset.
- user.set(null);
- String plainUrl = "http://localhost:"+server.getPort()+"/plain";
- try(RDFConnection conn = RDFConnectionFactory.connect(plainUrl)) {
- conn.update("INSERT DATA { <x:s> <x:p> 123 , 456 }");
- conn.queryResultSet("SELECT * { ?s ?p ?o }",
- rs->{
- int x = ResultSetFormatter.consume(rs);
- assertEquals(2, x);
- });
- }
- } finally { server.stop(); }
- }
-
- // Shared dataset
- @Test public void assembler4() {
- AtomicReference<String> user = new AtomicReference<>();
- FusekiServer server = setup(DIR+"assem-security-shared.ttl", user);
-
- String x = StrUtils.strjoinNL
- ("PREFIX : <http://example/>"
- ,"INSERT DATA {"
- ," GRAPH <http://host/graphname1> {:s1 :p :o}"
- ," GRAPH <http://host/graphname3> {:s3 :p :o}"
- ," GRAPH <http://host/graphname9> {:s9 :p :o}"
- ,"}"
- );
-
- server.start();
- try {
- user.set(null);
- String plainUrl = "http://localhost:"+server.getPort()+"/plain";
- try(RDFConnection conn = RDFConnectionFactory.connect(plainUrl)) {
- conn.update(x);
- conn.queryResultSet("SELECT * { GRAPH ?g { ?s ?p ?o } }",
- rs->{
- int c = ResultSetFormatter.consume(rs);
- assertEquals(3, c);
- });
- }
- testAssembler(server.getPort(), user);
- } finally { server.stop(); }
- }
-
- private void testAssembler(int port, AtomicReference<String> user) {
- // The access controlled dataset.
- String url = "http://localhost:"+port+"/database";
-
- Node s1 = SSE.parseNode(":s1");
- Node s3 = SSE.parseNode(":s3");
- Node s9 = SSE.parseNode(":s9");
-
- user.set("user1");
- try(RDFConnection conn = RDFConnectionFactory.connect(url)) {
- Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
- assertSeen(visible, s1, s3);
- }
-
- user.set("userX"); // No such user in the registry
- try(RDFConnection conn = RDFConnectionFactory.connect(url)) {
- Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
- assertSeen(visible);
- }
- user.set(null); // No user.
- try(RDFConnection conn = RDFConnectionFactory.connect(url)) {
- Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
- assertSeen(visible);
- }
-
- user.set("user2");
- try(RDFConnection conn = RDFConnectionFactory.connect(url)) {
- Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
- assertSeen(visible, s9);
- }
-
- user.set("userZ"); // No graphs with data.
- try(RDFConnection conn = RDFConnectionFactory.connect(url)) {
- Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
- assertSeen(visible);
- }
-
- }
-
- private static void assertSeen(Set<Node> visible, Node ... expected) {
- Set<Node> expectedNodes = new HashSet<>(Arrays.asList(expected));
- assertEquals(expectedNodes, visible);
- }
-
- private Set<Node> query(RDFConnection conn, String queryString) {
- Set<Node> results = new HashSet<>();
- conn.queryResultSet(queryString, rs->{
- List<QuerySolution> list = Iter.toList(rs);
- list.stream()
- .map(qs->qs.get("s"))
- .filter(Objects::nonNull)
- .map(RDFNode::asNode)
- .forEach(n->results.add(n));
- });
- return results;
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssemblerBuild.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssemblerBuild.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssemblerBuild.java
new file mode 100644
index 0000000..14610b1
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssemblerBuild.java
@@ -0,0 +1,46 @@
+/*
+ * 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.access;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.apache.jena.query.Dataset;
+import org.apache.jena.sparql.core.assembler.AssemblerUtils;
+import org.apache.jena.sys.JenaSystem;
+import org.junit.Test;
+
+public class TestSecurityAssemblerBuild {
+ static { JenaSystem.init(); }
+ static final String DIR = "testing/Access/";
+
+ @Test public void assembler1() {
+ assemblerFile(DIR+"assem-security.ttl");
+ }
+
+ @Test public void assembler2() {
+ assemblerFile(DIR+"assem-security-shared.ttl");
+ }
+
+ private void assemblerFile(String assemblerFile) {
+ Dataset ds = (Dataset)AssemblerUtils.build(assemblerFile, VocabSecurity.tAccessControlledDataset);
+ DatasetGraphAccessControl dsg = (DatasetGraphAccessControl)ds.asDatasetGraph();
+ SecurityRegistry securityRegistry = dsg.getRegistry();
+ assertNotNull(securityRegistry);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
index 4eb8dd4..c44540c 100644
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
@@ -30,11 +30,14 @@ import java.util.Objects;
import java.util.Set;
import org.apache.jena.atlas.iterator.Iter;
+import org.apache.jena.atlas.lib.SetUtils;
+import org.apache.jena.atlas.web.HttpException;
import org.apache.jena.fuseki.FusekiLib;
import org.apache.jena.fuseki.embedded.FusekiServer;
import org.apache.jena.fuseki.jetty.JettyLib;
import org.apache.jena.graph.Node;
import org.apache.jena.query.QuerySolution;
+import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdfconnection.RDFConnection;
import org.apache.jena.rdfconnection.RDFConnectionFactory;
@@ -105,9 +108,11 @@ public class TestSecurityFilterFuseki {
private static UserStore userStore() {
PropertyUserStore propertyUserStore = new PropertyUserStore();
String[] roles = new String[]{"**"};
- addUserPassword(propertyUserStore, "user0", "pw0", roles);
- addUserPassword(propertyUserStore, "user1", "pw1", roles);
- addUserPassword(propertyUserStore, "user2", "pw2", roles);
+ addUserPassword(propertyUserStore, "userNone", "pwNone", roles);
+ addUserPassword(propertyUserStore, "userDft", "pwDft", roles);
+ addUserPassword(propertyUserStore, "user0", "pw0", roles);
+ addUserPassword(propertyUserStore, "user1", "pw1", roles);
+ addUserPassword(propertyUserStore, "user2", "pw2", roles);
return propertyUserStore;
}
@@ -166,6 +171,16 @@ public class TestSecurityFilterFuseki {
}
}
+ @Test public void query_userDft() {
+ Set<Node> results = query("userDft", "pwDft", queryAll);
+ assertSeen(results, s0);
+ }
+
+ @Test public void query_userNone() {
+ Set<Node> results = query("userNone", "pwNone", queryAll);
+ assertSeen(results);
+ }
+
@Test public void query_user0() {
Set<Node> results = query("user0", "pw0", queryAll);
assertSeen(results, s0);
@@ -176,10 +191,6 @@ public class TestSecurityFilterFuseki {
assertSeen(results, s0, s1);
}
- @Test public void query_userX() {
- query401("userX", "pwX", queryAll);
- }
-
@Test public void query_bad_user() {
query401("userX", "pwX", queryAll);
}
@@ -188,4 +199,117 @@ public class TestSecurityFilterFuseki {
query401("user0", "not-the-password", queryAll);
}
+ private Set<Node> gsp(String user, String password, String graphName) {
+ Set<Node> results = new HashSet<>();
+ try (RDFConnection conn = RDFConnectionFactory.connectPW(baseUrl, user, password)) {
+ Model model = graphName == null ? conn.fetch() : conn.fetch(graphName);
+ // Extract subjects.
+ Set<Node> seen =
+ SetUtils.toSet(
+ Iter.asStream(model.listSubjects())
+ .map(r->r.asNode())
+ );
+ return seen;
+ }
+ }
+
+ private void gsp401(String user, String password, String graphName) {
+ gspHttp(401, user, password, graphName);
+ }
+
+ private void gsp403(String user, String password, String graphName) {
+ gspHttp(403, user, password, graphName);
+ }
+
+ private void gsp404(String user, String password, String graphName) {
+ gspHttp(404, user, password, graphName);
+ }
+
+ private void gspHttp(int statusCode, String user, String password, String queryString) {
+ try {
+ gsp(user, password, queryString);
+ if ( statusCode < 200 && statusCode > 299 )
+ fail("Should have responded with "+statusCode);
+ } catch (HttpException ex) {
+ assertEquals(statusCode, ex.getResponseCode());
+ }
+ }
+
+ // When a graph is not visible, it should return 404 except
+ // for the default graph which should be empty.
+
+ @Test public void gsp_dft_userDft() {
+ Set<Node> results = gsp("userDft", "pwDft", null);
+ assertSeen(results, s0);
+ }
+
+ @Test public void gsp_dft_userNone() {
+ Set<Node> results = gsp("userNone", "pwNone", null);
+ assertSeen(results);
+ }
+
+ @Test public void gsp_dft_user0() {
+ Set<Node> results = gsp("user0", "pw0", null);
+ assertSeen(results, s0);
+ }
+
+ @Test public void gsp_dft_user1() {
+ Set<Node> results = gsp("user1", "pw1", null);
+ assertSeen(results, s0);
+ }
+
+ @Test public void gsp_dft_user2() {
+ Set<Node> results = gsp("user2", "pw2", null);
+ assertSeen(results);
+ }
+
+ @Test public void gsp_graph1_userDft() {
+ gsp404("userDft", "pwDft", "http://test/g1");
+ }
+
+ @Test public void gsp_graph1_userNone() {
+ gsp404("userNone", "pwNone", "http://test/g1");
+ }
+
+ @Test public void gsp_graph1_user0() {
+ gsp404("user0", "pw0", "http://test/g1");
+ }
+
+ @Test public void gsp_graph1_user1() {
+ Set<Node> results = gsp("user1", "pw1", "http://test/g1");
+ assertSeen(results, s1);
+ }
+
+ @Test public void gsp_graph1_user2() {
+ gsp404("user2", "pw2", "http://test/g1");
+ }
+
+ // No such graph.
+ @Test public void gsp_graphX_userDft() {
+ gsp404("userDft", "pwDft", "http://test/gX");
+ }
+
+ @Test public void gsp_graphX_userNone() {
+ gsp404("userNone", "pwNone", "http://test/gX");
+ }
+
+ @Test public void gsp_graphX_user0() {
+ gsp404("user0", "pw0", "http://test/gX");
+ }
+
+ @Test public void gsp_graphX_user1() {
+ gsp404("user1", "pw1", "http://test/g1X");
+ }
+
+ @Test public void gsp_graphX_user2() {
+ gsp404("user2", "pw2", "http://test/gX");
+ }
+
+ @Test public void gsp_bad_user() {
+ gsp401("userX", "pwX", null);
+ }
+
+ @Test public void gsp_bad_password() {
+ gsp401("user0", "not-the-password", null);
+ }
}
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuilder.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuilder.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuilder.java
index 74eb2d4..2a673c7 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuilder.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuilder.java
@@ -45,6 +45,9 @@ import org.apache.jena.sparql.core.DatasetGraph ;
import org.apache.jena.sparql.util.FmtUtils ;
import org.apache.jena.vocabulary.RDF ;
+/**
+ * Helper functions use to construct Fuseki servers.
+ */
public class FusekiBuilder
{
/** Build a DataAccessPoint, including DataService, from the description at Resource svc */
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyLib.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyLib.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyLib.java
index 0d03ab4..d45d69f 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyLib.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyLib.java
@@ -102,7 +102,7 @@ public class JettyLib {
return makeUserStore(user, password, "**");
}
- /** Make a {@link UserStore} for a sigle user,password,role*/
+ /** Make a {@link UserStore} for a single user,password,role*/
public static UserStore makeUserStore(String user, String password, String role) {
Objects.requireNonNull(user);
Objects.requireNonNull(password);
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/REST_Quads_R.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/REST_Quads_R.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/REST_Quads_R.java
index f50d045..668f210 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/REST_Quads_R.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/REST_Quads_R.java
@@ -80,7 +80,7 @@ public class REST_Quads_R extends REST_Quads {
action.beginRead() ;
try {
- DatasetGraph dsg = action.getActiveDSG() ;
+ DatasetGraph dsg = actOn(action);
action.response.setHeader("Content-type", lang.getContentType().toHeaderString());
// ActionLib.contentNegotationQuads above
// RDF/XML is not a choice but this code is general.
@@ -101,6 +101,14 @@ public class REST_Quads_R extends REST_Quads {
}
}
+ /**
+ * Decide on the dataset to use for the operation. Can be overrided by specialist
+ * subclasses.
+ */
+ protected DatasetGraph actOn(HttpAction action) {
+ return action.getActiveDSG() ;
+ }
+
@Override
protected void doOptions(HttpAction action) {
action.response.setHeader(HttpNames.hAllow, "GET, HEAD, OPTIONS") ;
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP.java
index 2b44dd9..1321125 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP.java
@@ -34,8 +34,13 @@ import org.apache.jena.sparql.core.DatasetGraph ;
public abstract class SPARQL_GSP extends ActionREST
{
protected final static Target determineTarget(HttpAction action) {
+ DatasetGraph dsg = action.getActiveDSG();
+ return determineTarget(dsg, action);
+ }
+
+ protected final static Target determineTarget(DatasetGraph dsg, HttpAction action) {
// Delayed until inside a transaction.
- if ( action.getActiveDSG() == null )
+ if ( dsg == null )
ServletOps.errorOccurred("Internal error : No action graph (not in a transaction?)") ;
boolean dftGraph = getOneOnly(action.request, HttpNames.paramGraphDefault) != null ;
@@ -52,16 +57,16 @@ public abstract class SPARQL_GSP extends ActionREST
// No name (should have been a quads operations).
ServletOps.errorBadRequest("Neither default graph nor named graph specified and no direct name") ;
Node gn = NodeFactory.createURI(directName) ;
- return namedTarget(action, directName) ;
+ return namedTarget(dsg, directName) ;
}
if ( dftGraph )
- return Target.createDefault(action.getActiveDSG()) ;
+ return Target.createDefault(dsg) ;
// Named graph
if ( uri.equals(HttpNames.valueDefault ) )
// But "named" default
- return Target.createDefault(action.getActiveDSG()) ;
+ return Target.createDefault(dsg) ;
// Strictly, a bit naughty on the URI resolution. But more sensible.
// Base is dataset.
@@ -78,12 +83,12 @@ public abstract class SPARQL_GSP extends ActionREST
// Bad IRI
ServletOps.errorBadRequest("Bad IRI: "+ex.getMessage()) ;
}
- return namedTarget(action, absUri) ;
+ return namedTarget(dsg, absUri) ;
}
- private static Target namedTarget(HttpAction action, String graphName) {
+ private static Target namedTarget(DatasetGraph dsg, String graphName) {
Node gn = NodeFactory.createURI(graphName) ;
- return Target.createNamed(action.getActiveDSG(), graphName, gn) ;
+ return Target.createNamed(dsg, graphName, gn) ;
}
// struct for target
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP_R.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP_R.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP_R.java
index 090ea70..8204136 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP_R.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP_R.java
@@ -30,6 +30,7 @@ import org.apache.jena.graph.Graph ;
import org.apache.jena.riot.* ;
import org.apache.jena.riot.web.HttpNames ;
import org.apache.jena.shared.JenaException ;
+import org.apache.jena.sparql.core.DatasetGraph;
/** Only the READ operations */
public class SPARQL_GSP_R extends SPARQL_GSP
@@ -62,17 +63,20 @@ public class SPARQL_GSP_R extends SPARQL_GSP
action.beginRead() ;
setCommonHeaders(action.response) ;
try {
- Target target = determineTarget(action) ;
+ DatasetGraph dsg = actOn(action);
+ Target target = determineTarget(dsg, action) ;
if ( action.log.isDebugEnabled() )
action.log.debug("GET->"+target) ;
boolean exists = target.exists() ;
if ( ! exists )
ServletOps.errorNotFound("No such graph: <"+target.name+">") ;
+ Graph g = target.graph() ;
+ if ( ! target.isDefault && g.isEmpty() )
+ ServletOps.errorNotFound("No such graph: <"+target.name+">") ;
// If we want to set the Content-Length, we need to buffer.
//response.setContentLength(??) ;
String ct = lang.getContentType().toHeaderString() ;
action.response.setContentType(ct) ;
- Graph g = target.graph() ;
//Special case RDF/XML to be the plain (faster, less readable) form
RDFFormat fmt =
( lang == Lang.RDFXML ) ? RDFFormat.RDFXML_PLAIN : RDFWriterRegistry.defaultSerialization(lang) ;
@@ -91,6 +95,14 @@ public class SPARQL_GSP_R extends SPARQL_GSP
} finally { action.endRead() ; }
}
+ /**
+ * Decide on the dataset to use for the operation. Can be overrided by specialist
+ * subclasses.
+ */
+ protected DatasetGraph actOn(HttpAction action) {
+ return action.getActiveDSG() ;
+ }
+
@Override
protected void doOptions(HttpAction action) {
setCommonHeadersForOptions(action.response) ;
http://git-wip-us.apache.org/repos/asf/jena/blob/689c4cf8/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java
index 6c9e5b4..a14e75a 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java
@@ -388,9 +388,13 @@ public abstract class SPARQL_Query extends SPARQL_Protocol
}
private void setAnyProtocolTimeouts(QueryExecution qexec, HttpAction action) {
-// if ( !(action.getDataService().allowTimeoutOverride) )
-// return ;
-
+ // if ( !(action.getDataService().allowTimeoutOverride) )
+ // return ;
+ // See also QueryExecutionBase.setTimeouts to parse and process N,M form.
+ // ?? Set only if lower than any settings from the dataset or global contexts already in
+ // the QueryExecution.
+ // Add context setting for "allow increases".
+ // Documentation.
long desiredTimeout = Long.MAX_VALUE ;
String timeoutHeader = action.request.getHeader("Timeout") ;
String timeoutParameter = action.request.getParameter("timeout") ;
[02/27] jena git commit: JENA-1594: Initial machinery with SPARQL
Query filtering
Posted by an...@apache.org.
JENA-1594: Initial machinery with SPARQL Query filtering
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/344ae5d8
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/344ae5d8
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/344ae5d8
Branch: refs/heads/master
Commit: 344ae5d841c8d22ce8c87e4a2fa466fe2a263582
Parents: 06f5912
Author: Andy Seaborne <an...@apache.org>
Authored: Thu Aug 23 17:13:00 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Thu Aug 23 17:15:05 2018 +0100
----------------------------------------------------------------------
jena-fuseki2/jena-fuseki-access/pom.xml | 104 ++++++
.../fuseki/access/AssemblerAccessDataset.java | 63 ++++
.../access/AssemblerSecurityRegistry.java | 130 +++++++
.../jena/fuseki/access/DataAccessCtl.java | 179 +++++++++
.../jena/fuseki/access/DataAccessLib.java | 58 +++
.../access/DatasetGraphAccessControl.java | 49 +++
.../fuseki/access/Filtered_REST_Quads_R.java | 51 +++
.../fuseki/access/Filtered_SPARQL_GSP_R.java | 65 ++++
.../access/Filtered_SPARQL_QueryDataset.java | 64 ++++
.../apache/jena/fuseki/access/GraphFilter.java | 76 ++++
.../jena/fuseki/access/GraphFilterTDB1.java | 70 ++++
.../jena/fuseki/access/GraphFilterTDB2.java | 70 ++++
.../apache/jena/fuseki/access/InitSecurity.java | 38 ++
.../jena/fuseki/access/SecurityPolicy.java | 116 ++++++
.../jena/fuseki/access/SecurityRegistry.java | 72 ++++
.../jena/fuseki/access/VocabSecurity.java | 55 +++
.../org.apache.jena.sys.JenaSubsystemLifecycle | 1 +
.../apache/jena/fuseki/access/GraphData.java | 59 +++
.../fuseki/access/TS_SecurityFiltering.java | 42 +++
.../fuseki/access/TestSecurityAssembler.java | 193 ++++++++++
.../fuseki/access/TestSecurityFilterFuseki.java | 191 ++++++++++
.../fuseki/access/TestSecurityFilterLocal.java | 320 ++++++++++++++++
.../src/test/resources/log4j.properties | 40 ++
.../testing/Access/assem-security-shared.ttl | 58 +++
.../testing/Access/assem-security.ttl | 63 ++++
jena-fuseki2/jena-fuseki-core/pom.xml | 2 +
.../org/apache/jena/fuseki/jetty/JettyLib.java | 169 +++++++++
.../apache/jena/fuseki/server/Operation.java | 6 +-
.../jena/fuseki/servlets/ActionService.java | 2 +-
.../servlets/ServiceDispatchRegistry.java | 10 +-
.../jena/fuseki/embedded/FusekiServer.java | 126 ++++---
.../jena/fuseki/embedded/JettyServer.java | 369 +++++++++++++++++++
jena-fuseki2/pom.xml | 1 +
.../rdfconnection/RDFConnectionFactory.java | 25 ++
34 files changed, 2874 insertions(+), 63 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/pom.xml
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/pom.xml b/jena-fuseki2/jena-fuseki-access/pom.xml
new file mode 100644
index 0000000..867a956
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/pom.xml
@@ -0,0 +1,104 @@
+<?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 Data Access Control</name>
+ <artifactId>jena-fuseki-access</artifactId>
+
+ <parent>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>jena-fuseki</artifactId>
+ <version>3.9.0-SNAPSHOT</version>
+ </parent>
+
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>jena-fuseki-embedded</artifactId>
+ <version>3.9.0-SNAPSHOT</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar-no-fork</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>attach-sources-test</id>
+ <goals>
+ <goal>test-jar-no-fork</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>**/TS_*.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <configuration>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ </configuration>
+ </plugin>
+
+ </plugins>
+
+ </build>
+
+</project>
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerAccessDataset.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerAccessDataset.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerAccessDataset.java
new file mode 100644
index 0000000..75cb155
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerAccessDataset.java
@@ -0,0 +1,63 @@
+/*
+ * 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.access;
+
+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.RDFNode;
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.util.graph.GraphUtils;
+
+public class AssemblerAccessDataset extends AssemblerBase {
+
+ /*
+ * <#access_dataset> rdf:type access:AccessControlledDataset ;
+ * access:registry <#securityRegistry> ;
+ * access:dataset <#tdb_dataset_read> ;
+ * .
+ */
+ @Override
+ public Dataset open(Assembler a, Resource root, Mode mode) {
+ if ( ! GraphUtils.exactlyOneProperty(root, VocabSecurity.pSecurityRegistry) )
+ throw new AssemblerException(root, "Expected exactly one access:registry property");
+ if ( ! GraphUtils.exactlyOneProperty(root, VocabSecurity.pDataset) )
+ throw new AssemblerException(root, "Expected exactly one access:dataset property");
+
+ RDFNode rnRegistry = root.getProperty(VocabSecurity.pSecurityRegistry).getObject();
+ RDFNode rnDataset = root.getProperty(VocabSecurity.pDataset).getObject();
+
+ SecurityRegistry sr = (SecurityRegistry)a.open(rnRegistry.asResource()) ;
+ Dataset ds = (Dataset)a.open(rnDataset.asResource()) ;
+
+ DatasetGraph dsg = new DatasetGraphAccessControl(ds.asDatasetGraph(), sr);
+ ds = DatasetFactory.wrap(dsg);
+
+// // Add marker
+// ds.getContext().set(DataAccessCtl.symControlledAccess, true);
+// // Add security registry
+// ds.getContext().set(DataAccessCtl.symSecurityRegistry, sr);
+ return ds;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java
new file mode 100644
index 0000000..1e8a3e4
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java
@@ -0,0 +1,130 @@
+/*
+ * 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.access;
+
+import java.util.List;
+
+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.ext.com.google.common.collect.ArrayListMultimap;
+import org.apache.jena.ext.com.google.common.collect.Multimap;
+import org.apache.jena.graph.Node;
+import org.apache.jena.rdf.model.RDFList;
+import org.apache.jena.rdf.model.RDFNode;
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.rdf.model.StmtIterator;
+import org.apache.jena.rdf.model.impl.Util;
+import org.apache.jena.sparql.util.graph.GNode;
+import org.apache.jena.sparql.util.graph.GraphList;
+import org.apache.jena.sparql.util.graph.GraphUtils;
+
+public class AssemblerSecurityRegistry extends AssemblerBase {
+
+ /**
+ * SecurityRegistry.
+ * Builds a SecurityRegistry - a map fron user name to
+ *
+ * <#securityRegistry> rdf:type access:SecurityRegistry ;
+ * access:entry ("user1" <http://host/graphname1> <http://host/graphname2> ) ;) ;
+ * access:entry ("user1" <http://host/graphname3> ) ;
+ * access:entry ("user2" <http://host/graphname3> ) ;
+ * .
+ *
+ * access:entry [ :user "user2" ; :graphs (<http://host/graphname3> ) ] ;
+ */
+
+ @Override
+ public SecurityRegistry open(Assembler a, Resource root, Mode mode) {
+ SecurityRegistry registry = new SecurityRegistry();
+ // Java walking gives better error messages.
+ StmtIterator sIter = root.listProperties(VocabSecurity.pEntry);
+ if ( ! sIter.hasNext() )
+ throw new AssemblerException(root, "No access entries");
+ Multimap<String, Node> map = ArrayListMultimap.create();
+
+ sIter.forEachRemaining(s->{
+ RDFNode n = s.getObject();
+ if ( ! n.isResource())
+ throw new AssemblerException(root, "Found access:entry with non-resource");
+ Resource r = (Resource)n;
+ GNode entry = new GNode(root.getModel().getGraph(), n.asNode());
+ if ( GraphList.isListNode(entry) ) {
+ // Format:: access:entry ("user1" <http://host/graphname1> <http://host/graphname2> ) ;
+ parseList(map, root, entry);
+ } else if ( r.hasProperty(VocabSecurity.pUser) || r.hasProperty(VocabSecurity.pGraphs) ) {
+ // Format:: access:entry [ :user "user2" ; :graphs (<http://host/graphname3> ) ]
+ parseStruct(map, root, r);
+ } else
+ throw new AssemblerException(root, "Found access:entry but failed to parse the object: "+s.getSubject());
+ });
+
+ map.keySet().forEach(u->{
+ SecurityPolicy policy = new SecurityPolicy(map.get(u));
+ registry.put(u, policy);
+ });
+
+ return registry;
+ }
+
+ /**Format:: access:entry ("user1" <http://host/graphname1> <http://host/graphname2> ) ; */
+ private void parseList(Multimap<String, Node> map, Resource root, GNode entry) {
+ List<Node> members = GraphList.members(entry);
+ // string, then URIs.
+ if ( members.isEmpty() )
+ throw new AssemblerException(root, "Found access:entry with an empty list");
+ Node userNode = members.get(0);
+ if ( ! Util.isSimpleString(userNode) ) {}
+ String user = userNode.getLiteralLexicalForm();
+ for ( int i = 1 ; i < members.size() ; i++ ) {
+ Node gn = members.get(i);
+ //if ( gn.isBlank() )
+ if ( ! gn.isURI() ) { }
+ //System.out.printf("L: user %s : access : %s\n", user, gn);
+ map.put(user, gn);
+ }
+ }
+
+ /** Format:: access:entry [ :user "user2" ; :graphs (<http://host/graphname3> ) ] */
+ private void parseStruct(Multimap<String, Node> map, Resource root, Resource r) {
+ if ( ! GraphUtils.exactlyOneProperty(r, VocabSecurity.pUser) )
+ throw new AssemblerException(root, "Expected exactly one access:user property for "+r);
+ if ( ! GraphUtils.exactlyOneProperty(r, VocabSecurity.pGraphs) )
+ throw new AssemblerException(root, "Expected exactly one access:graphs property for "+r);
+
+ String user = GraphUtils.getStringValue(r, VocabSecurity.pUser);
+ r.listProperties(VocabSecurity.pGraphs).mapWith(s->s.getObject()).forEachRemaining(x->{
+ if ( x.isURIResource() ) {
+ //System.out.printf("S: user %s : access : %s\n", user, x.asNode());
+ map.put(user, x.asNode());
+ } else {
+ // List?
+ RDFList list = x.as(RDFList.class);
+ list.iterator().forEachRemaining(rn->{
+ if ( ! rn.isURIResource() )
+ throw new AssemblerException(root, "Not a graph name: "+rn);
+ //System.out.printf("S: user %s : access : %s\n", user, rn.asNode());
+ map.put(user, rn.asNode());
+ });
+ }
+ });
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
new file mode 100644
index 0000000..85b1f31
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
@@ -0,0 +1,179 @@
+/*
+ * 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.access;
+
+import java.util.function.Function;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.jena.fuseki.embedded.FusekiServer;
+import org.apache.jena.fuseki.server.Operation;
+import org.apache.jena.fuseki.servlets.ActionService;
+import org.apache.jena.fuseki.servlets.HttpAction;
+import org.apache.jena.fuseki.servlets.ServiceDispatchRegistry;
+import org.apache.jena.query.Dataset;
+import org.apache.jena.query.DatasetFactory;
+import org.apache.jena.riot.WebContent;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.util.Context;
+import org.apache.jena.sparql.util.Symbol;
+import org.eclipse.jetty.security.SecurityHandler;
+
+/** A library of operations related to data acess sexurity for Fuseki */
+public class DataAccessCtl {
+
+ /**
+ * Flag for whether this is data access controlled or not - boolean false or undef for "not
+ * controlled".
+ */
+ public static final Symbol symControlledAccess = Symbol.create(VocabSecurity.getURI() + "controlled");
+
+ /**
+ * Symbol for the {@link SecurityRegistry}. Must be present if
+ * {@link #symControlledAccess} indicates data access control.
+ */
+ public static final Symbol symSecurityRegistry = Symbol.create(VocabSecurity.getURI() + "registry");
+
+ /** Get the user from the servlet context via {@link HttpServletRequest#getRemoteUser} */
+ public static final Function<HttpAction, String> requestUserServlet = (action)->action.request.getRemoteUser();
+
+// /** Build a fuseki server with controlled access enabled. */
+// public static FusekiServer controlledFuseki(int port, Function<HttpAction, String> determineUser, Consumer<FusekiServer.Builder> configure) {
+// FusekiServer.Builder b = controlledFuseki(port, determineUser);
+// configure.accept(b);
+// return b.build();
+// }
+//
+// /** Builder for a read-only Fuseki server with controlled access actions enabled. */
+// public static FusekiServer.Builder controlledFuseki(int port, Function<HttpAction, String> determineUser) {
+// ServiceDispatchRegistry sdr = new ServiceDispatchRegistry(false);
+// ActionService actionQuery = new Filtered_SPARQL_QueryDataset(determineUser);
+// ActionService actionGspR = new Filtered_SPARQL_GSP_R(determineUser);
+// ActionService actionQuadsR = new Filtered_REST_Quads_R(determineUser);
+//
+// // Create empty and only add "read" operations.
+// FusekiServer.Builder builder = FusekiServer.create(sdr)
+// .port(port)
+// .registerOperation(Operation.Query, WebContent.contentTypeSPARQLQuery, actionQuery)
+// .registerOperation(Operation.GSP_R, actionGspR)
+// .registerOperation(Operation.Quads_R, actionQuadsR);
+// return builder;
+// }
+
+ /**
+ * Enable data access control on a {@link DatasetGraph}. This modifies the
+ * {@link DatasetGraph}'s {@link Context}.
+ */
+ public static void controlledDataset(DatasetGraph dsg, SecurityRegistry reg) {
+ // Or wrapper.
+ dsg.getContext().set(symControlledAccess, true);
+ dsg.getContext().set(symSecurityRegistry, reg);
+ }
+
+ /**
+ * Enable data access control on a {@link Dataset}. This modifies the
+ * {@link Dataset}'s {@link Context}.
+ */
+ public static void controlledDataset(Dataset ds, SecurityRegistry reg) {
+ ds.getContext().set(symControlledAccess, true);
+ ds.getContext().set(symSecurityRegistry, reg);
+ }
+
+ /**
+ * Return a {@link DatasetGraph} with added data access control. Use of the original
+ * {@code DatasetGraph} is not controlled.
+ */
+ public static Dataset wrapControlledDataset(Dataset dsBase, SecurityRegistry reg) {
+ DatasetGraph dsg = wrapControlledDataset(dsBase.asDatasetGraph(), reg);
+ return DatasetFactory.wrap(dsg);
+ }
+
+ /**
+ * Return a {@link DatasetGraph} with added data access control. Use of the original
+ * {@code DatasetGraph} is not controlled.
+ */
+ public static DatasetGraph wrapControlledDataset(DatasetGraph dsgBase, SecurityRegistry reg) {
+ if ( dsgBase instanceof DatasetGraphAccessControl ) {
+ DatasetGraphAccessControl dsgx = (DatasetGraphAccessControl)dsgBase;
+ if ( reg == dsgx.getRegistry() )
+ return dsgx;
+ throw new IllegalArgumentException("DatasetGraph is alerady wrapped on a DatasetGraphAccessControl with a different SecurityRegistry");
+ }
+
+ DatasetGraphAccessControl dsg1 = new DatasetGraphAccessControl(dsgBase, reg);
+ return dsg1;
+ }
+
+ /**
+ * Return a {@code FusekiServer.Builder} setup for data access control
+ * but with no Jetty security handler.
+ */
+ public static FusekiServer.Builder fusekiBuilder(Function<HttpAction, String> determineUser) {
+ return fusekiBuilder(null, determineUser);
+ }
+
+ /**
+ * Return a {@code FusekiServer.Builder} setup for data access control and with a
+ * Jetty security handler.
+ */
+ public static FusekiServer.Builder fusekiBuilder(SecurityHandler securityHandler, Function<HttpAction, String> determineUser) {
+ FusekiServer.Builder builder = FusekiServer.create();
+ if ( securityHandler != null )
+ builder.securityHandler(securityHandler);
+ // Replace the standard operations with the SecurityRegistry processing ones.
+ builder.registerOperation(Operation.Query, WebContent.contentTypeSPARQLQuery, new Filtered_SPARQL_QueryDataset(determineUser));
+ builder.registerOperation(Operation.GSP_R, new Filtered_SPARQL_GSP_R(determineUser));
+ builder.registerOperation(Operation.Quads_R, new Filtered_REST_Quads_R(determineUser));
+ return builder;
+ }
+
+ /**
+ * Modify in-place an existing {@link FusekiServer} so that the read-operations for
+ * query/GSP/Quads go to the data-filtering versions of the {@link ActionService ActionServices}.
+ * (It is better to create the server via {@link #DataAccessCtl.builder} first rather than modify afterwards.)
+ */
+ public static void enable(FusekiServer server, Function<HttpAction, String> determineUser) {
+ /*
+ * Reconfigure standard Jena Fuseki, replacing the default implementation of "query"
+ * with a filtering one. This for this server only.
+ */
+ // The mapping operation to handler is in the ServiceDispatchRegistry and is per
+ // server (per servlet context). "registerOrReplace" would be a better name,
+ ActionService queryServletAccessFilter = new Filtered_SPARQL_QueryDataset(determineUser);
+ ServletContext cxt = server.getServletContext();
+ ServiceDispatchRegistry.get(cxt).register(Operation.Query, WebContent.contentTypeSPARQLQuery, queryServletAccessFilter);
+ ServiceDispatchRegistry.get(cxt).register(Operation.GSP_R, null, new Filtered_SPARQL_GSP_R(determineUser));
+ ServiceDispatchRegistry.get(cxt).register(Operation.Quads_R, null, new Filtered_REST_Quads_R(determineUser));
+ }
+
+ /**
+ * Return whether a {@code DatasetGraph} has access control, either because it is wrapped in
+ * {@link DatasetGraphAccessControl} or because it has the context settings.
+ */
+ public static boolean isAccessControlled(DatasetGraph dsg) {
+ if ( dsg instanceof DatasetGraphAccessControl )
+ return true;
+ if ( dsg.getContext().isDefined(DataAccessCtl.symControlledAccess) )
+ return true;
+ if ( dsg.getContext().isDefined(DataAccessCtl.symSecurityRegistry) )
+ return true;
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java
new file mode 100644
index 0000000..4329cc6
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java
@@ -0,0 +1,58 @@
+/*
+ * 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.access;
+
+import java.util.function.Function;
+
+import org.apache.jena.fuseki.servlets.HttpAction;
+import org.apache.jena.fuseki.servlets.ServletOps;
+import org.apache.jena.sparql.core.DatasetGraph;
+
+/** Package-only operations */
+class DataAccessLib {
+
+ /** Determine the {@link SecurityPolicy} for this request */
+ static SecurityPolicy getSecurityPolicy(HttpAction action, DatasetGraph dataset, Function<HttpAction, String> requestUser) {
+ SecurityRegistry registry = getSecurityRegistry(action, dataset);
+ if ( registry == null )
+ ServletOps.errorOccurred("Internal Server Error");
+
+ SecurityPolicy sCxt = null;
+ String user = requestUser.apply(action);
+ sCxt = registry.get(user);
+ if ( sCxt == null )
+ sCxt = noSecurityPolicy();
+ return sCxt;
+ }
+
+
+ /** Get the {@link SecurityRegistry} for an action/query/dataset */
+ static SecurityRegistry getSecurityRegistry(HttpAction action, DatasetGraph dsg) {
+ if ( dsg instanceof DatasetGraphAccessControl )
+ return ((DatasetGraphAccessControl)dsg).getRegistry();
+ return dsg.getContext().get(DataAccessCtl.symSecurityRegistry);
+ }
+
+ static SecurityPolicy noSecurityPolicy() {
+ ServletOps.errorForbidden();
+ // Should not get here.
+ throw new InternalError();
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphAccessControl.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphAccessControl.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphAccessControl.java
new file mode 100644
index 0000000..d770ade
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphAccessControl.java
@@ -0,0 +1,49 @@
+/*
+ * 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.access;
+
+import java.util.Objects;
+
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.DatasetGraphWrapper;
+
+/** DatasetGraph layer that carries a SecurityRegistry. */
+class DatasetGraphAccessControl extends DatasetGraphWrapper {
+
+ private SecurityRegistry registry = null;
+
+ public DatasetGraphAccessControl(DatasetGraph dsg, SecurityRegistry registry) {
+ super(Objects.requireNonNull(dsg));
+ this.registry = Objects.requireNonNull(registry);
+ }
+
+ public SecurityRegistry getRegistry() {
+ return registry;
+ }
+
+ /**
+ * Return the underlying {@code DatasetGraph}. If the argument is not a
+ * {@code DatasetGraphAccessControl}, return the argument.
+ */
+ public static DatasetGraph unwrap(DatasetGraph dsg) {
+ if ( ! ( dsg instanceof DatasetGraphAccessControl ) )
+ return dsg;
+ return ((DatasetGraphAccessControl)dsg).getWrapped();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_R.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_R.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_R.java
new file mode 100644
index 0000000..d698ecb
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_R.java
@@ -0,0 +1,51 @@
+/*
+ * 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.access;
+
+import java.util.function.Function;
+
+import org.apache.jena.fuseki.servlets.HttpAction;
+import org.apache.jena.fuseki.servlets.REST_Quads_R;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.DatasetGraphWrapper;
+import org.apache.jena.sparql.util.Context;
+
+public class Filtered_REST_Quads_R extends REST_Quads_R {
+ public Filtered_REST_Quads_R(Function<HttpAction, String> determineUser) {}
+
+ @Override
+ protected void validate(HttpAction action) {
+ super.validate(action);
+ }
+
+ @Override
+ protected void doGet(HttpAction action) {
+
+ DatasetGraph dsg0 = action.getActiveDSG();
+ DatasetGraph dsg = new DatasetGraphWrapper(dsg0) {
+ @Override public Context getContext() { return super.getContext(); }
+ };
+ // Replace datasetGraph
+ // XXX Implement access control for REST_Quads_R
+
+ HttpAction action2 = action;
+
+ super.doGet(action2);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_R.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_R.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_R.java
new file mode 100644
index 0000000..1eae1d1
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_R.java
@@ -0,0 +1,65 @@
+/*
+ * 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.access;
+
+import java.util.function.Function;
+
+import org.apache.jena.fuseki.servlets.HttpAction;
+import org.apache.jena.fuseki.servlets.SPARQL_GSP_R;
+import org.apache.jena.sparql.util.Context;
+
+public class Filtered_SPARQL_GSP_R extends SPARQL_GSP_R {
+
+ private final Function<HttpAction, String> requestUser;
+
+ public Filtered_SPARQL_GSP_R(Function<HttpAction, String> determineUser) {
+ this.requestUser = determineUser;
+ }
+
+ @Override
+ protected void doGet(HttpAction action) {
+ // For this, mask on target.
+
+ // Avoid doing twice?
+ Target target = determineTarget(action);
+
+// Node gn = target.graphName;
+// boolean dftGraph = target.isDefault;
+ // Yes/no based on graph.
+
+ // 1:: DatsetGraphWrapper and modify action.activeDGS;
+ // 2:: action.getContext().set(...
+
+
+ DataAccessLib.getSecurityPolicy(action, action.getActiveDSG(), requestUser);
+
+ Context context = action.getActiveDSG().getContext();
+ //action.getContext(); // Is this the DGS? No. copied.
+ action.getContext().set(DataAccessCtl.symControlledAccess, true);
+ // XXX Implement access control for GSP_R
+ SecurityRegistry securityRegistry = null;
+ String user = requestUser.apply(action);
+
+
+
+ action.getContext().set(DataAccessCtl.symSecurityRegistry, securityRegistry);
+ super.doGet(action);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
new file mode 100644
index 0000000..cc260f2
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
@@ -0,0 +1,64 @@
+/*
+ * 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.access;
+
+import java.util.function.Function;
+
+import org.apache.jena.fuseki.servlets.ActionService;
+import org.apache.jena.fuseki.servlets.HttpAction;
+import org.apache.jena.fuseki.servlets.SPARQL_QueryDataset;
+import org.apache.jena.query.Dataset;
+import org.apache.jena.query.DatasetFactory;
+import org.apache.jena.query.Query;
+import org.apache.jena.query.QueryExecution;
+import org.apache.jena.sparql.core.DatasetGraph;
+
+/** A Query {@link ActionService} that inserts a security filter on each query. */
+final
+public class Filtered_SPARQL_QueryDataset extends SPARQL_QueryDataset {
+ private final Function<HttpAction, String> requestUser;
+
+ public Filtered_SPARQL_QueryDataset(Function<HttpAction, String> requestUser) {
+ this.requestUser = requestUser;
+ }
+
+ @Override
+ protected QueryExecution createQueryExecution(HttpAction action, Query query, Dataset dataset) {
+ // Server database, not the possibly dynamically built "dataset"
+ DatasetGraph dsg = action.getDataset();
+ if ( dsg == null )
+ return super.createQueryExecution(action, query, dataset);
+ if ( ! DataAccessCtl.isAccessControlled(dsg) )
+ return super.createQueryExecution(action, query, dataset);
+
+ SecurityPolicy sCxt = DataAccessLib.getSecurityPolicy(action, dataset.asDatasetGraph(), requestUser);
+ if ( dsg instanceof DatasetGraphAccessControl ) {
+ // Take off one layer.
+ dsg = DatasetGraphAccessControl.unwrap(dsg);
+ // Add back the Dataset for the createQueryExecution call.
+ dataset = DatasetFactory.wrap(dsg);
+ }
+
+ QueryExecution qExec = super.createQueryExecution(action, query, dataset);
+ if ( sCxt != null )
+ sCxt.filterTDB(dsg, qExec);
+ return qExec;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilter.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilter.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilter.java
new file mode 100644
index 0000000..33283d6
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilter.java
@@ -0,0 +1,76 @@
+/*
+ * 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.access;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.function.Predicate;
+
+import org.apache.jena.atlas.lib.tuple.Tuple;
+import org.apache.jena.sparql.util.Symbol;
+
+/**
+ * A graph filter for TDB1 and TDB2 (by generic type).
+ * <p>
+ * This filter takes a collection of graph names and returns true from
+ * {@link #test(Tuple)} if the tuple graph slot is in the collection of graph names or
+ * matchDefaultGraph is true. It can be used as an "allow" filter; it can be negated to
+ * become a "deny" filter.
+ *
+ * @see GraphFilterTDB1#graphFilter
+ * @see GraphFilterTDB2#graphFilter
+ */
+public abstract class GraphFilter<X> implements Predicate<Tuple<X>> {
+ private final Set<X> graphs;
+ private final boolean matchDefaultGraph;
+// // This makes the GraphFilter stateful.
+// private X slot = null;
+
+ protected GraphFilter(Collection<X> matches, boolean matchDefaultGraph) {
+ this.graphs = new HashSet<X>(matches);
+ this.matchDefaultGraph = matchDefaultGraph;
+ }
+
+ public abstract Symbol getContextKey();
+
+ @Override
+ public boolean test(Tuple<X> t) {
+ if ( t.len() == 3 ) {
+ // Default graph.
+ return matchDefaultGraph;
+ }
+ X g = t.get(0);
+ boolean b = perGraphTest(g);
+ return b;
+ }
+
+ // The per graph test.
+ private boolean perGraphTest(X g) {
+ return graphs.contains(g);
+// if ( g == slot ) {
+// System.err.println("Slot hit");
+// return true;
+// }
+// boolean b = matches.contains(g);
+// if ( b )
+// slot = g ;
+// return b;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB1.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB1.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB1.java
new file mode 100644
index 0000000..d15c57b
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB1.java
@@ -0,0 +1,70 @@
+/*
+ * 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.access;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.jena.atlas.lib.ListUtils;
+import org.apache.jena.graph.Node;
+import org.apache.jena.query.QueryExecution;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.util.Symbol;
+import org.apache.jena.system.Txn;
+import org.apache.jena.tdb.store.NodeId;
+import org.apache.jena.tdb.store.nodetable.NodeTable;
+import org.apache.jena.tdb.sys.SystemTDB;
+import org.apache.jena.tdb.sys.TDBInternal;
+
+/** {@link GraphFilter} for TDB1 */
+class GraphFilterTDB1 extends GraphFilter<NodeId> {
+
+ private GraphFilterTDB1(Collection<NodeId> matches, boolean matchDefaultGraph) {
+ super(matches, matchDefaultGraph);
+ }
+
+ @Override
+ public Symbol getContextKey() {
+ return SystemTDB.symTupleFilter;
+ }
+
+ /**
+ * Create a graph filter for a TDB1 {@link DatasetGraph}. The filter matches (returns
+ * true) for Tuples where the graph slot in quad is in the collection or for triples in the default
+ * graph according the boolean.
+ *
+ * @see SecurityPolicy#filterTDB(DatasetGraph, QueryExecution)
+ */
+ public static GraphFilterTDB1 graphFilter(DatasetGraph dsg, Collection<Node> namedGraphs, boolean matchDefaultGraph) {
+ if ( ! TDBInternal.isTDB1(dsg) )
+ throw new IllegalArgumentException("DatasetGraph is not TDB1-backed");
+ List<NodeId> x =
+ Txn.calculateRead(dsg, ()->{
+ NodeTable nt = TDBInternal.getDatasetGraphTDB(dsg).getQuadTable().getNodeTupleTable().getNodeTable();
+ return
+ ListUtils.toList(
+ namedGraphs.stream()
+ .map(n->nt.getNodeIdForNode(n))
+ .filter(Objects::nonNull)
+ );
+ });
+ return new GraphFilterTDB1(x, matchDefaultGraph);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB2.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB2.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB2.java
new file mode 100644
index 0000000..cf95244
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB2.java
@@ -0,0 +1,70 @@
+/*
+ * 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.access;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.jena.atlas.lib.ListUtils;
+import org.apache.jena.graph.Node;
+import org.apache.jena.query.QueryExecution;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.util.Symbol;
+import org.apache.jena.system.Txn;
+import org.apache.jena.tdb2.store.NodeId;
+import org.apache.jena.tdb2.store.nodetable.NodeTable;
+import org.apache.jena.tdb2.sys.SystemTDB;
+import org.apache.jena.tdb2.sys.TDBInternal;
+
+/** {@link GraphFilter} for TDB2 */
+class GraphFilterTDB2 extends GraphFilter<NodeId> {
+
+ private GraphFilterTDB2(Collection<NodeId> matches, boolean matchDefaultGraph) {
+ super(matches, matchDefaultGraph);
+ }
+
+ @Override
+ public Symbol getContextKey() {
+ return SystemTDB.symTupleFilter;
+ }
+
+ /**
+ * Create a graph filter for a TDB2 {@link DatasetGraph}. The filter matches (returns
+ * true) for Tuples where the graph slot in quad is in the collection or for triples in the default
+ * graph according the boolean.
+ *
+ * @see SecurityPolicy#filterTDB(DatasetGraph, QueryExecution)
+ */
+ public static GraphFilterTDB2 graphFilter(DatasetGraph dsg, Collection<Node> namedGraphs, boolean matchDefaultGraph) {
+ if ( ! TDBInternal.isTDB2(dsg) )
+ throw new IllegalArgumentException("DatasetGraph is not TDB2-backed");
+ List<NodeId> x =
+ Txn.calculateRead(dsg, ()->{
+ NodeTable nt = TDBInternal.getDatasetGraphTDB(dsg).getQuadTable().getNodeTupleTable().getNodeTable();
+ return
+ ListUtils.toList(
+ namedGraphs.stream()
+ .map(n->nt.getNodeIdForNode(n))
+ .filter(Objects::nonNull)
+ );
+ });
+ return new GraphFilterTDB2(x, matchDefaultGraph);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/InitSecurity.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/InitSecurity.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/InitSecurity.java
new file mode 100644
index 0000000..55e760e
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/InitSecurity.java
@@ -0,0 +1,38 @@
+/*
+ * 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.access;
+
+import org.apache.jena.sys.JenaSubsystemLifecycle;
+import org.apache.jena.sys.JenaSystem;
+
+public class InitSecurity implements JenaSubsystemLifecycle {
+
+ @Override
+ public void start() {
+ JenaSystem.logLifecycle("InitSecurity - start") ;
+ VocabSecurity.init();
+ JenaSystem.logLifecycle("InitSecurity - finish") ;
+ }
+
+ @Override
+ public void stop() {}
+
+ @Override
+ public int level() { return 100; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
new file mode 100644
index 0000000..808e980
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
@@ -0,0 +1,116 @@
+/*
+ * 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.access;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Predicate;
+
+import org.apache.jena.graph.Node;
+import org.apache.jena.query.QueryExecution;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.Quad;
+import org.apache.jena.sparql.util.Context;
+import org.apache.jena.sparql.util.NodeUtils;
+import org.apache.jena.tdb.TDBFactory;
+import org.apache.jena.tdb2.DatabaseMgr;
+
+/** A {@link SecurityPolicy} is the things actor (user, role) is allowed to do.
+ * Currently version: the set of graphs, by graph name, they can access.
+ * It can be inverted into a "deny" policy with {@link Predicate#negate()}.
+ */
+public class SecurityPolicy {
+
+ public static SecurityPolicy NONE = new SecurityPolicy();
+ public static SecurityPolicy DFT_GRAPH = new SecurityPolicy(true);
+
+ private final Collection<Node> graphNames = ConcurrentHashMap.newKeySet();
+ private final boolean matchDefaultGraph;
+
+ public SecurityPolicy() {
+ this(false);
+ }
+
+ public SecurityPolicy(boolean matchDefaultGraph) {
+ this.matchDefaultGraph = matchDefaultGraph;
+ }
+
+ public SecurityPolicy(String...graphNames) {
+ this(NodeUtils.convertToSetNodes(graphNames));
+ }
+
+ public SecurityPolicy(Node...graphNames) {
+ this(Arrays.asList(graphNames));
+ }
+
+ public SecurityPolicy(Collection<Node> graphNames) {
+ this.graphNames.addAll(graphNames);
+ this.matchDefaultGraph = graphNames.stream().anyMatch(Quad::isDefaultGraph);
+ }
+
+ /**
+ * Apply a filter suitable for the TDB-backed {@link DatasetGraph}, to the {@link Context} of the
+ * {@link QueryExecution}. This does not modify the {@link DatasetGraph}
+ */
+ public void filterTDB(DatasetGraph dsg, QueryExecution qExec) {
+ GraphFilter<?> predicate = predicate(dsg);
+ qExec.getContext().set(predicate.getContextKey(), predicate);
+ }
+
+ /** Modify the {@link Context} of the TDB-backed {@link DatasetGraph}. */
+ public void filterTDB(DatasetGraph dsg) {
+ GraphFilter<?> predicate = predicate(dsg);
+ dsg.getContext().set(predicate.getContextKey(), predicate);
+ }
+
+ @Override
+ public String toString() {
+ return "dft:"+matchDefaultGraph+" / "+graphNames.toString();
+ }
+
+ /**
+ * Create a GraphFilter for a TDB backed dataset.
+ *
+ * @return GraphFilter
+ * @throws IllegalArgumentException
+ * if not a TDB database, or a {@link DatasetGraphAccessControl} wrapped
+ * TDB database.
+ */
+ public GraphFilter<?> predicate(DatasetGraph dsg) {
+ dsg = DatasetGraphAccessControl.unwrap(dsg);
+ // dsg has to be the database dataset, not wrapped.
+ // DatasetGraphSwitchable is wrapped but should not be unwrapped.
+ if ( TDBFactory.isTDB1(dsg) )
+ return filterTDB1(dsg);
+ if ( DatabaseMgr.isTDB2(dsg) )
+ return filterTDB2(dsg);
+ throw new IllegalArgumentException("Not a TDB1 or TDB2 database: "+dsg.getClass().getSimpleName());
+ }
+
+ public GraphFilterTDB2 filterTDB2(DatasetGraph dsg) {
+ GraphFilterTDB2 f = GraphFilterTDB2.graphFilter(dsg, graphNames, matchDefaultGraph);
+ return f;
+ }
+
+ public GraphFilterTDB1 filterTDB1(DatasetGraph dsg) {
+ GraphFilterTDB1 f = GraphFilterTDB1.graphFilter(dsg, graphNames, matchDefaultGraph);
+ return f;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java
new file mode 100644
index 0000000..1ad4098
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java
@@ -0,0 +1,72 @@
+/*
+ * 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.access;
+
+import java.util.StringJoiner;
+
+import javax.servlet.ServletContext;
+
+import org.apache.jena.atlas.lib.Registry;
+import org.apache.jena.fuseki.Fuseki;
+
+/**
+ * A {@link SecurityRegistry} is mapping from a string (typically a user name or role
+ * name) to a {@link SecurityPolicy}, where the {@link SecurityPolicy}
+ * is the access control operations for the user/role.
+ */
+public class SecurityRegistry extends Registry<String, SecurityPolicy>{
+
+ public static SecurityRegistry get(ServletContext cxt) {
+ return (SecurityRegistry)cxt.getAttribute(Fuseki.attrSecurityRegistry);
+ }
+
+ public static void set(ServletContext cxt, SecurityRegistry securityRegistry) {
+ cxt.setAttribute(Fuseki.attrSecurityRegistry, securityRegistry);
+ }
+
+ public SecurityRegistry() {}
+
+ @Override
+ public SecurityPolicy get(String actor) {
+ if ( actor == null )
+ return SecurityPolicy.NONE;
+ SecurityPolicy policy = super.get(actor);
+ if ( policy == null )
+ policy = SecurityPolicy.NONE;
+ return policy;
+ }
+
+ @Override
+ public String toString() {
+ if ( true )
+ return "SecurityRegistry"+keys();
+ // Long form.
+ StringJoiner sj1 = new StringJoiner("\n", "{ SecurityRegistry\n", "\n}");
+ super.keys().forEach(u->{
+ SecurityPolicy x = super.get(u);
+ StringJoiner sj2 = new StringJoiner("");
+ sj2.add(" ")
+ .add(u)
+ .add(" -> ")
+ .add(x.toString());
+ sj1.add(sj2.toString());
+ });
+ return sj1.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/VocabSecurity.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/VocabSecurity.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/VocabSecurity.java
new file mode 100644
index 0000000..14ed959
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/VocabSecurity.java
@@ -0,0 +1,55 @@
+/*
+ * 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.access;
+
+import org.apache.jena.rdf.model.Property;
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.sparql.core.assembler.AssemblerUtils;
+import org.apache.jena.tdb.assembler.Vocab;
+
+public class VocabSecurity {
+ private static final String NS = "http://jena.apache.org/access#";
+
+ public static String getURI() { return NS ; }
+
+ // Types
+ public static final Resource tAccessControlledDataset = Vocab.type(NS, "AccessControlledDataset");
+ public static final Resource tSecurityRegistry = Vocab.type(NS, "SecurityRegistry");
+
+ // Make subproperty of.
+ public static final Property pDataset = Vocab.property(NS, "dataset");
+ public static final Property pSecurityRegistry = Vocab.property(NS, "registry");
+
+ public static final Property pEntry = Vocab.property(NS, "entry");
+ public static final Property pUser = Vocab.property(NS, "user");
+ public static final Property pGraphs = Vocab.property(NS, "graphs");
+
+ private static boolean initialized = false ;
+
+ static { init() ; }
+
+ static synchronized public void init() {
+ if ( initialized )
+ return;
+ initialized = true;
+ // AssemblerUtils.subProperty
+ AssemblerUtils.registerDataset(tAccessControlledDataset, new AssemblerAccessDataset());
+ AssemblerUtils.registerModel(tSecurityRegistry, new AssemblerSecurityRegistry());
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/main/resources/META-INF/services/org.apache.jena.sys.JenaSubsystemLifecycle
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/resources/META-INF/services/org.apache.jena.sys.JenaSubsystemLifecycle b/jena-fuseki2/jena-fuseki-access/src/main/resources/META-INF/services/org.apache.jena.sys.JenaSubsystemLifecycle
new file mode 100644
index 0000000..e1699d2
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/resources/META-INF/services/org.apache.jena.sys.JenaSubsystemLifecycle
@@ -0,0 +1 @@
+org.apache.jena.fuseki.access.InitSecurity
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/GraphData.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/GraphData.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/GraphData.java
new file mode 100644
index 0000000..9712b71
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/GraphData.java
@@ -0,0 +1,59 @@
+/*
+ * 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.access;
+
+import org.apache.jena.atlas.lib.StrUtils;
+import org.apache.jena.graph.Node;
+import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.RDFParser;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.sse.SSE;
+import org.apache.jena.system.Txn;
+
+/** Build graph data for the filter/security tests. */
+
+class GraphData {
+ private static String dataStr = StrUtils.strjoinNL
+ ("PREFIX : <http://test/>"
+ ,""
+ ,":s0 :p 0 ."
+ ,":g1 { :s1 :p 1 }"
+ ,":g2 { :s2 :p 2 }"
+ ,":g3 { :s3 :p 3 }"
+ ,":g4 { :s4 :p 4 }"
+ );
+
+
+ static Node s0 = SSE.parseNode("<http://test/s0>");
+ static Node s1 = SSE.parseNode("<http://test/s1>");
+ static Node s2 = SSE.parseNode("<http://test/s2>");
+ static Node s3 = SSE.parseNode("<http://test/s3>");
+ static Node s4 = SSE.parseNode("<http://test/s4>");
+
+ static Node g1 = SSE.parseNode("<http://test/g1>");
+ static Node g2 = SSE.parseNode("<http://test/g2>");
+ static Node g3 = SSE.parseNode("<http://test/g3>");
+ static Node g4 = SSE.parseNode("<http://test/g4>");
+
+ public static void fill(DatasetGraph dsg) {
+ Txn.executeWrite(dsg, ()->{
+ RDFParser.create().fromString(dataStr).lang(Lang.TRIG).parse(dsg);
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java
new file mode 100644
index 0000000..35cb7ed
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java
@@ -0,0 +1,42 @@
+/*
+ * 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.access;
+
+import org.apache.jena.atlas.logging.LogCtl;
+import org.apache.jena.fuseki.Fuseki;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses( {
+ TestSecurityFilterLocal.class
+ , TestSecurityFilterFuseki.class
+ , TestSecurityAssembler.class
+})
+
+public class TS_SecurityFiltering {
+ @BeforeClass public static void setupForFusekiServer() {
+ LogCtl.setLevel(Fuseki.serverLogName, "WARN");
+ LogCtl.setLevel(Fuseki.actionLogName, "WARN");
+ LogCtl.setLevel(Fuseki.requestLogName, "WARN");
+ LogCtl.setLevel(Fuseki.adminLogName, "WARN");
+ LogCtl.setLevel("org.eclipse.jetty", "WARN");
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssembler.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssembler.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssembler.java
new file mode 100644
index 0000000..eefdcd7
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssembler.java
@@ -0,0 +1,193 @@
+/*
+ * 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.access;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.jena.atlas.iterator.Iter;
+import org.apache.jena.atlas.lib.StrUtils;
+import org.apache.jena.fuseki.FusekiLib;
+import org.apache.jena.fuseki.embedded.FusekiServer;
+import org.apache.jena.graph.Node;
+import org.apache.jena.query.Dataset;
+import org.apache.jena.query.QuerySolution;
+import org.apache.jena.query.ResultSetFormatter;
+import org.apache.jena.rdf.model.RDFNode;
+import org.apache.jena.rdfconnection.RDFConnection;
+import org.apache.jena.rdfconnection.RDFConnectionFactory;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.assembler.AssemblerUtils;
+import org.apache.jena.sparql.sse.SSE;
+import org.apache.jena.system.Txn;
+import org.junit.Test;
+
+/**
+ * Test on the assembler for data access control.
+ * <ul>
+ * <li>assem-security.ttl - two services "/database" and "/plain" each with their own dataset.
+ * <li>assem-security-shared.ttl - two services "/database" and "/plain" with a shared dataset.
+ * </ul>
+ */
+public class TestSecurityAssembler {
+ static final String DIR = "testing/Access/";
+
+ // Check the main test inputs.
+ @Test public void assembler1() {
+ Dataset ds = (Dataset)AssemblerUtils.build(DIR+"assem-security.ttl", VocabSecurity.tAccessControlledDataset);
+ }
+
+ @Test public void assembler2() {
+ Dataset ds = (Dataset)AssemblerUtils.build(DIR+"assem-security-shared.ttl", VocabSecurity.tAccessControlledDataset);
+ SecurityRegistry securityRegistry = ds.getContext().get(DataAccessCtl.symSecurityRegistry);
+ }
+
+ private static FusekiServer setup(String assembler, AtomicReference<String> user) {
+ int port = FusekiLib.choosePort();
+ FusekiServer server = DataAccessCtl.fusekiBuilder((a)->user.get())
+ .port(port)
+ .parseConfigFile(assembler)
+ .build();
+
+ return server;
+ }
+
+ // Two separate datasets
+ @Test public void assembler3() {
+ AtomicReference<String> user = new AtomicReference<>();
+ FusekiServer server = setup(DIR+"assem-security.ttl", user);
+ // Add data directly to the datasets.
+ DatasetGraph dsg = server.getDataAccessPointRegistry().get("/database").getDataService().getDataset();
+ //System.out.println(dsg.getContext());
+ Txn.executeWrite(dsg, ()->{
+ dsg.add(SSE.parseQuad("(<http://host/graphname1> :s1 :p :o)"));
+ dsg.add(SSE.parseQuad("(<http://host/graphname3> :s3 :p :o)"));
+ dsg.add(SSE.parseQuad("(<http://host/graphname9> :s9 :p :o)"));
+ });
+ server.start();
+ try {
+ testAssembler(server.getPort(), user);
+
+ // Access the uncontrolled dataset.
+ user.set(null);
+ String plainUrl = "http://localhost:"+server.getPort()+"/plain";
+ try(RDFConnection conn = RDFConnectionFactory.connect(plainUrl)) {
+ conn.update("INSERT DATA { <x:s> <x:p> 123 , 456 }");
+ conn.queryResultSet("SELECT * { ?s ?p ?o }",
+ rs->{
+ int x = ResultSetFormatter.consume(rs);
+ assertEquals(2, x);
+ });
+ }
+ } finally { server.stop(); }
+ }
+
+ // Shared dataset
+ @Test public void assembler4() {
+ AtomicReference<String> user = new AtomicReference<>();
+ FusekiServer server = setup(DIR+"assem-security-shared.ttl", user);
+
+ String x = StrUtils.strjoinNL
+ ("PREFIX : <http://example/>"
+ ,"INSERT DATA {"
+ ," GRAPH <http://host/graphname1> {:s1 :p :o}"
+ ," GRAPH <http://host/graphname3> {:s3 :p :o}"
+ ," GRAPH <http://host/graphname9> {:s9 :p :o}"
+ ,"}"
+ );
+
+ server.start();
+ try {
+ user.set(null);
+ String plainUrl = "http://localhost:"+server.getPort()+"/plain";
+ try(RDFConnection conn = RDFConnectionFactory.connect(plainUrl)) {
+ conn.update(x);
+ conn.queryResultSet("SELECT * { GRAPH ?g { ?s ?p ?o } }",
+ rs->{
+ int c = ResultSetFormatter.consume(rs);
+ assertEquals(3, c);
+ });
+ }
+ testAssembler(server.getPort(), user);
+ } finally { server.stop(); }
+ }
+
+ private void testAssembler(int port, AtomicReference<String> user) {
+ // The access controlled dataset.
+ String url = "http://localhost:"+port+"/database";
+
+ Node s1 = SSE.parseNode(":s1");
+ Node s3 = SSE.parseNode(":s3");
+ Node s9 = SSE.parseNode(":s9");
+
+ user.set("user1");
+ try(RDFConnection conn = RDFConnectionFactory.connect(url)) {
+ Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
+ assertSeen(visible, s1, s3);
+ }
+
+ user.set("userX"); // No such user in the registry
+ try(RDFConnection conn = RDFConnectionFactory.connect(url)) {
+ Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
+ assertSeen(visible);
+ }
+ user.set(null); // No user.
+ try(RDFConnection conn = RDFConnectionFactory.connect(url)) {
+ Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
+ assertSeen(visible);
+ }
+
+ user.set("user2");
+ try(RDFConnection conn = RDFConnectionFactory.connect(url)) {
+ Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
+ assertSeen(visible, s9);
+ }
+
+ user.set("userZ"); // No graphs with data.
+ try(RDFConnection conn = RDFConnectionFactory.connect(url)) {
+ Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
+ assertSeen(visible);
+ }
+
+ }
+
+ private static void assertSeen(Set<Node> visible, Node ... expected) {
+ Set<Node> expectedNodes = new HashSet<>(Arrays.asList(expected));
+ assertEquals(expectedNodes, visible);
+ }
+
+ private Set<Node> query(RDFConnection conn, String queryString) {
+ Set<Node> results = new HashSet<>();
+ conn.queryResultSet(queryString, rs->{
+ List<QuerySolution> list = Iter.toList(rs);
+ list.stream()
+ .map(qs->qs.get("s"))
+ .filter(Objects::nonNull)
+ .map(RDFNode::asNode)
+ .forEach(n->results.add(n));
+ });
+ return results;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/344ae5d8/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
new file mode 100644
index 0000000..4eb8dd4
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
@@ -0,0 +1,191 @@
+/*
+ * 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.access;
+
+import static org.apache.jena.fuseki.access.GraphData.s0;
+import static org.apache.jena.fuseki.access.GraphData.s1;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import org.apache.jena.atlas.iterator.Iter;
+import org.apache.jena.fuseki.FusekiLib;
+import org.apache.jena.fuseki.embedded.FusekiServer;
+import org.apache.jena.fuseki.jetty.JettyLib;
+import org.apache.jena.graph.Node;
+import org.apache.jena.query.QuerySolution;
+import org.apache.jena.rdf.model.RDFNode;
+import org.apache.jena.rdfconnection.RDFConnection;
+import org.apache.jena.rdfconnection.RDFConnectionFactory;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.Quad;
+import org.apache.jena.sparql.engine.http.QueryExceptionHTTP;
+import org.apache.jena.tdb.TDBFactory;
+import org.apache.jena.tdb2.DatabaseMgr;
+import org.eclipse.jetty.security.PropertyUserStore;
+import org.eclipse.jetty.security.SecurityHandler;
+import org.eclipse.jetty.security.UserStore;
+import org.eclipse.jetty.util.security.Credential;
+import org.eclipse.jetty.util.security.Password;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class TestSecurityFilterFuseki {
+
+ @Parameters(name = "{index}: {0}")
+ public static Iterable<Object[]> data() {
+ Object[] obj1 = { "TDB", "data1" };
+ Object[] obj2 = { "TDB2", "data2" };
+ return Arrays.asList(obj1, obj2);
+ }
+
+ private final String baseUrl;
+ private static final DatasetGraph testdsg1 = TDBFactory.createDatasetGraph();
+ private static final DatasetGraph testdsg2 = DatabaseMgr.createDatasetGraph();
+ private static FusekiServer fusekiServer;
+
+ // Set up Fuseki with two datasets, "data1" backed by TDB and "data2" backed by TDB2.
+ @BeforeClass public static void beforeClass() {
+ int port = FusekiLib.choosePort();
+ GraphData.fill(testdsg1);
+ GraphData.fill(testdsg2);
+
+ SecurityRegistry reg = new SecurityRegistry();
+ reg.put("userNone", SecurityPolicy.NONE);
+ reg.put("userDft", SecurityPolicy.DFT_GRAPH);
+ reg.put("user0", new SecurityPolicy(Quad.defaultGraphIRI.getURI()));
+ reg.put("user1", new SecurityPolicy("http://test/g1", Quad.defaultGraphIRI.getURI()));
+ reg.put("user2", new SecurityPolicy("http://test/g1", "http://test/g2", "http://test/g3"));
+
+ // XXXX Also need wrapped tests
+ DataAccessCtl.controlledDataset(testdsg1, reg);
+ DataAccessCtl.controlledDataset(testdsg2, reg);
+
+ UserStore userStore = userStore();
+ SecurityHandler sh = JettyLib.makeSecurityHandler("/*", "DatasetRealm", userStore);
+
+ fusekiServer = DataAccessCtl.fusekiBuilder(sh, DataAccessCtl.requestUserServlet)
+ .port(port)
+ .add("data1", testdsg1)
+ .add("data2", testdsg2)
+ .build();
+ fusekiServer.start();
+ }
+
+ @AfterClass public static void afterClass() {
+ fusekiServer.stop();
+ }
+
+ private static UserStore userStore() {
+ PropertyUserStore propertyUserStore = new PropertyUserStore();
+ String[] roles = new String[]{"**"};
+ addUserPassword(propertyUserStore, "user0", "pw0", roles);
+ addUserPassword(propertyUserStore, "user1", "pw1", roles);
+ addUserPassword(propertyUserStore, "user2", "pw2", roles);
+ return propertyUserStore;
+ }
+
+ private static void addUserPassword(PropertyUserStore propertyUserStore, String user, String password, String[] roles) {
+ Credential cred = new Password(password);
+ propertyUserStore.addUser(user, cred, roles);
+ }
+
+ public TestSecurityFilterFuseki(String label, String dsName) {
+ int port = fusekiServer.getPort();
+ baseUrl = "http://localhost:"+port+"/"+dsName;
+ }
+
+ private static void assertSeen(Set<Node> visible, Node ... expected) {
+ Set<Node> expectedNodes = new HashSet<>(Arrays.asList(expected));
+ assertEquals(expectedNodes, visible);
+ }
+
+ private static String queryAll = "SELECT * { { ?s ?p ?o } UNION { GRAPH ?g { ?s ?p ?o } } }";
+ private static String queryDft = "SELECT * { ?s ?p ?o }";
+ private static String queryNamed = "SELECT * { GRAPH ?g { ?s ?p ?o } }";
+
+ private static String queryG2 = "SELECT * { GRAPH <http://test/graph2> { ?s ?p ?o } }";
+ private static String queryGraphNames = "SELECT * { GRAPH ?g { } }";
+
+ private Set<Node> query(String user, String password, String queryString) {
+ Set<Node> results = new HashSet<>();
+ try (RDFConnection conn = RDFConnectionFactory.connectPW(baseUrl, user, password)) {
+ conn.queryResultSet(queryString, rs->{
+ List<QuerySolution> list = Iter.toList(rs);
+ list.stream()
+ .map(qs->qs.get("s"))
+ .filter(Objects::nonNull)
+ .map(RDFNode::asNode)
+ .forEach(n->results.add(n));
+ });
+ }
+ return results;
+ }
+
+ private void query401(String user, String password, String queryString) {
+ queryHttp(401, user, password, queryString);
+ }
+
+ private void query403(String user, String password, String queryString) {
+ queryHttp(403, user, password, queryString);
+ }
+
+ private void queryHttp(int statusCode, String user, String password, String queryString) {
+ try {
+ query(user, password, queryString);
+ if ( statusCode < 200 && statusCode > 299 )
+ fail("Should have responded with "+statusCode);
+ } catch (QueryExceptionHTTP ex) {
+ assertEquals(statusCode, ex.getResponseCode());
+ }
+ }
+
+ @Test public void query_user0() {
+ Set<Node> results = query("user0", "pw0", queryAll);
+ assertSeen(results, s0);
+ }
+
+ @Test public void query_user1() {
+ Set<Node> results = query("user1", "pw1", queryAll);
+ assertSeen(results, s0, s1);
+ }
+
+ @Test public void query_userX() {
+ query401("userX", "pwX", queryAll);
+ }
+
+ @Test public void query_bad_user() {
+ query401("userX", "pwX", queryAll);
+ }
+
+ @Test public void query_bad_password() {
+ query401("user0", "not-the-password", queryAll);
+ }
+
+}
[23/27] jena git commit: Rename SecuriyPolicy to SecurityContext
Posted by an...@apache.org.
Rename SecuriyPolicy to SecurityContext
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/5e000338
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/5e000338
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/5e000338
Branch: refs/heads/master
Commit: 5e0003389eddfd86f92ab22277c7cd2f7c4aad5f
Parents: 80a2f7b
Author: Andy Seaborne <an...@apache.org>
Authored: Mon Aug 27 12:14:59 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Mon Aug 27 12:14:59 2018 +0100
----------------------------------------------------------------------
.../access/AssemblerSecurityRegistry.java | 4 +-
.../jena/fuseki/access/DataAccessCtl.java | 4 +-
.../jena/fuseki/access/DataAccessLib.java | 10 +-
.../access/Filtered_SPARQL_QueryDataset.java | 2 +-
.../jena/fuseki/access/GraphFilterTDB1.java | 2 +-
.../jena/fuseki/access/GraphFilterTDB2.java | 2 +-
.../jena/fuseki/access/SecurityContext.java | 162 +++++++++++++++++++
.../jena/fuseki/access/SecurityPolicy.java | 162 -------------------
.../jena/fuseki/access/SecurityRegistry.java | 18 +--
.../fuseki/access/TestSecurityFilterFuseki.java | 10 +-
.../fuseki/access/TestSecurityFilterLocal.java | 38 ++---
11 files changed, 207 insertions(+), 207 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/5e000338/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java
index 1e8a3e4..dc66768 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java
@@ -77,8 +77,8 @@ public class AssemblerSecurityRegistry extends AssemblerBase {
});
map.keySet().forEach(u->{
- SecurityPolicy policy = new SecurityPolicy(map.get(u));
- registry.put(u, policy);
+ SecurityContext sCxt = new SecurityContext(map.get(u));
+ registry.put(u, sCxt);
});
return registry;
http://git-wip-us.apache.org/repos/asf/jena/blob/5e000338/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
index 3bc0812..f1bf7d3 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
@@ -155,9 +155,9 @@ public class DataAccessCtl {
}
/**
- * Return a read-only {@link DatasetGraphFilteredView} that fulfils the {@link SecurityPolicy}.
+ * Return a read-only {@link DatasetGraphFilteredView} that fulfils the {@link SecurityContext}.
*/
- public static DatasetGraphFilteredView filteredDataset(DatasetGraph dsg, SecurityPolicy sCxt) {
+ public static DatasetGraphFilteredView filteredDataset(DatasetGraph dsg, SecurityContext sCxt) {
return new DatasetGraphFilteredView(dsg, sCxt.predicateQuad(), sCxt.visibleGraphs());
}
}
http://git-wip-us.apache.org/repos/asf/jena/blob/5e000338/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java
index 127aa92..c9b98bf 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java
@@ -27,13 +27,13 @@ import org.apache.jena.sparql.core.DatasetGraph;
/** Package-only operations */
class DataAccessLib {
- /** Determine the {@link SecurityPolicy} for this request */
- static SecurityPolicy getSecurityPolicy(HttpAction action, DatasetGraph dataset, Function<HttpAction, String> requestUser) {
+ /** Determine the {@link SecurityContext} for this request */
+ static SecurityContext getSecurityContext(HttpAction action, DatasetGraph dataset, Function<HttpAction, String> requestUser) {
SecurityRegistry registry = getSecurityRegistry(action, dataset);
if ( registry == null )
ServletOps.errorOccurred("Internal Server Error");
- SecurityPolicy sCxt = null;
+ SecurityContext sCxt = null;
String user = requestUser.apply(action);
sCxt = registry.get(user);
if ( sCxt == null )
@@ -48,7 +48,7 @@ class DataAccessLib {
return dsg.getContext().get(DataAccessCtl.symSecurityRegistry);
}
- static SecurityPolicy noSecurityPolicy() {
+ static SecurityContext noSecurityPolicy() {
ServletOps.errorForbidden();
// Should not get here.
throw new InternalError();
@@ -61,7 +61,7 @@ class DataAccessLib {
if ( ! DataAccessCtl.isAccessControlled(dsg) )
// Not access controlled.
return dsg;//super.actOn(action);
- SecurityPolicy sCxt = DataAccessLib.getSecurityPolicy(action, dsg, requestUser);
+ SecurityContext sCxt = DataAccessLib.getSecurityContext(action, dsg, requestUser);
dsg = DatasetGraphAccessControl.removeWrapper(dsg);
dsg = DataAccessCtl.filteredDataset(dsg, sCxt);
return dsg;
http://git-wip-us.apache.org/repos/asf/jena/blob/5e000338/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
index 8162f91..06a5829 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
@@ -54,7 +54,7 @@ public class Filtered_SPARQL_QueryDataset extends SPARQL_QueryDataset {
if ( ! DataAccessCtl.isAccessControlled(dsg) )
return super.createQueryExecution(action, query, dataset);
- SecurityPolicy sCxt = DataAccessLib.getSecurityPolicy(action, dataset.asDatasetGraph(), requestUser);
+ SecurityContext sCxt = DataAccessLib.getSecurityContext(action, dataset.asDatasetGraph(), requestUser);
// A QueryExecution for controlled access
QueryExecution qExec = sCxt.createQueryExecution(query, dsg);
return qExec;
http://git-wip-us.apache.org/repos/asf/jena/blob/5e000338/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB1.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB1.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB1.java
index d15c57b..1d799aa 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB1.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB1.java
@@ -50,7 +50,7 @@ class GraphFilterTDB1 extends GraphFilter<NodeId> {
* true) for Tuples where the graph slot in quad is in the collection or for triples in the default
* graph according the boolean.
*
- * @see SecurityPolicy#filterTDB(DatasetGraph, QueryExecution)
+ * @see SecurityContext#filterTDB(DatasetGraph, QueryExecution)
*/
public static GraphFilterTDB1 graphFilter(DatasetGraph dsg, Collection<Node> namedGraphs, boolean matchDefaultGraph) {
if ( ! TDBInternal.isTDB1(dsg) )
http://git-wip-us.apache.org/repos/asf/jena/blob/5e000338/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB2.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB2.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB2.java
index cf95244..7c6b126 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB2.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/GraphFilterTDB2.java
@@ -50,7 +50,7 @@ class GraphFilterTDB2 extends GraphFilter<NodeId> {
* true) for Tuples where the graph slot in quad is in the collection or for triples in the default
* graph according the boolean.
*
- * @see SecurityPolicy#filterTDB(DatasetGraph, QueryExecution)
+ * @see SecurityContext#filterTDB(DatasetGraph, QueryExecution)
*/
public static GraphFilterTDB2 graphFilter(DatasetGraph dsg, Collection<Node> namedGraphs, boolean matchDefaultGraph) {
if ( ! TDBInternal.isTDB2(dsg) )
http://git-wip-us.apache.org/repos/asf/jena/blob/5e000338/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityContext.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityContext.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityContext.java
new file mode 100644
index 0000000..2ffaea0
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityContext.java
@@ -0,0 +1,162 @@
+/*
+ * 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.access;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Predicate;
+
+import org.apache.jena.graph.Node;
+import org.apache.jena.query.Query;
+import org.apache.jena.query.QueryExecution;
+import org.apache.jena.query.QueryExecutionFactory;
+import org.apache.jena.query.QueryFactory;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.Quad;
+import org.apache.jena.sparql.util.Context;
+import org.apache.jena.sparql.util.NodeUtils;
+import org.apache.jena.tdb.TDBFactory;
+import org.apache.jena.tdb2.DatabaseMgr;
+
+/** A {@link SecurityContext} is the things actor (user, role) is allowed to do.
+ * Currently version: the set of graphs, by graph name, they can access.
+ * It can be inverted into a "deny" policy with {@link Predicate#negate()}.
+ */
+public class SecurityContext {
+
+ public static SecurityContext NONE = new SecurityContext();
+ public static SecurityContext DFT_GRAPH = new SecurityContext(true);
+
+ private final Collection<Node> graphNames = ConcurrentHashMap.newKeySet();
+ private final boolean matchDefaultGraph;
+
+ public SecurityContext() {
+ this(false);
+ }
+
+ public SecurityContext(boolean matchDefaultGraph) {
+ this.matchDefaultGraph = matchDefaultGraph;
+ }
+
+ public SecurityContext(String...graphNames) {
+ this(NodeUtils.convertToSetNodes(graphNames));
+ }
+
+ public SecurityContext(Node...graphNames) {
+ this(Arrays.asList(graphNames));
+ }
+
+ public SecurityContext(Collection<Node> visibleGraphs) {
+ this.graphNames.addAll(visibleGraphs);
+ this.matchDefaultGraph = visibleGraphs.stream().anyMatch(Quad::isDefaultGraph);
+ if ( matchDefaultGraph ) {
+ this.graphNames.remove(Quad.defaultGraphIRI);
+ this.graphNames.remove(Quad.defaultGraphNodeGenerated);
+ }
+ }
+
+ public Collection<Node> visibleGraphs() {
+ return Collections.unmodifiableCollection(graphNames);
+ }
+
+ /**
+ * Apply a filter suitable for the TDB-backed {@link DatasetGraph}, to the {@link Context} of the
+ * {@link QueryExecution}. This does not modify the {@link DatasetGraph}
+ */
+ /*package*/ void filterTDB(DatasetGraph dsg, QueryExecution qExec) {
+ GraphFilter<?> predicate = predicate(dsg);
+ qExec.getContext().set(predicate.getContextKey(), predicate);
+ }
+
+ public QueryExecution createQueryExecution(String queryString, DatasetGraph dsg) {
+ return createQueryExecution(QueryFactory.create(queryString), dsg);
+ }
+
+ public QueryExecution createQueryExecution(Query query, DatasetGraph dsg) {
+ if ( ! ( dsg instanceof DatasetGraphAccessControl ) ) {
+ return QueryExecutionFactory.create(query, dsg);
+ }
+ if ( isAccessControlledTDB(dsg) ) {
+ QueryExecution qExec = QueryExecutionFactory.create(query, dsg);
+ filterTDB(dsg, qExec);
+ return qExec;
+ }
+
+ DatasetGraph dsgA = DataAccessCtl.filteredDataset(dsg, this);
+ return QueryExecutionFactory.create(query, dsgA);
+ }
+
+ @Override
+ public String toString() {
+ return "dft:"+matchDefaultGraph+" / "+graphNames.toString();
+ }
+
+ public Predicate<Quad> predicateQuad() {
+ return quad -> {
+ if ( quad.isDefaultGraph() )
+ return matchDefaultGraph;
+ if ( quad.isUnionGraph() )
+ // Union graph is automatically there but its visible contents are different.
+ return true;
+ return graphNames.contains(quad.getGraph());
+ };
+ }
+
+ /**
+ * Create a GraphFilter for a TDB backed dataset.
+ *
+ * @return GraphFilter
+ * @throws IllegalArgumentException
+ * if not a TDB database, or a {@link DatasetGraphAccessControl} wrapped
+ * TDB database.
+ */
+ public GraphFilter<?> predicate(DatasetGraph dsg) {
+ dsg = DatasetGraphAccessControl.removeWrapper(dsg);
+ // dsg has to be the database dataset, not wrapped.
+ // DatasetGraphSwitchable is wrapped but should not be unwrapped.
+ if ( TDBFactory.isTDB1(dsg) )
+ return filterTDB1(dsg);
+ if ( DatabaseMgr.isTDB2(dsg) )
+ return filterTDB2(dsg);
+ throw new IllegalArgumentException("Not a TDB1 or TDB2 database: "+dsg.getClass().getSimpleName());
+ }
+
+ public boolean isAccessControlledTDB(DatasetGraph dsg) {
+ DatasetGraph dsgBase = DatasetGraphAccessControl.unwrapOrNull(dsg);
+ if ( dsgBase == null )
+ return false;
+ if ( TDBFactory.isTDB1(dsgBase) )
+ return true;
+ if ( DatabaseMgr.isTDB2(dsgBase) )
+ return true;
+ return false;
+ }
+
+ public GraphFilterTDB2 filterTDB2(DatasetGraph dsg) {
+ GraphFilterTDB2 f = GraphFilterTDB2.graphFilter(dsg, graphNames, matchDefaultGraph);
+ return f;
+ }
+
+ public GraphFilterTDB1 filterTDB1(DatasetGraph dsg) {
+ GraphFilterTDB1 f = GraphFilterTDB1.graphFilter(dsg, graphNames, matchDefaultGraph);
+ return f;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/5e000338/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
deleted file mode 100644
index ca19794..0000000
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
+++ /dev/null
@@ -1,162 +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.access;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Predicate;
-
-import org.apache.jena.graph.Node;
-import org.apache.jena.query.Query;
-import org.apache.jena.query.QueryExecution;
-import org.apache.jena.query.QueryExecutionFactory;
-import org.apache.jena.query.QueryFactory;
-import org.apache.jena.sparql.core.DatasetGraph;
-import org.apache.jena.sparql.core.Quad;
-import org.apache.jena.sparql.util.Context;
-import org.apache.jena.sparql.util.NodeUtils;
-import org.apache.jena.tdb.TDBFactory;
-import org.apache.jena.tdb2.DatabaseMgr;
-
-/** A {@link SecurityPolicy} is the things actor (user, role) is allowed to do.
- * Currently version: the set of graphs, by graph name, they can access.
- * It can be inverted into a "deny" policy with {@link Predicate#negate()}.
- */
-public class SecurityPolicy {
-
- public static SecurityPolicy NONE = new SecurityPolicy();
- public static SecurityPolicy DFT_GRAPH = new SecurityPolicy(true);
-
- private final Collection<Node> graphNames = ConcurrentHashMap.newKeySet();
- private final boolean matchDefaultGraph;
-
- public SecurityPolicy() {
- this(false);
- }
-
- public SecurityPolicy(boolean matchDefaultGraph) {
- this.matchDefaultGraph = matchDefaultGraph;
- }
-
- public SecurityPolicy(String...graphNames) {
- this(NodeUtils.convertToSetNodes(graphNames));
- }
-
- public SecurityPolicy(Node...graphNames) {
- this(Arrays.asList(graphNames));
- }
-
- public SecurityPolicy(Collection<Node> visibleGraphs) {
- this.graphNames.addAll(visibleGraphs);
- this.matchDefaultGraph = visibleGraphs.stream().anyMatch(Quad::isDefaultGraph);
- if ( matchDefaultGraph ) {
- this.graphNames.remove(Quad.defaultGraphIRI);
- this.graphNames.remove(Quad.defaultGraphNodeGenerated);
- }
- }
-
- public Collection<Node> visibleGraphs() {
- return Collections.unmodifiableCollection(graphNames);
- }
-
- /**
- * Apply a filter suitable for the TDB-backed {@link DatasetGraph}, to the {@link Context} of the
- * {@link QueryExecution}. This does not modify the {@link DatasetGraph}
- */
- /*package*/ void filterTDB(DatasetGraph dsg, QueryExecution qExec) {
- GraphFilter<?> predicate = predicate(dsg);
- qExec.getContext().set(predicate.getContextKey(), predicate);
- }
-
- public QueryExecution createQueryExecution(String queryString, DatasetGraph dsg) {
- return createQueryExecution(QueryFactory.create(queryString), dsg);
- }
-
- public QueryExecution createQueryExecution(Query query, DatasetGraph dsg) {
- if ( ! ( dsg instanceof DatasetGraphAccessControl ) ) {
- return QueryExecutionFactory.create(query, dsg);
- }
- if ( isAccessControlledTDB(dsg) ) {
- QueryExecution qExec = QueryExecutionFactory.create(query, dsg);
- filterTDB(dsg, qExec);
- return qExec;
- }
-
- DatasetGraph dsgA = DataAccessCtl.filteredDataset(dsg, this);
- return QueryExecutionFactory.create(query, dsgA);
- }
-
- @Override
- public String toString() {
- return "dft:"+matchDefaultGraph+" / "+graphNames.toString();
- }
-
- public Predicate<Quad> predicateQuad() {
- return quad -> {
- if ( quad.isDefaultGraph() )
- return matchDefaultGraph;
- if ( quad.isUnionGraph() )
- // Union graph is automatically there but its visible contents are different.
- return true;
- return graphNames.contains(quad.getGraph());
- };
- }
-
- /**
- * Create a GraphFilter for a TDB backed dataset.
- *
- * @return GraphFilter
- * @throws IllegalArgumentException
- * if not a TDB database, or a {@link DatasetGraphAccessControl} wrapped
- * TDB database.
- */
- public GraphFilter<?> predicate(DatasetGraph dsg) {
- dsg = DatasetGraphAccessControl.removeWrapper(dsg);
- // dsg has to be the database dataset, not wrapped.
- // DatasetGraphSwitchable is wrapped but should not be unwrapped.
- if ( TDBFactory.isTDB1(dsg) )
- return filterTDB1(dsg);
- if ( DatabaseMgr.isTDB2(dsg) )
- return filterTDB2(dsg);
- throw new IllegalArgumentException("Not a TDB1 or TDB2 database: "+dsg.getClass().getSimpleName());
- }
-
- public boolean isAccessControlledTDB(DatasetGraph dsg) {
- DatasetGraph dsgBase = DatasetGraphAccessControl.unwrapOrNull(dsg);
- if ( dsgBase == null )
- return false;
- if ( TDBFactory.isTDB1(dsgBase) )
- return true;
- if ( DatabaseMgr.isTDB2(dsgBase) )
- return true;
- return false;
- }
-
- public GraphFilterTDB2 filterTDB2(DatasetGraph dsg) {
- GraphFilterTDB2 f = GraphFilterTDB2.graphFilter(dsg, graphNames, matchDefaultGraph);
- return f;
- }
-
- public GraphFilterTDB1 filterTDB1(DatasetGraph dsg) {
- GraphFilterTDB1 f = GraphFilterTDB1.graphFilter(dsg, graphNames, matchDefaultGraph);
- return f;
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/5e000338/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java
index 490a785..10b9a08 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityRegistry.java
@@ -27,10 +27,10 @@ import org.apache.jena.fuseki.Fuseki;
/**
* A {@link SecurityRegistry} is mapping from a string (typically a user name or role
- * name) to a {@link SecurityPolicy}, where the {@link SecurityPolicy}
+ * name) to a {@link SecurityContext}, where the {@link SecurityContext}
* is the access control operations for the user/role.
*/
-public class SecurityRegistry extends Registry<String, SecurityPolicy>{
+public class SecurityRegistry extends Registry<String, SecurityContext>{
public static SecurityRegistry get(ServletContext cxt) {
return (SecurityRegistry)cxt.getAttribute(Fuseki.attrSecurityRegistry);
@@ -43,13 +43,13 @@ public class SecurityRegistry extends Registry<String, SecurityPolicy>{
public SecurityRegistry() {}
@Override
- public SecurityPolicy get(String actor) {
+ public SecurityContext get(String actor) {
if ( actor == null )
- return SecurityPolicy.NONE;
- SecurityPolicy policy = super.get(actor);
- if ( policy == null )
- policy = SecurityPolicy.NONE;
- return policy;
+ return SecurityContext.NONE;
+ SecurityContext sCxt = super.get(actor);
+ if ( sCxt == null )
+ sCxt = SecurityContext.NONE;
+ return sCxt;
}
@Override
@@ -61,7 +61,7 @@ public class SecurityRegistry extends Registry<String, SecurityPolicy>{
// Long form.
StringJoiner sj1 = new StringJoiner("\n", "{ SecurityRegistry\n", "\n}");
super.keys().forEach(u->{
- SecurityPolicy x = super.get(u);
+ SecurityContext x = super.get(u);
StringJoiner sj2 = new StringJoiner("");
sj2.add(" ")
.add(u)
http://git-wip-us.apache.org/repos/asf/jena/blob/5e000338/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
index c9d188a..bbbd87c 100644
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
@@ -84,11 +84,11 @@ public class TestSecurityFilterFuseki {
addTestData(testdsg3);
SecurityRegistry reg = new SecurityRegistry();
- reg.put("userNone", SecurityPolicy.NONE);
- reg.put("userDft", SecurityPolicy.DFT_GRAPH);
- reg.put("user0", new SecurityPolicy(Quad.defaultGraphIRI.getURI()));
- reg.put("user1", new SecurityPolicy("http://test/g1", Quad.defaultGraphIRI.getURI()));
- reg.put("user2", new SecurityPolicy("http://test/g1", "http://test/g2", "http://test/g3"));
+ reg.put("userNone", SecurityContext.NONE);
+ reg.put("userDft", SecurityContext.DFT_GRAPH);
+ reg.put("user0", new SecurityContext(Quad.defaultGraphIRI.getURI()));
+ reg.put("user1", new SecurityContext("http://test/g1", Quad.defaultGraphIRI.getURI()));
+ reg.put("user2", new SecurityContext("http://test/g1", "http://test/g2", "http://test/g3"));
testdsg1 = DataAccessCtl.controlledDataset(testdsg1, reg);
testdsg2 = DataAccessCtl.controlledDataset(testdsg2, reg);
http://git-wip-us.apache.org/repos/asf/jena/blob/5e000338/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java
index 1e03aba..ac0bd0f 100644
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java
@@ -93,11 +93,11 @@ public class TestSecurityFilterLocal {
public TestSecurityFilterLocal(String name, Creator<DatasetGraph> source, boolean applyFilterTDB) {
DatasetGraph dsgBase = source.create();
AccessTestLib.addTestData(dsgBase);
- reg.put("userNone", SecurityPolicy.NONE);
- reg.put("userDft", SecurityPolicy.DFT_GRAPH);
- reg.put("user0", new SecurityPolicy(Quad.defaultGraphIRI.getURI()));
- reg.put("user1", new SecurityPolicy("http://test/g1", Quad.defaultGraphIRI.getURI()));
- reg.put("user2", new SecurityPolicy("http://test/g1", "http://test/g2", "http://test/g3"));
+ reg.put("userNone", SecurityContext.NONE);
+ reg.put("userDft", SecurityContext.DFT_GRAPH);
+ reg.put("user0", new SecurityContext(Quad.defaultGraphIRI.getURI()));
+ reg.put("user1", new SecurityContext("http://test/g1", Quad.defaultGraphIRI.getURI()));
+ reg.put("user2", new SecurityContext("http://test/g1", "http://test/g2", "http://test/g3"));
testdsg = DataAccessCtl.controlledDataset(dsgBase, reg);
this.applyFilterTDB = applyFilterTDB;
this.applyFilterDSG = ! applyFilterTDB;
@@ -115,7 +115,7 @@ public class TestSecurityFilterLocal {
private static String queryG2 = "SELECT * { GRAPH <http://test/graph2> { ?s ?p ?o } }";
private static String queryGraphNames = "SELECT * { GRAPH ?g { } }";
- private Set<Node> subjects(DatasetGraph dsg, String queryString, SecurityPolicy sCxt) {
+ private Set<Node> subjects(DatasetGraph dsg, String queryString, SecurityContext sCxt) {
final DatasetGraph dsg1 = applyFilterDSG
? DataAccessCtl.filteredDataset(dsg, sCxt)
: dsg;
@@ -135,7 +135,7 @@ public class TestSecurityFilterLocal {
});
}
- private Set<Node> subjects(DatasetGraph dsg, Function<DatasetGraph, Graph> graphChoice, String queryString, SecurityPolicy sCxt) {
+ private Set<Node> subjects(DatasetGraph dsg, Function<DatasetGraph, Graph> graphChoice, String queryString, SecurityContext sCxt) {
final DatasetGraph dsg1 = applyFilterDSG
? DataAccessCtl.filteredDataset(dsg, sCxt)
: dsg;
@@ -153,7 +153,7 @@ public class TestSecurityFilterLocal {
});
}
- private Set<Node> graphs(DatasetGraph dsg, SecurityPolicy sCxt) {
+ private Set<Node> graphs(DatasetGraph dsg, SecurityContext sCxt) {
final DatasetGraph dsg1 = applyFilterDSG
? DataAccessCtl.filteredDataset(dsg, sCxt)
: dsg;
@@ -171,14 +171,14 @@ public class TestSecurityFilterLocal {
}
@Test public void filter_setup() {
- Set<Node> visible = subjects(testdsg, queryAll, SecurityPolicy.NONE);
+ Set<Node> visible = subjects(testdsg, queryAll, SecurityContext.NONE);
assertEquals(0, visible.size());
assertSeen(visible);
}
// QueryExecution
private void filter_user(String user, Node ... expected) {
- SecurityPolicy sCxt = reg.get(user);
+ SecurityContext sCxt = reg.get(user);
Set<Node> visible = subjects(testdsg, queryAll, sCxt);
assertSeen(visible, expected);
}
@@ -209,50 +209,50 @@ public class TestSecurityFilterLocal {
// "Access Denied"
@Test public void no_access_user1() {
- SecurityPolicy sCxt = reg.get("user1");
+ SecurityContext sCxt = reg.get("user1");
Set<Node> visible = subjects(testdsg, queryG2, sCxt);
assertTrue(visible.isEmpty());
}
@Test public void graph_names_userNone() {
- SecurityPolicy sCxt = reg.get("userNone");
+ SecurityContext sCxt = reg.get("userNone");
Set<Node> visible = graphs(testdsg, sCxt);
assertSeen(visible);
}
@Test public void graph_names_userDft() {
- SecurityPolicy sCxt = reg.get("userDft");
+ SecurityContext sCxt = reg.get("userDft");
Set<Node> visible = graphs(testdsg, sCxt);
assertSeen(visible);
}
@Test public void graph_names_user0() {
- SecurityPolicy sCxt = reg.get("user0");
+ SecurityContext sCxt = reg.get("user0");
Set<Node> visible = graphs(testdsg, sCxt);
assertSeen(visible);
}
@Test public void graph_names_user1() {
- SecurityPolicy sCxt = reg.get("user1");
+ SecurityContext sCxt = reg.get("user1");
Set<Node> visible = graphs(testdsg, sCxt);
assertSeen(visible, g1);
}
@Test public void graph_names_user2() {
- SecurityPolicy sCxt = reg.get("user2");
+ SecurityContext sCxt = reg.get("user2");
Set<Node> visible = graphs(testdsg, sCxt);
assertSeen(visible, g1, g2, g3);
}
@Test public void graph_names_userX() {
- SecurityPolicy sCxt = reg.get("userX");
+ SecurityContext sCxt = reg.get("userX");
Set<Node> visible = graphs(testdsg, sCxt);
assertSeen(visible);
}
// QueryExecution w/ Union default graph
private void filter_union_user(String user, Node ... expected) {
- SecurityPolicy sCxt = reg.get(user);
+ SecurityContext sCxt = reg.get(user);
Set<Node> visible;
if ( applyFilterTDB ) {
// TDB special version. Set the TDB flags for union default graph
@@ -348,7 +348,7 @@ public class TestSecurityFilterLocal {
}
private void query_model_user(DatasetGraph dsg, Function<DatasetGraph, Graph> graphChoice, String user, Node ... expected) {
- SecurityPolicy sCxt = reg.get(user);
+ SecurityContext sCxt = reg.get(user);
Set<Node> visible = subjects(dsg, graphChoice, queryDft, sCxt);
assertSeen(visible, expected);
}
[08/27] jena git commit: Minor formatting tiding
Posted by an...@apache.org.
Minor formatting tiding
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/ea7f95ef
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/ea7f95ef
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/ea7f95ef
Branch: refs/heads/master
Commit: ea7f95efb493f3a1a8c8638e2496fceed178a0aa
Parents: ba3b4b6
Author: Andy Seaborne <an...@apache.org>
Authored: Wed Aug 22 16:40:06 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Thu Aug 23 17:15:05 2018 +0100
----------------------------------------------------------------------
.../src/main/java/org/apache/jena/query/DatasetFactory.java | 9 +--------
.../org/apache/jena/sparql/core/DatasetGraphFactory.java | 5 ++---
2 files changed, 3 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/ea7f95ef/jena-arq/src/main/java/org/apache/jena/query/DatasetFactory.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/query/DatasetFactory.java b/jena-arq/src/main/java/org/apache/jena/query/DatasetFactory.java
index 45dac4a..de99b71 100644
--- a/jena-arq/src/main/java/org/apache/jena/query/DatasetFactory.java
+++ b/jena-arq/src/main/java/org/apache/jena/query/DatasetFactory.java
@@ -64,7 +64,6 @@ public class DatasetFactory {
* so overheads can accumulate).
*
* @return a transactional, in-memory, modifiable Dataset
- *
*/
public static Dataset createTxnMem() {
return wrap(DatasetGraphFactory.createTxnMem());
@@ -72,7 +71,7 @@ public class DatasetFactory {
/**
* Create a general-purpose {@link Dataset}.<br/>
- * Any graphs needed are in-memory unless explciitly added with {@link Dataset#addNamedModel}.
+ * Any graphs needed are in-memory unless explicitly added with {@link Dataset#addNamedModel}.
* </p>
* This dataset type can contain graphs from any source when added via {@link Dataset#addNamedModel}.
* These are held as links to the supplied graph and not copied.
@@ -194,7 +193,6 @@ public class DatasetFactory {
* @param namedSourceList
* @return a named graph container of graphs based on a list of URIs.
*/
-
public static Dataset createNamed(List<String> namedSourceList) {
return create((List<String>) null, namedSourceList, null);
}
@@ -209,7 +207,6 @@ public class DatasetFactory {
* @param namedSourceList graphs to be attached as named graphs
* @return Dataset
*/
-
public static Dataset create(List<String> uriList, List<String> namedSourceList) {
return create(uriList, namedSourceList, null);
}
@@ -224,7 +221,6 @@ public class DatasetFactory {
* @param namedSourceList graphs to be attached as named graphs
* @return Dataset
*/
-
public static Dataset create(String uri, List<String> namedSourceList) {
return create(uri, namedSourceList, null);
}
@@ -240,7 +236,6 @@ public class DatasetFactory {
* @param baseURI baseURI for relative URI expansion
* @return Dataset
*/
-
public static Dataset create(String uri, List<String> namedSourceList, String baseURI) {
return DatasetUtils.createDataset(uri, namedSourceList, baseURI);
}
@@ -256,7 +251,6 @@ public class DatasetFactory {
* @param baseURI baseURI for relative URI expansion
* @return Dataset
*/
-
public static Dataset create(List<String> uriList, List<String> namedSourceList, String baseURI) {
return DatasetUtils.createDataset(uriList, namedSourceList, baseURI);
}
@@ -316,7 +310,6 @@ public class DatasetFactory {
* @param resource The resource for the dataset
* @return Dataset
*/
-
public static Dataset assemble(Resource resource) {
Objects.requireNonNull(resource, "resource can not be null") ;
Dataset ds = (Dataset) Assembler.general.open(resource);
http://git-wip-us.apache.org/repos/asf/jena/blob/ea7f95ef/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFactory.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFactory.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFactory.java
index 29af401..140e62f 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFactory.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFactory.java
@@ -37,7 +37,7 @@ public class DatasetGraphFactory
* This implementation copies models when {@link Dataset#addNamedModel(String, Model)} is called.
* <p>
* This implementation provides "best effort" transactions; it only provides MRSW locking.
- * Use {@link #createTxnMem} for a proper in-memeory transactional {@code DatasetGraph}.
+ * Use {@link #createTxnMem} for a proper in-memory transactional {@code DatasetGraph}.
*
* @see #createTxnMem
*/
@@ -54,8 +54,7 @@ public class DatasetGraphFactory
* (the implementation adds a begin/commit around each add or delete
* so overheads can accumulate).
*
- * @return a transactional, in-memory, modifiable Dataset
- *
+ * @return a transactional, in-memory, modifiable DatasetGraph
*/
public static DatasetGraph createTxnMem() { return new DatasetGraphInMemory(); }
[15/27] jena git commit: Decouple FusekiLogging from the webapp.
Posted by an...@apache.org.
Decouple FusekiLogging from the webapp.
Pass in an addition allocation to look for a log4j1 properties file.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/24901120
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/24901120
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/24901120
Branch: refs/heads/master
Commit: 2490112032af274391c4b6bca558ff358ce34c3c
Parents: 689c4cf
Author: Andy Seaborne <an...@apache.org>
Authored: Sat Aug 25 17:12:12 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sat Aug 25 17:12:12 2018 +0100
----------------------------------------------------------------------
.../org/apache/jena/fuseki/cmd/FusekiCmd.java | 5 +++--
.../apache/jena/fuseki/system/FusekiLogging.java | 18 +++++++++++++-----
.../webapp/FusekiServerEnvironmentInit.java | 5 +++--
.../java/org/apache/jena/fuseki/TS_Fuseki.java | 2 +-
4 files changed, 20 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/24901120/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/FusekiCmd.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/FusekiCmd.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/FusekiCmd.java
index e62b118..e2957b8 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/FusekiCmd.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/FusekiCmd.java
@@ -58,8 +58,9 @@ public class FusekiCmd {
// statics of a class are run.
static {
- FusekiEnv.mode = FusekiEnv.INIT.STANDALONE ;
- FusekiLogging.setLogging() ;
+ FusekiEnv.mode = FusekiEnv.INIT.STANDALONE;
+ FusekiEnv.setEnvironment();
+ FusekiLogging.setLogging(FusekiEnv.FUSEKI_BASE);
}
static public void main(String... argv) {
http://git-wip-us.apache.org/repos/asf/jena/blob/24901120/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/FusekiLogging.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/FusekiLogging.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/FusekiLogging.java
index 404c581..147fbd0 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/FusekiLogging.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/FusekiLogging.java
@@ -20,11 +20,11 @@ package org.apache.jena.fuseki.system;
import java.io.File ;
import java.net.URL ;
+import java.nio.file.Path;
import org.apache.jena.atlas.lib.StrUtils ;
import org.apache.jena.atlas.logging.LogCtl ;
import org.apache.jena.fuseki.Fuseki;
-import org.apache.jena.fuseki.webapp.FusekiEnv;
import org.apache.jena.riot.SysRIOT ;
import org.apache.log4j.PropertyConfigurator ;
import org.apache.log4j.helpers.Loader ;
@@ -65,12 +65,20 @@ public class FusekiLogging
/** Set up logging - standalone and war packaging */
public static synchronized void setLogging() {
+ setLogging(null);
+
+ }
+
+ /** Set up logging. Allow an extra location (string directory name without trailing "/"). This may be null
+ *
+ * @param extraDir
+ */
+ public static synchronized void setLogging(Path extraDir) {
if ( ! allowLoggingReset )
return ;
if ( loggingInitialized )
return ;
loggingInitialized = true ;
- FusekiEnv.setEnvironment() ;
logLogging("Fuseki logging") ;
// No loggers have been created but configuration may have been set up.
@@ -86,12 +94,12 @@ public class FusekiLogging
}
logLogging("Fuseki logging - setup") ;
// Look for a log4j.properties in the current working directory
- // and an existing FUSEKI_BASE for easy customization.
+ // and a plane (e.g. FUSEKI_BASE in the webapp/full server) for easy customization.
String fn1 = "log4j.properties" ;
String fn2 = null ;
- if ( FusekiEnv.FUSEKI_BASE != null )
- fn2 = FusekiEnv.FUSEKI_BASE.toString()+"/log4j.properties" ;
+ if ( extraDir != null )
+ fn2 = extraDir.resolve("log4j.properties").toString() ;
if ( attempt(fn1) ) return ;
if ( attempt(fn2) ) return ;
http://git-wip-us.apache.org/repos/asf/jena/blob/24901120/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/webapp/FusekiServerEnvironmentInit.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/webapp/FusekiServerEnvironmentInit.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/webapp/FusekiServerEnvironmentInit.java
index b950550..6d3d889 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/webapp/FusekiServerEnvironmentInit.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/webapp/FusekiServerEnvironmentInit.java
@@ -34,9 +34,10 @@ public class FusekiServerEnvironmentInit implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
- FusekiLogging.setLogging();
- JenaSystem.init() ;
+ // These two do not touch Jena.
FusekiEnv.setEnvironment() ;
+ FusekiLogging.setLogging(FusekiEnv.FUSEKI_BASE);
+ JenaSystem.init() ;
}
@Override
http://git-wip-us.apache.org/repos/asf/jena/blob/24901120/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java
index d3e51c4..42e33df 100644
--- a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java
+++ b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java
@@ -55,8 +55,8 @@ public class TS_Fuseki extends ServerTest
FileOps.ensureDir(FusekiTestHome);
FileOps.clearDirectory(FusekiTestHome);
System.setProperty("FUSEKI_HOME", FusekiTestHome) ;
- FusekiLogging.setLogging();
FusekiEnv.setEnvironment() ;
+ FusekiLogging.setLogging();
// To avoid confusion with log4j.properties in the main part of the server,
// we modify in place the logging, not try to set it with another
// Log4j properties file from the classpath.
[25/27] jena git commit: JENA-1594: Structure to allow the
adding/modifying of server setup.
Posted by an...@apache.org.
JENA-1594: Structure to allow the adding/modifying of server setup.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/20eb07ca
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/20eb07ca
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/20eb07ca
Branch: refs/heads/master
Commit: 20eb07ca560d85e4bf6d74ae29342422dec665db
Parents: 228f4b9
Author: Andy Seaborne <an...@apache.org>
Authored: Mon Aug 27 18:23:04 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Mon Aug 27 18:23:04 2018 +0100
----------------------------------------------------------------------
.../apache/jena/fuseki/cmds/FusekiBasicCmd.java | 537 +------------------
.../jena/fuseki/cmds/FusekiBasicMain.java | 513 ++++++++++++++++++
.../apache/jena/fuseki/cmds/ServerConfig.java | 51 ++
3 files changed, 576 insertions(+), 525 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/20eb07ca/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicCmd.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicCmd.java b/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicCmd.java
index f1ba1f2..72f0879 100644
--- a/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicCmd.java
+++ b/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicCmd.java
@@ -18,52 +18,9 @@
package org.apache.jena.fuseki.cmds;
-import java.net.BindException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import arq.cmdline.CmdARQ;
-import arq.cmdline.ModAssembler;
-import arq.cmdline.ModDatasetAssembler;
-import jena.cmd.ArgDecl;
-import jena.cmd.CmdException;
-import org.apache.jena.assembler.exceptions.AssemblerException;
-import org.apache.jena.atlas.lib.DateTimeUtils ;
-import org.apache.jena.atlas.lib.FileOps;
-import org.apache.jena.atlas.logging.FmtLog;
-import org.apache.jena.fuseki.Fuseki;
-import org.apache.jena.fuseki.FusekiException;
-import org.apache.jena.fuseki.embedded.FusekiServer;
-import org.apache.jena.fuseki.server.DataAccessPoint;
-import org.apache.jena.fuseki.server.DataAccessPointRegistry;
-import org.apache.jena.fuseki.server.DataService;
-import org.apache.jena.fuseki.servlets.SPARQL_QueryGeneral ;
import org.apache.jena.fuseki.system.FusekiLogging;
-import org.apache.jena.fuseki.validation.DataValidator ;
-import org.apache.jena.fuseki.validation.IRIValidator ;
-import org.apache.jena.fuseki.validation.QueryValidator ;
-import org.apache.jena.fuseki.validation.UpdateValidator ;
-import org.apache.jena.query.ARQ;
-import org.apache.jena.query.Dataset;
-import org.apache.jena.riot.Lang;
-import org.apache.jena.riot.RDFDataMgr;
-import org.apache.jena.riot.RDFLanguages;
-import org.apache.jena.sparql.core.DatasetGraph;
-import org.apache.jena.sparql.core.DatasetGraphFactory;
-import org.apache.jena.sys.JenaSystem;
-import org.apache.jena.system.Txn;
-import org.apache.jena.tdb.TDB;
-import org.apache.jena.tdb.TDBFactory;
-import org.apache.jena.tdb.transaction.TransactionManager;
-import org.apache.jena.tdb2.DatabaseMgr;
-import org.slf4j.Logger;
-/** Fuseki command that runs a Fuseki server with no UI, just SPARQL services.
+/** Fuseki command that runs a Fuseki server without the admin UI, just SPARQL services.
* <p>
* Use {@code --conf=} for multiple datasets and specific service names.
* <p>
@@ -71,489 +28,19 @@ import org.slf4j.Logger;
*/
public class FusekiBasicCmd {
- // Own module (or optional dependency on jena-cmds)
- // Needs jena-cmds.
+ // This class wraps FusekiBasicMain so that it can take control of logging setup.
+ // It does not depend via inheritance on any Jena code - FusekiBasicMain does.
+ // Inheritance causes initialization in the super class first, before class
+ // initialization code in this class.
- static {
- FusekiLogging.setLogging();
- }
+ static { FusekiLogging.setLogging(); }
- /** Build and run, a server based on command line syntax. This operation does not return. */
+ /**
+ * Build and run, a server based on command line syntax. This operation does not
+ * return. See {@link FusekiBasicMain#build} to build a server using command line
+ * syntax but not start it.
+ */
static public void main(String... argv) {
- FusekiCmdInner.innerMain(argv);
- }
-
- /** Build, but do not start, a server based on command line syntax. */
- static public FusekiServer build(String... argv) {
- return FusekiCmdInner.build(argv);
- }
-
- /** Dataset setup (command line, config file) for a dataset (or several if config file) */
- static class ServerConfig {
- public int port;
- // Dataset name on the command line.
- public String datasetPath = null;
- // Command line --update.
- public boolean allowUpdate = false;
-
- // This is set ...
- public DatasetGraph dsg = null;
- // ... or this.
- public String serverConfig = null;
-
-
- // Allow there to be no registered datasets without it being an error.
- // which is "return dsg==null && serverConfig==null;"
- public boolean empty = false ;
- // Setup for SPARQLer - validators and general query engine, some pages.
- public boolean sparqler = false ;
- public boolean validators = false ;
- public boolean loopback = false;
- public String datasetDescription;
- public String contentDirectory = null;
- }
-
- static class FusekiCmdInner extends CmdARQ {
- private static int defaultPort = 3030;
-
- private static ArgDecl argMem = new ArgDecl(ArgDecl.NoValue, "mem");
- private static ArgDecl argUpdate = new ArgDecl(ArgDecl.NoValue, "update", "allowUpdate");
- private static ArgDecl argFile = new ArgDecl(ArgDecl.HasValue, "file");
-
- private static ArgDecl argTDB2mode = new ArgDecl(ArgDecl.NoValue, "tdb2");
- private static ArgDecl argMemTDB = new ArgDecl(ArgDecl.NoValue, "memtdb", "memTDB", "tdbmem");
- private static ArgDecl argTDB = new ArgDecl(ArgDecl.HasValue, "loc", "location", "tdb");
-
- // No SPARQL dataset or services
- private static ArgDecl argEmpty = new ArgDecl(ArgDecl.NoValue, "empty", "no-dataset");
- private static ArgDecl argPort = new ArgDecl(ArgDecl.HasValue, "port");
- private static ArgDecl argLocalhost = new ArgDecl(ArgDecl.NoValue, "localhost", "local");
- private static ArgDecl argTimeout = new ArgDecl(ArgDecl.HasValue, "timeout");
- private static ArgDecl argConfig = new ArgDecl(ArgDecl.HasValue, "config", "conf");
- private static ArgDecl argGZip = new ArgDecl(ArgDecl.HasValue, "gzip");
- private static ArgDecl argBase = new ArgDecl(ArgDecl.HasValue, "base", "files");
- private static ArgDecl argSparqler = new ArgDecl(ArgDecl.HasValue, "sparqler");
- private static ArgDecl argValidators = new ArgDecl(ArgDecl.NoValue, "validators");
- // private static ModLocation modLocation = new ModLocation();
- private static ModDatasetAssembler modDataset = new ModDatasetAssembler();
-
- static void innerMain(String... argv) {
- JenaSystem.init();
- new FusekiCmdInner(argv).mainRun();
- }
-
- /** Build, but do not start, a server based on command line syntax. */
- static FusekiServer build(String... argv) {
- FusekiCmdInner inner = new FusekiCmdInner(argv);
- inner.process();
- return inner.buildServer();
- }
-
- private final ServerConfig serverConfig = new ServerConfig();
- private boolean useTDB2;
-
- public FusekiCmdInner(String... argv) {
- super(argv);
-
- if ( false )
- // Consider ...
- TransactionManager.QueueBatchSize = TransactionManager.QueueBatchSize / 2;
-
- getUsage().startCategory("Fuseki");
- addModule(modDataset);
- add(argMem, "--mem",
- "Create an in-memory, non-persistent dataset for the server");
- add(argFile, "--file=FILE",
- "Create an in-memory, non-persistent dataset for the server, initialised with the contents of the file");
- add(argTDB2mode, "--tdb2",
- "Create command line persistent datasets with TDB2");
- add(argTDB, "--loc=DIR",
- "Use an existing TDB database (or create if does not exist)");
- add(argMemTDB, "--memTDB",
- "Create an in-memory, non-persistent dataset using TDB (testing only)");
-// add(argEmpty, "--empty",
-// "Run with no datasets and services (validators only)");
- add(argEmpty); // Hidden for now.
- add(argPort, "--port",
- "Listen on this port number");
- add(argLocalhost, "--localhost",
- "Listen only on the localhost interface");
- add(argTimeout, "--timeout=",
- "Global timeout applied to queries (value in ms) -- format is X[,Y] ");
- add(argUpdate, "--update",
- "Allow updates (via SPARQL Update and SPARQL HTTP Update)");
- add(argConfig, "--config=",
- "Use a configuration file to determine the services");
- add(argGZip, "--gzip=on|off",
- "Enable GZip compression (HTTP Accept-Encoding) if request header set");
- add(argBase, "--base=DIR",
- "Directory for static content");
- add(argSparqler, "--sparqler=DIR",
- "Run with SPARQLer services Directory for static content");
- add(argValidators, "--validators", "Install validators");
-
- super.modVersion.addClass(TDB.class);
- super.modVersion.addClass(Fuseki.class);
- }
-
- static String argUsage = "[--config=FILE] [--mem|--desc=AssemblerFile|--file=FILE] [--port PORT] /DatasetPathName";
-
- @Override
- protected String getSummary() {
- return getCommandName() + " " + argUsage;
- }
-
- @Override
- protected void processModulesAndArgs() {
- int x = 0;
-
- Logger log = Fuseki.serverLog;
-
- // ---- Checking
-
- if ( contains(argMem) )
- x++;
- if ( contains(argFile) )
- x++;
- if ( contains(ModAssembler.assemblerDescDecl) )
- x++;
- if ( contains(argTDB) )
- x++;
- if ( contains(argMemTDB) )
- x++;
- if ( contains(argConfig) )
- x++;
-
- boolean allowEmpty = contains(argEmpty) || contains(argSparqler);
-
-
- if ( x == 0 && ! allowEmpty )
- throw new CmdException("No dataset specified on the command line.");
-
- if ( x > 1 )
- throw new CmdException("Multiple ways providing a dataset. Only one of --mem, --file, --loc or --desc");
-
- if ( x > 0 && allowEmpty )
- throw new CmdException("Dataset provided but 'no dataset' flag given");
-
- //---- check: Invalid: --conf + service name.
- if ( contains(argConfig) ) {
- if ( getPositional().size() != 0 )
- throw new CmdException("Can't have both a configutation file and a service name");
- } else if ( ! allowEmpty ) {
- if ( getPositional().size() == 0 )
- throw new CmdException("Missing service name");
- if ( getPositional().size() > 1 )
- throw new CmdException("Multiple dataset path names given");
- serverConfig.datasetPath = DataAccessPoint.canonical(getPositionalArg(0));
- }
-
- serverConfig.datasetDescription = "<unset>";
-
- // ---- check: Invalid: --update + --conf
- if ( contains(argUpdate) && contains(argConfig) )
- throw new CmdException("--update and a configuration file does not make sense (control using the configuration file only)");
- boolean allowUpdate = contains(argUpdate);
- serverConfig.allowUpdate = allowUpdate;
-
- // ---- Port
- serverConfig.port = defaultPort;
-
- if ( contains(argPort) ) {
- String portStr = getValue(argPort);
- try {
- int port = Integer.parseInt(portStr);
- serverConfig.port = port;
- } catch (NumberFormatException ex) {
- throw new CmdException(argPort.getKeyName() + " : bad port number: " + portStr);
- }
- }
- if ( contains(argLocalhost) )
- serverConfig.loopback = true;
-
- // ---- Dataset
- // Only one of these is choose from the checking above.
-
- // Which TDB to use to create a command line TDB database.
- useTDB2 = contains(argTDB2mode);
- String tag = useTDB2 ? "TDB2" : "TDB";
-
- if ( allowEmpty ) {
- serverConfig.empty = true;
- serverConfig.datasetDescription = "No dataset";
- }
-
- // Fuseki config file
- if ( contains(argConfig) ) {
- String file = getValue(argConfig);
- if ( file.startsWith("file:") )
- file = file.substring("file:".length());
-
- Path path = Paths.get(file);
- if ( ! Files.exists(path) )
- throw new CmdException("File not found: "+file);
- if ( Files.isDirectory(path) )
- throw new CmdException("Is a directory: "+file);
- serverConfig.datasetDescription = "Configuration: "+path.toAbsolutePath();
- serverConfig.serverConfig = getValue(argConfig);
- }
-
- // Ways to setup a dataset.
- if ( contains(argMem) ) {
- serverConfig.datasetDescription = "in-memory";
- // Only one setup should be called by the test above but to be safe
- // and in case of future changes, clear the configuration.
- serverConfig.dsg = DatasetGraphFactory.createTxnMem();
- // Always allow, else you can't do very much!
- serverConfig.allowUpdate = true;
- }
-
- if ( contains(argFile) ) {
- String filename = getValue(argFile);
- String pathname = filename;
- if ( filename.startsWith("file:") )
- pathname = filename.substring("file:".length());
-
- serverConfig.datasetDescription = "file:"+filename;
- if ( !FileOps.exists(pathname) )
- throw new CmdException("File not found: " + filename);
- serverConfig.dsg = DatasetGraphFactory.createTxnMem();
-
- // INITIAL DATA.
- Lang language = RDFLanguages.filenameToLang(filename);
- if ( language == null )
- throw new CmdException("Can't guess language for file: " + filename);
- Txn.executeWrite(serverConfig.dsg, ()->RDFDataMgr.read(serverConfig.dsg, filename));
- }
-
-// if ( contains(argMemTDB) ) {
-// //log.info("TDB dataset: in-memory") ;
-// cmdLineConfig.reset();
-// cmdLineConfig.argTemplateFile = useTDB2 ? Template.templateTDB2_MemFN : Template.templateTDB1_MemFN ;
-// cmdLineConfig.params.put(Template.DIR, Names.memName) ;
-// // Always allow.
-// cmdLineConfig.allowUpdate = true ;
-// cmdLineConfig.datasetDescription = useTDB2 ? "TDB2 dataset (in-memory)" : "TDB dataset (in-memory)";
-// }
-//
-// if ( contains(argTDB) ) {
-// cmdLineConfig.reset();
-// cmdLineConfig.argTemplateFile =
-// useTDB2 ? Template.templateTDB2_DirFN : Template.templateTDB1_DirFN;
-// String dir = getValue(argTDB) ;
-// cmdLineConfig.params.put(Template.DIR, dir) ;
-// cmdLineConfig.datasetDescription = useTDB2 ? "TDB2 dataset: "+dir : "TDB dataset: "+dir;
-// }
-
- if ( contains(argMemTDB) ) {
- serverConfig.datasetDescription = tag+" dataset in-memory";
- serverConfig.dsg =
- useTDB2
- ? DatabaseMgr.createDatasetGraph()
- : TDBFactory.createDatasetGraph();
- serverConfig.allowUpdate = true;
- }
-
- if ( contains(argTDB) ) {
- String dir = getValue(argTDB);
- serverConfig.datasetDescription = tag+" dataset: "+dir;
- serverConfig.dsg =
- useTDB2
- ? DatabaseMgr.connectDatasetGraph(dir)
- : TDBFactory.createDatasetGraph(dir);
- }
-
- if ( contains(ModAssembler.assemblerDescDecl) ) {
- serverConfig.datasetDescription = "Assembler: "+ getValue(ModAssembler.assemblerDescDecl);
- // Need to add service details.
- Dataset ds = modDataset.createDataset();
- serverConfig.dsg = ds.asDatasetGraph();
- }
-
- // ---- Misc features.
- if ( contains(argTimeout) ) {
- String str = getValue(argTimeout);
- ARQ.getContext().set(ARQ.queryTimeout, str);
- }
-
- if ( contains(argValidators) ) {
- serverConfig.validators = true;
- }
-
- if ( contains(argSparqler) ) {
- String filebase = getValue(argSparqler);
- if ( ! FileOps.exists(filebase) )
- throw new CmdException("File area not found: "+filebase);
- serverConfig.contentDirectory = filebase;
- serverConfig.sparqler = true;
- serverConfig.validators = true;
- }
-
- if ( contains(argBase) ) {
- // Static files.
- String filebase = getValue(argBase);
- if ( ! FileOps.exists(filebase) ) {
- throw new CmdException("File area not found: "+filebase);
- //FmtLog.warn(Fuseki.configLog, "File area not found: "+filebase);
- }
- serverConfig.contentDirectory = filebase;
- }
-
-// if ( contains(argGZip) ) {
-// if ( !hasValueOfTrue(argGZip) && !hasValueOfFalse(argGZip) )
-// throw new CmdException(argGZip.getNames().get(0) + ": Not understood: " + getValue(argGZip));
-// jettyServerConfig.enableCompression = super.hasValueOfTrue(argGZip);
-// }
- }
-
-// private static String sort_out_dir(String path) {
-// path.replace('\\', '/');
-// if ( !path.endsWith("/") )
-// path = path + "/";
-// return path;
-// }
-
- @Override
- protected void exec() {
- try {
- FusekiServer server = buildServer(serverConfig);
- info(server, serverConfig);
- try {
- server.start();
- } catch (FusekiException ex) {
- if ( ex.getCause() instanceof BindException ) {
- Fuseki.serverLog.error("Failed to start server: "+ex.getCause().getMessage()+ ": port="+serverConfig.port) ;
- System.exit(1);
- }
- throw ex;
- } catch (Exception ex) {
- throw new FusekiException("Failed to start server: " + ex.getMessage(), ex) ;
- }
- server.join();
- System.exit(0);
- }
- catch (AssemblerException ex) {
- if ( ex.getCause() != null )
- System.err.println(ex.getCause().getMessage());
- else
- System.err.println(ex.getMessage());
- }
- }
-
- private FusekiServer buildServer() {
- return buildServer(serverConfig);
- }
-
- // ServerConfig -> Setup the builder.
- private static FusekiServer buildServer(ServerConfig serverConfig) {
- FusekiServer.Builder builder = FusekiServer.create();
- // Loopback.
- builder.port(serverConfig.port);
- builder.loopback(serverConfig.loopback);
-
- if ( serverConfig.validators ) {
- if ( serverConfig.sparqler )
- builder.addServlet("/sparql", new SPARQL_QueryGeneral());
- // Validators.
- builder.addServlet("/validate/query", new QueryValidator());
- builder.addServlet("/validate/update", new UpdateValidator());
- builder.addServlet("/validate/iri", new IRIValidator());
- builder.addServlet("/validate/data", new DataValidator());
- }
- if ( ! serverConfig.empty ) {
- if ( serverConfig.serverConfig != null )
- // Config file.
- builder.parseConfigFile(serverConfig.serverConfig);
- else
- // One dataset.
- builder.add(serverConfig.datasetPath, serverConfig.dsg, serverConfig.allowUpdate);
- }
-
- if ( serverConfig.contentDirectory != null )
- builder.staticFileBase(serverConfig.contentDirectory) ;
-
- return builder.build();
- }
-
- private void info(FusekiServer server, ServerConfig serverConfig) {
- if ( super.isQuiet() )
- return;
-
- Logger log = Fuseki.serverLog;
-
- String version = Fuseki.VERSION;
- String buildDate = Fuseki.BUILD_DATE ;
-
- if ( version != null && version.equals("${project.version}") )
- version = null ;
- if ( buildDate != null && buildDate.equals("${build.time.xsd}") )
- buildDate = DateTimeUtils.nowAsXSDDateTimeString() ;
-
- String name = Fuseki.NAME;
- name = name +" (basic server)";
-
- if ( version != null ) {
- if ( Fuseki.developmentMode && buildDate != null )
- FmtLog.info(log, "%s %s %s", name, version, buildDate) ;
- else
- FmtLog.info(log, "%s %s", name, version);
- }
-
- // Dataset -> Endpoints
- Map<String, List<String>> mapDatasetEndpoints = description(DataAccessPointRegistry.get(server.getServletContext()));
-
- if ( serverConfig.empty ) {
- FmtLog.info(log, "No SPARQL datasets services");
- } else {
- if ( serverConfig.datasetPath == null && serverConfig.serverConfig == null )
- log.error("No dataset path nor server configuration file");
- }
-
- if ( serverConfig.datasetPath != null ) {
- if ( mapDatasetEndpoints.size() != 1 )
- log.error("Expected only one dataset");
- List<String> endpoints = mapDatasetEndpoints.get(serverConfig.datasetPath);
- FmtLog.info(log, "Dataset Type = %s", serverConfig.datasetDescription);
- FmtLog.info(log, "Path = %s; Services = %s", serverConfig.datasetPath, endpoints);
- }
- if ( serverConfig.serverConfig != null ) {
- // May be many datasets and services.
- FmtLog.info(log, "Configuration file %s", serverConfig.serverConfig);
- mapDatasetEndpoints.forEach((path, endpoints)->{
- FmtLog.info(log, "Path = %s; Services = %s", path, endpoints);
- });
- }
-
- if ( serverConfig.contentDirectory != null )
- FmtLog.info(log, "Static files = %s", serverConfig.contentDirectory);
-
- if ( super.isVerbose() )
- PlatformInfo.logDetailsVerbose(log);
- else if ( !super.isQuiet() )
- PlatformInfo.logDetails(log);
- }
-
- private static Map<String, List<String>> description(DataAccessPointRegistry reg) {
- Map<String, List<String>> desc = new LinkedHashMap<>();
- reg.forEach((ds,dap)->{
- List<String> endpoints = new ArrayList<>();
- desc.put(ds, endpoints);
- DataService dSrv = dap.getDataService();
- dSrv.getOperations().forEach((op)->{
- dSrv.getEndpoints(op).forEach(ep-> {
- String x = ep.getEndpoint();
- if ( x.isEmpty() )
- x = "quads";
- endpoints.add(x);
- });
- });
- });
- return desc;
- }
-
- @Override
- protected String getCommandName() {
- return "fuseki";
- }
+ FusekiBasicMain.innerMain(argv);
}
}
http://git-wip-us.apache.org/repos/asf/jena/blob/20eb07ca/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicMain.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicMain.java b/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicMain.java
new file mode 100644
index 0000000..6febd26
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicMain.java
@@ -0,0 +1,513 @@
+/*
+ * 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.cmds;
+
+import java.net.BindException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import arq.cmdline.CmdARQ;
+import arq.cmdline.ModAssembler;
+import arq.cmdline.ModDatasetAssembler;
+import jena.cmd.ArgDecl;
+import jena.cmd.CmdException;
+import org.apache.jena.assembler.exceptions.AssemblerException;
+import org.apache.jena.atlas.lib.DateTimeUtils;
+import org.apache.jena.atlas.lib.FileOps;
+import org.apache.jena.atlas.logging.FmtLog;
+import org.apache.jena.fuseki.Fuseki;
+import org.apache.jena.fuseki.FusekiException;
+import org.apache.jena.fuseki.embedded.FusekiServer;
+import org.apache.jena.fuseki.server.DataAccessPoint;
+import org.apache.jena.fuseki.server.DataAccessPointRegistry;
+import org.apache.jena.fuseki.server.DataService;
+import org.apache.jena.fuseki.servlets.SPARQL_QueryGeneral;
+import org.apache.jena.fuseki.validation.DataValidator;
+import org.apache.jena.fuseki.validation.IRIValidator;
+import org.apache.jena.fuseki.validation.QueryValidator;
+import org.apache.jena.fuseki.validation.UpdateValidator;
+import org.apache.jena.query.ARQ;
+import org.apache.jena.query.Dataset;
+import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.RDFDataMgr;
+import org.apache.jena.riot.RDFLanguages;
+import org.apache.jena.sparql.core.DatasetGraphFactory;
+import org.apache.jena.sys.JenaSystem;
+import org.apache.jena.system.Txn;
+import org.apache.jena.tdb.TDB;
+import org.apache.jena.tdb.TDBFactory;
+import org.apache.jena.tdb.transaction.TransactionManager;
+import org.apache.jena.tdb2.DatabaseMgr;
+import org.slf4j.Logger;
+
+public class FusekiBasicMain extends CmdARQ {
+ private static int defaultPort = 3030;
+
+ private static ArgDecl argMem = new ArgDecl(ArgDecl.NoValue, "mem");
+ private static ArgDecl argUpdate = new ArgDecl(ArgDecl.NoValue, "update", "allowUpdate");
+ private static ArgDecl argFile = new ArgDecl(ArgDecl.HasValue, "file");
+
+ private static ArgDecl argTDB2mode = new ArgDecl(ArgDecl.NoValue, "tdb2");
+ private static ArgDecl argMemTDB = new ArgDecl(ArgDecl.NoValue, "memtdb", "memTDB", "tdbmem");
+ private static ArgDecl argTDB = new ArgDecl(ArgDecl.HasValue, "loc", "location", "tdb");
+
+ // No SPARQL dataset or services
+ private static ArgDecl argEmpty = new ArgDecl(ArgDecl.NoValue, "empty", "no-dataset");
+ private static ArgDecl argPort = new ArgDecl(ArgDecl.HasValue, "port");
+ private static ArgDecl argLocalhost = new ArgDecl(ArgDecl.NoValue, "localhost", "local");
+ private static ArgDecl argTimeout = new ArgDecl(ArgDecl.HasValue, "timeout");
+ private static ArgDecl argConfig = new ArgDecl(ArgDecl.HasValue, "config", "conf");
+ private static ArgDecl argGZip = new ArgDecl(ArgDecl.HasValue, "gzip");
+ private static ArgDecl argBase = new ArgDecl(ArgDecl.HasValue, "base", "files");
+ private static ArgDecl argSparqler = new ArgDecl(ArgDecl.HasValue, "sparqler");
+ private static ArgDecl argValidators = new ArgDecl(ArgDecl.NoValue, "validators");
+ // private static ModLocation modLocation = new ModLocation();
+ private static ModDatasetAssembler modDataset = new ModDatasetAssembler();
+
+ private final ServerConfig serverConfig = new ServerConfig();
+ private boolean useTDB2;
+
+ /** Build, but do not start, a server based on command line syntax. */
+ public static FusekiServer build(String... argv) {
+ FusekiBasicMain inner = new FusekiBasicMain(argv);
+ inner.process();
+ return inner.buildServer();
+ }
+
+ static void innerMain(String... argv) {
+ JenaSystem.init();
+ new FusekiBasicMain(argv).mainRun();
+ }
+
+ protected FusekiBasicMain(String... argv) {
+ super(argv);
+
+ if ( false )
+ // Consider ...
+ TransactionManager.QueueBatchSize = TransactionManager.QueueBatchSize / 2;
+
+ getUsage().startCategory("Fuseki");
+ addModule(modDataset);
+ add(argMem, "--mem",
+ "Create an in-memory, non-persistent dataset for the server");
+ add(argFile, "--file=FILE",
+ "Create an in-memory, non-persistent dataset for the server, initialised with the contents of the file");
+ add(argTDB2mode, "--tdb2",
+ "Create command line persistent datasets with TDB2");
+ add(argTDB, "--loc=DIR",
+ "Use an existing TDB database (or create if does not exist)");
+ add(argMemTDB, "--memTDB",
+ "Create an in-memory, non-persistent dataset using TDB (testing only)");
+// add(argEmpty, "--empty",
+// "Run with no datasets and services (validators only)");
+ add(argEmpty); // Hidden for now.
+ add(argPort, "--port",
+ "Listen on this port number");
+ add(argLocalhost, "--localhost",
+ "Listen only on the localhost interface");
+ add(argTimeout, "--timeout=",
+ "Global timeout applied to queries (value in ms) -- format is X[,Y] ");
+ add(argUpdate, "--update",
+ "Allow updates (via SPARQL Update and SPARQL HTTP Update)");
+ add(argConfig, "--config=",
+ "Use a configuration file to determine the services");
+ add(argGZip, "--gzip=on|off",
+ "Enable GZip compression (HTTP Accept-Encoding) if request header set");
+ add(argBase, "--base=DIR",
+ "Directory for static content");
+ add(argSparqler, "--sparqler=DIR",
+ "Run with SPARQLer services Directory for static content");
+ add(argValidators, "--validators", "Install validators");
+
+ super.modVersion.addClass(TDB.class);
+ super.modVersion.addClass(Fuseki.class);
+ }
+
+ static String argUsage = "[--config=FILE] [--mem|--desc=AssemblerFile|--file=FILE] [--port PORT] /DatasetPathName";
+
+ @Override
+ protected String getSummary() {
+ return getCommandName() + " " + argUsage;
+ }
+
+ @Override
+ protected void processModulesAndArgs() {
+ int x = 0;
+
+ Logger log = Fuseki.serverLog;
+
+ // ---- Checking
+
+ if ( contains(argMem) )
+ x++;
+ if ( contains(argFile) )
+ x++;
+ if ( contains(ModAssembler.assemblerDescDecl) )
+ x++;
+ if ( contains(argTDB) )
+ x++;
+ if ( contains(argMemTDB) )
+ x++;
+ if ( contains(argConfig) )
+ x++;
+
+ boolean allowEmpty = contains(argEmpty) || contains(argSparqler);
+
+
+ if ( x == 0 && ! allowEmpty )
+ throw new CmdException("No dataset specified on the command line.");
+
+ if ( x > 1 )
+ throw new CmdException("Multiple ways providing a dataset. Only one of --mem, --file, --loc or --desc");
+
+ if ( x > 0 && allowEmpty )
+ throw new CmdException("Dataset provided but 'no dataset' flag given");
+
+ //---- check: Invalid: --conf + service name.
+ if ( contains(argConfig) ) {
+ if ( getPositional().size() != 0 )
+ throw new CmdException("Can't have both a configutation file and a service name");
+ } else if ( ! allowEmpty ) {
+ if ( getPositional().size() == 0 )
+ throw new CmdException("Missing service name");
+ if ( getPositional().size() > 1 )
+ throw new CmdException("Multiple dataset path names given");
+ serverConfig.datasetPath = DataAccessPoint.canonical(getPositionalArg(0));
+ }
+
+ serverConfig.datasetDescription = "<unset>";
+
+ // ---- check: Invalid: --update + --conf
+ if ( contains(argUpdate) && contains(argConfig) )
+ throw new CmdException("--update and a configuration file does not make sense (control using the configuration file only)");
+ boolean allowUpdate = contains(argUpdate);
+ serverConfig.allowUpdate = allowUpdate;
+
+ // ---- Port
+ serverConfig.port = defaultPort;
+
+ if ( contains(argPort) ) {
+ String portStr = getValue(argPort);
+ try {
+ int port = Integer.parseInt(portStr);
+ serverConfig.port = port;
+ } catch (NumberFormatException ex) {
+ throw new CmdException(argPort.getKeyName() + " : bad port number: " + portStr);
+ }
+ }
+ if ( contains(argLocalhost) )
+ serverConfig.loopback = true;
+
+ // ---- Dataset
+ // Only one of these is choose from the checking above.
+
+ // Which TDB to use to create a command line TDB database.
+ useTDB2 = contains(argTDB2mode);
+ String tag = useTDB2 ? "TDB2" : "TDB";
+
+ if ( allowEmpty ) {
+ serverConfig.empty = true;
+ serverConfig.datasetDescription = "No dataset";
+ }
+
+ // Fuseki config file
+ if ( contains(argConfig) ) {
+ String file = getValue(argConfig);
+ if ( file.startsWith("file:") )
+ file = file.substring("file:".length());
+
+ Path path = Paths.get(file);
+ if ( ! Files.exists(path) )
+ throw new CmdException("File not found: "+file);
+ if ( Files.isDirectory(path) )
+ throw new CmdException("Is a directory: "+file);
+ serverConfig.datasetDescription = "Configuration: "+path.toAbsolutePath();
+ serverConfig.serverConfig = getValue(argConfig);
+ }
+
+ // Ways to setup a dataset.
+ if ( contains(argMem) ) {
+ serverConfig.datasetDescription = "in-memory";
+ // Only one setup should be called by the test above but to be safe
+ // and in case of future changes, clear the configuration.
+ serverConfig.dsg = DatasetGraphFactory.createTxnMem();
+ // Always allow, else you can't do very much!
+ serverConfig.allowUpdate = true;
+ }
+
+ if ( contains(argFile) ) {
+ String filename = getValue(argFile);
+ String pathname = filename;
+ if ( filename.startsWith("file:") )
+ pathname = filename.substring("file:".length());
+
+ serverConfig.datasetDescription = "file:"+filename;
+ if ( !FileOps.exists(pathname) )
+ throw new CmdException("File not found: " + filename);
+ serverConfig.dsg = DatasetGraphFactory.createTxnMem();
+
+ // INITIAL DATA.
+ Lang language = RDFLanguages.filenameToLang(filename);
+ if ( language == null )
+ throw new CmdException("Can't guess language for file: " + filename);
+ Txn.executeWrite(serverConfig.dsg, ()->RDFDataMgr.read(serverConfig.dsg, filename));
+ }
+
+// if ( contains(argMemTDB) ) {
+// //log.info("TDB dataset: in-memory") ;
+// cmdLineConfig.reset();
+// cmdLineConfig.argTemplateFile = useTDB2 ? Template.templateTDB2_MemFN : Template.templateTDB1_MemFN ;
+// cmdLineConfig.params.put(Template.DIR, Names.memName) ;
+// // Always allow.
+// cmdLineConfig.allowUpdate = true ;
+// cmdLineConfig.datasetDescription = useTDB2 ? "TDB2 dataset (in-memory)" : "TDB dataset (in-memory)";
+// }
+//
+// if ( contains(argTDB) ) {
+// cmdLineConfig.reset();
+// cmdLineConfig.argTemplateFile =
+// useTDB2 ? Template.templateTDB2_DirFN : Template.templateTDB1_DirFN;
+// String dir = getValue(argTDB) ;
+// cmdLineConfig.params.put(Template.DIR, dir) ;
+// cmdLineConfig.datasetDescription = useTDB2 ? "TDB2 dataset: "+dir : "TDB dataset: "+dir;
+// }
+
+ if ( contains(argMemTDB) ) {
+ serverConfig.datasetDescription = tag+" dataset in-memory";
+ serverConfig.dsg =
+ useTDB2
+ ? DatabaseMgr.createDatasetGraph()
+ : TDBFactory.createDatasetGraph();
+ serverConfig.allowUpdate = true;
+ }
+
+ if ( contains(argTDB) ) {
+ String dir = getValue(argTDB);
+ serverConfig.datasetDescription = tag+" dataset: "+dir;
+ serverConfig.dsg =
+ useTDB2
+ ? DatabaseMgr.connectDatasetGraph(dir)
+ : TDBFactory.createDatasetGraph(dir);
+ }
+
+ if ( contains(ModAssembler.assemblerDescDecl) ) {
+ serverConfig.datasetDescription = "Assembler: "+ getValue(ModAssembler.assemblerDescDecl);
+ // Need to add service details.
+ Dataset ds = modDataset.createDataset();
+ serverConfig.dsg = ds.asDatasetGraph();
+ }
+
+ // ---- Misc features.
+ if ( contains(argTimeout) ) {
+ String str = getValue(argTimeout);
+ ARQ.getContext().set(ARQ.queryTimeout, str);
+ }
+
+ if ( contains(argValidators) ) {
+ serverConfig.validators = true;
+ }
+
+ if ( contains(argSparqler) ) {
+ String filebase = getValue(argSparqler);
+ if ( ! FileOps.exists(filebase) )
+ throw new CmdException("File area not found: "+filebase);
+ serverConfig.contentDirectory = filebase;
+ serverConfig.sparqler = true;
+ serverConfig.validators = true;
+ }
+
+ if ( contains(argBase) ) {
+ // Static files.
+ String filebase = getValue(argBase);
+ if ( ! FileOps.exists(filebase) ) {
+ throw new CmdException("File area not found: "+filebase);
+ //FmtLog.warn(Fuseki.configLog, "File area not found: "+filebase);
+ }
+ serverConfig.contentDirectory = filebase;
+ }
+
+// if ( contains(argGZip) ) {
+// if ( !hasValueOfTrue(argGZip) && !hasValueOfFalse(argGZip) )
+// throw new CmdException(argGZip.getNames().get(0) + ": Not understood: " + getValue(argGZip));
+// jettyServerConfig.enableCompression = super.hasValueOfTrue(argGZip);
+// }
+ }
+
+// private static String sort_out_dir(String path) {
+// path.replace('\\', '/');
+// if ( !path.endsWith("/") )
+// path = path + "/";
+// return path;
+// }
+
+ @Override
+ protected void exec() {
+ try {
+ FusekiServer server = buildServer(serverConfig);
+ info(server, serverConfig);
+ try {
+ server.start();
+ } catch (FusekiException ex) {
+ if ( ex.getCause() instanceof BindException ) {
+ Fuseki.serverLog.error("Failed to start server: "+ex.getCause().getMessage()+ ": port="+serverConfig.port) ;
+ System.exit(1);
+ }
+ throw ex;
+ } catch (Exception ex) {
+ throw new FusekiException("Failed to start server: " + ex.getMessage(), ex) ;
+ }
+ server.join();
+ System.exit(0);
+ }
+ catch (AssemblerException ex) {
+ if ( ex.getCause() != null )
+ System.err.println(ex.getCause().getMessage());
+ else
+ System.err.println(ex.getMessage());
+ }
+ }
+
+ private FusekiServer buildServer() {
+ return buildServer(serverConfig);
+ }
+
+ // ServerConfig -> Setup the builder.
+ private FusekiServer buildServer(ServerConfig serverConfig) {
+ FusekiServer.Builder builder = builder();
+ return buildServer(builder, serverConfig);
+ }
+
+ protected FusekiServer.Builder builder() {
+ return FusekiServer.create();
+ }
+
+ private static FusekiServer buildServer(FusekiServer.Builder builder, ServerConfig serverConfig) {
+ builder.port(serverConfig.port);
+ builder.loopback(serverConfig.loopback);
+
+ if ( serverConfig.validators ) {
+ if ( serverConfig.sparqler )
+ builder.addServlet("/sparql", new SPARQL_QueryGeneral());
+ // Validators.
+ builder.addServlet("/validate/query", new QueryValidator());
+ builder.addServlet("/validate/update", new UpdateValidator());
+ builder.addServlet("/validate/iri", new IRIValidator());
+ builder.addServlet("/validate/data", new DataValidator());
+ }
+ if ( ! serverConfig.empty ) {
+ if ( serverConfig.serverConfig != null )
+ // Config file.
+ builder.parseConfigFile(serverConfig.serverConfig);
+ else
+ // One dataset.
+ builder.add(serverConfig.datasetPath, serverConfig.dsg, serverConfig.allowUpdate);
+ }
+
+ if ( serverConfig.contentDirectory != null )
+ builder.staticFileBase(serverConfig.contentDirectory) ;
+
+ return builder.build();
+ }
+
+ private void info(FusekiServer server, ServerConfig serverConfig) {
+ if ( super.isQuiet() )
+ return;
+
+ Logger log = Fuseki.serverLog;
+
+ String version = Fuseki.VERSION;
+ String buildDate = Fuseki.BUILD_DATE ;
+
+ if ( version != null && version.equals("${project.version}") )
+ version = null ;
+ if ( buildDate != null && buildDate.equals("${build.time.xsd}") )
+ buildDate = DateTimeUtils.nowAsXSDDateTimeString() ;
+
+ String name = Fuseki.NAME;
+ name = name +" (basic server)";
+
+ if ( version != null ) {
+ if ( Fuseki.developmentMode && buildDate != null )
+ FmtLog.info(log, "%s %s %s", name, version, buildDate) ;
+ else
+ FmtLog.info(log, "%s %s", name, version);
+ }
+
+ // Dataset -> Endpoints
+ Map<String, List<String>> mapDatasetEndpoints = description(DataAccessPointRegistry.get(server.getServletContext()));
+
+ if ( serverConfig.empty ) {
+ FmtLog.info(log, "No SPARQL datasets services");
+ } else {
+ if ( serverConfig.datasetPath == null && serverConfig.serverConfig == null )
+ log.error("No dataset path nor server configuration file");
+ }
+
+ if ( serverConfig.datasetPath != null ) {
+ if ( mapDatasetEndpoints.size() != 1 )
+ log.error("Expected only one dataset");
+ List<String> endpoints = mapDatasetEndpoints.get(serverConfig.datasetPath);
+ FmtLog.info(log, "Dataset Type = %s", serverConfig.datasetDescription);
+ FmtLog.info(log, "Path = %s; Services = %s", serverConfig.datasetPath, endpoints);
+ }
+ if ( serverConfig.serverConfig != null ) {
+ // May be many datasets and services.
+ FmtLog.info(log, "Configuration file %s", serverConfig.serverConfig);
+ mapDatasetEndpoints.forEach((path, endpoints)->{
+ FmtLog.info(log, "Path = %s; Services = %s", path, endpoints);
+ });
+ }
+
+ if ( serverConfig.contentDirectory != null )
+ FmtLog.info(log, "Static files = %s", serverConfig.contentDirectory);
+
+ if ( super.isVerbose() )
+ PlatformInfo.logDetailsVerbose(log);
+ else if ( !super.isQuiet() )
+ PlatformInfo.logDetails(log);
+ }
+
+ private static Map<String, List<String>> description(DataAccessPointRegistry reg) {
+ Map<String, List<String>> desc = new LinkedHashMap<>();
+ reg.forEach((ds,dap)->{
+ List<String> endpoints = new ArrayList<>();
+ desc.put(ds, endpoints);
+ DataService dSrv = dap.getDataService();
+ dSrv.getOperations().forEach((op)->{
+ dSrv.getEndpoints(op).forEach(ep-> {
+ String x = ep.getEndpoint();
+ if ( x.isEmpty() )
+ x = "quads";
+ endpoints.add(x);
+ });
+ });
+ });
+ return desc;
+ }
+
+ @Override
+ protected String getCommandName() {
+ return "fuseki";
+ }
+ }
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/20eb07ca/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/ServerConfig.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/ServerConfig.java b/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/ServerConfig.java
new file mode 100644
index 0000000..e8301e6
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/ServerConfig.java
@@ -0,0 +1,51 @@
+/*
+ * 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.cmds;
+
+import org.apache.jena.sparql.core.DatasetGraph;
+
+/** Setup details (command line, config file) from command line processing.
+ * Thisis built by {@link FusekiBasicMain#exec}.
+ * This is processed by {@link FusekiBasicMain#buildServer}.
+ */
+class ServerConfig {
+ /** Server port */
+ public int port;
+ /** Loopback */
+ public boolean loopback = false;
+ /** The dataset name */
+ public String datasetPath = null;
+ /** Allow update */
+ public boolean allowUpdate = false;
+
+ // This is set ...
+ public DatasetGraph dsg = null;
+ // ... or this.
+ public String serverConfig = null;
+
+
+ /** Allow there to be no registered datasets without it being an error. */
+ public boolean empty = false ;
+ /** Setup for SPARQLer - validators and general query engine, some pages. */
+ public boolean sparqler = false ;
+ public boolean validators = false ;
+ /** An informative label */
+ public String datasetDescription;
+ public String contentDirectory = null;
+}
\ No newline at end of file
[07/27] jena git commit: Refactor to make subclassing easier
Posted by an...@apache.org.
Refactor to make subclassing easier
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/62656645
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/62656645
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/62656645
Branch: refs/heads/master
Commit: 62656645e698792116e82495320cca131ae45304
Parents: ea7f95e
Author: Andy Seaborne <an...@apache.org>
Authored: Wed Aug 22 16:40:47 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Thu Aug 23 17:15:05 2018 +0100
----------------------------------------------------------------------
.../org/apache/jena/sparql/util/Context.java | 89 +++++++++++++-------
1 file changed, 59 insertions(+), 30 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/62656645/jena-arq/src/main/java/org/apache/jena/sparql/util/Context.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/Context.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/Context.java
index 9318cf1..44c7812 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/util/Context.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/Context.java
@@ -20,6 +20,8 @@ package org.apache.jena.sparql.util ;
import java.util.* ;
import java.util.concurrent.ConcurrentHashMap ;
+import java.util.function.BiConsumer;
+
import org.apache.jena.atlas.lib.Lib ;
import org.apache.jena.query.ARQ ;
import org.apache.jena.sparql.ARQConstants ;
@@ -54,6 +56,44 @@ public class Context {
putAll(cxt) ;
}
+ // All access to the underlying goes via map*.
+
+ protected Object mapGet(Symbol property) {
+ return context.get(property);
+ }
+
+ protected void mapPut(Symbol property, Object value) {
+ if ( readonly )
+ throw new ARQException("Context is readonly") ;
+ if ( property == null )
+ throw new ARQException("Context key is null") ;
+ if ( value == null ) {
+ mapRemove(property) ;
+ return ;
+ }
+ context.put(property, value) ;
+ }
+
+ protected void mapRemove(Symbol property) {
+ context.remove(property);
+ }
+
+ protected boolean mapContains(Symbol property) {
+ return context.containsKey(property);
+ }
+
+ protected Set<Symbol> mapKeySet() {
+ return context.keySet();
+ }
+
+ protected int mapSize() {
+ return context.size();
+ }
+
+ protected void mapForEach(BiConsumer<Symbol, Object> action) {
+ context.forEach(action);
+ }
+
/**
* Return a copy of this context. Modifications of the copy do not affect
* the original context.
@@ -67,7 +107,7 @@ public class Context {
/** Get the object value of a property or null */
@SuppressWarnings("unchecked")
public <T> T get(Symbol property) {
- return (T) context.get(property) ;
+ return (T) mapGet(property) ;
}
/**
@@ -75,7 +115,7 @@ public class Context {
* present .
*/
public Object get(Symbol property, Object defaultValue) {
- Object x = context.get(property) ;
+ Object x = mapGet(property) ;
if ( x == null )
return defaultValue ;
return x ;
@@ -83,26 +123,16 @@ public class Context {
/** Store a named value - overwrites any previous set value */
public void put(Symbol property, Object value) {
- _put(property, value) ;
+ mapPut(property, value) ;
}
/** Store a named value - overwrites any previous set value */
public void set(Symbol property, Object value) {
- _put(property, value) ;
- }
-
- private void _put(Symbol property, Object value) {
- if ( readonly )
- throw new ARQException("Context is readonly") ;
- if ( property == null )
- throw new ARQException("Context key is null") ;
- if ( value == null ) {
- context.remove(property) ;
- return ;
- }
- context.put(property, value) ;
+ mapPut(property, value) ;
}
+ // All access to the underlying goes via map*.
+
/** Store a named value - overwrites any previous set value */
public void set(Symbol property, boolean value) {
if ( value )
@@ -113,19 +143,19 @@ public class Context {
/** Store a named value only if it is not currently set */
public void setIfUndef(Symbol property, Object value) {
- Object x = context.get(property) ;
+ Object x = mapGet(property) ;
if ( x == null )
put(property, value) ;
}
/** Remove any value associated with a property */
public void remove(Symbol property) {
- context.remove(property) ;
+ mapRemove(property) ;
}
/** Remove any value associated with a property - alternative method name */
public void unset(Symbol property) {
- context.remove(property) ;
+ remove(property) ;
}
// ---- Helpers
@@ -134,7 +164,7 @@ public class Context {
/** Is a property set? */
public boolean isDefined(Symbol property) {
- return context.containsKey(property) ;
+ return mapContains(property) ;
}
/** Is a property not set? */
@@ -157,7 +187,7 @@ public class Context {
/** Get the value a string (uses .toString() if the value is not null) */
public String getAsString(Symbol property) {
- Object x = context.get(property) ;
+ Object x = mapGet(property) ;
if ( x == null )
return null ;
return x.toString() ;
@@ -167,7 +197,7 @@ public class Context {
public int getInt(Symbol symbol, int defaultValue) {
if ( isUndef(symbol) )
return defaultValue ;
- Object obj = context.get(symbol) ;
+ Object obj = mapGet(symbol) ;
if ( obj instanceof String ) {
return Integer.parseInt((String)obj) ;
} else if ( obj instanceof Integer ) {
@@ -181,7 +211,7 @@ public class Context {
public long getLong(Symbol symbol, long defaultValue) {
if ( isUndef(symbol) )
return defaultValue ;
- Object obj = context.get(symbol) ;
+ Object obj = mapGet(symbol) ;
if ( obj instanceof String ) {
return Long.parseLong((String)obj) ;
} else if ( obj instanceof Integer ) {
@@ -189,7 +219,7 @@ public class Context {
} else if ( obj instanceof Long ) {
return ((Long)obj) ;
} else {
- throw new ARQException("Value for "+symbol+" is not a recoginized class: "+Lib.className(obj)) ;
+ throw new ARQException("Value for "+symbol+" is not a recognized class: "+Lib.className(obj)) ;
}
}
@@ -197,7 +227,7 @@ public class Context {
if ( readonly )
throw new ARQException("Context is readonly") ;
if ( other != null )
- other.context.forEach(this::put);
+ other.mapForEach(this::put);
}
// -- true/false
@@ -299,12 +329,12 @@ public class Context {
/** Set of properties (as Symbols) currently defined */
public Set<Symbol> keys() {
- return context.keySet() ;
+ return mapKeySet() ;
}
/** Return the number of context items */
public int size() {
- return context.size() ;
+ return mapSize() ;
}
@Override
@@ -319,7 +349,7 @@ public class Context {
return x ;
}
- /** Setup a context using anouter context and a dataset.
+ /** Setup a context using another context and a dataset.
* This adds the current time.
*/
public static Context setupContextExec(Context globalContext, DatasetGraph dataset) {
@@ -343,7 +373,7 @@ public class Context {
return context;
}
- /** Merge an outer (fglobal) and local context to produce a new context
+ /** Merge an outer (global) and local context to produce a new context
* The new context is always a separate copy.
*/
public static Context mergeCopy(Context contextGlobal, Context contextLocal) {
@@ -383,5 +413,4 @@ public class Context {
return false ;
return true ;
}
-
}
[27/27] jena git commit: JENA-1594: Merge commit 'refs/pull/465/head'
of https://github.com/apache/jena
Posted by an...@apache.org.
JENA-1594: Merge commit 'refs/pull/465/head' of https://github.com/apache/jena
This closes #465.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/c8a31476
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/c8a31476
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/c8a31476
Branch: refs/heads/master
Commit: c8a31476d4072b44790965d5d79963c545e6c2ec
Parents: 0a0b831 3b01252
Author: Andy Seaborne <an...@apache.org>
Authored: Fri Aug 31 13:04:11 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Fri Aug 31 13:04:11 2018 +0100
----------------------------------------------------------------------
.travis.yml | 2 +-
.../org/apache/jena/query/DatasetFactory.java | 9 +-
.../jena/query/QueryExecutionFactory.java | 62 ++-
.../apache/jena/sparql/core/DatasetGraph.java | 4 +-
.../jena/sparql/core/DatasetGraphCopyAdd.java | 41 --
.../jena/sparql/core/DatasetGraphFactory.java | 5 +-
.../sparql/core/DatasetGraphFilteredView.java | 159 ++++++
.../jena/sparql/core/DatasetGraphReadOnly.java | 21 +-
.../jena/sparql/core/DatasetGraphWrapper.java | 17 +-
.../sparql/core/DatasetGraphWrapperView.java | 30 ++
.../engine/QueryEngineFactoryWrapper.java | 13 +-
.../jena/sparql/engine/QueryExecutionBase.java | 36 +-
.../org/apache/jena/sparql/expr/ExprSystem.java | 9 +-
.../jena/sparql/sse/builders/BuilderLib.java | 245 ++++-----
.../org/apache/jena/sparql/util/Context.java | 89 +--
.../org/apache/jena/sparql/util/FmtUtils.java | 2 +-
.../org/apache/jena/sparql/core/TS_Core.java | 3 +-
.../core/TestDatasetGraphFilteredView.java | 162 ++++++
jena-base/pom.xml | 7 +
.../rulesys/impl/TestLPBRuleEngine.java | 4 +-
.../tdb2/solver/StageGeneratorDirectTDB.java | 2 +-
.../jena/tdb2/store/GraphViewSwitchable.java | 11 +-
jena-fuseki2/jena-fuseki-access/pom.xml | 104 ++++
.../fuseki/access/AssemblerAccessDataset.java | 63 +++
.../access/AssemblerSecurityRegistry.java | 130 +++++
.../fuseki/access/AuthorizationService.java | 30 ++
.../jena/fuseki/access/DataAccessCtl.java | 163 ++++++
.../jena/fuseki/access/DataAccessLib.java | 81 +++
.../access/DatasetGraphAccessControl.java | 59 ++
.../fuseki/access/Filtered_REST_Quads_R.java | 43 ++
.../fuseki/access/Filtered_SPARQL_GSP_R.java | 39 ++
.../access/Filtered_SPARQL_QueryDataset.java | 63 +++
.../apache/jena/fuseki/access/GraphFilter.java | 76 +++
.../jena/fuseki/access/GraphFilterTDB1.java | 70 +++
.../jena/fuseki/access/GraphFilterTDB2.java | 70 +++
.../apache/jena/fuseki/access/InitSecurity.java | 38 ++
.../jena/fuseki/access/SecurityContext.java | 162 ++++++
.../jena/fuseki/access/SecurityRegistry.java | 63 +++
.../jena/fuseki/access/VocabSecurity.java | 55 ++
.../org.apache.jena.sys.JenaSubsystemLifecycle | 1 +
.../access/AbstractTestSecurityAssembler.java | 326 +++++++++++
.../jena/fuseki/access/AccessTestLib.java | 70 +++
.../fuseki/access/TS_SecurityFiltering.java | 44 ++
.../fuseki/access/TestAssemblerSeparate.java | 26 +
.../jena/fuseki/access/TestAssemblerShared.java | 26 +
.../access/TestSecurityAssemblerBuild.java | 46 ++
.../fuseki/access/TestSecurityFilterFuseki.java | 315 +++++++++++
.../fuseki/access/TestSecurityFilterLocal.java | 355 ++++++++++++
.../src/test/resources/log4j.properties | 40 ++
.../testing/Access/assem-security-shared.ttl | 58 ++
.../testing/Access/assem-security.ttl | 63 +++
.../apache/jena/fuseki/cmds/FusekiBasicCmd.java | 539 +------------------
.../jena/fuseki/cmds/FusekiBasicMain.java | 513 ++++++++++++++++++
.../apache/jena/fuseki/cmds/ServerConfig.java | 51 ++
jena-fuseki2/jena-fuseki-core/pom.xml | 2 +
.../java/org/apache/jena/fuseki/Fuseki.java | 2 +-
.../jena/fuseki/build/FusekiBuildLib.java | 5 +-
.../apache/jena/fuseki/build/FusekiBuilder.java | 3 +
.../apache/jena/fuseki/build/FusekiConfig.java | 3 +-
.../apache/jena/fuseki/build/FusekiConst.java | 41 ++
.../org/apache/jena/fuseki/cmd/FusekiCmd.java | 6 +-
.../org/apache/jena/fuseki/cmd/JettyFuseki.java | 325 +++++++++++
.../apache/jena/fuseki/ctl/ActionAsyncTask.java | 1 -
.../apache/jena/fuseki/ctl/ActionBackup.java | 65 ---
.../jena/fuseki/ctl/ActionBackupList.java | 94 ----
.../org/apache/jena/fuseki/ctl/ActionItem.java | 46 ++
.../org/apache/jena/fuseki/ctl/ActionStats.java | 11 +-
.../apache/jena/fuseki/ctl/JsonDescription.java | 73 +++
.../org/apache/jena/fuseki/ctl/TaskBase.java | 4 +-
.../apache/jena/fuseki/jetty/JettyFuseki.java | 325 -----------
.../org/apache/jena/fuseki/jetty/JettyLib.java | 169 ++++++
.../apache/jena/fuseki/mgt/ActionBackup.java | 68 +++
.../jena/fuseki/mgt/ActionBackupList.java | 95 ++++
.../apache/jena/fuseki/mgt/ActionDatasets.java | 7 +-
.../org/apache/jena/fuseki/mgt/ActionItem.java | 46 --
.../jena/fuseki/mgt/ActionServerStatus.java | 12 +-
.../apache/jena/fuseki/mgt/JsonDescription.java | 72 ---
.../org/apache/jena/fuseki/mgt/MgtConst.java | 52 --
.../java/org/apache/jena/fuseki/mgt/MgtJMX.java | 61 ---
.../apache/jena/fuseki/mgt/ServerMgtConst.java | 39 ++
.../apache/jena/fuseki/mgt/ServiceMXBean.java | 32 --
.../apache/jena/fuseki/server/Operation.java | 6 +-
.../apache/jena/fuseki/server/ServerConst.java | 41 ++
.../apache/jena/fuseki/servlets/ActionREST.java | 9 +
.../jena/fuseki/servlets/ActionService.java | 2 +-
.../jena/fuseki/servlets/REST_Quads_R.java | 2 +-
.../jena/fuseki/servlets/REST_Quads_RW.java | 4 +-
.../apache/jena/fuseki/servlets/SPARQL_GSP.java | 16 +-
.../jena/fuseki/servlets/SPARQL_GSP_R.java | 13 +-
.../jena/fuseki/servlets/SPARQL_GSP_RW.java | 21 +-
.../jena/fuseki/servlets/SPARQL_Query.java | 16 +-
.../servlets/ServiceDispatchRegistry.java | 10 +-
.../jena/fuseki/system/FusekiLogging.java | 18 +-
.../webapp/FusekiServerEnvironmentInit.java | 5 +-
.../apache/jena/fuseki/webapp/SystemState.java | 16 -
.../src/main/webapp/WEB-INF/web.xml | 8 +-
.../src/main/webapp/js/app/controllers/.svnkeep | 0
.../src/main/webapp/js/app/layouts/.svnkeep | 0
.../src/main/webapp/js/app/routers/.svnkeep | 0
.../src/main/webapp/js/app/views/.svnkeep | 0
.../java/org/apache/jena/fuseki/ServerCtl.java | 2 +-
.../java/org/apache/jena/fuseki/TS_Fuseki.java | 2 +-
.../java/org/apache/jena/fuseki/TestAdmin.java | 19 +-
.../jena/fuseki/embedded/FusekiServer.java | 126 +++--
.../jena/fuseki/embedded/JettyServer.java | 369 +++++++++++++
jena-fuseki2/pom.xml | 1 +
.../jena/permissions/SecurityEvaluator.java | 67 +--
.../rdfconnection/RDFConnectionFactory.java | 25 +
.../jena/rdfconnection/RDFConnectionRemote.java | 2 +-
pom.xml | 4 +-
110 files changed, 5432 insertions(+), 1746 deletions(-)
----------------------------------------------------------------------
[12/27] jena git commit: Use the connection's httpClient and
httpContext for fetchDataset().
Posted by an...@apache.org.
Use the connection's httpClient and httpContext for fetchDataset().
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/dfa40be2
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/dfa40be2
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/dfa40be2
Branch: refs/heads/master
Commit: dfa40be260e8e604223693f25d93ea3dc675b7c5
Parents: 09f0e8b
Author: Andy Seaborne <an...@apache.org>
Authored: Fri Aug 24 12:03:32 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Fri Aug 24 12:03:32 2018 +0100
----------------------------------------------------------------------
.../java/org/apache/jena/rdfconnection/RDFConnectionRemote.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/dfa40be2/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionRemote.java
----------------------------------------------------------------------
diff --git a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionRemote.java b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionRemote.java
index 7570daf..7f730c9 100644
--- a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionRemote.java
+++ b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionRemote.java
@@ -421,7 +421,7 @@ public class RDFConnectionRemote implements RDFConnection {
throw new ARQException("Dataset operations not available - no dataset URL provided");
Dataset ds = DatasetFactory.createTxnMem();
Txn.executeWrite(ds, ()->{
- TypedInputStream s = exec(()->HttpOp.execHttpGet(destination, acceptDataset));
+ TypedInputStream s = exec(()->HttpOp.execHttpGet(destination, acceptDataset, this.httpClient, this.httpContext));
Lang lang = RDFLanguages.contentTypeToLang(s.getContentType());
RDFDataMgr.read(ds, s, lang);
});
[24/27] jena git commit: Correct indentation.
Posted by an...@apache.org.
Correct indentation.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/228f4b96
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/228f4b96
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/228f4b96
Branch: refs/heads/master
Commit: 228f4b96e0eea3081d6b707613b63eaba6ae013f
Parents: 5e00033
Author: Andy Seaborne <an...@apache.org>
Authored: Mon Aug 27 18:21:00 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Mon Aug 27 18:21:00 2018 +0100
----------------------------------------------------------------------
jena-fuseki2/jena-fuseki-core/src/main/webapp/WEB-INF/web.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/228f4b96/jena-fuseki2/jena-fuseki-core/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/webapp/WEB-INF/web.xml b/jena-fuseki2/jena-fuseki-core/src/main/webapp/WEB-INF/web.xml
index b9f1ff1..0737e76 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/webapp/WEB-INF/web.xml
+++ b/jena-fuseki2/jena-fuseki-core/src/main/webapp/WEB-INF/web.xml
@@ -232,8 +232,8 @@
</servlet>
<servlet-mapping>
- <servlet-name>DumpServlet</servlet-name>
- <url-pattern>/$/dump</url-pattern>
+ <servlet-name>DumpServlet</servlet-name>
+ <url-pattern>/$/dump</url-pattern>
</servlet-mapping>
<servlet-mapping>
[20/27] jena git commit: JENA-1594: General mechanism for data accesx
control using DatasetGraphFilteredView
Posted by an...@apache.org.
JENA-1594: General mechanism for data accesx control using DatasetGraphFilteredView
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/99b99463
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/99b99463
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/99b99463
Branch: refs/heads/master
Commit: 99b994637cd1d91ce1eba0d61e0576776dcf708e
Parents: 7b0661f
Author: Andy Seaborne <an...@apache.org>
Authored: Sun Aug 26 18:08:53 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sun Aug 26 19:27:52 2018 +0100
----------------------------------------------------------------------
.../sparql/core/DatasetGraphFilteredView.java | 9 +-
.../jena/sparql/core/DatasetGraphWrapper.java | 17 +-
.../sparql/core/DatasetGraphWrapperView.java | 30 ++++
.../engine/QueryEngineFactoryWrapper.java | 13 +-
.../org/apache/jena/sparql/core/TS_Core.java | 3 +-
.../core/TestDatasetGraphFilteredView.java | 162 +++++++++++++++++
.../jena/fuseki/access/DataAccessCtl.java | 53 ++----
.../jena/fuseki/access/DataAccessLib.java | 14 +-
.../access/DatasetGraphAccessControl.java | 12 +-
.../fuseki/access/DatasetGraphFiltered.java | 144 ---------------
.../fuseki/access/Filtered_REST_Quads_R.java | 22 +--
.../fuseki/access/Filtered_SPARQL_GSP_R.java | 17 +-
.../access/Filtered_SPARQL_QueryDataset.java | 26 +--
.../jena/fuseki/access/SecurityPolicy.java | 50 ++++--
.../access/AbstractTestSecurityAssembler.java | 7 +-
.../jena/fuseki/access/AccessTestLib.java | 70 ++++++++
.../apache/jena/fuseki/access/GraphData.java | 59 -------
.../fuseki/access/TestSecurityFilterFuseki.java | 22 +--
.../fuseki/access/TestSecurityFilterLocal.java | 173 +++++++++++--------
.../apache/jena/fuseki/servlets/ActionREST.java | 9 +
.../jena/fuseki/servlets/REST_Quads_R.java | 10 +-
.../jena/fuseki/servlets/REST_Quads_RW.java | 4 +-
.../apache/jena/fuseki/servlets/SPARQL_GSP.java | 5 -
.../jena/fuseki/servlets/SPARQL_GSP_R.java | 15 +-
.../jena/fuseki/servlets/SPARQL_GSP_RW.java | 21 ++-
25 files changed, 530 insertions(+), 437 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
index a9fa8f2..3084e33 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
@@ -34,7 +34,7 @@ import org.apache.jena.sparql.graph.GraphUnionRead;
* A read-only {@link DatasetGraph} that applies a filter testing all triples and quads
* returned by accessing the data. Only quads where the filter tests for "true" are exposed.
*/
-public class DatasetGraphFilteredView extends DatasetGraphReadOnly {
+public class DatasetGraphFilteredView extends DatasetGraphReadOnly implements DatasetGraphWrapperView {
/*
Write operations
add(Quad)
@@ -104,12 +104,15 @@ public class DatasetGraphFilteredView extends DatasetGraphReadOnly {
@Override
public Iterator<Node> listGraphNodes() {
-// Predicate<Node> notSpecial = x-> ! ( Quad.isDefaultGraph(x)|| Quad.isUnionGraph(x) );
-// return Iter.filter(visibleGraphs.iterator(), notSpecial);
return visibleGraphs.iterator();
}
@Override
+ public long size() {
+ return visibleGraphs.size();
+ }
+
+ @Override
public Graph getUnionGraph() {
return new GraphUnionRead(this, visibleGraphs);
}
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphWrapper.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphWrapper.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphWrapper.java
index 426faef..f1d9861 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphWrapper.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphWrapper.java
@@ -40,7 +40,7 @@ public class DatasetGraphWrapper implements DatasetGraph, Sync
return get();
}
- /** Recursively unwrap a DatasetGraphWrapped.
+ /** Recursively unwrap a {@link DatasetGraphWrapper}.
*
* @return the first found {@link DatasetGraph} that is not an instance of {@link DatasetGraphWrapper}
*/
@@ -51,6 +51,21 @@ public class DatasetGraphWrapper implements DatasetGraph, Sync
}
return dsgw;
}
+
+ /** Recursively unwrap a {@link DatasetGraphWrapper}, stopping at a {@link DatasetGraphWrapper}
+ * that indicate it is "view changing", ie shows quads to the base dataset graph.
+ *
+ * @return the first found {@link DatasetGraph} that is not an instance of {@link DatasetGraphWrapper}
+ */
+ public final DatasetGraph getBaseForQuery() {
+ DatasetGraph dsgw = dsg;
+ while (dsgw instanceof DatasetGraphWrapper) {
+ if ( dsgw instanceof DatasetGraphWrapperView )
+ break;
+ dsgw = ((DatasetGraphWrapper)dsg).getWrapped();
+ }
+ return dsgw;
+ }
/** The dataset to use for redirection - can be overridden.
* It is also guarantee that this is called only once per
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphWrapperView.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphWrapperView.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphWrapperView.java
new file mode 100644
index 0000000..181ace1
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphWrapperView.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+import org.apache.jena.sparql.engine.QueryEngineFactoryWrapper;
+
+/**
+ * Marker interface that indicates a DatasetGraphWrapper
+ * is one that defined a different view on the base dataset data.
+ * Hence, query should not access the wrapped dataset.
+ *
+ * @see QueryEngineFactoryWrapper
+ */
+public interface DatasetGraphWrapperView extends DatasetGraph {}
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryEngineFactoryWrapper.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryEngineFactoryWrapper.java b/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryEngineFactoryWrapper.java
index 2f00eee..9d5f775 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryEngineFactoryWrapper.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryEngineFactoryWrapper.java
@@ -22,9 +22,7 @@ import org.apache.jena.query.Query ;
import org.apache.jena.sparql.algebra.Op ;
import org.apache.jena.sparql.core.DatasetGraph ;
import org.apache.jena.sparql.core.DatasetGraphWrapper ;
-import org.apache.jena.sparql.engine.Plan ;
-import org.apache.jena.sparql.engine.QueryEngineFactory ;
-import org.apache.jena.sparql.engine.QueryEngineRegistry ;
+import org.apache.jena.sparql.core.DatasetGraphWrapperView;
import org.apache.jena.sparql.engine.binding.Binding ;
import org.apache.jena.sparql.util.Context ;
@@ -36,7 +34,8 @@ public class QueryEngineFactoryWrapper implements QueryEngineFactory
@Override
public boolean accept(Query query, DatasetGraph dsg, Context context) {
- if ( !( dsg instanceof DatasetGraphWrapper ) )
+ // DatasetGraphFilteredView changes the seen contents so we can't unwrap it for query.
+ if ( !( dsg instanceof DatasetGraphWrapper ) || dsg instanceof DatasetGraphWrapperView )
return false ;
DatasetGraph dsg2 = ((DatasetGraphWrapper)dsg).getWrapped() ;
return QueryEngineRegistry.findFactory(query, dsg2, context).accept(query, dsg2, context) ;
@@ -44,7 +43,7 @@ public class QueryEngineFactoryWrapper implements QueryEngineFactory
@Override
public Plan create(Query query, DatasetGraph dsg, Binding inputBinding, Context context) {
- if ( ! ( dsg instanceof DatasetGraphWrapper ) )
+ if ( !( dsg instanceof DatasetGraphWrapper ) || dsg instanceof DatasetGraphWrapperView )
return null ;
DatasetGraph dsg2 = ((DatasetGraphWrapper)dsg).getWrapped() ;
return QueryEngineRegistry.findFactory(query, dsg2, context).create(query, dsg2, inputBinding, context) ;
@@ -52,7 +51,7 @@ public class QueryEngineFactoryWrapper implements QueryEngineFactory
@Override
public boolean accept(Op op, DatasetGraph dsg, Context context) {
- if ( ! ( dsg instanceof DatasetGraphWrapper ) )
+ if ( !( dsg instanceof DatasetGraphWrapper ) || dsg instanceof DatasetGraphWrapperView )
return false ;
DatasetGraph dsg2 = ((DatasetGraphWrapper)dsg).getWrapped() ;
return QueryEngineRegistry.findFactory(op, dsg2, context).accept(op, dsg2, context) ;
@@ -60,7 +59,7 @@ public class QueryEngineFactoryWrapper implements QueryEngineFactory
@Override
public Plan create(Op op, DatasetGraph dsg, Binding inputBinding, Context context) {
- if ( ! ( dsg instanceof DatasetGraphWrapper ) )
+ if ( !( dsg instanceof DatasetGraphWrapper ) || dsg instanceof DatasetGraphWrapperView )
return null ;
DatasetGraph dsg2 = ((DatasetGraphWrapper)dsg).getWrapped() ;
return QueryEngineRegistry.findFactory(op, dsg2, context).create(op, dsg2, inputBinding, context) ;
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-arq/src/test/java/org/apache/jena/sparql/core/TS_Core.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/core/TS_Core.java b/jena-arq/src/test/java/org/apache/jena/sparql/core/TS_Core.java
index 800e428..fcdab02 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/core/TS_Core.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/core/TS_Core.java
@@ -40,8 +40,9 @@ import org.junit.runners.Suite ;
, TestDatasetGraphBaseFind_Mem.class
, TestDatasetGraphBaseFindPattern_General.class
, TestDatasetGraphBaseFindPattern_Mem.class
-
, TestSpecialGraphNames.class
+
+ , TestDatasetGraphFilteredView.class
, TestSpecials.class
})
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-arq/src/test/java/org/apache/jena/sparql/core/TestDatasetGraphFilteredView.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/core/TestDatasetGraphFilteredView.java b/jena-arq/src/test/java/org/apache/jena/sparql/core/TestDatasetGraphFilteredView.java
new file mode 100644
index 0000000..4ae6e78
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/core/TestDatasetGraphFilteredView.java
@@ -0,0 +1,162 @@
+/*
+ * 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;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+import java.util.function.Predicate;
+
+import org.apache.jena.atlas.iterator.Iter;
+import org.apache.jena.atlas.lib.Creator;
+import org.apache.jena.atlas.lib.StrUtils;
+import org.apache.jena.graph.Node;
+import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.RDFParser;
+import org.apache.jena.sparql.sse.SSE;
+import org.apache.jena.system.Txn;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Tests for API access via DatasetGraphFiltered
+ */
+@RunWith(Parameterized.class)
+public class TestDatasetGraphFilteredView {
+ @Parameters(name = "{index}: {0}")
+ public static Iterable<Object[]> data() {
+ Creator<DatasetGraph> c1 = DatasetGraphFactory::create;
+ Object[] obj1 = { "General", c1 };
+ Creator<DatasetGraph> c2 = DatasetGraphFactory::createTxnMem;
+ Object[] obj2 = { "TIM", c2 };
+ return Arrays.asList(obj1, obj2);
+ }
+
+ final DatasetGraph basedsg;
+
+ private static String dataStr = StrUtils.strjoinNL
+ ("PREFIX : <http://test/>"
+ ,""
+ ,":s0 :p 0 ."
+ ,":g1 { :s1 :p 1 }"
+ ,":g2 { :s2 :p 2 , '02' }"
+ ,":g3 { :s3 :p 3 , '03' , '003' }"
+ ,":g4 { :s4 :p 4 , '04' , '004', '0004' }"
+ );
+
+ public static Node s0 = SSE.parseNode("<http://test/s0>");
+ public static Node s1 = SSE.parseNode("<http://test/s1>");
+ public static Node s2 = SSE.parseNode("<http://test/s2>");
+ public static Node s3 = SSE.parseNode("<http://test/s3>");
+ public static Node s4 = SSE.parseNode("<http://test/s4>");
+
+ public static Node g1 = SSE.parseNode("<http://test/g1>");
+ public static Node g2 = SSE.parseNode("<http://test/g2>");
+ public static Node g3 = SSE.parseNode("<http://test/g3>");
+ public static Node g4 = SSE.parseNode("<http://test/g4>");
+
+ public static void addTestData(DatasetGraph dsg) {
+ Txn.executeWrite(dsg, ()->{
+ RDFParser.create().fromString(dataStr).lang(Lang.TRIG).parse(dsg);
+ });
+ }
+
+ public TestDatasetGraphFilteredView(String name, Creator<DatasetGraph> source) {
+ basedsg = source.create();
+ addTestData(basedsg);
+ }
+
+ @Test public void filtered1() {
+ Predicate<Quad> filter = x->true;
+ Txn.executeRead(basedsg, ()->{
+ DatasetGraph dsg = new DatasetGraphFilteredView(basedsg, filter, Iter.toList(basedsg.listGraphNodes()));
+ assertSame(basedsg, dsg);
+ });
+ }
+
+ @Test public void filtered2() {
+ Predicate<Quad> filter = x->x.getGraph().equals(g2);
+ Txn.executeRead(basedsg, ()->{
+ DatasetGraph dsg = new DatasetGraphFilteredView(basedsg, filter, Collections.singleton(g1));
+ long x0 = Iter.count(dsg.find(null, null, null, null));
+ assertEquals(2,x0);
+ long x1 = Iter.count(dsg.find(g2, null, null, null));
+ assertEquals(2,x1);
+ long x2 = Iter.count(dsg.find(null, s2, null, null));
+ assertEquals(2,x2);
+ long x3 = Iter.count(dsg.find(g1, null, null, null));
+ assertEquals(0,x3);
+ assertEquals(1, dsg.size());
+ });
+ }
+
+ @Test public void filtered3() {
+ Predicate<Quad> filter = x->x.getSubject().equals(s2);
+ Txn.executeRead(basedsg, ()->{
+ DatasetGraph dsg = new DatasetGraphFilteredView(basedsg, filter, Collections.singleton(g1));
+ long x0 = Iter.count(dsg.find(null, null, null, null));
+ assertEquals(2,x0);
+ long x1 = Iter.count(dsg.find(g2, null, null, null));
+ assertEquals(2,x1);
+ long x2 = Iter.count(dsg.find(null, s2, null, null));
+ assertEquals(2,x2);
+ long x3 = Iter.count(dsg.find(g1, s2, null, null));
+ assertEquals(0,x3);
+ assertEquals(1, dsg.size());
+ });
+ }
+
+ @Test public void filtered4() {
+ Predicate<Quad> filter = x->x.getSubject().equals(s2);
+ Txn.executeRead(basedsg, ()->{
+ DatasetGraph dsg = new DatasetGraphFilteredView(basedsg, filter, Arrays.asList(g1, g2));
+ long x0 = Iter.count(dsg.find(null, null, null, null));
+ assertEquals(2,x0);
+ long x1 = Iter.count(dsg.find(g2, null, null, null));
+ assertEquals(2,x1);
+ long x2 = Iter.count(dsg.find(null, s2, null, null));
+ assertEquals(2,x2);
+ long x3 = Iter.count(dsg.find(g1, s2, null, null));
+ assertEquals(0,x3);
+ assertEquals(2, dsg.size());
+ });
+ }
+
+ @Test public void filtered5() {
+ Predicate<Quad> filter = x-> x.getSubject().equals(s2) || x.getSubject().equals(s1);
+ Txn.executeRead(basedsg, ()->{
+ DatasetGraph dsg = new DatasetGraphFilteredView(basedsg, filter, Arrays.asList(g1, g2));
+ long x0 = Iter.count(dsg.find(null, null, null, null));
+ assertEquals(3,x0);
+ long x1 = Iter.count(dsg.find(g2, null, null, null));
+ assertEquals(2,x1);
+ });
+ }
+
+ private void assertSame(DatasetGraph dsg1, DatasetGraph dsg2) {
+ Set<Quad> quads1 = Iter.toSet(dsg1.find());
+ Set<Quad> quads2 = Iter.toSet(dsg2.find());
+ assertEquals(quads1, quads2);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
index 85b1f31..dc8c913 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
@@ -32,6 +32,7 @@ import org.apache.jena.query.Dataset;
import org.apache.jena.query.DatasetFactory;
import org.apache.jena.riot.WebContent;
import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.DatasetGraphFilteredView;
import org.apache.jena.sparql.util.Context;
import org.apache.jena.sparql.util.Symbol;
import org.eclipse.jetty.security.SecurityHandler;
@@ -54,47 +55,24 @@ public class DataAccessCtl {
/** Get the user from the servlet context via {@link HttpServletRequest#getRemoteUser} */
public static final Function<HttpAction, String> requestUserServlet = (action)->action.request.getRemoteUser();
-// /** Build a fuseki server with controlled access enabled. */
-// public static FusekiServer controlledFuseki(int port, Function<HttpAction, String> determineUser, Consumer<FusekiServer.Builder> configure) {
-// FusekiServer.Builder b = controlledFuseki(port, determineUser);
-// configure.accept(b);
-// return b.build();
-// }
-//
-// /** Builder for a read-only Fuseki server with controlled access actions enabled. */
-// public static FusekiServer.Builder controlledFuseki(int port, Function<HttpAction, String> determineUser) {
-// ServiceDispatchRegistry sdr = new ServiceDispatchRegistry(false);
-// ActionService actionQuery = new Filtered_SPARQL_QueryDataset(determineUser);
-// ActionService actionGspR = new Filtered_SPARQL_GSP_R(determineUser);
-// ActionService actionQuadsR = new Filtered_REST_Quads_R(determineUser);
-//
-// // Create empty and only add "read" operations.
-// FusekiServer.Builder builder = FusekiServer.create(sdr)
-// .port(port)
-// .registerOperation(Operation.Query, WebContent.contentTypeSPARQLQuery, actionQuery)
-// .registerOperation(Operation.GSP_R, actionGspR)
-// .registerOperation(Operation.Quads_R, actionQuadsR);
-// return builder;
-// }
-
/**
- * Enable data access control on a {@link DatasetGraph}. This modifies the
+ * Add data access control information on a {@link DatasetGraph}. This modifies the
* {@link DatasetGraph}'s {@link Context}.
*/
- public static void controlledDataset(DatasetGraph dsg, SecurityRegistry reg) {
+ private static void controlledDataset(DatasetGraph dsg, SecurityRegistry reg) {
// Or wrapper.
dsg.getContext().set(symControlledAccess, true);
dsg.getContext().set(symSecurityRegistry, reg);
}
- /**
- * Enable data access control on a {@link Dataset}. This modifies the
- * {@link Dataset}'s {@link Context}.
- */
- public static void controlledDataset(Dataset ds, SecurityRegistry reg) {
- ds.getContext().set(symControlledAccess, true);
- ds.getContext().set(symSecurityRegistry, reg);
- }
+// /**
+// * Enable data access control on a {@link Dataset}. This modifies the
+// * {@link Dataset}'s {@link Context}.
+// */
+// private static void controlledDataset(Dataset ds, SecurityRegistry reg) {
+// ds.getContext().set(symControlledAccess, true);
+// ds.getContext().set(symSecurityRegistry, reg);
+// }
/**
* Return a {@link DatasetGraph} with added data access control. Use of the original
@@ -149,7 +127,7 @@ public class DataAccessCtl {
* query/GSP/Quads go to the data-filtering versions of the {@link ActionService ActionServices}.
* (It is better to create the server via {@link #DataAccessCtl.builder} first rather than modify afterwards.)
*/
- public static void enable(FusekiServer server, Function<HttpAction, String> determineUser) {
+ public static void modifyForAccessCtl(FusekiServer server, Function<HttpAction, String> determineUser) {
/*
* Reconfigure standard Jena Fuseki, replacing the default implementation of "query"
* with a filtering one. This for this server only.
@@ -176,4 +154,11 @@ public class DataAccessCtl {
return true;
return false;
}
+
+ /**
+ * Return a read-only {@link DatasetGraphFilteredView} that fulfils the {@link SecurityPolicy}.
+ */
+ public static DatasetGraphFilteredView filteredDataset(DatasetGraph dsg, SecurityPolicy sCxt) {
+ return new DatasetGraphFilteredView(dsg, sCxt.predicateQuad(), sCxt.visibleGraphs());
+ }
}
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java
index 4329cc6..127aa92 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessLib.java
@@ -40,7 +40,6 @@ class DataAccessLib {
sCxt = noSecurityPolicy();
return sCxt;
}
-
/** Get the {@link SecurityRegistry} for an action/query/dataset */
static SecurityRegistry getSecurityRegistry(HttpAction action, DatasetGraph dsg) {
@@ -54,5 +53,18 @@ class DataAccessLib {
// Should not get here.
throw new InternalError();
}
+
+ static DatasetGraph decideDataset(HttpAction action, Function<HttpAction, String> requestUser) {
+ DatasetGraph dsg = action.getDataset();
+ if ( dsg == null )
+ return dsg;//super.actOn(action);
+ if ( ! DataAccessCtl.isAccessControlled(dsg) )
+ // Not access controlled.
+ return dsg;//super.actOn(action);
+ SecurityPolicy sCxt = DataAccessLib.getSecurityPolicy(action, dsg, requestUser);
+ dsg = DatasetGraphAccessControl.removeWrapper(dsg);
+ dsg = DataAccessCtl.filteredDataset(dsg, sCxt);
+ return dsg;
+ }
}
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphAccessControl.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphAccessControl.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphAccessControl.java
index d770ade..f58bdcd 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphAccessControl.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphAccessControl.java
@@ -41,9 +41,19 @@ class DatasetGraphAccessControl extends DatasetGraphWrapper {
* Return the underlying {@code DatasetGraph}. If the argument is not a
* {@code DatasetGraphAccessControl}, return the argument.
*/
- public static DatasetGraph unwrap(DatasetGraph dsg) {
+ public static DatasetGraph removeWrapper(DatasetGraph dsg) {
if ( ! ( dsg instanceof DatasetGraphAccessControl ) )
return dsg;
return ((DatasetGraphAccessControl)dsg).getWrapped();
}
+
+ /**
+ * Return the underlying {@code DatasetGraph}. If the argument is not a
+ * {@code DatasetGraphAccessControl}, return null.
+ */
+ public static DatasetGraph unwrapOrNull(DatasetGraph dsg) {
+ if ( ! ( dsg instanceof DatasetGraphAccessControl ) )
+ return null;
+ return ((DatasetGraphAccessControl)dsg).getWrapped();
+ }
}
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphFiltered.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphFiltered.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphFiltered.java
deleted file mode 100644
index a7842ba..0000000
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DatasetGraphFiltered.java
+++ /dev/null
@@ -1,144 +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.access;
-
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.function.Predicate;
-
-import org.apache.jena.atlas.iterator.Iter;
-import org.apache.jena.graph.Graph;
-import org.apache.jena.graph.Node;
-import org.apache.jena.sparql.core.DatasetGraph;
-import org.apache.jena.sparql.core.DatasetGraphReadOnly;
-import org.apache.jena.sparql.core.GraphView;
-import org.apache.jena.sparql.core.Quad;
-import org.apache.jena.sparql.graph.GraphReadOnly;
-import org.apache.jena.sparql.graph.GraphUnionRead;
-
-/**
- * A read-only {@link DatasetGraph} that applies a filter testing all triples and quads
- * returned by accessing the data. Only quads where the filter tests for "true" are exposed.
- *
- */
-public class DatasetGraphFiltered extends DatasetGraphReadOnly {
-
- // Or DatasetGraphTriplesQuads
-
- // Core operations at the triple/quad level.
- // This would work for TDB where the root access is triples/quads
- // but not for graph-style root access.
- /*
- Write operations
- add(Quad)
- delete(Quad)
- add(Node, Node, Node, Node)
- delete(Node, Node, Node, Node)
- deleteAny(Node, Node, Node, Node)
- clear()
-
- Read operations
- listGraphNodes()
- isEmpty()
- find()
- find(Quad)
- find(Node, Node, Node, Node)
- findNG(Node, Node, Node, Node)
- contains(Quad)
- contains(Node, Node, Node, Node)
- size()
- toString()
- */
- /*
- getGraph(Node)
- getDefaultGraph()
- containsGraph(Node)
- */
-
- private final Predicate<Quad> quadFilter;
- private final Collection<Node> visibleGraphs;
-
- public DatasetGraphFiltered(DatasetGraph dsg, Predicate<Quad> filter, Collection<Node> visibleGraphs) {
- super(dsg);
- this.quadFilter = filter;
- this.visibleGraphs = visibleGraphs;
- }
-
- private boolean filter(Quad quad) {
- return quadFilter.test(quad);
- }
-
- private Iterator<Quad> filter(Iterator<Quad> iter) {
- return Iter.filter(iter, this::filter);
- }
-
- // Need to intercept these because otherwise that are a GraphView of the wrapped "dsg", not this one.
-
- @Override
- public Graph getDefaultGraph()
- {
- Graph g = GraphView.createDefaultGraph(this);
- return new GraphReadOnly(g);
- }
-
- @Override
- public Graph getGraph(Node graphNode) {
- if ( Quad.isUnionGraph(graphNode))
- return getUnionGraph();
- Graph g = GraphView.createNamedGraph(this, graphNode);
- return new GraphReadOnly(g);
- }
-
- @Override
- public Graph getUnionGraph() {
- return new GraphUnionRead(get(), visibleGraphs);
- }
-
- @Override
- public Iterator<Quad> find() {
- return filter(super.find());
- }
-
- @Override public Iterator<Quad> find(Node g, Node s, Node p, Node o) {
- // Need union handling if for general API use.
- return filter(super.find(g, s, p, o));
- }
-
- @Override public Iterator<Quad> find(Quad quad) {
- // union
- return filter(super.find(quad));
- }
-
- @Override public Iterator<Quad> findNG(Node g, Node s, Node p , Node o) {
- // union
- return filter(super.findNG(g, s, p, o));
- }
-
- @Override public boolean contains(Node g, Node s, Node p , Node o) {
- return filter(super.find(g, s, p, o)).hasNext();
- }
-
- @Override public boolean contains(Quad quad) {
- return filter(super.find(quad)).hasNext();
- }
-
- @Override public boolean isEmpty() {
- return ! this.find().hasNext();
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_R.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_R.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_R.java
index 9a7fdd0..f5e7a78 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_R.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_R.java
@@ -19,12 +19,10 @@
package org.apache.jena.fuseki.access;
import java.util.function.Function;
-import java.util.function.Predicate;
import org.apache.jena.fuseki.servlets.HttpAction;
import org.apache.jena.fuseki.servlets.REST_Quads_R;
import org.apache.jena.sparql.core.DatasetGraph;
-import org.apache.jena.sparql.core.Quad;
/**
* Filter for {@link REST_Quads_R} that inserts a security filter on read-access to the
@@ -39,23 +37,7 @@ public class Filtered_REST_Quads_R extends REST_Quads_R {
}
@Override
- protected void validate(HttpAction action) {
- super.validate(action);
- }
-
- // Where? REST_Quads_R < REST_Quads < ActionREST < ActionService
- @Override
- protected DatasetGraph actOn(HttpAction action) {
- DatasetGraph dsg = action.getDataset();
- if ( dsg == null )
- return dsg;//super.actOn(action);
- if ( ! DataAccessCtl.isAccessControlled(dsg) )
- // Not access controlled.
- return dsg;//super.actOn(action);
- SecurityPolicy sCxt = DataAccessLib.getSecurityPolicy(action, dsg, requestUser);
- dsg = DatasetGraphAccessControl.unwrap(dsg);
- Predicate<Quad> filter = sCxt.predicateQuad();
- dsg = new DatasetGraphFiltered(dsg, filter, sCxt.visibleGraphs());
- return dsg;
+ protected DatasetGraph decideDataset(HttpAction action) {
+ return DataAccessLib.decideDataset(action, requestUser);
}
}
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_R.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_R.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_R.java
index d2803cc..5634c7c 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_R.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_R.java
@@ -19,12 +19,10 @@
package org.apache.jena.fuseki.access;
import java.util.function.Function;
-import java.util.function.Predicate;
import org.apache.jena.fuseki.servlets.HttpAction;
import org.apache.jena.fuseki.servlets.SPARQL_GSP_R;
import org.apache.jena.sparql.core.DatasetGraph;
-import org.apache.jena.sparql.core.Quad;
public class Filtered_SPARQL_GSP_R extends SPARQL_GSP_R {
@@ -34,19 +32,8 @@ public class Filtered_SPARQL_GSP_R extends SPARQL_GSP_R {
this.requestUser = determineUser;
}
- // Where? SPARQL_GSP_R < SPARQL_GSP < ActionREST < ActionService
@Override
- protected DatasetGraph actOn(HttpAction action) {
- DatasetGraph dsg = action.getDataset();
- if ( dsg == null )
- return dsg;//super.actOn(action);
- if ( ! DataAccessCtl.isAccessControlled(dsg) )
- // Not access controlled.
- return dsg;//super.actOn(action);
- SecurityPolicy sCxt = DataAccessLib.getSecurityPolicy(action, dsg, requestUser);
- dsg = DatasetGraphAccessControl.unwrap(dsg);
- Predicate<Quad> filter = sCxt.predicateQuad();
- dsg = new DatasetGraphFiltered(dsg, filter, sCxt.visibleGraphs());
- return dsg;
+ protected DatasetGraph decideDataset(HttpAction action) {
+ return DataAccessLib.decideDataset(action, requestUser);
}
}
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
index 596bef1..49efc4f 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
@@ -24,7 +24,6 @@ import org.apache.jena.fuseki.servlets.ActionService;
import org.apache.jena.fuseki.servlets.HttpAction;
import org.apache.jena.fuseki.servlets.SPARQL_QueryDataset;
import org.apache.jena.query.Dataset;
-import org.apache.jena.query.DatasetFactory;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.sparql.core.DatasetGraph;
@@ -41,25 +40,26 @@ public class Filtered_SPARQL_QueryDataset extends SPARQL_QueryDataset {
@Override
protected QueryExecution createQueryExecution(HttpAction action, Query query, Dataset dataset) {
// Server database, not the possibly dynamically built "dataset"
- // ---- XXX DRY
DatasetGraph dsg = action.getDataset();
if ( dsg == null )
return super.createQueryExecution(action, query, dataset);
if ( ! DataAccessCtl.isAccessControlled(dsg) )
return super.createQueryExecution(action, query, dataset);
-
+
+ // XXX Generalize to any DSG.
SecurityPolicy sCxt = DataAccessLib.getSecurityPolicy(action, dataset.asDatasetGraph(), requestUser);
- if ( dsg instanceof DatasetGraphAccessControl ) {
- // Take off one layer.
- dsg = DatasetGraphAccessControl.unwrap(dsg);
- // Add back the Dataset for the createQueryExecution call.
- dataset = DatasetFactory.wrap(dsg);
- }
- // ----
- QueryExecution qExec = super.createQueryExecution(action, query, dataset);
- if ( sCxt != null )
- sCxt.filterTDB(dsg, qExec);
+ QueryExecution qExec = sCxt.createQueryExecution(query, dsg);
+
+// if ( dsg instanceof DatasetGraphAccessControl ) {
+// // Take off one layer.
+// dsg = DatasetGraphAccessControl.removeWrapper(dsg);
+// // Add back the Dataset for the createQueryExecution call.
+// dataset = DatasetFactory.wrap(dsg);
+// }
+// QueryExecution qExec = super.createQueryExecution(action, query, dataset);
+// if ( sCxt != null )
+// sCxt.filterTDB(dsg, qExec);
return qExec;
}
}
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
index 8d59911..c0d420a 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
@@ -25,7 +25,10 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import org.apache.jena.graph.Node;
+import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
+import org.apache.jena.query.QueryExecutionFactory;
+import org.apache.jena.query.QueryFactory;
import org.apache.jena.sparql.core.DatasetGraph;
import org.apache.jena.sparql.core.Quad;
import org.apache.jena.sparql.util.Context;
@@ -61,9 +64,13 @@ public class SecurityPolicy {
this(Arrays.asList(graphNames));
}
- public SecurityPolicy(Collection<Node> graphNames) {
- this.graphNames.addAll(graphNames);
- this.matchDefaultGraph = graphNames.stream().anyMatch(Quad::isDefaultGraph);
+ public SecurityPolicy(Collection<Node> visibleGraphs) {
+ this.graphNames.addAll(visibleGraphs);
+ this.matchDefaultGraph = visibleGraphs.stream().anyMatch(Quad::isDefaultGraph);
+ if ( matchDefaultGraph ) {
+ this.graphNames.remove(Quad.defaultGraphIRI);
+ this.graphNames.remove(Quad.defaultGraphNodeGenerated);
+ }
}
public Collection<Node> visibleGraphs() {
@@ -74,17 +81,29 @@ public class SecurityPolicy {
* Apply a filter suitable for the TDB-backed {@link DatasetGraph}, to the {@link Context} of the
* {@link QueryExecution}. This does not modify the {@link DatasetGraph}
*/
- public void filterTDB(DatasetGraph dsg, QueryExecution qExec) {
+ /*package*/ void filterTDB(DatasetGraph dsg, QueryExecution qExec) {
GraphFilter<?> predicate = predicate(dsg);
qExec.getContext().set(predicate.getContextKey(), predicate);
}
+
+ public QueryExecution createQueryExecution(String queryString, DatasetGraph dsg) {
+ return createQueryExecution(QueryFactory.create(queryString), dsg);
+ }
- /** Modify the {@link Context} of the TDB-backed {@link DatasetGraph}. */
- public void filterTDB(DatasetGraph dsg) {
- GraphFilter<?> predicate = predicate(dsg);
- dsg.getContext().set(predicate.getContextKey(), predicate);
+ public QueryExecution createQueryExecution(Query query, DatasetGraph dsg) {
+ if ( ! ( dsg instanceof DatasetGraphAccessControl ) ) {
+ return QueryExecutionFactory.create(query, dsg);
+ }
+ if ( isAccessControlledTDB(dsg) ) {
+ QueryExecution qExec = QueryExecutionFactory.create(query, dsg);
+ filterTDB(dsg, qExec);
+ return qExec;
+ }
+
+ DatasetGraph dsgA = DataAccessCtl.filteredDataset(dsg, this);
+ return QueryExecutionFactory.create(query, dsgA);
}
-
+
@Override
public String toString() {
return "dft:"+matchDefaultGraph+" / "+graphNames.toString();
@@ -111,7 +130,7 @@ public class SecurityPolicy {
* TDB database.
*/
public GraphFilter<?> predicate(DatasetGraph dsg) {
- dsg = DatasetGraphAccessControl.unwrap(dsg);
+ dsg = DatasetGraphAccessControl.removeWrapper(dsg);
// dsg has to be the database dataset, not wrapped.
// DatasetGraphSwitchable is wrapped but should not be unwrapped.
if ( TDBFactory.isTDB1(dsg) )
@@ -121,6 +140,17 @@ public class SecurityPolicy {
throw new IllegalArgumentException("Not a TDB1 or TDB2 database: "+dsg.getClass().getSimpleName());
}
+ public boolean isAccessControlledTDB(DatasetGraph dsg) {
+ DatasetGraph dsgBase = DatasetGraphAccessControl.unwrapOrNull(dsg);
+ if ( dsgBase == null )
+ return false;
+ if ( TDBFactory.isTDB1(dsgBase) )
+ return true;
+ if ( DatabaseMgr.isTDB2(dsgBase) )
+ return true;
+ return false;
+ }
+
public GraphFilterTDB2 filterTDB2(DatasetGraph dsg) {
GraphFilterTDB2 f = GraphFilterTDB2.graphFilter(dsg, graphNames, matchDefaultGraph);
return f;
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestSecurityAssembler.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestSecurityAssembler.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestSecurityAssembler.java
index c062012..9c62c28 100644
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestSecurityAssembler.java
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestSecurityAssembler.java
@@ -20,8 +20,8 @@ package org.apache.jena.fuseki.access;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
+import static org.apache.jena.fuseki.access.AccessTestLib.assertSeen;
-import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
@@ -323,9 +323,4 @@ public abstract class AbstractTestSecurityAssembler {
});
return results;
}
-
- private static void assertSeen(Set<Node> visible, Node ... expected) {
- Set<Node> expectedNodes = new HashSet<>(Arrays.asList(expected));
- assertEquals(expectedNodes, visible);
- }
}
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AccessTestLib.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AccessTestLib.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AccessTestLib.java
new file mode 100644
index 0000000..e95a3e9
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AccessTestLib.java
@@ -0,0 +1,70 @@
+/*
+ * 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.access;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.jena.atlas.lib.StrUtils;
+import org.apache.jena.graph.Node;
+import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.RDFParser;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.sse.SSE;
+import org.apache.jena.system.Txn;
+
+
+/** Some data and functions common to access control tests. */
+public class AccessTestLib {
+ private static String dataStr = StrUtils.strjoinNL
+ ("PREFIX : <http://test/>"
+ ,""
+ ,":s0 :p 0 ."
+ ,":g1 { :s1 :p 1 }"
+ ,":g2 { :s2 :p 2 }"
+ ,":g3 { :s3 :p 3 }"
+ ,":g4 { :s4 :p 4 }"
+ );
+
+
+ public static Node s0 = SSE.parseNode("<http://test/s0>");
+ public static Node s1 = SSE.parseNode("<http://test/s1>");
+ public static Node s2 = SSE.parseNode("<http://test/s2>");
+ public static Node s3 = SSE.parseNode("<http://test/s3>");
+ public static Node s4 = SSE.parseNode("<http://test/s4>");
+
+ public static Node g1 = SSE.parseNode("<http://test/g1>");
+ public static Node g2 = SSE.parseNode("<http://test/g2>");
+ public static Node g3 = SSE.parseNode("<http://test/g3>");
+ public static Node g4 = SSE.parseNode("<http://test/g4>");
+
+ public static void addTestData(DatasetGraph dsg) {
+ Txn.executeWrite(dsg, ()->{
+ RDFParser.create().fromString(dataStr).lang(Lang.TRIG).parse(dsg);
+ });
+ }
+
+ public static void assertSeen(Set<Node> visible, Node ... expected) {
+ Set<Node> expectedNodes = new HashSet<>(Arrays.asList(expected));
+ assertEquals(expectedNodes, visible);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/GraphData.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/GraphData.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/GraphData.java
deleted file mode 100644
index 9712b71..0000000
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/GraphData.java
+++ /dev/null
@@ -1,59 +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.access;
-
-import org.apache.jena.atlas.lib.StrUtils;
-import org.apache.jena.graph.Node;
-import org.apache.jena.riot.Lang;
-import org.apache.jena.riot.RDFParser;
-import org.apache.jena.sparql.core.DatasetGraph;
-import org.apache.jena.sparql.sse.SSE;
-import org.apache.jena.system.Txn;
-
-/** Build graph data for the filter/security tests. */
-
-class GraphData {
- private static String dataStr = StrUtils.strjoinNL
- ("PREFIX : <http://test/>"
- ,""
- ,":s0 :p 0 ."
- ,":g1 { :s1 :p 1 }"
- ,":g2 { :s2 :p 2 }"
- ,":g3 { :s3 :p 3 }"
- ,":g4 { :s4 :p 4 }"
- );
-
-
- static Node s0 = SSE.parseNode("<http://test/s0>");
- static Node s1 = SSE.parseNode("<http://test/s1>");
- static Node s2 = SSE.parseNode("<http://test/s2>");
- static Node s3 = SSE.parseNode("<http://test/s3>");
- static Node s4 = SSE.parseNode("<http://test/s4>");
-
- static Node g1 = SSE.parseNode("<http://test/g1>");
- static Node g2 = SSE.parseNode("<http://test/g2>");
- static Node g3 = SSE.parseNode("<http://test/g3>");
- static Node g4 = SSE.parseNode("<http://test/g4>");
-
- public static void fill(DatasetGraph dsg) {
- Txn.executeWrite(dsg, ()->{
- RDFParser.create().fromString(dataStr).lang(Lang.TRIG).parse(dsg);
- });
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
index c44540c..7050ef0 100644
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
@@ -18,8 +18,7 @@
package org.apache.jena.fuseki.access;
-import static org.apache.jena.fuseki.access.GraphData.s0;
-import static org.apache.jena.fuseki.access.GraphData.s1;
+import static org.apache.jena.fuseki.access.AccessTestLib.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
@@ -69,15 +68,15 @@ public class TestSecurityFilterFuseki {
}
private final String baseUrl;
- private static final DatasetGraph testdsg1 = TDBFactory.createDatasetGraph();
- private static final DatasetGraph testdsg2 = DatabaseMgr.createDatasetGraph();
+ private static DatasetGraph testdsg1 = TDBFactory.createDatasetGraph();
+ private static DatasetGraph testdsg2 = DatabaseMgr.createDatasetGraph();
private static FusekiServer fusekiServer;
// Set up Fuseki with two datasets, "data1" backed by TDB and "data2" backed by TDB2.
@BeforeClass public static void beforeClass() {
int port = FusekiLib.choosePort();
- GraphData.fill(testdsg1);
- GraphData.fill(testdsg2);
+ addTestData(testdsg1);
+ addTestData(testdsg2);
SecurityRegistry reg = new SecurityRegistry();
reg.put("userNone", SecurityPolicy.NONE);
@@ -86,9 +85,9 @@ public class TestSecurityFilterFuseki {
reg.put("user1", new SecurityPolicy("http://test/g1", Quad.defaultGraphIRI.getURI()));
reg.put("user2", new SecurityPolicy("http://test/g1", "http://test/g2", "http://test/g3"));
- // XXXX Also need wrapped tests
- DataAccessCtl.controlledDataset(testdsg1, reg);
- DataAccessCtl.controlledDataset(testdsg2, reg);
+ // XXX Also need wrapped tests
+ testdsg1 = DataAccessCtl.wrapControlledDataset(testdsg1, reg);
+ testdsg2 = DataAccessCtl.wrapControlledDataset(testdsg2, reg);
UserStore userStore = userStore();
SecurityHandler sh = JettyLib.makeSecurityHandler("/*", "DatasetRealm", userStore);
@@ -126,11 +125,6 @@ public class TestSecurityFilterFuseki {
baseUrl = "http://localhost:"+port+"/"+dsName;
}
- private static void assertSeen(Set<Node> visible, Node ... expected) {
- Set<Node> expectedNodes = new HashSet<>(Arrays.asList(expected));
- assertEquals(expectedNodes, visible);
- }
-
private static String queryAll = "SELECT * { { ?s ?p ?o } UNION { GRAPH ?g { ?s ?p ?o } } }";
private static String queryDft = "SELECT * { ?s ?p ?o }";
private static String queryNamed = "SELECT * { GRAPH ?g { ?s ?p ?o } }";
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java
index 3c4ead4..0268b5b 100644
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java
@@ -18,24 +18,22 @@
package org.apache.jena.fuseki.access;
-import static org.apache.jena.fuseki.access.GraphData.*;
+import static org.apache.jena.fuseki.access.AccessTestLib.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
-import java.util.function.Consumer;
+import java.util.function.Function;
import java.util.stream.Stream;
import org.apache.jena.atlas.iterator.Iter;
import org.apache.jena.atlas.lib.Creator;
import org.apache.jena.atlas.lib.SetUtils;
-import org.apache.jena.fuseki.access.DataAccessCtl;
-import org.apache.jena.fuseki.access.SecurityPolicy;
-import org.apache.jena.fuseki.access.SecurityRegistry;
import org.apache.jena.graph.Graph;
import org.apache.jena.graph.Node;
import org.apache.jena.query.Dataset;
@@ -47,41 +45,60 @@ import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.DatasetGraphFactory;
import org.apache.jena.sparql.core.Quad;
import org.apache.jena.system.Txn;
-import org.apache.jena.tdb.TDB;
import org.apache.jena.tdb.TDBFactory;
import org.apache.jena.tdb2.DatabaseMgr;
-import org.apache.jena.tdb2.TDB2;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
+/** Test a controlled Dataset with access by TDB filter or general DatasetGraphFiltered. */
@RunWith(Parameterized.class)
public class TestSecurityFilterLocal {
@Parameters(name = "{index}: {0}")
public static Iterable<Object[]> data() {
+ // By filtering on the TDB database
Creator<DatasetGraph> c1 = TDBFactory::createDatasetGraph;
- Object[] obj1 = { "TDB", c1};
Creator<DatasetGraph> c2 = DatabaseMgr::createDatasetGraph;
- Object[] obj2 = { "TDB2", c2 };
- return Arrays.asList(obj1, obj2);
+ Creator<DatasetGraph> c3 = DatasetGraphFactory::createTxnMem;
+ Creator<DatasetGraph> c4 = DatasetGraphFactory::create;
+
+ Object[] obj1 = { "TDB/db", c1, true};
+ Object[] obj2 = { "TDB2/db", c2, true };
+
+ // By adding the general, but slower, DatasetGraphFilter
+ Object[] obj3 = { "TDB/filtered", c1, false };
+ Object[] obj4 = { "TDB2/filtered", c2, false };
+ Object[] obj5 = { "TIM/filtered", c3, false };
+ Object[] obj6 = { "Plain/filtered", c4, false };
+
+ List<Object[]> x = new ArrayList<>();
+ return Arrays.asList(obj1, obj2, obj3, obj4, obj5, obj6);
+// x.add(obj1);
+// x.add(obj3);
+// x.add(obj5);
+// return x;
}
- private DatasetGraph testdsg;
+ private final DatasetGraph testdsg;
private SecurityRegistry reg = new SecurityRegistry();
+ private final boolean applyFilterDSG;
+ private final boolean applyFilterQExec;
- public TestSecurityFilterLocal(String name, Creator<DatasetGraph> source) {
- testdsg = source.create();
- fill(testdsg);
+ public TestSecurityFilterLocal(String name, Creator<DatasetGraph> source, boolean applyFilterTDB) {
+ DatasetGraph dsgBase = source.create();
+ AccessTestLib.addTestData(dsgBase);
reg.put("userNone", SecurityPolicy.NONE);
reg.put("userDft", SecurityPolicy.DFT_GRAPH);
reg.put("user0", new SecurityPolicy(Quad.defaultGraphIRI.getURI()));
reg.put("user1", new SecurityPolicy("http://test/g1", Quad.defaultGraphIRI.getURI()));
reg.put("user2", new SecurityPolicy("http://test/g1", "http://test/g2", "http://test/g3"));
- DataAccessCtl.controlledDataset(testdsg, reg);
- //testdsg = DataAccessCtl.wrapControlledDataset(testdsg, reg);
+ testdsg = DataAccessCtl.wrapControlledDataset(dsgBase, reg);
+ this.applyFilterDSG = ! applyFilterTDB;
+ this.applyFilterQExec = applyFilterTDB;
}
private static void assertSeen(Set<Node> visible, Node ... expected) {
@@ -96,13 +113,16 @@ public class TestSecurityFilterLocal {
private static String queryG2 = "SELECT * { GRAPH <http://test/graph2> { ?s ?p ?o } }";
private static String queryGraphNames = "SELECT * { GRAPH ?g { } }";
- private Set<Node> subjects(DatasetGraph dsg, String queryString, Consumer<QueryExecution> modifier) {
- Dataset ds = DatasetFactory.wrap(dsg);
+ private Set<Node> subjects(DatasetGraph dsg, String queryString, SecurityPolicy sCxt) {
+ final DatasetGraph dsg1 = applyFilterDSG
+ ? DataAccessCtl.filteredDataset(dsg, sCxt)
+ : dsg;
+ Dataset ds = DatasetFactory.wrap(dsg1);
return
Txn.calculateRead(ds, ()->{
try(QueryExecution qExec = QueryExecutionFactory.create(queryString, ds)) {
- if ( modifier != null )
- modifier.accept(qExec);
+ if ( applyFilterQExec )
+ sCxt.filterTDB(dsg1, qExec);
List<QuerySolution> results = Iter.toList(qExec.execSelect());
Stream<Node> stream = results.stream()
.map(qs->qs.get("s"))
@@ -113,13 +133,34 @@ public class TestSecurityFilterLocal {
});
}
- private Set<Node> graphs(DatasetGraph dsg, Consumer<QueryExecution> modifier) {
- Dataset ds = DatasetFactory.wrap(dsg);
+ private Set<Node> subjects(DatasetGraph dsg, Function<DatasetGraph, Graph> graphChoice, String queryString, SecurityPolicy sCxt) {
+ final DatasetGraph dsg1 = applyFilterDSG
+ ? DataAccessCtl.filteredDataset(dsg, sCxt)
+ : dsg;
+ Graph graph = graphChoice.apply(dsg1);
+ Model model = ModelFactory.createModelForGraph(graph);
+ return
+ Txn.calculateRead(testdsg, ()->{
+ try(QueryExecution qExec = QueryExecutionFactory.create(queryString, model)) {
+ if ( applyFilterQExec )
+ sCxt.filterTDB(dsg1, qExec);
+ List<QuerySolution> results = Iter.toList(qExec.execSelect());
+ Stream<Node> stream = results.stream().map(qs->qs.get("s")).filter(Objects::nonNull).map(RDFNode::asNode);
+ return SetUtils.toSet(stream);
+ }
+ });
+ }
+
+ private Set<Node> graphs(DatasetGraph dsg, SecurityPolicy sCxt) {
+ final DatasetGraph dsg1 = applyFilterDSG
+ ? DataAccessCtl.filteredDataset(dsg, sCxt)
+ : dsg;
+ Dataset ds = DatasetFactory.wrap(dsg1);
return
Txn.calculateRead(ds, ()->{
try(QueryExecution qExec = QueryExecutionFactory.create(queryGraphNames, ds)) {
- if ( modifier != null )
- modifier.accept(qExec);
+ if ( applyFilterQExec )
+ sCxt.filterTDB(dsg1, qExec);
List<QuerySolution> results = Iter.toList(qExec.execSelect());
Stream<Node> stream = results.stream().map(qs->qs.get("g")).filter(Objects::nonNull).map(RDFNode::asNode);
return SetUtils.toSet(stream);
@@ -128,19 +169,15 @@ public class TestSecurityFilterLocal {
}
@Test public void filter_setup() {
- Set<Node> visible = subjects(testdsg, queryAll, null);
- assertEquals(5, visible.size());
- assertSeen(visible, s0, s1, s2, s3, s4);
- }
-
- private static Consumer<QueryExecution> qExecAddFiler(DatasetGraph dsg, SecurityPolicy sCxt) {
- return qExec->sCxt.filterTDB(dsg, qExec);
+ Set<Node> visible = subjects(testdsg, queryAll, SecurityPolicy.NONE);
+ assertEquals(0, visible.size());
+ assertSeen(visible);
}
// QueryExecution
private void filter_user(String user, Node ... expected) {
SecurityPolicy sCxt = reg.get(user);
- Set<Node> visible = subjects(testdsg, queryAll, qExecAddFiler(testdsg, sCxt));
+ Set<Node> visible = subjects(testdsg, queryAll, sCxt);
assertSeen(visible, expected);
}
@@ -171,55 +208,58 @@ public class TestSecurityFilterLocal {
// "Access Denied"
@Test public void no_access_user1() {
SecurityPolicy sCxt = reg.get("user1");
- Set<Node> visible = subjects(testdsg, queryG2, qExecAddFiler(testdsg, sCxt));
+ Set<Node> visible = subjects(testdsg, queryG2, sCxt);
assertTrue(visible.isEmpty());
}
@Test public void graph_names_userNone() {
SecurityPolicy sCxt = reg.get("userNone");
- Set<Node> visible = graphs(testdsg, qExecAddFiler(testdsg, sCxt));
+ Set<Node> visible = graphs(testdsg, sCxt);
assertSeen(visible);
}
@Test public void graph_names_userDft() {
SecurityPolicy sCxt = reg.get("userDft");
- Set<Node> visible = graphs(testdsg, qExecAddFiler(testdsg, sCxt));
+ Set<Node> visible = graphs(testdsg, sCxt);
assertSeen(visible);
}
@Test public void graph_names_user0() {
SecurityPolicy sCxt = reg.get("user0");
- Set<Node> visible = graphs(testdsg, qExecAddFiler(testdsg, sCxt));
+ Set<Node> visible = graphs(testdsg, sCxt);
assertSeen(visible);
}
@Test public void graph_names_user1() {
SecurityPolicy sCxt = reg.get("user1");
- Set<Node> visible = graphs(testdsg, qExecAddFiler(testdsg, sCxt));
+ Set<Node> visible = graphs(testdsg, sCxt);
assertSeen(visible, g1);
}
@Test public void graph_names_user2() {
SecurityPolicy sCxt = reg.get("user2");
- Set<Node> visible = graphs(testdsg, qExecAddFiler(testdsg, sCxt));
+ Set<Node> visible = graphs(testdsg, sCxt);
assertSeen(visible, g1, g2, g3);
}
@Test public void graph_names_userX() {
SecurityPolicy sCxt = reg.get("userX");
- Set<Node> visible = graphs(testdsg, qExecAddFiler(testdsg, sCxt));
+ Set<Node> visible = graphs(testdsg, sCxt);
assertSeen(visible);
}
// QueryExecution w/ Union default graph
private void filter_union_user(String user, Node ... expected) {
SecurityPolicy sCxt = reg.get(user);
- Consumer<QueryExecution> modifier = qExec-> {
- qExec.getContext().set(TDB.symUnionDefaultGraph, true);
- qExec.getContext().set(TDB2.symUnionDefaultGraph, true); // Not strictly necessary.
- sCxt.filterTDB(testdsg, qExec);
- };
- Set<Node> visible = subjects(testdsg, queryDft, modifier);
+ // XXX Need to set union.
+// Consumer<QueryExecution> modifier = qExec-> {
+// qExec.getContext().set(TDB.symUnionDefaultGraph, true);
+// qExec.getContext().set(TDB2.symUnionDefaultGraph, true);
+// sCxt.filterTDB(testdsg, qExec);
+// };
+// Set<Node> visible = subjects(testdsg, queryDft, sCxt);
+
+ Set<Node> visible = subjects(testdsg, dsg->dsg.getUnionGraph(), queryDft, sCxt);
assertSeen(visible, expected);
}
@@ -249,72 +289,59 @@ public class TestSecurityFilterLocal {
filter_union_user("userX");
}
- private Set<Node> subjects(Graph graph, String queryString, Consumer<QueryExecution> modifier) {
- Model model = ModelFactory.createModelForGraph(graph);
- return
- Txn.calculateRead(testdsg, ()->{
- try(QueryExecution qExec = QueryExecutionFactory.create(queryString, model)) {
- if ( modifier != null )
- modifier.accept(qExec);
- List<QuerySolution> results = Iter.toList(qExec.execSelect());
- Stream<Node> stream = results.stream().map(qs->qs.get("s")).filter(Objects::nonNull).map(RDFNode::asNode);
- return SetUtils.toSet(stream);
- }
- });
- }
-
+
// Graph/Model
@Test public void query_model_userNone() {
- query_model_user(testdsg.getDefaultGraph(), "userNone");
+ query_model_user(testdsg, dsg->dsg.getDefaultGraph(), "userNone");
}
@Test public void query_model_userDft() {
- query_model_user(testdsg.getDefaultGraph(), "userDft", s0);
+ query_model_user(testdsg, dsg->dsg.getDefaultGraph(), "userDft", s0);
}
@Test public void query_model_user0() {
- query_model_user(testdsg.getDefaultGraph(), "user0", s0);
+ query_model_user(testdsg, dsg->dsg.getDefaultGraph(), "user0", s0);
}
@Test public void query_model_user1() {
- query_model_user(testdsg.getDefaultGraph(), "user1", s0);
+ query_model_user(testdsg, dsg->dsg.getDefaultGraph(), "user1", s0);
}
@Test public void query_model_user2() {
- query_model_user(testdsg.getDefaultGraph(), "user2");
+ query_model_user(testdsg, dsg->dsg.getDefaultGraph(), "user2");
}
@Test public void query_model_ng_userNone() {
- query_model_user(testdsg.getGraph(g1), "userNone");
+ query_model_user(testdsg, dsg->dsg.getGraph(g1), "userNone");
}
@Test public void query_model_ng_user11() {
- query_model_user(testdsg.getGraph(g1), "user1", s1);
+ query_model_user(testdsg, dsg->dsg.getGraph(g1), "user1", s1);
}
@Test public void query_model_ng_user21() {
- query_model_user(testdsg.getGraph(g1), "user2", s1);
+ query_model_user(testdsg, dsg->dsg.getGraph(g1), "user2", s1);
}
@Test public void query_model_ng_user12() {
- query_model_user(testdsg.getGraph(g2), "user1");
+ query_model_user(testdsg, dsg->dsg.getGraph(g2), "user1");
}
@Test public void query_model_ng_user22() {
- query_model_user(testdsg.getGraph(g2), "user2", s2);
+ query_model_user(testdsg, dsg->dsg.getGraph(g2), "user2", s2);
}
@Test public void query_model_userXa() {
- query_model_user(testdsg.getDefaultGraph(), "userX");
+ query_model_user(testdsg, dsg->dsg.getDefaultGraph(), "userX");
}
@Test public void query_model_userXb() {
- query_model_user(testdsg.getGraph(g1), "userX");
+ query_model_user(testdsg, dsg->dsg.getGraph(g1), "userX");
}
- private void query_model_user(Graph g, String user, Node ... expected) {
+ private void query_model_user(DatasetGraph dsg, Function<DatasetGraph, Graph> graphChoice, String user, Node ... expected) {
SecurityPolicy sCxt = reg.get(user);
- Set<Node> visible = subjects(g, queryDft, qExecAddFiler(testdsg, sCxt));
+ Set<Node> visible = subjects(dsg, graphChoice, queryDft, sCxt);
assertSeen(visible, expected);
}
}
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionREST.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionREST.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionREST.java
index f9f0443..e16e793 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionREST.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionREST.java
@@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletRequest ;
import javax.servlet.http.HttpServletResponse ;
import org.apache.jena.fuseki.server.CounterName ;
+import org.apache.jena.sparql.core.DatasetGraph;
/** Common point for operations that are "REST"ish (use GET/PUT etc as operations). */
public abstract class ActionREST extends ActionService
@@ -68,6 +69,14 @@ public abstract class ActionREST extends ActionService
ServletOps.errorNotImplemented("Unknown method: "+method) ;
}
+ /**
+ * Decide on the dataset to use for the operation. This can be overridden
+ * by specialist subclasses e.g. data access control.
+ */
+ protected DatasetGraph decideDataset(HttpAction action) {
+ return action.getActiveDSG() ;
+ }
+
// Counter wrappers
private final void doGet$(HttpAction action) {
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/REST_Quads_R.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/REST_Quads_R.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/REST_Quads_R.java
index 668f210..845ef16 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/REST_Quads_R.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/REST_Quads_R.java
@@ -80,7 +80,7 @@ public class REST_Quads_R extends REST_Quads {
action.beginRead() ;
try {
- DatasetGraph dsg = actOn(action);
+ DatasetGraph dsg = decideDataset(action);
action.response.setHeader("Content-type", lang.getContentType().toHeaderString());
// ActionLib.contentNegotationQuads above
// RDF/XML is not a choice but this code is general.
@@ -101,14 +101,6 @@ public class REST_Quads_R extends REST_Quads {
}
}
- /**
- * Decide on the dataset to use for the operation. Can be overrided by specialist
- * subclasses.
- */
- protected DatasetGraph actOn(HttpAction action) {
- return action.getActiveDSG() ;
- }
-
@Override
protected void doOptions(HttpAction action) {
action.response.setHeader(HttpNames.hAllow, "GET, HEAD, OPTIONS") ;
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/REST_Quads_RW.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/REST_Quads_RW.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/REST_Quads_RW.java
index 98589c9..859ef95 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/REST_Quads_RW.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/REST_Quads_RW.java
@@ -90,7 +90,7 @@ public class REST_Quads_RW extends REST_Quads_R {
UploadDetails details = null ;
action.beginWrite() ;
try {
- DatasetGraph dsg = action.getActiveDSG() ;
+ DatasetGraph dsg = decideDataset(action);
if ( clearFirst )
dsg.clear() ;
StreamRDF dest = StreamRDFLib.dataset(dsg) ;
@@ -128,7 +128,7 @@ public class REST_Quads_RW extends REST_Quads_R {
// Now insert into dataset
action.beginWrite() ;
try {
- DatasetGraph dsg = action.getActiveDSG() ;
+ DatasetGraph dsg = decideDataset(action);
if ( clearFirst )
dsg.clear() ;
FusekiLib.addDataInto(dsgTmp, dsg) ;
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP.java
index 1321125..af4d42a 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP.java
@@ -33,11 +33,6 @@ import org.apache.jena.sparql.core.DatasetGraph ;
public abstract class SPARQL_GSP extends ActionREST
{
- protected final static Target determineTarget(HttpAction action) {
- DatasetGraph dsg = action.getActiveDSG();
- return determineTarget(dsg, action);
- }
-
protected final static Target determineTarget(DatasetGraph dsg, HttpAction action) {
// Delayed until inside a transaction.
if ( dsg == null )
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP_R.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP_R.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP_R.java
index 8204136..e3f0925 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP_R.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP_R.java
@@ -63,7 +63,7 @@ public class SPARQL_GSP_R extends SPARQL_GSP
action.beginRead() ;
setCommonHeaders(action.response) ;
try {
- DatasetGraph dsg = actOn(action);
+ DatasetGraph dsg = decideDataset(action);
Target target = determineTarget(dsg, action) ;
if ( action.log.isDebugEnabled() )
action.log.debug("GET->"+target) ;
@@ -95,14 +95,6 @@ public class SPARQL_GSP_R extends SPARQL_GSP
} finally { action.endRead() ; }
}
- /**
- * Decide on the dataset to use for the operation. Can be overrided by specialist
- * subclasses.
- */
- protected DatasetGraph actOn(HttpAction action) {
- return action.getActiveDSG() ;
- }
-
@Override
protected void doOptions(HttpAction action) {
setCommonHeadersForOptions(action.response) ;
@@ -115,8 +107,9 @@ public class SPARQL_GSP_R extends SPARQL_GSP
protected void doHead(HttpAction action) {
action.beginRead() ;
setCommonHeaders(action.response) ;
- try {
- Target target = determineTarget(action) ;
+ try {
+ DatasetGraph dsg = decideDataset(action);
+ Target target = determineTarget(dsg, action) ;
if ( action.log.isDebugEnabled() )
action.log.debug("HEAD->"+target) ;
if ( ! target.exists() )
http://git-wip-us.apache.org/repos/asf/jena/blob/99b99463/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP_RW.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP_RW.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP_RW.java
index 4ba5ffe..2b4952f 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP_RW.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_GSP_RW.java
@@ -34,6 +34,7 @@ import org.apache.jena.riot.RiotException ;
import org.apache.jena.riot.system.StreamRDF ;
import org.apache.jena.riot.system.StreamRDFLib ;
import org.apache.jena.riot.web.HttpNames ;
+import org.apache.jena.sparql.core.DatasetGraph;
import org.apache.jena.sparql.graph.GraphFactory ;
import org.apache.jena.web.HttpSC ;
@@ -55,7 +56,8 @@ public class SPARQL_GSP_RW extends SPARQL_GSP_R
protected void doDelete(HttpAction action) {
action.beginWrite() ;
try {
- Target target = determineTarget(action) ;
+ DatasetGraph dsg = decideDataset(action);
+ Target target = determineTarget(dsg, action) ;
if ( action.log.isDebugEnabled() )
action.log.debug("DELETE->"+target) ;
boolean existedBefore = target.exists() ;
@@ -113,10 +115,11 @@ public class SPARQL_GSP_RW extends SPARQL_GSP_R
* @param cleanDest Whether to remove data first (true = PUT, false = POST)
* @return whether the target existed beforehand
*/
- protected static UploadDetails addDataIntoTxn(HttpAction action, boolean overwrite) {
+ protected UploadDetails addDataIntoTxn(HttpAction action, boolean overwrite) {
action.beginWrite();
try {
- Target target = determineTarget(action) ;
+ DatasetGraph dsg = decideDataset(action);
+ Target target = determineTarget(dsg, action) ;
if ( action.log.isDebugEnabled() )
action.log.debug(action.request.getMethod().toUpperCase()+"->"+target) ;
boolean existedBefore = target.exists() ;
@@ -156,7 +159,7 @@ public class SPARQL_GSP_RW extends SPARQL_GSP_R
* @return whether the target existed beforehand.
*/
- protected static UploadDetails addDataIntoNonTxn(HttpAction action, boolean overwrite) {
+ protected UploadDetails addDataIntoNonTxn(HttpAction action, boolean overwrite) {
Graph graphTmp = GraphFactory.createGraphMem() ;
StreamRDF dest = StreamRDFLib.graph(graphTmp) ;
@@ -168,7 +171,8 @@ public class SPARQL_GSP_RW extends SPARQL_GSP_R
}
// Now insert into dataset
action.beginWrite() ;
- Target target = determineTarget(action) ;
+ DatasetGraph dsg = decideDataset(action);
+ Target target = determineTarget(dsg, action) ;
boolean existedBefore = false ;
try {
if ( action.log.isDebugEnabled() )
@@ -194,8 +198,9 @@ public class SPARQL_GSP_RW extends SPARQL_GSP_R
/** Delete a graph. This removes the storage choice and looses the setup.
* The default graph is cleared, not removed.
*/
- protected static void deleteGraph(HttpAction action) {
- Target target = determineTarget(action) ;
+ protected void deleteGraph(HttpAction action) {
+ DatasetGraph dsg = decideDataset(action);
+ Target target = determineTarget(dsg, action) ;
if ( target.isDefault )
clearGraph(target) ;
else
@@ -203,7 +208,7 @@ public class SPARQL_GSP_RW extends SPARQL_GSP_R
}
/** Clear a graph - this leaves the storage choice and setup in-place */
- protected static void clearGraph(Target target) {
+ protected void clearGraph(Target target) {
Graph g = target.graph() ;
g.getPrefixMapping().clearNsPrefixMap() ;
g.clear() ;
[19/27] jena git commit: General use DatasetGraphFilteredView
Posted by an...@apache.org.
General use DatasetGraphFilteredView
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/7b0661fb
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/7b0661fb
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/7b0661fb
Branch: refs/heads/master
Commit: 7b0661fbb8d4f99fbc6b02726e082fb7d99042b0
Parents: dc7f38f
Author: Andy Seaborne <an...@apache.org>
Authored: Sun Aug 26 18:07:47 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sun Aug 26 18:07:47 2018 +0100
----------------------------------------------------------------------
.../sparql/core/DatasetGraphFilteredView.java | 153 +++++++++++++++++++
1 file changed, 153 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/7b0661fb/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
new file mode 100644
index 0000000..a9fa8f2
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
@@ -0,0 +1,153 @@
+/*
+ * 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;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.function.Predicate;
+
+import org.apache.jena.atlas.iterator.Iter;
+import org.apache.jena.atlas.logging.Log;
+import org.apache.jena.graph.Graph;
+import org.apache.jena.graph.Node;
+import org.apache.jena.sparql.graph.GraphReadOnly;
+import org.apache.jena.sparql.graph.GraphUnionRead;
+
+/**
+ * A read-only {@link DatasetGraph} that applies a filter testing all triples and quads
+ * returned by accessing the data. Only quads where the filter tests for "true" are exposed.
+ */
+public class DatasetGraphFilteredView extends DatasetGraphReadOnly {
+ /*
+ Write operations
+ add(Quad)
+ delete(Quad)
+ add(Node, Node, Node, Node)
+ delete(Node, Node, Node, Node)
+ deleteAny(Node, Node, Node, Node)
+ clear()
+
+ Read operations
+ listGraphNodes()
+ isEmpty()
+ find()
+ find(Quad)
+ find(Node, Node, Node, Node)
+ findNG(Node, Node, Node, Node)
+ contains(Quad)
+ contains(Node, Node, Node, Node)
+ size()
+ toString()
+
+ Graph operations
+ listGraphNodes()
+ getGraph(Node)
+ getDefaultGraph()
+ containsGraph(Node)
+ */
+
+ private final Predicate<Quad> quadFilter;
+ private final Collection<Node> visibleGraphs;
+
+ public DatasetGraphFilteredView(DatasetGraph dsg, Predicate<Quad> filter, Collection<Node> visibleGraphs) {
+ super(dsg);
+ this.quadFilter = filter;
+ if ( visibleGraphs.contains(Quad.defaultGraphIRI) || visibleGraphs.contains(Quad.defaultGraphNodeGenerated) ) {
+ Log.warn(DatasetGraphFilteredView.class, "default graph Node in visibleGraphs colelction - fix up applied");
+ visibleGraphs = new HashSet<>(visibleGraphs);
+ visibleGraphs.remove(Quad.defaultGraphIRI);
+ visibleGraphs.remove(Quad.defaultGraphNodeGenerated);
+ }
+ this.visibleGraphs = visibleGraphs;
+ }
+
+ private boolean filter(Quad quad) {
+ return quadFilter.test(quad);
+ }
+
+ private Iterator<Quad> filter(Iterator<Quad> iter) {
+ return Iter.filter(iter, this::filter);
+ }
+
+ // Need to intercept these because otherwise that are a GraphView of the wrapped "dsg", not this one.
+
+ @Override
+ public Graph getDefaultGraph() {
+ Graph g = GraphView.createDefaultGraph(this);
+ return new GraphReadOnly(g);
+ }
+
+ @Override
+ public Graph getGraph(Node graphNode) {
+ if ( Quad.isUnionGraph(graphNode))
+ return getUnionGraph();
+ Graph g = GraphView.createNamedGraph(this, graphNode);
+ return new GraphReadOnly(g);
+ }
+
+ @Override
+ public Iterator<Node> listGraphNodes() {
+// Predicate<Node> notSpecial = x-> ! ( Quad.isDefaultGraph(x)|| Quad.isUnionGraph(x) );
+// return Iter.filter(visibleGraphs.iterator(), notSpecial);
+ return visibleGraphs.iterator();
+ }
+
+ @Override
+ public Graph getUnionGraph() {
+ return new GraphUnionRead(this, visibleGraphs);
+ }
+
+ @Override
+ public Iterator<Quad> find() {
+ return filter(super.find());
+ }
+
+ @Override public Iterator<Quad> find(Node g, Node s, Node p, Node o) {
+ // Need union handling if for general API use.
+ return filter(super.find(g, s, p, o));
+ }
+
+ @Override public Iterator<Quad> find(Quad quad) {
+ // union
+ return filter(super.find(quad));
+ }
+
+ @Override public Iterator<Quad> findNG(Node g, Node s, Node p , Node o) {
+ // union
+ return filter(super.findNG(g, s, p, o));
+ }
+
+ @Override public boolean contains(Node g, Node s, Node p , Node o) {
+ return filter(super.find(g, s, p, o)).hasNext();
+ }
+
+ @Override public boolean contains(Quad quad) {
+ return filter(super.find(quad)).hasNext();
+ }
+
+ @Override public boolean isEmpty() {
+ return ! this.find().hasNext();
+ }
+
+// @Override public String toString() {
+// return
+// }
+
+}
[10/27] jena git commit: JENA-1595: Put log4j and slf4j-log4j into
scope test for all modules
Posted by an...@apache.org.
JENA-1595: Put log4j and slf4j-log4j into scope test for all modules
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/a17c6dd7
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/a17c6dd7
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/a17c6dd7
Branch: refs/heads/master
Commit: a17c6dd732ca32ef4122dc089c8717fccc5b75b1
Parents: 344ae5d
Author: Andy Seaborne <an...@apache.org>
Authored: Thu Aug 23 18:27:39 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Thu Aug 23 18:27:39 2018 +0100
----------------------------------------------------------------------
jena-base/pom.xml | 7 +++++++
pom.xml | 4 ++--
2 files changed, 9 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/a17c6dd7/jena-base/pom.xml
----------------------------------------------------------------------
diff --git a/jena-base/pom.xml b/jena-base/pom.xml
index 5fd602a..438f9e2 100644
--- a/jena-base/pom.xml
+++ b/jena-base/pom.xml
@@ -44,7 +44,14 @@
<version>3.9.0-SNAPSHOT</version>
</dependency>
+ <!-- For compiling the log4j1 helper code. -->
<dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <optional>true</optional>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
</dependency>
http://git-wip-us.apache.org/repos/asf/jena/blob/a17c6dd7/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 9744eb3..8ffc688 100644
--- a/pom.xml
+++ b/pom.xml
@@ -558,13 +558,13 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
- <optional>true</optional>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <optional>true</optional>
+ <scope>test</scope>
</dependency>
</dependencies>
[22/27] jena git commit: JENA-1494: Handle any dataset
Posted by an...@apache.org.
JENA-1494: Handle any dataset
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/80a2f7b5
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/80a2f7b5
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/80a2f7b5
Branch: refs/heads/master
Commit: 80a2f7b543137fd35cb1e8c2b55fa432854d5f18
Parents: 2ec9065
Author: Andy Seaborne <an...@apache.org>
Authored: Sun Aug 26 21:46:07 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sun Aug 26 23:27:13 2018 +0100
----------------------------------------------------------------------
.../sparql/core/DatasetGraphFilteredView.java | 3 ++
.../jena/fuseki/access/DataAccessCtl.java | 35 +++++++++---------
.../access/Filtered_SPARQL_QueryDataset.java | 21 +++++------
.../jena/fuseki/access/SecurityPolicy.java | 3 +-
.../fuseki/access/TestSecurityFilterFuseki.java | 18 ++++++----
.../fuseki/access/TestSecurityFilterLocal.java | 38 ++++++++++++--------
.../apache/jena/fuseki/cmds/FusekiBasicCmd.java | 4 +--
.../jena/fuseki/servlets/SPARQL_Query.java | 6 ++--
8 files changed, 69 insertions(+), 59 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/80a2f7b5/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
index 3084e33..4c49bd1 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
@@ -114,6 +114,9 @@ public class DatasetGraphFilteredView extends DatasetGraphReadOnly implements Da
@Override
public Graph getUnionGraph() {
+ // Does not exploit TDB-isms, but is general.
+ // To exploit TDB, we'd have to modify the dataset
+ // to set union graph but that's not per-request.
return new GraphUnionRead(this, visibleGraphs);
}
http://git-wip-us.apache.org/repos/asf/jena/blob/80a2f7b5/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
index dc8c913..3bc0812 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/DataAccessCtl.java
@@ -35,20 +35,23 @@ import org.apache.jena.sparql.core.DatasetGraph;
import org.apache.jena.sparql.core.DatasetGraphFilteredView;
import org.apache.jena.sparql.util.Context;
import org.apache.jena.sparql.util.Symbol;
+import org.apache.jena.sys.JenaSystem;
import org.eclipse.jetty.security.SecurityHandler;
/** A library of operations related to data acess sexurity for Fuseki */
public class DataAccessCtl {
-
+ static { JenaSystem.init(); }
+
/**
* Flag for whether this is data access controlled or not - boolean false or undef for "not
- * controlled".
+ * controlled". This is an alternative to {@link DatasetGraphAccessControl}.
*/
public static final Symbol symControlledAccess = Symbol.create(VocabSecurity.getURI() + "controlled");
/**
* Symbol for the {@link SecurityRegistry}. Must be present if
* {@link #symControlledAccess} indicates data access control.
+ * This is an alternative to {@link DatasetGraphAccessControl}.
*/
public static final Symbol symSecurityRegistry = Symbol.create(VocabSecurity.getURI() + "registry");
@@ -56,30 +59,26 @@ public class DataAccessCtl {
public static final Function<HttpAction, String> requestUserServlet = (action)->action.request.getRemoteUser();
/**
+ * Get the user from {@code ?user} query string parameter. Use carefully; for situations where the user name has
+ * been authenticated already and is being passed on securely. Also for testing.
+ */
+ public static final Function<HttpAction, String> paramUserServlet = (action)->action.request.getParameter("user");
+
+ /**
* Add data access control information on a {@link DatasetGraph}. This modifies the
* {@link DatasetGraph}'s {@link Context}.
*/
- private static void controlledDataset(DatasetGraph dsg, SecurityRegistry reg) {
- // Or wrapper.
+ private static void addSecurityRegistry(DatasetGraph dsg, SecurityRegistry reg) {
dsg.getContext().set(symControlledAccess, true);
dsg.getContext().set(symSecurityRegistry, reg);
}
-// /**
-// * Enable data access control on a {@link Dataset}. This modifies the
-// * {@link Dataset}'s {@link Context}.
-// */
-// private static void controlledDataset(Dataset ds, SecurityRegistry reg) {
-// ds.getContext().set(symControlledAccess, true);
-// ds.getContext().set(symSecurityRegistry, reg);
-// }
-
/**
- * Return a {@link DatasetGraph} with added data access control. Use of the original
- * {@code DatasetGraph} is not controlled.
+ * Return a {@link DatasetGraph} with added data access control.
+ * Use of the original {@code DatasetGraph} is not controlled.
*/
- public static Dataset wrapControlledDataset(Dataset dsBase, SecurityRegistry reg) {
- DatasetGraph dsg = wrapControlledDataset(dsBase.asDatasetGraph(), reg);
+ public static Dataset controlledDataset(Dataset dsBase, SecurityRegistry reg) {
+ DatasetGraph dsg = controlledDataset(dsBase.asDatasetGraph(), reg);
return DatasetFactory.wrap(dsg);
}
@@ -87,7 +86,7 @@ public class DataAccessCtl {
* Return a {@link DatasetGraph} with added data access control. Use of the original
* {@code DatasetGraph} is not controlled.
*/
- public static DatasetGraph wrapControlledDataset(DatasetGraph dsgBase, SecurityRegistry reg) {
+ public static DatasetGraph controlledDataset(DatasetGraph dsgBase, SecurityRegistry reg) {
if ( dsgBase instanceof DatasetGraphAccessControl ) {
DatasetGraphAccessControl dsgx = (DatasetGraphAccessControl)dsgBase;
if ( reg == dsgx.getRegistry() )
http://git-wip-us.apache.org/repos/asf/jena/blob/80a2f7b5/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
index 49efc4f..8162f91 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_QueryDataset.java
@@ -18,6 +18,8 @@
package org.apache.jena.fuseki.access;
+import java.util.Collection;
+import java.util.Collections;
import java.util.function.Function;
import org.apache.jena.fuseki.servlets.ActionService;
@@ -38,6 +40,12 @@ public class Filtered_SPARQL_QueryDataset extends SPARQL_QueryDataset {
}
@Override
+ protected Collection<String> customParams() {
+ // The additional ?user.
+ return Collections.singletonList("user");
+ }
+
+ @Override
protected QueryExecution createQueryExecution(HttpAction action, Query query, Dataset dataset) {
// Server database, not the possibly dynamically built "dataset"
DatasetGraph dsg = action.getDataset();
@@ -46,20 +54,9 @@ public class Filtered_SPARQL_QueryDataset extends SPARQL_QueryDataset {
if ( ! DataAccessCtl.isAccessControlled(dsg) )
return super.createQueryExecution(action, query, dataset);
- // XXX Generalize to any DSG.
SecurityPolicy sCxt = DataAccessLib.getSecurityPolicy(action, dataset.asDatasetGraph(), requestUser);
-
+ // A QueryExecution for controlled access
QueryExecution qExec = sCxt.createQueryExecution(query, dsg);
-
-// if ( dsg instanceof DatasetGraphAccessControl ) {
-// // Take off one layer.
-// dsg = DatasetGraphAccessControl.removeWrapper(dsg);
-// // Add back the Dataset for the createQueryExecution call.
-// dataset = DatasetFactory.wrap(dsg);
-// }
-// QueryExecution qExec = super.createQueryExecution(action, query, dataset);
-// if ( sCxt != null )
-// sCxt.filterTDB(dsg, qExec);
return qExec;
}
}
http://git-wip-us.apache.org/repos/asf/jena/blob/80a2f7b5/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
index c0d420a..ca19794 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/SecurityPolicy.java
@@ -114,8 +114,7 @@ public class SecurityPolicy {
if ( quad.isDefaultGraph() )
return matchDefaultGraph;
if ( quad.isUnionGraph() )
- // XXX What to do here.
- // Need special union graph?
+ // Union graph is automatically there but its visible contents are different.
return true;
return graphNames.contains(quad.getGraph());
};
http://git-wip-us.apache.org/repos/asf/jena/blob/80a2f7b5/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
index 7050ef0..c9d188a 100644
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterFuseki.java
@@ -41,6 +41,7 @@ import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdfconnection.RDFConnection;
import org.apache.jena.rdfconnection.RDFConnectionFactory;
import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.DatasetGraphFactory;
import org.apache.jena.sparql.core.Quad;
import org.apache.jena.sparql.engine.http.QueryExceptionHTTP;
import org.apache.jena.tdb.TDBFactory;
@@ -62,14 +63,17 @@ public class TestSecurityFilterFuseki {
@Parameters(name = "{index}: {0}")
public static Iterable<Object[]> data() {
- Object[] obj1 = { "TDB", "data1" };
+ Object[] obj1 = { "TDB", "data1" };
Object[] obj2 = { "TDB2", "data2" };
- return Arrays.asList(obj1, obj2);
+ Object[] obj3 = { "TIM", "data3" };
+ return Arrays.asList(obj1, obj2, obj3);
}
private final String baseUrl;
private static DatasetGraph testdsg1 = TDBFactory.createDatasetGraph();
private static DatasetGraph testdsg2 = DatabaseMgr.createDatasetGraph();
+ private static DatasetGraph testdsg3 = DatasetGraphFactory.createTxnMem();
+
private static FusekiServer fusekiServer;
// Set up Fuseki with two datasets, "data1" backed by TDB and "data2" backed by TDB2.
@@ -77,6 +81,7 @@ public class TestSecurityFilterFuseki {
int port = FusekiLib.choosePort();
addTestData(testdsg1);
addTestData(testdsg2);
+ addTestData(testdsg3);
SecurityRegistry reg = new SecurityRegistry();
reg.put("userNone", SecurityPolicy.NONE);
@@ -85,10 +90,10 @@ public class TestSecurityFilterFuseki {
reg.put("user1", new SecurityPolicy("http://test/g1", Quad.defaultGraphIRI.getURI()));
reg.put("user2", new SecurityPolicy("http://test/g1", "http://test/g2", "http://test/g3"));
- // XXX Also need wrapped tests
- testdsg1 = DataAccessCtl.wrapControlledDataset(testdsg1, reg);
- testdsg2 = DataAccessCtl.wrapControlledDataset(testdsg2, reg);
-
+ testdsg1 = DataAccessCtl.controlledDataset(testdsg1, reg);
+ testdsg2 = DataAccessCtl.controlledDataset(testdsg2, reg);
+ testdsg3 = DataAccessCtl.controlledDataset(testdsg3, reg);
+
UserStore userStore = userStore();
SecurityHandler sh = JettyLib.makeSecurityHandler("/*", "DatasetRealm", userStore);
@@ -96,6 +101,7 @@ public class TestSecurityFilterFuseki {
.port(port)
.add("data1", testdsg1)
.add("data2", testdsg2)
+ .add("data3", testdsg3)
.build();
fusekiServer.start();
}
http://git-wip-us.apache.org/repos/asf/jena/blob/80a2f7b5/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java
index 0268b5b..1e03aba 100644
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityFilterLocal.java
@@ -48,8 +48,10 @@ import org.apache.jena.sparql.core.DatasetGraph;
import org.apache.jena.sparql.core.DatasetGraphFactory;
import org.apache.jena.sparql.core.Quad;
import org.apache.jena.system.Txn;
+import org.apache.jena.tdb.TDB;
import org.apache.jena.tdb.TDBFactory;
import org.apache.jena.tdb2.DatabaseMgr;
+import org.apache.jena.tdb2.TDB2;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -86,7 +88,7 @@ public class TestSecurityFilterLocal {
private final DatasetGraph testdsg;
private SecurityRegistry reg = new SecurityRegistry();
private final boolean applyFilterDSG;
- private final boolean applyFilterQExec;
+ private final boolean applyFilterTDB;
public TestSecurityFilterLocal(String name, Creator<DatasetGraph> source, boolean applyFilterTDB) {
DatasetGraph dsgBase = source.create();
@@ -96,9 +98,9 @@ public class TestSecurityFilterLocal {
reg.put("user0", new SecurityPolicy(Quad.defaultGraphIRI.getURI()));
reg.put("user1", new SecurityPolicy("http://test/g1", Quad.defaultGraphIRI.getURI()));
reg.put("user2", new SecurityPolicy("http://test/g1", "http://test/g2", "http://test/g3"));
- testdsg = DataAccessCtl.wrapControlledDataset(dsgBase, reg);
+ testdsg = DataAccessCtl.controlledDataset(dsgBase, reg);
+ this.applyFilterTDB = applyFilterTDB;
this.applyFilterDSG = ! applyFilterTDB;
- this.applyFilterQExec = applyFilterTDB;
}
private static void assertSeen(Set<Node> visible, Node ... expected) {
@@ -121,7 +123,7 @@ public class TestSecurityFilterLocal {
return
Txn.calculateRead(ds, ()->{
try(QueryExecution qExec = QueryExecutionFactory.create(queryString, ds)) {
- if ( applyFilterQExec )
+ if ( applyFilterTDB )
sCxt.filterTDB(dsg1, qExec);
List<QuerySolution> results = Iter.toList(qExec.execSelect());
Stream<Node> stream = results.stream()
@@ -142,7 +144,7 @@ public class TestSecurityFilterLocal {
return
Txn.calculateRead(testdsg, ()->{
try(QueryExecution qExec = QueryExecutionFactory.create(queryString, model)) {
- if ( applyFilterQExec )
+ if ( applyFilterTDB )
sCxt.filterTDB(dsg1, qExec);
List<QuerySolution> results = Iter.toList(qExec.execSelect());
Stream<Node> stream = results.stream().map(qs->qs.get("s")).filter(Objects::nonNull).map(RDFNode::asNode);
@@ -159,7 +161,7 @@ public class TestSecurityFilterLocal {
return
Txn.calculateRead(ds, ()->{
try(QueryExecution qExec = QueryExecutionFactory.create(queryGraphNames, ds)) {
- if ( applyFilterQExec )
+ if ( applyFilterTDB )
sCxt.filterTDB(dsg1, qExec);
List<QuerySolution> results = Iter.toList(qExec.execSelect());
Stream<Node> stream = results.stream().map(qs->qs.get("g")).filter(Objects::nonNull).map(RDFNode::asNode);
@@ -251,15 +253,21 @@ public class TestSecurityFilterLocal {
// QueryExecution w/ Union default graph
private void filter_union_user(String user, Node ... expected) {
SecurityPolicy sCxt = reg.get(user);
- // XXX Need to set union.
-// Consumer<QueryExecution> modifier = qExec-> {
-// qExec.getContext().set(TDB.symUnionDefaultGraph, true);
-// qExec.getContext().set(TDB2.symUnionDefaultGraph, true);
-// sCxt.filterTDB(testdsg, qExec);
-// };
-// Set<Node> visible = subjects(testdsg, queryDft, sCxt);
-
- Set<Node> visible = subjects(testdsg, dsg->dsg.getUnionGraph(), queryDft, sCxt);
+ Set<Node> visible;
+ if ( applyFilterTDB ) {
+ // TDB special version. Set the TDB flags for union default graph
+ try {
+ testdsg.getContext().set(TDB.symUnionDefaultGraph, true);
+ testdsg.getContext().set(TDB2.symUnionDefaultGraph, true);
+ visible = subjects(testdsg, queryDft, sCxt);
+ } finally {
+ // And unset them.
+ testdsg.getContext().unset(TDB.symUnionDefaultGraph);
+ testdsg.getContext().unset(TDB2.symUnionDefaultGraph);
+ }
+ } else {
+ visible = subjects(testdsg, dsg->dsg.getUnionGraph(), queryDft, sCxt);
+ }
assertSeen(visible, expected);
}
http://git-wip-us.apache.org/repos/asf/jena/blob/80a2f7b5/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicCmd.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicCmd.java b/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicCmd.java
index baa3b28..f1ba1f2 100644
--- a/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicCmd.java
+++ b/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicCmd.java
@@ -510,10 +510,8 @@ public class FusekiBasicCmd {
}
if ( serverConfig.datasetPath != null ) {
- if ( mapDatasetEndpoints.size() != 1 ) {
- System.err.println(serverConfig.datasetPath);
+ if ( mapDatasetEndpoints.size() != 1 )
log.error("Expected only one dataset");
- }
List<String> endpoints = mapDatasetEndpoints.get(serverConfig.datasetPath);
FmtLog.info(log, "Dataset Type = %s", serverConfig.datasetDescription);
FmtLog.info(log, "Path = %s; Services = %s", serverConfig.datasetPath, endpoints);
http://git-wip-us.apache.org/repos/asf/jena/blob/80a2f7b5/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java
index a14e75a..931f27f 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java
@@ -108,9 +108,9 @@ public abstract class SPARQL_Query extends SPARQL_Protocol
if ( acceptedParams_ == null ) {
synchronized(this) {
if ( acceptedParams_ == null )
- // Does not matter about race condition here because the same Set should be
- // created on any call to generateAcceptedParams.
- acceptedParams_ = generateAcceptedParams();
+ // Does not matter about race condition here because the same Set should be
+ // created on any call to generateAcceptedParams.
+ acceptedParams_ = generateAcceptedParams();
}
}
return acceptedParams_;
[04/27] jena git commit: Copy dataset context to execution for query
over model
Posted by an...@apache.org.
Copy dataset context to execution for query over model
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/d8e51a82
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/d8e51a82
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/d8e51a82
Branch: refs/heads/master
Commit: d8e51a82fea80ea21e7cdef8445dc00adec42ee2
Parents: 0a0b831
Author: Andy Seaborne <an...@apache.org>
Authored: Mon Aug 20 20:34:04 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Thu Aug 23 17:15:05 2018 +0100
----------------------------------------------------------------------
.../jena/query/QueryExecutionFactory.java | 29 ++++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/d8e51a82/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java b/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java
index 2414d3a..f784d1a 100644
--- a/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java
+++ b/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java
@@ -22,8 +22,11 @@ import java.util.List ;
import org.apache.http.client.HttpClient;
import org.apache.http.protocol.HttpContext;
import org.apache.jena.atlas.logging.Log ;
+import org.apache.jena.graph.Graph;
+import org.apache.jena.graph.impl.WrappedGraph;
import org.apache.jena.rdf.model.Model ;
import org.apache.jena.sparql.core.DatasetGraph ;
+import org.apache.jena.sparql.core.GraphView;
import org.apache.jena.sparql.engine.Plan ;
import org.apache.jena.sparql.engine.QueryEngineFactory ;
import org.apache.jena.sparql.engine.QueryEngineRegistry ;
@@ -31,6 +34,7 @@ import org.apache.jena.sparql.engine.QueryExecutionBase ;
import org.apache.jena.sparql.engine.binding.Binding ;
import org.apache.jena.sparql.engine.binding.BindingRoot ;
import org.apache.jena.sparql.engine.http.QueryEngineHTTP ;
+import org.apache.jena.sparql.graph.GraphWrapper;
import org.apache.jena.sparql.syntax.Element ;
import org.apache.jena.sparql.util.Context ;
@@ -126,7 +130,7 @@ public class QueryExecutionFactory
static public QueryExecution create(Query query, Model model) {
checkArg(query) ;
checkArg(model) ;
- return make(query, DatasetFactory.wrap(model)) ;
+ return make(query, model) ;
}
/** Create a QueryExecution to execute over the Model.
@@ -569,7 +573,28 @@ public class QueryExecutionFactory
}
static protected QueryExecution make(Query query) {
- return make(query, null) ;
+ return make(query, (Dataset)null) ;
+ }
+
+ protected static QueryExecution make(Query query, Model model) {
+ Dataset dataset = DatasetFactory.wrap(model);
+ Graph g = unwrap(model.getGraph());
+ if ( g instanceof GraphView ) {
+ GraphView gv = (GraphView)model.getGraph();
+ // Copy context of the storage dataset to the wrapper dataset.
+ dataset.getContext().putAll(gv.getDataset().getContext());
+ }
+ return make(query, dataset);
+ }
+
+ private static Graph unwrap(Graph graph) {
+ for(;;) {
+ if ( graph instanceof GraphWrapper )
+ graph = ((GraphWrapper)graph).get();
+ else if ( graph instanceof WrappedGraph )
+ graph = ((WrappedGraph)graph).getWrapped();
+ else return graph;
+ }
}
protected static QueryExecution make(Query query, Dataset dataset)
[17/27] jena git commit: Provide DatasetGraph operation
Posted by an...@apache.org.
Provide DatasetGraph operation
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/ec54d3dd
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/ec54d3dd
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/ec54d3dd
Branch: refs/heads/master
Commit: ec54d3ddc3eeab1e33cf0a8f0d4e44be40c4d16b
Parents: cdb9619
Author: Andy Seaborne <an...@apache.org>
Authored: Sun Aug 26 18:04:53 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sun Aug 26 18:04:53 2018 +0100
----------------------------------------------------------------------
.../jena/query/QueryExecutionFactory.java | 35 +++++++++++++------
.../jena/sparql/engine/QueryExecutionBase.java | 36 +++++++++++++++++---
2 files changed, 57 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/ec54d3dd/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java b/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java
index f784d1a..1894ca5 100644
--- a/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java
+++ b/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java
@@ -18,6 +18,7 @@
package org.apache.jena.query;
import java.util.List ;
+import java.util.Objects;
import org.apache.http.client.HttpClient;
import org.apache.http.protocol.HttpContext;
@@ -93,7 +94,19 @@ public class QueryExecutionFactory
// checkArg(dataset) ; // Allow null
return make(query, dataset) ;
}
-
+
+ /**
+ * Create a QueryExecution to execute over the {@link DatasetGraph}.
+ *
+ * @param query Query
+ * @param datasetGraph Target of the query
+ * @return QueryExecution
+ */
+ static public QueryExecution create(Query query, DatasetGraph datasetGraph) {
+ Objects.requireNonNull(query, "Query is null") ;
+ Objects.requireNonNull(datasetGraph, "DatasetGraph is null") ;
+ return make(query, datasetGraph) ;
+ }
/** Create a QueryExecution to execute over the Dataset.
*
* @param queryStr Query string
@@ -580,7 +593,7 @@ public class QueryExecutionFactory
Dataset dataset = DatasetFactory.wrap(model);
Graph g = unwrap(model.getGraph());
if ( g instanceof GraphView ) {
- GraphView gv = (GraphView)model.getGraph();
+ GraphView gv = (GraphView)g;
// Copy context of the storage dataset to the wrapper dataset.
dataset.getContext().putAll(gv.getDataset().getContext());
}
@@ -597,23 +610,25 @@ public class QueryExecutionFactory
}
}
- protected static QueryExecution make(Query query, Dataset dataset)
- { return make(query, dataset, null) ; }
+ protected static QueryExecution make(Query query, Dataset dataset)
+ { return make(query, dataset, null, null) ; }
-
- protected static QueryExecution make(Query query, Dataset dataset, Context context) {
+ protected static QueryExecution make(Query query, DatasetGraph datasetGraph)
+ { return make(query, null, datasetGraph, null) ; }
+
+ // Both Dataset and DatasetGraph for full backwards compatibility
+ protected static QueryExecution make(Query query, Dataset dataset, DatasetGraph dsg, Context context) {
+ if ( dsg == null && dataset != null )
+ dsg = dataset.asDatasetGraph();
query.setResultVars() ;
if ( context == null )
context = ARQ.getContext() ; // .copy done in QueryExecutionBase -> Context.setupContext.
- DatasetGraph dsg = null ;
- if ( dataset != null )
- dsg = dataset.asDatasetGraph() ;
QueryEngineFactory f = findFactory(query, dsg, context) ;
if ( f == null ) {
Log.warn(QueryExecutionFactory.class, "Failed to find a QueryEngineFactory") ;
return null ;
}
- return new QueryExecutionBase(query, dataset, context, f) ;
+ return new QueryExecutionBase(query, dataset, dsg, context, f) ;
}
static private QueryEngineFactory findFactory(Query query, DatasetGraph dataset, Context context) {
http://git-wip-us.apache.org/repos/asf/jena/blob/ec54d3dd/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryExecutionBase.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryExecutionBase.java b/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryExecutionBase.java
index e86c857..16aea26 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryExecutionBase.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryExecutionBase.java
@@ -33,7 +33,11 @@ import org.apache.jena.atlas.logging.Log;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.Triple;
import org.apache.jena.query.* ;
-import org.apache.jena.rdf.model.* ;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.rdf.model.RDFNode;
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.rdf.model.Statement;
import org.apache.jena.shared.PrefixMapping;
import org.apache.jena.sparql.ARQConstants;
import org.apache.jena.sparql.core.DatasetGraph;
@@ -82,16 +86,40 @@ public class QueryExecutionBase implements QueryExecution
private long timeout2 = TIMEOUT_UNSET;
private final AlarmClock alarmClock = AlarmClock.get();
- public QueryExecutionBase(Query query, Dataset dataset,
+ public QueryExecutionBase(Query query, Dataset dataset, Context context, QueryEngineFactory qeFactory) {
+ this(query, dataset, null, context, qeFactory);
+ }
+
+ public QueryExecutionBase(Query query, DatasetGraph datasetGraph, Context context, QueryEngineFactory qeFactory) {
+ this(query, null, datasetGraph, context, qeFactory);
+ }
+
+ public QueryExecutionBase(Query query, Dataset dataset, DatasetGraph datasetGraph,
Context context, QueryEngineFactory qeFactory) {
this.query = query;
- this.dataset = dataset ;
+ this.dataset = formDataset(dataset, datasetGraph);
this.qeFactory = qeFactory ;
- this.dsg = (dataset == null) ? null : dataset.asDatasetGraph() ;
+ this.dsg = formDatasetGraph(datasetGraph, dataset);
this.context = Context.setupContextExec(context, dsg) ;
init() ;
}
+ private static Dataset formDataset(Dataset dataset, DatasetGraph datasetGraph) {
+ if ( dataset != null )
+ return dataset;
+ if ( datasetGraph != null )
+ return DatasetFactory.wrap(datasetGraph);
+ return null;
+ }
+
+ private static DatasetGraph formDatasetGraph(DatasetGraph datasetGraph, Dataset dataset) {
+ if ( datasetGraph != null )
+ return datasetGraph;
+ if ( dataset != null )
+ return dataset.asDatasetGraph();
+ return null;
+ }
+
private void init() {
if ( query != null )
context.put(ARQConstants.sysCurrentQuery, query) ;
[09/27] jena git commit: Fix javadoc
Posted by an...@apache.org.
Fix javadoc
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/ba3b4b6d
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/ba3b4b6d
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/ba3b4b6d
Branch: refs/heads/master
Commit: ba3b4b6d1e6d64073db90f69b8a5feda195f3854
Parents: 9a60253
Author: Andy Seaborne <an...@apache.org>
Authored: Wed Aug 22 16:39:28 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Thu Aug 23 17:15:05 2018 +0100
----------------------------------------------------------------------
.../jena/permissions/SecurityEvaluator.java | 67 ++++++++------------
1 file changed, 28 insertions(+), 39 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/ba3b4b6d/jena-permissions/src/main/java/org/apache/jena/permissions/SecurityEvaluator.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/main/java/org/apache/jena/permissions/SecurityEvaluator.java b/jena-permissions/src/main/java/org/apache/jena/permissions/SecurityEvaluator.java
index b442dd3..41c157a 100644
--- a/jena-permissions/src/main/java/org/apache/jena/permissions/SecurityEvaluator.java
+++ b/jena-permissions/src/main/java/org/apache/jena/permissions/SecurityEvaluator.java
@@ -30,62 +30,51 @@ import org.apache.jena.shared.AuthenticationRequiredException;
/**
* SecurityEvaluator.
* <p>
- * The security evaluator is the link between the graph security system and an
- * external security system. This interface specifies the methods that are
- * required by the graph security system. It is assumed that the implementation
- * will handle tracking the current user and will query some underlying data
- * source to determine what actions the user can and can not take.
+ * The security evaluator is the link between the graph security system and an external
+ * security system. This interface specifies the methods that are required by the graph
+ * security system. It is assumed that the implementation will handle tracking the current
+ * user and will query some underlying data source to determine what actions the user can
+ * and can not take.
* </p>
* <p>
- * All questions of white listing or black listing will be handled in the
- * concrete implementation.
+ * All questions of white listing or black listing will be handled in the concrete
+ * implementation.
* </p>
* <p>
- * Implementations of this class should probably cache any evaluate calculations
- * as the evaluate methods are called frequently. However, the underlying
- * classes do cache results within a single method check.
+ * Implementations of this class should probably cache any evaluate calculations as the
+ * evaluate methods are called frequently. However, the underlying classes do cache
+ * results within a single method check.
* </p>
* <p>
* <dl>
* <dt>Secured operations</dt>
- * <dd>The security system recognizes and secures each of the CRUD (Create,
- * Read, Update and Delete) operations as represented by the Action enumeration.
- * </dd>
- * </dl>
- * <dl>
+ * <dd>The security system recognizes and secures each of the CRUD (Create, Read, Update
+ * and Delete) operations as represented by the Action enumeration.</dd>
* <dt>Levels of security</dt>
- * <dd>The security interfaces operates at two (2) levels: graph (or Model) and
- * triple.
+ * <dd>The security interfaces operates at two (2) levels: graph (or Model) and triple.
* <p>
- * At the the graph level the security evaluator may restrict CRUD access to the
- * graph or model as a whole. When evaluating the restriction, if the user it
- * not permitted to perform the operation on the graph or model access is
- * denied. If the user is permitted any triple restrictions are evaluated.
+ * At the the graph level the security evaluator may restrict CRUD access to the graph or
+ * model as a whole. When evaluating the restriction, if the user it not permitted to
+ * perform the operation on the graph or model access is denied. If the user is permitted
+ * any triple restrictions are evaluated.
* </p>
* <p>
- * At the triple level the security evaluator may restrict CRUD access to
- * specific triples. In order to skip potentially expensive triple security
- * checks the system will generally ask if the user is permitted the CRUD action
- * on any triple. This is represented by the SecTriple
- * <code>(ANY, ANY, ANY)</code>.
+ * At the triple level the security evaluator may restrict CRUD access to specific
+ * triples. In order to skip potentially expensive triple security checks the system will
+ * generally ask if the user is permitted the CRUD action on any triple. This is
+ * represented by the SecTriple <code>(ANY, ANY, ANY)</code>.
+ * </p>
* <ul>
- * <li>
- * If the system does not support triple level security the system should always
- * return <code>true</code>.</li>
- * If the system does support triple level security and is unable to verify that
- * the user can execute the CRUD action against any arbitrary triple the system
- * should return <code>false</code>. </li>
+ * <li>If the system does not support triple level security the system should always
+ * return <code>true</code>.</li> If the system does support triple level security and is
+ * unable to verify that the user can execute the CRUD action against any arbitrary triple
+ * the system should return <code>false</code>.</li>
* <li>See <code>Node.ANY</code>, <code>SecurityEvaluator.FUTURE</code>, and
- * <code>SecurityEvaluator.VARIABLE</code> for discussion of specifics of their
- * respective usages.</li>
+ * <code>SecurityEvaluator.VARIABLE</code> for discussion of specifics of their respective
+ * usages.</li>
* </ul>
- * </p>
* </dd>
* </dl>
- * <dl>
- * <dt>
- *
- * </p>
*/
public interface SecurityEvaluator {
/**
[21/27] jena git commit: travis.yaml: put openjdk8 first
Posted by an...@apache.org.
travis.yaml: put openjdk8 first
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/2ec9065c
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/2ec9065c
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/2ec9065c
Branch: refs/heads/master
Commit: 2ec9065c23923379dbe437a9cd37c1390bfe91ba
Parents: 99b9946
Author: Andy Seaborne <an...@apache.org>
Authored: Sun Aug 26 21:20:26 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sun Aug 26 21:20:26 2018 +0100
----------------------------------------------------------------------
.travis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/2ec9065c/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
index 4b582ee..7b39dcc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,7 +3,7 @@ sudo: false
install: true
script: mvn -B clean install
jdk:
- - oraclejdk8
- openjdk8
+ - oraclejdk8
env:
- JAVA_OPTS="-Xmx3072M -Xms512M -XX:+UseG1GC"
[16/27] jena git commit: JENA-901: Allow for the GC having freed some
weak values.
Posted by an...@apache.org.
JENA-901: Allow for the GC having freed some weak values.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/cdb9619b
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/cdb9619b
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/cdb9619b
Branch: refs/heads/master
Commit: cdb9619b559fd262b54e3e7d48973e96ebd90825
Parents: 2490112
Author: Andy Seaborne <an...@apache.org>
Authored: Sun Aug 26 14:14:27 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sun Aug 26 14:14:27 2018 +0100
----------------------------------------------------------------------
.../org/apache/jena/reasoner/rulesys/impl/TestLPBRuleEngine.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/cdb9619b/jena-core/src/test/java/org/apache/jena/reasoner/rulesys/impl/TestLPBRuleEngine.java
----------------------------------------------------------------------
diff --git a/jena-core/src/test/java/org/apache/jena/reasoner/rulesys/impl/TestLPBRuleEngine.java b/jena-core/src/test/java/org/apache/jena/reasoner/rulesys/impl/TestLPBRuleEngine.java
index fd940dd..4e5075a 100644
--- a/jena-core/src/test/java/org/apache/jena/reasoner/rulesys/impl/TestLPBRuleEngine.java
+++ b/jena-core/src/test/java/org/apache/jena/reasoner/rulesys/impl/TestLPBRuleEngine.java
@@ -162,8 +162,8 @@ public class TestLPBRuleEngine extends TestCase {
it.close();
}
- // Let's see how many were cached
- assertEquals(MAX, engine.tabledGoals.size());
+ // Let's see how many were cached - should be MAX or less (less if a GC freed weak values in the cache).
+ assertTrue(engine.tabledGoals.size() <= MAX);
// and no leaks of activeInterpreters (this will happen if we forget
// to call hasNext above)
assertEquals(0, engine.activeInterpreters.size());
[18/27] jena git commit: ARQ cleanup
Posted by an...@apache.org.
ARQ cleanup
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/dc7f38f5
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/dc7f38f5
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/dc7f38f5
Branch: refs/heads/master
Commit: dc7f38f5ff67444c2d8da26d5230f99ceaa4254b
Parents: ec54d3d
Author: Andy Seaborne <an...@apache.org>
Authored: Sun Aug 26 18:05:43 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sun Aug 26 18:05:43 2018 +0100
----------------------------------------------------------------------
.../jena/sparql/core/DatasetGraphCopyAdd.java | 41 ----
.../org/apache/jena/sparql/expr/ExprSystem.java | 9 +-
.../jena/sparql/sse/builders/BuilderLib.java | 245 ++++++++-----------
.../org/apache/jena/sparql/util/FmtUtils.java | 2 +-
4 files changed, 111 insertions(+), 186 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/dc7f38f5/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphCopyAdd.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphCopyAdd.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphCopyAdd.java
deleted file mode 100644
index 296b555..0000000
--- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphCopyAdd.java
+++ /dev/null
@@ -1,41 +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.sparql.core;
-
-import org.apache.jena.graph.Graph ;
-import org.apache.jena.graph.Node ;
-
-/** Override {@link DatasetGraph#addGraph} so that it always copies
- * content from the added graph data.
- */
-
-/*package*/ class DatasetGraphCopyAdd extends DatasetGraphWrapper
-{
- public DatasetGraphCopyAdd(boolean x , DatasetGraph dsg) {
- super(dsg);
- }
-
- @Override
- public void addGraph(Node graphName, Graph graph) {
- graph.find(null,null,null).forEachRemaining(t-> {
- Quad q = Quad.create(graphName, t) ;
- super.add(q) ;
- }) ;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/dc7f38f5/jena-arq/src/main/java/org/apache/jena/sparql/expr/ExprSystem.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/ExprSystem.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/ExprSystem.java
index dc31292..62cd25e 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/ExprSystem.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/ExprSystem.java
@@ -25,7 +25,7 @@ import org.apache.jena.sparql.util.Symbol ;
public abstract class ExprSystem extends ExprFunction0
{
- private final Symbol systemSymbol ;
+ protected final Symbol systemSymbol ;
protected ExprSystem(String fName, Symbol systemSymbol)
{
@@ -41,12 +41,11 @@ public abstract class ExprSystem extends ExprFunction0
if ( obj == null )
throw new ExprEvalException("null for system symbol: "+systemSymbol) ;
if ( ! ( obj instanceof Node ) )
- throw new ExprEvalException("Not a Node: "+Lib.className(obj)) ;
+ throw new ExprEvalException("ExprSystem: Not a Node: "+Lib.className(obj)) ;
Node n = (Node)obj ;
-// if ( n == null )
-// throw new ExprEvalException("No value for system variable: "+systemSymbol) ;
- // NodeValue.makeNode could have a cache.
+ if ( n == null )
+ throw new ExprEvalException("No value for system variable: "+systemSymbol) ;
NodeValue nv = NodeValue.makeNode(n) ;
return nv ;
}
http://git-wip-us.apache.org/repos/asf/jena/blob/dc7f38f5/jena-arq/src/main/java/org/apache/jena/sparql/sse/builders/BuilderLib.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/sse/builders/BuilderLib.java b/jena-arq/src/main/java/org/apache/jena/sparql/sse/builders/BuilderLib.java
index a154ac2..ed7b3e8 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/sse/builders/BuilderLib.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/sse/builders/BuilderLib.java
@@ -18,168 +18,135 @@
package org.apache.jena.sparql.sse.builders;
-import org.apache.jena.sparql.sse.Item ;
-import org.apache.jena.sparql.sse.ItemList ;
-import org.apache.jena.sparql.sse.ItemLocation ;
-
-public class BuilderLib
-{
-
- public static void checkNode(Item item)
- {
- if ( item.isNode() )
- return ;
- broken(item, "Not a node: "+item.shortString()) ;
- }
-
- public static void checkSymbol(Item item)
- {
- if ( item.isSymbol() )
- return ;
- broken(item, "Not a symbol: "+item.shortString()) ;
- }
-
- public static void checkTagged(Item item, String tag, String msg)
- {
- if ( item.isTagged(tag) ) return ;
- broken(item, msg, item) ;
- }
-
- public static void checkTagged(Item item, int len, String tag, String msg)
- {
- if ( item.isTagged(tag) && item.getList().size() == len )
- return ;
- broken(item, msg, item) ;
- }
-
-
- public static void checkTag(ItemList list, String tag)
- {
+import org.apache.jena.sparql.sse.Item;
+import org.apache.jena.sparql.sse.ItemList;
+import org.apache.jena.sparql.sse.ItemLocation;
+
+public class BuilderLib {
+
+ public static void checkNode(Item item) {
+ if ( item.isNode() )
+ return;
+ broken(item, "Not a node: " + item.shortString());
+ }
+
+ public static void checkSymbol(Item item) {
+ if ( item.isSymbol() )
+ return;
+ broken(item, "Not a symbol: " + item.shortString());
+ }
+
+ public static void checkTagged(Item item, String tag, String msg) {
+ if ( item.isTagged(tag) )
+ return;
+ broken(item, msg, item);
+ }
+
+ public static void checkTagged(Item item, int len, String tag, String msg) {
+ if ( item.isTagged(tag) && item.getList().size() == len )
+ return;
+ broken(item, msg, item);
+ }
+
+ public static void checkTag(ItemList list, String tag) {
if ( list.size() == 0 )
- broken(list, "Empty list") ;
- if ( ! list.get(0).isSymbolIgnoreCase(tag) )
- broken(list, "List does not start ("+tag+ "...) : "+list.shortString()) ;
+ broken(list, "Empty list");
+ if ( !list.get(0).isSymbolIgnoreCase(tag) )
+ broken(list, "List does not start (" + tag + "...) : " + list.shortString());
}
- public static void checkList(Item item)
- {
- if ( item.isList() )
- return ;
- broken(item, "Not a list: "+item.shortString()) ;
+ public static void checkList(Item item) {
+ if ( item.isList() )
+ return;
+ broken(item, "Not a list: " + item.shortString());
}
- public static void checkList(Item item, String msg)
- {
+ public static void checkList(Item item, String msg) {
if ( item.isList() )
- return ;
- if ( msg == null && item.isSymbol())
- msg = "Attempt to use a symbol where list expected: "+item.shortString() ;
- if ( msg == null && item.isNode())
- msg = "Attempt to use a node where list expected: "+item.shortString() ;
+ return;
+ if ( msg == null && item.isSymbol() )
+ msg = "Attempt to use a symbol where list expected: " + item.shortString();
+ if ( msg == null && item.isNode() )
+ msg = "Attempt to use a node where list expected: " + item.shortString();
if ( msg == null )
- msg = "Not a list" ;
- broken(item, msg) ;
- }
-
- public static void warning(ItemLocation location, String msg)
- {
- msg = msg(location, msg) ;
- System.err.println(msg) ;
+ msg = "Not a list";
+ broken(item, msg);
}
- public static void checkLength(int len1, int len2, ItemList list, String msg)
- {
+ public static void checkLength(int len1, int len2, ItemList list, String msg) {
if ( list.size() >= len1 && list.size() <= len2 )
- return ;
+ return;
if ( msg == null )
- msg = "Wrong number of arguments: ("+len1+"-"+len2+")/"+list.size()+" : "+list.shortString() ;
+ msg = "Wrong number of arguments: (" + len1 + "-" + len2 + ")/" + list.size() + " : " + list.shortString();
else
- msg = msg+" : "+list.shortString() ;
- broken(list, msg) ;
- }
-
-
-
- public static void checkLength(int len, ItemList list, String msg)
- {
+ msg = msg + " : " + list.shortString();
+ broken(list, msg);
+ }
+
+ public static void checkLength(int len, ItemList list, String msg) {
if ( list.size() == len )
- return ;
-
+ return;
+
if ( msg == null )
- msg = "Wrong number of arguments: "+len+"/"+list.size()+" : "+list.shortString() ;
+ msg = "Wrong number of arguments: " + len + "/" + list.size() + " : " + list.shortString();
else
- msg = msg+" : "+list.shortString() ;
- broken(list, msg) ;
+ msg = msg + " : " + list.shortString();
+ broken(list, msg);
}
- public static void checkLengthAtLeast(int len, ItemList list, String msg)
- {
- if ( list.size()>= len )
- return ;
-
+ public static void checkLengthAtLeast(int len, ItemList list, String msg) {
+ if ( list.size() >= len )
+ return;
+
if ( msg == null )
- msg = "Too few arguments: want > "+len+" :got : "+list.size()+" : "+list.shortString() ;
+ msg = "Too few arguments: want > " + len + " :got : " + list.size() + " : " + list.shortString();
else
- msg = msg+" : "+list.shortString() ;
- broken(list, msg) ;
- }
-
- public static void broken(Item item, String msg)
- {
- broken(item, msg, item) ;
- }
-
- public static void broken(String msg)
- {
- System.err.println(msg) ;
- exception(msg) ;
- }
-
- public static void exception(String msg)
- {
- throw new ExprBuildException(msg) ;
- }
-
- public static void broken(ItemLocation location, String msg, Item item)
- {
- msg = msg(location, msg) ;
- System.err.println(msg+": "+item.shortString()) ;
- exception(msg) ;
- }
-
- public static void broken(ItemList list, String msg)
- {
- broken(list, msg, list) ;
- }
-
- public static void broken(ItemLocation location, String msg, ItemList list)
- {
- msg = msg(location, msg) ;
- System.err.println(msg+": "+list.shortString()) ;
- exception(msg) ;
- }
-
- public static void broken(ItemLocation location, String msg)
- {
- msg = msg(location, msg) ;
- System.err.println(msg) ;
- exception(msg) ;
- }
-
- public static String msg(ItemLocation location, String msg)
- {
+ msg = msg + " : " + list.shortString();
+ broken(list, msg);
+ }
+
+ public static void broken(Item item, String msg) {
+ broken(item, msg, item);
+ }
+
+ public static void broken(String msg) {
+ exception(msg);
+ }
+
+ public static void exception(String msg) {
+ throw new ExprBuildException(msg);
+ }
+
+ public static void broken(ItemLocation location, String msg, Item item) {
+ msg = msg(location, msg);
+ exception(msg);
+ }
+
+ public static void broken(ItemList list, String msg) {
+ broken(list, msg, list);
+ }
+
+ public static void broken(ItemLocation location, String msg, ItemList list) {
+ msg = msg(location, msg);
+ exception(msg);
+ }
+
+ public static void broken(ItemLocation location, String msg) {
+ msg = msg(location, msg);
+ exception(msg);
+ }
+
+ public static String msg(ItemLocation location, String msg) {
if ( location != null )
- msg = location.location()+": "+msg ;
- return msg ;
+ msg = location.location() + ": " + msg;
+ return msg;
}
- public static ItemList skipTag(ItemList list, String tag)
- {
- if ( list.size() > 0 )
- {
+ public static ItemList skipTag(ItemList list, String tag) {
+ if ( list.size() > 0 ) {
if ( list.get(0).isSymbol(tag) )
- list = list.cdr() ;
+ list = list.cdr();
}
- return list ;
+ return list;
}
}
http://git-wip-us.apache.org/repos/asf/jena/blob/dc7f38f5/jena-arq/src/main/java/org/apache/jena/sparql/util/FmtUtils.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/FmtUtils.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/FmtUtils.java
index 8452fbe..e9a3ada 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/util/FmtUtils.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/FmtUtils.java
@@ -49,7 +49,7 @@ public class FmtUtils
{
// OLD CODE - being replaced by riot.NodeFmtLib
- // Consider withdrawing non-serialzation context forms of this.
+ // Consider withdrawing non-serialization context forms of this.
// Or a temporary SerialzationContext does not abbreviate bNodes.
static final String indentPrefix = " " ;
public static boolean multiLineExpr = false ;
[06/27] jena git commit: JENA-1585: Refactoring webapp code to
separate from the core server.
Posted by an...@apache.org.
JENA-1585: Refactoring webapp code to separate from the core server.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/06f59125
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/06f59125
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/06f59125
Branch: refs/heads/master
Commit: 06f59125002992a13160fbc0d855ee819f035816
Parents: 6265664
Author: Andy Seaborne <an...@apache.org>
Authored: Thu Aug 23 16:32:48 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Thu Aug 23 17:15:05 2018 +0100
----------------------------------------------------------------------
.../jena/fuseki/build/FusekiBuildLib.java | 5 +-
.../apache/jena/fuseki/build/FusekiConfig.java | 3 +-
.../apache/jena/fuseki/build/FusekiConst.java | 41 +++
.../org/apache/jena/fuseki/cmd/FusekiCmd.java | 1 -
.../org/apache/jena/fuseki/cmd/JettyFuseki.java | 325 +++++++++++++++++++
.../apache/jena/fuseki/ctl/ActionAsyncTask.java | 1 -
.../apache/jena/fuseki/ctl/ActionBackup.java | 65 ----
.../jena/fuseki/ctl/ActionBackupList.java | 94 ------
.../org/apache/jena/fuseki/ctl/ActionItem.java | 46 +++
.../org/apache/jena/fuseki/ctl/ActionStats.java | 11 +-
.../apache/jena/fuseki/ctl/JsonDescription.java | 73 +++++
.../org/apache/jena/fuseki/ctl/TaskBase.java | 4 +-
.../apache/jena/fuseki/jetty/JettyFuseki.java | 325 -------------------
.../apache/jena/fuseki/mgt/ActionBackup.java | 68 ++++
.../jena/fuseki/mgt/ActionBackupList.java | 95 ++++++
.../apache/jena/fuseki/mgt/ActionDatasets.java | 7 +-
.../org/apache/jena/fuseki/mgt/ActionItem.java | 46 ---
.../jena/fuseki/mgt/ActionServerStatus.java | 12 +-
.../apache/jena/fuseki/mgt/JsonDescription.java | 72 ----
.../org/apache/jena/fuseki/mgt/MgtConst.java | 52 ---
.../java/org/apache/jena/fuseki/mgt/MgtJMX.java | 61 ----
.../apache/jena/fuseki/mgt/ServerMgtConst.java | 39 +++
.../apache/jena/fuseki/mgt/ServiceMXBean.java | 32 --
.../apache/jena/fuseki/server/ServerConst.java | 41 +++
.../apache/jena/fuseki/webapp/SystemState.java | 16 -
.../src/main/webapp/WEB-INF/web.xml | 4 +-
.../src/main/webapp/js/app/controllers/.svnkeep | 0
.../src/main/webapp/js/app/layouts/.svnkeep | 0
.../src/main/webapp/js/app/routers/.svnkeep | 0
.../src/main/webapp/js/app/views/.svnkeep | 0
.../java/org/apache/jena/fuseki/ServerCtl.java | 2 +-
.../java/org/apache/jena/fuseki/TestAdmin.java | 19 +-
32 files changed, 763 insertions(+), 797 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuildLib.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuildLib.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuildLib.java
index e71edce..a964c9d 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuildLib.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuildLib.java
@@ -19,7 +19,6 @@
package org.apache.jena.fuseki.build;
import org.apache.jena.fuseki.FusekiConfigException;
-import org.apache.jena.fuseki.webapp.SystemState;
import org.apache.jena.query.* ;
import org.apache.jena.rdf.model.Literal ;
import org.apache.jena.rdf.model.Model ;
@@ -55,7 +54,7 @@ public class FusekiBuildLib {
}
public static ResultSet query(String string, Model m, String varName, RDFNode value) {
- Query query = QueryFactory.create(SystemState.PREFIXES + string) ;
+ Query query = QueryFactory.create(FusekiConst.PREFIXES + string) ;
QuerySolutionMap initValues = null ;
if ( varName != null )
initValues = querySolution(varName, value) ;
@@ -65,7 +64,7 @@ public class FusekiBuildLib {
}
public static ResultSet query(String string, Dataset ds, String varName, RDFNode value) {
- Query query = QueryFactory.create(SystemState.PREFIXES + string) ;
+ Query query = QueryFactory.create(FusekiConst.PREFIXES + string) ;
QuerySolutionMap initValues = null ;
if ( varName != null )
initValues = querySolution(varName, value) ;
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java
----------------------------------------------------------------------
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 7919099..9673cfa 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
@@ -38,7 +38,6 @@ import org.apache.jena.atlas.lib.StrUtils ;
import org.apache.jena.fuseki.Fuseki ;
import org.apache.jena.fuseki.FusekiConfigException ;
import org.apache.jena.fuseki.server.* ;
-import org.apache.jena.fuseki.webapp.SystemState;
import org.apache.jena.query.Dataset ;
import org.apache.jena.query.QuerySolution ;
import org.apache.jena.query.ReadWrite ;
@@ -202,7 +201,7 @@ public class FusekiConfig {
public static List<DataAccessPoint> readSystemDatabase(Dataset ds) {
DatasetDescriptionRegistry dsDescMap = new DatasetDescriptionRegistry() ;
String qs = StrUtils.strjoinNL
- (SystemState.PREFIXES ,
+ (FusekiConst.PREFIXES ,
"SELECT * {" ,
" GRAPH ?g {",
" ?s fu:name ?name ;" ,
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConst.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConst.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConst.java
new file mode 100644
index 0000000..3e75555
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConst.java
@@ -0,0 +1,41 @@
+/*
+ * 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.build;
+
+import org.apache.jena.atlas.lib.StrUtils;
+
+/** Internal constants */
+public class FusekiConst {
+
+ public static String PREFIXES = StrUtils.strjoinNL
+ ("BASE <http://example/base#>",
+ "PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>",
+ "PREFIX fu: <http://jena.apache.org/fuseki#>",
+ "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 sdb: <http://jena.hpl.hp.com/2007/sdb#>",
+ "PREFIX list: <http://jena.apache.org/ARQ/list#>",
+ "PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>",
+ "PREFIX apf: <http://jena.apache.org/ARQ/property#>",
+ "PREFIX afn: <http://jena.apache.org/ARQ/function#>",
+ "") ;
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/FusekiCmd.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/FusekiCmd.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/FusekiCmd.java
index 9fd5075..e62b118 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/FusekiCmd.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/FusekiCmd.java
@@ -30,7 +30,6 @@ import org.apache.jena.atlas.lib.FileOps ;
import org.apache.jena.fuseki.Fuseki ;
import org.apache.jena.fuseki.FusekiException;
import org.apache.jena.fuseki.build.Template ;
-import org.apache.jena.fuseki.jetty.JettyFuseki ;
import org.apache.jena.fuseki.jetty.JettyServerConfig ;
import org.apache.jena.fuseki.server.FusekiInitialConfig ;
import org.apache.jena.fuseki.system.FusekiLogging;
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/JettyFuseki.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/JettyFuseki.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/JettyFuseki.java
new file mode 100644
index 0000000..29608d0
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/JettyFuseki.java
@@ -0,0 +1,325 @@
+/*
+ * 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.cmd ;
+
+import static java.lang.String.format ;
+import static org.apache.jena.fuseki.Fuseki.serverLog ;
+
+import java.io.FileInputStream ;
+
+import javax.servlet.ServletContext ;
+
+import org.apache.jena.atlas.lib.DateTimeUtils ;
+import org.apache.jena.atlas.lib.FileOps ;
+import org.apache.jena.fuseki.Fuseki ;
+import org.apache.jena.fuseki.FusekiException ;
+import org.apache.jena.fuseki.jetty.FusekiErrorHandler;
+import org.apache.jena.fuseki.jetty.JettyServerConfig;
+import org.apache.jena.fuseki.server.DataAccessPointRegistry ;
+import org.apache.jena.fuseki.webapp.FusekiEnv;
+import org.eclipse.jetty.security.* ;
+import org.eclipse.jetty.security.authentication.BasicAuthenticator ;
+import org.eclipse.jetty.server.HttpConnectionFactory ;
+import org.eclipse.jetty.server.Server ;
+import org.eclipse.jetty.server.ServerConnector ;
+import org.eclipse.jetty.server.handler.AllowSymLinkAliasChecker ;
+import org.eclipse.jetty.server.handler.ContextHandler ;
+import org.eclipse.jetty.server.handler.gzip.GzipHandler ;
+import org.eclipse.jetty.servlet.ServletContextHandler ;
+import org.eclipse.jetty.util.security.Constraint ;
+import org.eclipse.jetty.webapp.WebAppContext ;
+import org.eclipse.jetty.xml.XmlConfiguration ;
+
+/** Standalone full server, not run as a WAR file.
+ * Used in testing and development.
+ *
+ * SPARQLServer is the Jena server instance which wraps/utilizes
+ * {@link org.eclipse.jetty.server.Server}. This class provides
+ * immediate access to the {@link org.eclipse.jetty.server.Server#start()} and
+ * {@link org.eclipse.jetty.server.Server#stop()} commands as well as obtaining
+ * instances of the server and server configuration. Finally we can obtain
+ * instances of {@link org.apache.jena.fuseki.jetty.JettyServerConfig}.
+ */
+public class JettyFuseki {
+ // Jetty specific.
+ // This class is becoming less important - it now sets up a Jetty server for in-process use
+ // either for the command line in development
+ // and in testing but not direct webapp deployments.
+ static { Fuseki.init() ; }
+
+ public static JettyFuseki instance = null ;
+
+ private ServerConnector serverConnector = null ;
+ // If a separate ...
+ private ServerConnector mgtConnector = null ;
+
+ private JettyServerConfig serverConfig ;
+
+ // The jetty server.
+
+ private Server server = null ;
+ private ServletContext servletContext = null ;
+
+ // webapp setup - standard maven layout
+ public static String contextpath = "/" ;
+ // Standalone jar
+ public static final String resourceBase1 = "webapp" ;
+ // Development
+ public static final String resourceBase2 = "src/main/webapp" ;
+
+ /**
+ * Default setup which requires a {@link org.apache.jena.fuseki.jetty.JettyServerConfig}
+ * object as input. We use this config to pass in the command line arguments for dataset,
+ * name etc.
+ * @param config
+ */
+
+ public static void initializeServer(JettyServerConfig config) {
+ instance = new JettyFuseki(config) ;
+ }
+
+ private JettyFuseki(JettyServerConfig config) {
+ this.serverConfig = config ;
+ buildServerWebapp(serverConfig.contextPath, serverConfig.jettyConfigFile) ;
+ if ( mgtConnector == null )
+ mgtConnector = serverConnector ;
+
+ if ( config.enableCompression ) {
+ GzipHandler gzipHandler = new GzipHandler();
+ gzipHandler.setHandler(server.getHandler());
+ server.setHandler(gzipHandler);
+ }
+ }
+
+ /**
+ * Initialize the {@link JettyFuseki} instance.
+ */
+ public void start() {
+
+ String version = Fuseki.VERSION ;
+ String buildDate = Fuseki.BUILD_DATE ;
+
+ if ( version != null && version.equals("${project.version}") )
+ version = null ;
+ if ( buildDate != null && buildDate.equals("${build.time.xsd}") )
+ buildDate = DateTimeUtils.nowAsXSDDateTimeString() ;
+
+ if ( version != null ) {
+ if ( Fuseki.developmentMode && buildDate != null )
+ serverLog.info(format("%s %s %s", Fuseki.NAME, version, buildDate)) ;
+ else
+ serverLog.info(format("%s %s", Fuseki.NAME, version)) ;
+ }
+ // This does not get set usefully for Jetty as we use it.
+ // String jettyVersion = org.eclipse.jetty.server.Server.getVersion() ;
+ // serverLog.info(format("Jetty %s",jettyVersion)) ;
+
+ String host = serverConnector.getHost() ;
+ if ( host != null )
+ serverLog.info("Incoming connections limited to " + host) ;
+
+ try {
+ server.start() ;
+ } catch (java.net.BindException ex) {
+ serverLog.error("SPARQLServer (port="+serverConnector.getPort()+"): Failed to start server: " + ex.getMessage()) ;
+ throw new FusekiException("BindException: port="+serverConnector.getPort()+": Failed to start server: " + ex.getMessage(), ex) ;
+ } catch (Exception ex) {
+ serverLog.error("SPARQLServer: Failed to start server: " + ex.getMessage(), ex) ;
+ throw new FusekiException("Failed to start server: " + ex.getMessage(), ex) ;
+ }
+ String now = DateTimeUtils.nowAsString() ;
+ serverLog.info(format("Started %s on port %d", now, serverConnector.getPort())) ;
+ }
+
+ /**
+ * Sync with the {@link JettyFuseki} instance.
+ * Returns only if the server exits cleanly
+ */
+ public void join() {
+ try {
+ server.join() ;
+ } catch (InterruptedException ex) { }
+ }
+
+ /**
+ * Stop the {@link JettyFuseki} instance.
+ */
+ public void stop() {
+ String now = DateTimeUtils.nowAsString() ;
+ serverLog.info(format("Stopped %s on port %d", now, serverConnector.getPort())) ;
+ try {
+ server.stop() ;
+ } catch (Exception ex) {
+ Fuseki.serverLog.warn("SPARQLServer: Exception while stopping server: " + ex.getMessage(), ex) ;
+ }
+ }
+
+ public static WebAppContext createWebApp(String contextPath) {
+ FusekiEnv.setEnvironment();
+ WebAppContext webapp = new WebAppContext();
+ webapp.getServletContext().getContextHandler().setMaxFormContentSize(10 * 1000 * 1000) ;
+
+ // Hunt for the webapp for the standalone jar (or development system).
+ // Note that Path FUSEKI_HOME is not initialized until the webapp starts
+ // so it is not available here.
+
+ String resourceBase3 = null ;
+ String resourceBase4 = null ;
+ if ( FusekiEnv.FUSEKI_HOME != null ) {
+ String HOME = FusekiEnv.FUSEKI_HOME.toString() ;
+ resourceBase3 = HOME+"/"+resourceBase1 ;
+ resourceBase4 = HOME+"/"+resourceBase2 ;
+ }
+
+ String resourceBase = tryResourceBase(resourceBase1, null) ;
+ resourceBase = tryResourceBase(resourceBase2, resourceBase) ;
+ resourceBase = tryResourceBase(resourceBase3, resourceBase) ;
+ resourceBase = tryResourceBase(resourceBase4, resourceBase) ;
+
+ if ( resourceBase == null ) {
+ if ( resourceBase3 == null )
+ Fuseki.serverLog.error("Can't find resourceBase (tried "+resourceBase1+" and "+resourceBase2+")") ;
+ else
+ Fuseki.serverLog.error("Can't find resourceBase (tried "+resourceBase1+", "+resourceBase2+", "+resourceBase3+" and "+resourceBase4+")") ;
+ Fuseki.serverLog.error("Failed to start") ;
+ throw new FusekiException("Failed to start") ;
+ }
+
+ webapp.setDescriptor(resourceBase+"/WEB-INF/web.xml");
+ webapp.setResourceBase(resourceBase);
+ webapp.setContextPath(contextPath);
+
+ //-- Jetty setup for the ServletContext logger.
+ // The name of the Jetty-allocated slf4j/log4j logger is
+ // the display name or, if null, the context path name.
+ // It is set, without checking for a previous call of setLogger in "doStart"
+ // 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()) ;
+ return webapp ;
+ }
+
+ public static String getenv(String name) {
+ String x = System.getenv(name) ;
+ if ( x == null )
+ x = System.getProperty(name) ;
+ return x ;
+ }
+
+ public DataAccessPointRegistry getDataAccessPointRegistry() {
+ return DataAccessPointRegistry.get(servletContext) ;
+ }
+
+ private static String tryResourceBase(String maybeResourceBase, String currentResourceBase) {
+ if ( currentResourceBase != null )
+ return currentResourceBase ;
+ if ( maybeResourceBase != null && FileOps.exists(maybeResourceBase) )
+ return maybeResourceBase ;
+ return currentResourceBase ;
+ }
+
+ private void buildServerWebapp(String contextPath, String jettyConfig) {
+ if ( jettyConfig != null )
+ // --jetty-config=jetty-fuseki.xml
+ // for detailed configuration of the server using Jetty features.
+ configServer(jettyConfig) ;
+ else
+ defaultServerConfig(serverConfig.port, serverConfig.loopback) ;
+
+ WebAppContext webapp = createWebApp(contextPath) ;
+ if ( false /*enable symbolic links */ ) {
+ // See http://www.eclipse.org/jetty/documentation/current/serving-aliased-files.html
+ // Record what would be needed:
+ // 1 - Allow all symbolic links without checking
+ webapp.addAliasCheck(new ContextHandler.ApproveAliases());
+ // 2 - Check links are to valid resources. But default for Unix?
+ webapp.addAliasCheck(new AllowSymLinkAliasChecker()) ;
+ }
+ servletContext = webapp.getServletContext() ;
+ server.setHandler(webapp) ;
+ // Replaced by Shiro.
+ if ( jettyConfig == null && serverConfig.authConfigFile != null )
+ security(webapp, serverConfig.authConfigFile) ;
+ }
+
+ // This is now provided by Shiro.
+ private static void security(ServletContextHandler context, String authfile) {
+ Constraint constraint = new Constraint() ;
+ constraint.setName(Constraint.__BASIC_AUTH) ;
+ constraint.setRoles(new String[]{"fuseki"}) ;
+ constraint.setAuthenticate(true) ;
+
+ ConstraintMapping mapping = new ConstraintMapping() ;
+ mapping.setConstraint(constraint) ;
+ mapping.setPathSpec("/*") ;
+
+ IdentityService identService = new DefaultIdentityService() ;
+
+ ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler() ;
+ securityHandler.addConstraintMapping(mapping) ;
+ securityHandler.setIdentityService(identService) ;
+
+ HashLoginService loginService = new HashLoginService("Fuseki Authentication", authfile) ;
+ loginService.setIdentityService(identService) ;
+
+ securityHandler.setLoginService(loginService) ;
+ securityHandler.setAuthenticator(new BasicAuthenticator()) ;
+
+ context.setSecurityHandler(securityHandler) ;
+
+ serverLog.debug("Basic Auth Configuration = " + authfile) ;
+ }
+
+ private void configServer(String jettyConfig) {
+ try {
+ serverLog.info("Jetty server config file = " + jettyConfig) ;
+ server = new Server() ;
+ XmlConfiguration configuration = new XmlConfiguration(new FileInputStream(jettyConfig)) ;
+ configuration.configure(server) ;
+ serverConnector = (ServerConnector)server.getConnectors()[0] ;
+ } catch (Exception ex) {
+ serverLog.error("SPARQLServer: Failed to configure server: " + ex.getMessage(), ex) ;
+ throw new FusekiException("Failed to configure a server using configuration file '" + jettyConfig + "'") ;
+ }
+ }
+
+ private void defaultServerConfig(int port, boolean loopback) {
+ server = new Server() ;
+ HttpConnectionFactory f1 = new HttpConnectionFactory() ;
+ // Some people do try very large operations ... really, should use POST.
+ f1.getHttpConfiguration().setRequestHeaderSize(512 * 1024);
+ f1.getHttpConfiguration().setOutputBufferSize(5 * 1024 * 1024) ;
+ // Do not add "Server: Jetty(....) when not a development system.
+ if ( ! Fuseki.outputJettyServerHeader )
+ f1.getHttpConfiguration().setSendServerVersion(false) ;
+
+ // https is better done with a Jetty configuration file
+ // because there are several things to configure.
+ // See "examples/fuseki-jetty-https.xml"
+
+ ServerConnector connector = new ServerConnector(server, f1) ;
+ connector.setPort(port) ;
+ server.addConnector(connector);
+ if ( loopback )
+ connector.setHost("localhost");
+ serverConnector = connector ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionAsyncTask.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionAsyncTask.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionAsyncTask.java
index 5c3ec01..4310c6f 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionAsyncTask.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionAsyncTask.java
@@ -22,7 +22,6 @@ import org.apache.jena.atlas.json.JsonValue ;
import org.apache.jena.atlas.lib.InternalErrorException ;
import org.apache.jena.fuseki.async.AsyncPool ;
import org.apache.jena.fuseki.async.AsyncTask ;
-import org.apache.jena.fuseki.mgt.ActionItem;
import org.apache.jena.fuseki.servlets.HttpAction ;
import org.apache.jena.fuseki.servlets.ServletOps ;
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionBackup.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionBackup.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionBackup.java
deleted file mode 100644
index b83c736..0000000
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionBackup.java
+++ /dev/null
@@ -1,65 +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.ctl;
-
-import static java.lang.String.format ;
-
-import org.apache.jena.fuseki.servlets.HttpAction ;
-import org.apache.jena.fuseki.servlets.ServletOps ;
-import org.slf4j.Logger ;
-import org.slf4j.LoggerFactory ;
-
-public class ActionBackup extends ActionAsyncTask
-{
- public ActionBackup() { super() ; }
-
- @Override
- protected Runnable createRunnable(HttpAction action) {
- String name = action.getDatasetName() ;
- if ( name == null ) {
- action.log.error("Null for dataset name in item request") ;
- ServletOps.errorOccurred("Null for dataset name in item request");
- return null ;
- }
-
- action.log.info(format("[%d] Backup dataset %s", action.id, name)) ;
- return new BackupTask(action) ;
- }
-
- static class BackupTask extends TaskBase {
- static private Logger log = LoggerFactory.getLogger("Backup") ;
-
- public BackupTask(HttpAction action) {
- super(action) ;
- }
-
- @Override
- public void run() {
- try {
- String backupFilename = Backup.chooseFileName(datasetName) ;
- log.info(format("[%d] >>>> Start backup %s -> %s", actionId, datasetName, backupFilename)) ;
- Backup.backup(transactional, dataset, backupFilename) ;
- log.info(format("[%d] <<<< Finish backup %s -> %s", actionId, datasetName, backupFilename)) ;
- } catch (Exception ex) {
- log.info(format("[%d] **** Exception in backup", actionId), ex) ;
- }
- }
- }
-}
-
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionBackupList.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionBackupList.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionBackupList.java
deleted file mode 100644
index 509408e..0000000
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionBackupList.java
+++ /dev/null
@@ -1,94 +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.ctl;
-
-import static java.lang.String.format ;
-
-import java.io.File ;
-import java.io.IOException ;
-import java.nio.file.DirectoryStream ;
-import java.nio.file.Files ;
-import java.nio.file.Path ;
-import java.util.ArrayList ;
-import java.util.List ;
-import java.util.stream.Collectors ;
-
-import javax.servlet.http.HttpServletRequest ;
-import javax.servlet.http.HttpServletResponse ;
-
-import org.apache.jena.atlas.json.JsonBuilder ;
-import org.apache.jena.atlas.json.JsonValue ;
-import org.apache.jena.fuseki.servlets.HttpAction ;
-import org.apache.jena.fuseki.servlets.ServletOps ;
-import org.apache.jena.fuseki.webapp.FusekiSystem;
-
-/**
- * A JSON API to list all the backups in the backup directory
- */
-public class ActionBackupList extends ActionCtl {
-
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
- doCommon(req, resp);
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
- doCommon(req, resp);
- }
-
- @Override
- protected void perform(HttpAction action) {
- JsonValue result = description(action) ;
- ServletOps.setNoCache(action.response) ;
- ServletOps.sendJsonReponse(action, result);
- }
-
- private static DirectoryStream.Filter<Path> filterVisibleFiles = (entry) -> {
- File f = entry.toFile() ;
- return f.isFile() && !f.isHidden() ;
- } ;
-
- private JsonValue description(HttpAction action) {
- if ( ! Files.isDirectory(FusekiSystem.dirBackups) )
- ServletOps.errorOccurred(format("[%d] Backup area '%s' is not a directory", action.id, FusekiSystem.dirBackups)) ;
-
- List<Path> paths = new ArrayList<>() ;
- try (DirectoryStream<Path> stream = Files.newDirectoryStream(FusekiSystem.dirBackups, filterVisibleFiles)) {
- stream.forEach(paths::add) ;
- } catch (IOException ex) {
- action.log.error(format("[%d] Backup file list :: IOException :: %s", action.id, ex.getMessage())) ;
- ServletOps.errorOccurred(ex);
- }
-
- List<String> fileNames = paths.stream().map((p)->p.getFileName().toString()).sorted().collect(Collectors.toList()) ;
-
- JsonBuilder builder = new JsonBuilder() ;
- builder.startObject("top") ;
- builder.key("backups") ;
-
- builder.startArray() ;
- fileNames.forEach(builder::value) ;
- builder.finishArray() ;
-
- builder.finishObject("top") ;
- return builder.build() ;
-
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionItem.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionItem.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionItem.java
new file mode 100644
index 0000000..ea015e5
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionItem.java
@@ -0,0 +1,46 @@
+/**
+ * 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.ctl;
+
+import org.apache.jena.atlas.json.JsonValue ;
+import org.apache.jena.fuseki.ctl.ActionContainerItem;
+import org.apache.jena.fuseki.servlets.HttpAction;
+import org.apache.jena.fuseki.servlets.ServletOps;
+import org.apache.jena.web.HttpSC ;
+
+/** Action on items in a container, but not the container itself */
+public abstract class ActionItem extends ActionContainerItem
+{
+ public ActionItem() { super() ; }
+
+ @Override
+ final
+ protected JsonValue execGetContainer(HttpAction action) {
+ ServletOps.error(HttpSC.METHOD_NOT_ALLOWED_405) ;
+ return null ;
+ }
+
+ @Override
+ final
+ protected JsonValue execPostContainer(HttpAction action) {
+ ServletOps.error(HttpSC.METHOD_NOT_ALLOWED_405) ;
+ return null ;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionStats.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionStats.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionStats.java
index dacd151..f9ab32f 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionStats.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionStats.java
@@ -32,7 +32,6 @@ import javax.servlet.http.HttpServletResponse ;
import org.apache.jena.atlas.json.JsonBuilder ;
import org.apache.jena.atlas.json.JsonObject ;
import org.apache.jena.atlas.json.JsonValue ;
-import org.apache.jena.fuseki.mgt.MgtConst;
import org.apache.jena.fuseki.server.* ;
import org.apache.jena.fuseki.servlets.HttpAction ;
@@ -50,7 +49,7 @@ public class ActionStats extends ActionContainerItem
public static JsonObject generateStats(DataAccessPointRegistry registry) {
JsonBuilder builder = new JsonBuilder() ;
builder.startObject("top") ;
- builder.key(MgtConst.datasets) ;
+ builder.key(ServerConst.datasets) ;
builder.startObject("datasets") ;
registry.forEach((name, access)->statsDataset(builder, access));
builder.finishObject("datasets") ;
@@ -66,7 +65,7 @@ public class ActionStats extends ActionContainerItem
String datasetPath = DataAccessPoint.canonical(action.getDatasetName()) ;
builder.startObject("TOP") ;
- builder.key(MgtConst.datasets) ;
+ builder.key(ServerConst.datasets) ;
builder.startObject("datasets") ;
statsDataset(builder, datasetPath, action.getDataAccessPointRegistry()) ;
builder.finishObject("datasets") ;
@@ -96,7 +95,7 @@ public class ActionStats extends ActionContainerItem
builder.key(CounterName.RequestsGood.getName()).value(dSrv.getCounters().value(CounterName.RequestsGood)) ;
builder.key(CounterName.RequestsBad.getName()).value(dSrv.getCounters().value(CounterName.RequestsBad)) ;
- builder.key(MgtConst.endpoints).startObject("endpoints") ;
+ builder.key(ServerConst.endpoints).startObject("endpoints") ;
for ( Operation operName : dSrv.getOperations() ) {
List<Endpoint> endpoints = access.getDataService().getEndpoints(operName) ;
@@ -107,8 +106,8 @@ public class ActionStats extends ActionContainerItem
builder.startObject() ;
operationCounters(builder, endpoint);
- builder.key(MgtConst.operation).value(operName.getName()) ;
- builder.key(MgtConst.description).value(operName.getDescription());
+ builder.key(ServerConst.operation).value(operName.getName()) ;
+ builder.key(ServerConst.description).value(operName.getDescription());
builder.finishObject() ;
}
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/JsonDescription.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/JsonDescription.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/JsonDescription.java
new file mode 100644
index 0000000..d4d4ad5
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/JsonDescription.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.fuseki.ctl;
+
+import java.util.List ;
+
+import org.apache.jena.atlas.json.JsonBuilder ;
+import org.apache.jena.fuseki.server.DataAccessPoint ;
+import org.apache.jena.fuseki.server.DataAccessPointRegistry ;
+import org.apache.jena.fuseki.server.Endpoint ;
+import org.apache.jena.fuseki.server.Operation ;
+import org.apache.jena.fuseki.server.ServerConst;
+
+/** Create a description of a service */
+public class JsonDescription {
+
+ public static void arrayDatasets(JsonBuilder builder, DataAccessPointRegistry registry) {
+ builder.startArray() ;
+ for ( String ds : registry.keys() ) {
+ DataAccessPoint access = registry.get(ds) ;
+ JsonDescription.describe(builder, access) ;
+ }
+ builder.finishArray() ;
+ }
+
+ public static void describe(JsonBuilder builder, DataAccessPoint access) {
+ builder.startObject() ;
+ builder.key(ServerConst.dsName).value(access.getName()) ;
+
+ builder.key(ServerConst.dsState).value(access.getDataService().isAcceptingRequests()) ;
+
+ builder.key(ServerConst.dsService) ;
+ builder.startArray() ;
+
+ for ( Operation operation : access.getDataService().getOperations() ) {
+ List<Endpoint> endpoints = access.getDataService().getEndpoints(operation) ;
+ describe(builder, operation, endpoints) ;
+ }
+ builder.finishArray() ;
+ builder.finishObject() ;
+ }
+
+ private static void describe(JsonBuilder builder, Operation operation, List<Endpoint> endpoints) {
+ builder.startObject() ;
+
+ builder.key(ServerConst.srvType).value(operation.getName()) ;
+ builder.key(ServerConst.srvDescription).value(operation.getDescription()) ;
+ builder.key(ServerConst.srvEndpoints) ;
+ builder.startArray() ;
+ for ( Endpoint endpoint : endpoints )
+ builder.value(endpoint.getEndpoint()) ;
+ builder.finishArray() ;
+
+ builder.finishObject() ;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/TaskBase.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/TaskBase.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/TaskBase.java
index f885839..8b73a98 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/TaskBase.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/TaskBase.java
@@ -22,10 +22,10 @@ import org.apache.jena.fuseki.servlets.HttpAction ;
import org.apache.jena.sparql.core.DatasetGraph ;
import org.apache.jena.sparql.core.Transactional ;
-/** Base of async tasks - this caries some useful information around, leaving the
+/** Base of async tasks - this carries some useful information around, leaving the
* implementation of Callable.run() to the specific task.
*/
-abstract class TaskBase implements Runnable {
+public abstract class TaskBase implements Runnable {
public final long actionId ;
public final DatasetGraph dataset ;
public final String datasetName ;
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyFuseki.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyFuseki.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyFuseki.java
deleted file mode 100644
index aa1340b..0000000
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyFuseki.java
+++ /dev/null
@@ -1,325 +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 static org.apache.jena.fuseki.Fuseki.serverLog ;
-
-import java.io.FileInputStream ;
-
-import javax.servlet.ServletContext ;
-
-import org.apache.jena.atlas.lib.DateTimeUtils ;
-import org.apache.jena.atlas.lib.FileOps ;
-import org.apache.jena.fuseki.Fuseki ;
-import org.apache.jena.fuseki.FusekiException ;
-import org.apache.jena.fuseki.mgt.MgtJMX ;
-import org.apache.jena.fuseki.server.DataAccessPointRegistry ;
-import org.apache.jena.fuseki.webapp.FusekiEnv;
-import org.eclipse.jetty.security.* ;
-import org.eclipse.jetty.security.authentication.BasicAuthenticator ;
-import org.eclipse.jetty.server.HttpConnectionFactory ;
-import org.eclipse.jetty.server.Server ;
-import org.eclipse.jetty.server.ServerConnector ;
-import org.eclipse.jetty.server.handler.AllowSymLinkAliasChecker ;
-import org.eclipse.jetty.server.handler.ContextHandler ;
-import org.eclipse.jetty.server.handler.gzip.GzipHandler ;
-import org.eclipse.jetty.servlet.ServletContextHandler ;
-import org.eclipse.jetty.util.security.Constraint ;
-import org.eclipse.jetty.webapp.WebAppContext ;
-import org.eclipse.jetty.xml.XmlConfiguration ;
-
-/** Standalone server, not run as a WAR file.
- * Used in testing and development.
- *
- * SPARQLServer is the Jena server instance which wraps/utilizes
- * {@link org.eclipse.jetty.server.Server}. This class provides
- * immediate access to the {@link org.eclipse.jetty.server.Server#start()} and
- * {@link org.eclipse.jetty.server.Server#stop()} commands as well as obtaining
- * instances of the server and server configuration. Finally we can obtain
- * instances of {@link org.apache.jena.fuseki.jetty.JettyServerConfig}.
- */
-public class JettyFuseki {
- // Jetty specific.
- // This class is becoming less important - it now sets up a Jetty server for in-process use
- // either for the command line in development
- // and in testing but not direct webapp deployments.
- static { Fuseki.init() ; }
-
- public static JettyFuseki instance = null ;
-
- private ServerConnector serverConnector = null ;
- // If a separate ...
- private ServerConnector mgtConnector = null ;
-
- private JettyServerConfig serverConfig ;
-
- // The jetty server.
-
- private Server server = null ;
- private ServletContext servletContext = null ;
-
- // webapp setup - standard maven layout
- public static String contextpath = "/" ;
- // Standalone jar
- public static final String resourceBase1 = "webapp" ;
- // Development
- public static final String resourceBase2 = "src/main/webapp" ;
-
- /**
- * Default setup which requires a {@link org.apache.jena.fuseki.jetty.JettyServerConfig}
- * object as input. We use this config to pass in the command line arguments for dataset,
- * name etc.
- * @param config
- */
-
- public static void initializeServer(JettyServerConfig config) {
- instance = new JettyFuseki(config) ;
- }
-
- private JettyFuseki(JettyServerConfig config) {
- this.serverConfig = config ;
- buildServerWebapp(serverConfig.contextPath, serverConfig.jettyConfigFile) ;
- if ( mgtConnector == null )
- mgtConnector = serverConnector ;
-
- if ( config.enableCompression ) {
- GzipHandler gzipHandler = new GzipHandler();
- gzipHandler.setHandler(server.getHandler());
- server.setHandler(gzipHandler);
- }
- }
-
- /**
- * Initialize the {@link JettyFuseki} instance.
- */
- public void start() {
-
- String version = Fuseki.VERSION ;
- String buildDate = Fuseki.BUILD_DATE ;
-
- if ( version != null && version.equals("${project.version}") )
- version = null ;
- if ( buildDate != null && buildDate.equals("${build.time.xsd}") )
- buildDate = DateTimeUtils.nowAsXSDDateTimeString() ;
-
- if ( version != null ) {
- if ( Fuseki.developmentMode && buildDate != null )
- serverLog.info(format("%s %s %s", Fuseki.NAME, version, buildDate)) ;
- else
- serverLog.info(format("%s %s", Fuseki.NAME, version)) ;
- }
- // This does not get set usefully for Jetty as we use it.
- // String jettyVersion = org.eclipse.jetty.server.Server.getVersion() ;
- // serverLog.info(format("Jetty %s",jettyVersion)) ;
-
- String host = serverConnector.getHost() ;
- if ( host != null )
- serverLog.info("Incoming connections limited to " + host) ;
-
- try {
- server.start() ;
- } catch (java.net.BindException ex) {
- serverLog.error("SPARQLServer (port="+serverConnector.getPort()+"): Failed to start server: " + ex.getMessage()) ;
- throw new FusekiException("BindException: port="+serverConnector.getPort()+": Failed to start server: " + ex.getMessage(), ex) ;
- } catch (Exception ex) {
- serverLog.error("SPARQLServer: Failed to start server: " + ex.getMessage(), ex) ;
- throw new FusekiException("Failed to start server: " + ex.getMessage(), ex) ;
- }
- String now = DateTimeUtils.nowAsString() ;
- serverLog.info(format("Started %s on port %d", now, serverConnector.getPort())) ;
- }
-
- /**
- * Sync with the {@link JettyFuseki} instance.
- * Returns only if the server exits cleanly
- */
- public void join() {
- try {
- server.join() ;
- } catch (InterruptedException ex) { }
- }
-
- /**
- * Stop the {@link JettyFuseki} instance.
- */
- public void stop() {
- String now = DateTimeUtils.nowAsString() ;
- serverLog.info(format("Stopped %s on port %d", now, serverConnector.getPort())) ;
- try {
- server.stop() ;
- } catch (Exception ex) {
- Fuseki.serverLog.warn("SPARQLServer: Exception while stopping server: " + ex.getMessage(), ex) ;
- }
- MgtJMX.removeJMX() ;
- }
-
- public static WebAppContext createWebApp(String contextPath) {
- FusekiEnv.setEnvironment();
- WebAppContext webapp = new WebAppContext();
- webapp.getServletContext().getContextHandler().setMaxFormContentSize(10 * 1000 * 1000) ;
-
- // Hunt for the webapp for the standalone jar (or development system).
- // Note that Path FUSEKI_HOME is not initialized until the webapp starts
- // so it is not available here.
-
- String resourceBase3 = null ;
- String resourceBase4 = null ;
- if ( FusekiEnv.FUSEKI_HOME != null ) {
- String HOME = FusekiEnv.FUSEKI_HOME.toString() ;
- resourceBase3 = HOME+"/"+resourceBase1 ;
- resourceBase4 = HOME+"/"+resourceBase2 ;
- }
-
- String resourceBase = tryResourceBase(resourceBase1, null) ;
- resourceBase = tryResourceBase(resourceBase2, resourceBase) ;
- resourceBase = tryResourceBase(resourceBase3, resourceBase) ;
- resourceBase = tryResourceBase(resourceBase4, resourceBase) ;
-
- if ( resourceBase == null ) {
- if ( resourceBase3 == null )
- Fuseki.serverLog.error("Can't find resourceBase (tried "+resourceBase1+" and "+resourceBase2+")") ;
- else
- Fuseki.serverLog.error("Can't find resourceBase (tried "+resourceBase1+", "+resourceBase2+", "+resourceBase3+" and "+resourceBase4+")") ;
- Fuseki.serverLog.error("Failed to start") ;
- throw new FusekiException("Failed to start") ;
- }
-
- webapp.setDescriptor(resourceBase+"/WEB-INF/web.xml");
- webapp.setResourceBase(resourceBase);
- webapp.setContextPath(contextPath);
-
- //-- Jetty setup for the ServletContext logger.
- // The name of the Jetty-allocated slf4j/log4j logger is
- // the display name or, if null, the context path name.
- // It is set, without checking for a previous call of setLogger in "doStart"
- // 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()) ;
- return webapp ;
- }
-
- public static String getenv(String name) {
- String x = System.getenv(name) ;
- if ( x == null )
- x = System.getProperty(name) ;
- return x ;
- }
-
- public DataAccessPointRegistry getDataAccessPointRegistry() {
- return DataAccessPointRegistry.get(servletContext) ;
- }
-
- private static String tryResourceBase(String maybeResourceBase, String currentResourceBase) {
- if ( currentResourceBase != null )
- return currentResourceBase ;
- if ( maybeResourceBase != null && FileOps.exists(maybeResourceBase) )
- return maybeResourceBase ;
- return currentResourceBase ;
- }
-
- private void buildServerWebapp(String contextPath, String jettyConfig) {
- if ( jettyConfig != null )
- // --jetty-config=jetty-fuseki.xml
- // for detailed configuration of the server using Jetty features.
- configServer(jettyConfig) ;
- else
- defaultServerConfig(serverConfig.port, serverConfig.loopback) ;
-
- WebAppContext webapp = createWebApp(contextPath) ;
- if ( false /*enable symbolic links */ ) {
- // See http://www.eclipse.org/jetty/documentation/current/serving-aliased-files.html
- // Record what would be needed:
- // 1 - Allow all symbolic links without checking
- webapp.addAliasCheck(new ContextHandler.ApproveAliases());
- // 2 - Check links are to valid resources. But default for Unix?
- webapp.addAliasCheck(new AllowSymLinkAliasChecker()) ;
- }
- servletContext = webapp.getServletContext() ;
- server.setHandler(webapp) ;
- // Replaced by Shiro.
- if ( jettyConfig == null && serverConfig.authConfigFile != null )
- security(webapp, serverConfig.authConfigFile) ;
- }
-
- // This is now provided by Shiro.
- private static void security(ServletContextHandler context, String authfile) {
- Constraint constraint = new Constraint() ;
- constraint.setName(Constraint.__BASIC_AUTH) ;
- constraint.setRoles(new String[]{"fuseki"}) ;
- constraint.setAuthenticate(true) ;
-
- ConstraintMapping mapping = new ConstraintMapping() ;
- mapping.setConstraint(constraint) ;
- mapping.setPathSpec("/*") ;
-
- IdentityService identService = new DefaultIdentityService() ;
-
- ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler() ;
- securityHandler.addConstraintMapping(mapping) ;
- securityHandler.setIdentityService(identService) ;
-
- HashLoginService loginService = new HashLoginService("Fuseki Authentication", authfile) ;
- loginService.setIdentityService(identService) ;
-
- securityHandler.setLoginService(loginService) ;
- securityHandler.setAuthenticator(new BasicAuthenticator()) ;
-
- context.setSecurityHandler(securityHandler) ;
-
- serverLog.debug("Basic Auth Configuration = " + authfile) ;
- }
-
- private void configServer(String jettyConfig) {
- try {
- serverLog.info("Jetty server config file = " + jettyConfig) ;
- server = new Server() ;
- XmlConfiguration configuration = new XmlConfiguration(new FileInputStream(jettyConfig)) ;
- configuration.configure(server) ;
- serverConnector = (ServerConnector)server.getConnectors()[0] ;
- } catch (Exception ex) {
- serverLog.error("SPARQLServer: Failed to configure server: " + ex.getMessage(), ex) ;
- throw new FusekiException("Failed to configure a server using configuration file '" + jettyConfig + "'") ;
- }
- }
-
- private void defaultServerConfig(int port, boolean loopback) {
- server = new Server() ;
- HttpConnectionFactory f1 = new HttpConnectionFactory() ;
- // Some people do try very large operations ... really, should use POST.
- f1.getHttpConfiguration().setRequestHeaderSize(512 * 1024);
- f1.getHttpConfiguration().setOutputBufferSize(5 * 1024 * 1024) ;
- // Do not add "Server: Jetty(....) when not a development system.
- if ( ! Fuseki.outputJettyServerHeader )
- f1.getHttpConfiguration().setSendServerVersion(false) ;
-
- // https is better done with a Jetty configuration file
- // because there are several things to configure.
- // See "examples/fuseki-jetty-https.xml"
-
- ServerConnector connector = new ServerConnector(server, f1) ;
- connector.setPort(port) ;
- server.addConnector(connector);
- if ( loopback )
- connector.setHost("localhost");
- serverConnector = connector ;
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackup.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackup.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackup.java
new file mode 100644
index 0000000..55ab7d7
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackup.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.fuseki.mgt;
+
+import static java.lang.String.format ;
+
+import org.apache.jena.fuseki.ctl.ActionAsyncTask;
+import org.apache.jena.fuseki.ctl.Backup;
+import org.apache.jena.fuseki.ctl.TaskBase;
+import org.apache.jena.fuseki.servlets.HttpAction ;
+import org.apache.jena.fuseki.servlets.ServletOps ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+public class ActionBackup extends ActionAsyncTask
+{
+ public ActionBackup() { super() ; }
+
+ @Override
+ protected Runnable createRunnable(HttpAction action) {
+ String name = action.getDatasetName() ;
+ if ( name == null ) {
+ action.log.error("Null for dataset name in item request") ;
+ ServletOps.errorOccurred("Null for dataset name in item request");
+ return null ;
+ }
+
+ action.log.info(format("[%d] Backup dataset %s", action.id, name)) ;
+ return new BackupTask(action) ;
+ }
+
+ static class BackupTask extends TaskBase {
+ static private Logger log = LoggerFactory.getLogger("Backup") ;
+
+ public BackupTask(HttpAction action) {
+ super(action) ;
+ }
+
+ @Override
+ public void run() {
+ try {
+ String backupFilename = Backup.chooseFileName(datasetName) ;
+ log.info(format("[%d] >>>> Start backup %s -> %s", actionId, datasetName, backupFilename)) ;
+ Backup.backup(transactional, dataset, backupFilename) ;
+ log.info(format("[%d] <<<< Finish backup %s -> %s", actionId, datasetName, backupFilename)) ;
+ } catch (Exception ex) {
+ log.info(format("[%d] **** Exception in backup", actionId), ex) ;
+ }
+ }
+ }
+}
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java
new file mode 100644
index 0000000..0dc540d
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java
@@ -0,0 +1,95 @@
+/**
+ * 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.mgt;
+
+import static java.lang.String.format ;
+
+import java.io.File ;
+import java.io.IOException ;
+import java.nio.file.DirectoryStream ;
+import java.nio.file.Files ;
+import java.nio.file.Path ;
+import java.util.ArrayList ;
+import java.util.List ;
+import java.util.stream.Collectors ;
+
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.atlas.json.JsonBuilder ;
+import org.apache.jena.atlas.json.JsonValue ;
+import org.apache.jena.fuseki.ctl.ActionCtl;
+import org.apache.jena.fuseki.servlets.HttpAction ;
+import org.apache.jena.fuseki.servlets.ServletOps ;
+import org.apache.jena.fuseki.webapp.FusekiSystem;
+
+/**
+ * A JSON API to list all the backups in the backup directory
+ */
+public class ActionBackupList extends ActionCtl {
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
+ doCommon(req, resp);
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
+ doCommon(req, resp);
+ }
+
+ @Override
+ protected void perform(HttpAction action) {
+ JsonValue result = description(action) ;
+ ServletOps.setNoCache(action.response) ;
+ ServletOps.sendJsonReponse(action, result);
+ }
+
+ private static DirectoryStream.Filter<Path> filterVisibleFiles = (entry) -> {
+ File f = entry.toFile() ;
+ return f.isFile() && !f.isHidden() ;
+ } ;
+
+ private JsonValue description(HttpAction action) {
+ if ( ! Files.isDirectory(FusekiSystem.dirBackups) )
+ ServletOps.errorOccurred(format("[%d] Backup area '%s' is not a directory", action.id, FusekiSystem.dirBackups)) ;
+
+ List<Path> paths = new ArrayList<>() ;
+ try (DirectoryStream<Path> stream = Files.newDirectoryStream(FusekiSystem.dirBackups, filterVisibleFiles)) {
+ stream.forEach(paths::add) ;
+ } catch (IOException ex) {
+ action.log.error(format("[%d] Backup file list :: IOException :: %s", action.id, ex.getMessage())) ;
+ ServletOps.errorOccurred(ex);
+ }
+
+ List<String> fileNames = paths.stream().map((p)->p.getFileName().toString()).sorted().collect(Collectors.toList()) ;
+
+ JsonBuilder builder = new JsonBuilder() ;
+ builder.startObject("top") ;
+ builder.key("backups") ;
+
+ builder.startArray() ;
+ fileNames.forEach(builder::value) ;
+ builder.finishArray() ;
+
+ builder.finishObject("top") ;
+ return builder.build() ;
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
index 229726a..79b6d13 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
@@ -43,12 +43,15 @@ import org.apache.jena.datatypes.xsd.XSDDatatype ;
import org.apache.jena.fuseki.FusekiLib ;
import org.apache.jena.fuseki.build.DatasetDescriptionRegistry;
import org.apache.jena.fuseki.build.FusekiBuilder;
+import org.apache.jena.fuseki.build.FusekiConst;
import org.apache.jena.fuseki.build.Template;
import org.apache.jena.fuseki.build.TemplateFunctions;
import org.apache.jena.fuseki.ctl.ActionContainerItem;
+import org.apache.jena.fuseki.ctl.JsonDescription;
import org.apache.jena.fuseki.server.DataAccessPoint;
import org.apache.jena.fuseki.server.DataService;
import org.apache.jena.fuseki.server.FusekiVocab;
+import org.apache.jena.fuseki.server.ServerConst;
import org.apache.jena.fuseki.servlets.ActionLib;
import org.apache.jena.fuseki.servlets.HttpAction;
import org.apache.jena.fuseki.servlets.ServletOps;
@@ -95,7 +98,7 @@ public class ActionDatasets extends ActionContainerItem {
action.log.info(format("[%d] GET datasets", action.id)) ;
JsonBuilder builder = new JsonBuilder() ;
builder.startObject("D") ;
- builder.key(MgtConst.datasets) ;
+ builder.key(ServerConst.datasets) ;
JsonDescription.arrayDatasets(builder, action.getDataAccessPointRegistry());
builder.finishObject("D") ;
return builder.build() ;
@@ -434,7 +437,7 @@ public class ActionDatasets extends ActionContainerItem {
dbName = dbName.substring(1) ;
String update = StrUtils.strjoinNL
- (SystemState.PREFIXES,
+ (FusekiConst.PREFIXES,
"DELETE { GRAPH ?g { ?s fu:status ?state } }",
"INSERT { GRAPH ?g { ?s fu:status "+FmtUtils.stringForRDFNode(newState)+" } }",
"WHERE {",
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionItem.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionItem.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionItem.java
deleted file mode 100644
index 3308880..0000000
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionItem.java
+++ /dev/null
@@ -1,46 +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.mgt;
-
-import org.apache.jena.atlas.json.JsonValue ;
-import org.apache.jena.fuseki.ctl.ActionContainerItem;
-import org.apache.jena.fuseki.servlets.HttpAction ;
-import org.apache.jena.fuseki.servlets.ServletOps ;
-import org.apache.jena.web.HttpSC ;
-
-/** Action on items in a container, but not the container itself */
-public abstract class ActionItem extends ActionContainerItem
-{
- public ActionItem() { super() ; }
-
- @Override
- final
- protected JsonValue execGetContainer(HttpAction action) {
- ServletOps.error(HttpSC.METHOD_NOT_ALLOWED_405) ;
- return null ;
- }
-
- @Override
- final
- protected JsonValue execPostContainer(HttpAction action) {
- ServletOps.error(HttpSC.METHOD_NOT_ALLOWED_405) ;
- return null ;
- }
-}
-
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionServerStatus.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionServerStatus.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionServerStatus.java
index 3e060cd..d3c0873 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionServerStatus.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionServerStatus.java
@@ -32,7 +32,9 @@ import org.apache.jena.atlas.json.JsonBuilder ;
import org.apache.jena.atlas.json.JsonValue ;
import org.apache.jena.fuseki.Fuseki ;
import org.apache.jena.fuseki.ctl.ActionCtl;
+import org.apache.jena.fuseki.ctl.JsonDescription;
import org.apache.jena.fuseki.server.DataAccessPointRegistry ;
+import org.apache.jena.fuseki.server.ServerConst;
import org.apache.jena.fuseki.servlets.HttpAction ;
import org.apache.jena.fuseki.servlets.ServletOps ;
@@ -98,16 +100,16 @@ public class ActionServerStatus extends ActionCtl
// .finishObject() ;
builder
- .key(MgtConst.version).value(versionStr)
- .key(MgtConst.built).value(builtDateStr)
- .key(MgtConst.startDT).value(Fuseki.serverStartedAt())
- .key(MgtConst.uptime).value(Fuseki.serverUptimeSeconds())
+ .key(ServerMgtConst.version).value(versionStr)
+ .key(ServerMgtConst.built).value(builtDateStr)
+ .key(ServerMgtConst.startDT).value(Fuseki.serverStartedAt())
+ .key(ServerMgtConst.uptime).value(Fuseki.serverUptimeSeconds())
;
}
private void describeDatasets(JsonBuilder builder, DataAccessPointRegistry registry) {
- builder.key(MgtConst.datasets) ;
+ builder.key(ServerConst.datasets) ;
JsonDescription.arrayDatasets(builder, registry);
}
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/JsonDescription.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/JsonDescription.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/JsonDescription.java
deleted file mode 100644
index 749aa3e..0000000
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/JsonDescription.java
+++ /dev/null
@@ -1,72 +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.mgt;
-
-import java.util.List ;
-
-import org.apache.jena.atlas.json.JsonBuilder ;
-import org.apache.jena.fuseki.server.DataAccessPoint ;
-import org.apache.jena.fuseki.server.DataAccessPointRegistry ;
-import org.apache.jena.fuseki.server.Endpoint ;
-import org.apache.jena.fuseki.server.Operation ;
-
-/** Create a description of a service */
-public class JsonDescription {
-
- public static void arrayDatasets(JsonBuilder builder, DataAccessPointRegistry registry) {
- builder.startArray() ;
- for ( String ds : registry.keys() ) {
- DataAccessPoint access = registry.get(ds) ;
- JsonDescription.describe(builder, access) ;
- }
- builder.finishArray() ;
- }
-
- public static void describe(JsonBuilder builder, DataAccessPoint access) {
- builder.startObject() ;
- builder.key(MgtConst.dsName).value(access.getName()) ;
-
- builder.key(MgtConst.dsState).value(access.getDataService().isAcceptingRequests()) ;
-
- builder.key(MgtConst.dsService) ;
- builder.startArray() ;
-
- for ( Operation operation : access.getDataService().getOperations() ) {
- List<Endpoint> endpoints = access.getDataService().getEndpoints(operation) ;
- describe(builder, operation, endpoints) ;
- }
- builder.finishArray() ;
- builder.finishObject() ;
- }
-
- private static void describe(JsonBuilder builder, Operation operation, List<Endpoint> endpoints) {
- builder.startObject() ;
-
- builder.key(MgtConst.srvType).value(operation.getName()) ;
- builder.key(MgtConst.srvDescription).value(operation.getDescription()) ;
- builder.key(MgtConst.srvEndpoints) ;
- builder.startArray() ;
- for ( Endpoint endpoint : endpoints )
- builder.value(endpoint.getEndpoint()) ;
- builder.finishArray() ;
-
- builder.finishObject() ;
- }
-}
-
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/MgtConst.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/MgtConst.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/MgtConst.java
deleted file mode 100644
index 2659313..0000000
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/MgtConst.java
+++ /dev/null
@@ -1,52 +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.mgt;
-
-/** Various constants used in the admin functions */
-public class MgtConst {
- public static final String opDump = "dump" ;
- public static final String opPing = "ping" ;
-
- public static final String opStats = "stats" ;
- public static final String opDatasets = "datasets" ;
- public static final String opListBackups = "backups-list" ;
- public static final String opServer = "server" ;
-
- // JSON constants
- public static final String datasets = "datasets" ;
- public static final String uptime = "uptime" ;
- public static final String startDT = "startDateTime" ;
- public static final String server = "server" ;
- public static final String port = "port" ;
- public static final String hostname = "hostname" ;
- public static final String admin = "admin" ;
- public static final String version = "version" ;
- public static final String built = "built" ;
- public static final String services = "services" ;
- public static final String operation = "operation" ;
- public static final String description = "description" ;
- public static final String endpoints = "endpoints" ;
- public static final String dsName = "ds.name" ;
- public static final String dsState = "ds.state" ;
- public static final String dsService = "ds.services" ;
- public static final String srvType = "srv.type" ;
- public static final String srvDescription = "srv.description" ;
- public static final String srvEndpoints = "srv.endpoints" ;
-}
-
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/MgtJMX.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/MgtJMX.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/MgtJMX.java
deleted file mode 100644
index f9023fe..0000000
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/MgtJMX.java
+++ /dev/null
@@ -1,61 +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.mgt ;
-
-
-public class MgtJMX
-{
- public static void removeJMX() { }
-
-// public static void addJMX() {
-// DatasetRegistry registry = DatasetRegistry.get() ;
-// for (String ds : registry.keys()) {
-// DataAccessPoint dsRef = registry.get(ds) ;
-// addJMX(dsRef) ;
-// }
-// }
-//
-// private static void addJMX(DataAccessPoint dapt) {
-// String x = datasetNames ;
-// // if ( x.startsWith("/") )
-// // x = x.substring(1) ;
-// ARQMgt.register(Fuseki.PATH + ".dataset:name=" + x, dapt) ;
-// // For all endpoints
-// for (ServiceRef sRef : dapt.getServiceRefs()) {
-// ARQMgt.register(Fuseki.PATH + ".dataset:name=" + x + "/" + sRef.name, sRef) ;
-// }
-// }
-//
-// public static void removeJMX() {
-// DatasetRegistry registry = DatasetRegistry.get() ;
-// for (String ds : registry.keys()) {
-// DataAccessPoint ref = registry.get(ds) ;
-// removeJMX(ref) ;
-// }
-// }
-//
-// private static void removeJMX(DatasetRef dsRef) {
-// String x = dsRef.getName() ;
-// ARQMgt.unregister(Fuseki.PATH + ".dataset:name=" + x) ;
-// for (ServiceRef sRef : dsRef.getServiceRefs()) {
-// ARQMgt.unregister(Fuseki.PATH + ".dataset:name=" + x + "/" + sRef.name) ;
-// }
-// }
-
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ServerMgtConst.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ServerMgtConst.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ServerMgtConst.java
new file mode 100644
index 0000000..2af5e44
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ServerMgtConst.java
@@ -0,0 +1,39 @@
+/*
+ * 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.mgt;
+
+/**
+ * Various constants used in the management API functions and JSON responses in the
+ * webapp/full server.
+ */
+public class ServerMgtConst {
+ public static final String opDatasets = "datasets" ;
+ public static final String opListBackups = "backups-list" ;
+ public static final String opServer = "server" ;
+
+ public static final String uptime = "uptime" ;
+ public static final String startDT = "startDateTime" ;
+// public static final String server = "server" ;
+// public static final String port = "port" ;
+ public static final String hostname = "hostname" ;
+ public static final String admin = "admin" ;
+ public static final String version = "version" ;
+ public static final String built = "built" ;
+ public static final String services = "services" ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ServiceMXBean.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ServiceMXBean.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ServiceMXBean.java
deleted file mode 100644
index 72ce3a3..0000000
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ServiceMXBean.java
+++ /dev/null
@@ -1,32 +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.mgt;
-
-public interface ServiceMXBean
-{
- String getName() ;
-
- long getRequests() ;
- long getRequestsGood() ;
- long getRequestsBad() ;
-
-// void enable() ;
-// void disable() ;
-}
-
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/ServerConst.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/ServerConst.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/ServerConst.java
new file mode 100644
index 0000000..f8b0f91
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/ServerConst.java
@@ -0,0 +1,41 @@
+/**
+ * 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;
+
+/** Various constants used in the API functions and JSON responses. */
+public class ServerConst {
+ // Location under /$/
+ public static final String opDump = "dump" ;
+ public static final String opPing = "ping" ;
+ public static final String opStats = "stats" ;
+
+// // JSON constants
+ public static final String datasets = "datasets" ;
+ public static final String operation = "operation" ;
+ public static final String description = "description" ;
+ public static final String endpoints = "endpoints" ;
+
+ public static final String dsName = "ds.name" ;
+ public static final String dsState = "ds.state" ;
+ public static final String dsService = "ds.services" ;
+ public static final String srvType = "srv.type" ;
+ public static final String srvDescription = "srv.description" ;
+ public static final String srvEndpoints = "srv.endpoints" ;
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/06f59125/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/webapp/SystemState.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/webapp/SystemState.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/webapp/SystemState.java
index ada2f28..c5431a2 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/webapp/SystemState.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/webapp/SystemState.java
@@ -19,7 +19,6 @@
package org.apache.jena.fuseki.webapp;
import org.apache.jena.atlas.lib.FileOps ;
-import org.apache.jena.atlas.lib.StrUtils ;
import org.apache.jena.fuseki.Fuseki ;
import org.apache.jena.query.Dataset ;
import org.apache.jena.tdb.StoreConnection ;
@@ -93,20 +92,5 @@ public class SystemState {
dsg = (DatasetGraphTransaction)(dataset.asDatasetGraph()) ;
dsg.getContext().set(TDB.symUnionDefaultGraph, false) ;
}
-
- public static String PREFIXES = StrUtils.strjoinNL
- ("BASE <http://example/base#>",
- "PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>",
- "PREFIX fu: <http://jena.apache.org/fuseki#>",
- "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 sdb: <http://jena.hpl.hp.com/2007/sdb#>",
- "PREFIX list: <http://jena.apache.org/ARQ/list#>",
- "PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>",
- "PREFIX apf: <http://jena.apache.org/ARQ/property#>",
- "PREFIX afn: <http://jena.apache.org/ARQ/function#>",
- "") ;
}
[13/27] jena git commit: Javadoc formatting.
Posted by an...@apache.org.
Javadoc formatting.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/aa65883b
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/aa65883b
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/aa65883b
Branch: refs/heads/master
Commit: aa65883b159c9a3ca6f2130d45bfa7249ba3c744
Parents: dfa40be
Author: Andy Seaborne <an...@apache.org>
Authored: Fri Aug 24 17:37:09 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Fri Aug 24 17:37:09 2018 +0100
----------------------------------------------------------------------
.../src/main/java/org/apache/jena/sparql/core/DatasetGraph.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/aa65883b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraph.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraph.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraph.java
index 2ab9f68..23df9c9 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraph.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraph.java
@@ -123,10 +123,10 @@ public interface DatasetGraph extends Transactional, Closeable
*/
public Iterator<Quad> findNG(Node g, Node s, Node p , Node o) ;
- /** Test whether the dataset (including default graph) contains a quad - may include wildcards, Node.ANY or null */
+ /** Test whether the dataset (including default graph) contains a quad - may include wildcards, Node.ANY or null */
public boolean contains(Node g, Node s, Node p , Node o) ;
- /** Test whether the dataset contains a quad (including default graph)- may include wildcards, Node.ANY or null */
+ /** Test whether the dataset contains a quad (including default graph)- may include wildcards, Node.ANY or null */
public boolean contains(Quad quad) ;
/** Remove everything - remove all named graphs, clear the default graph */
[03/27] jena git commit: JENA-1592: Unwrap TDB2 graphs
Posted by an...@apache.org.
JENA-1592: Unwrap TDB2 graphs
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/9a60253c
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/9a60253c
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/9a60253c
Branch: refs/heads/master
Commit: 9a60253c00aec6763adbb0253588fe4dc0b484d4
Parents: d8e51a8
Author: Andy Seaborne <an...@apache.org>
Authored: Mon Aug 20 20:35:06 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Thu Aug 23 17:15:05 2018 +0100
----------------------------------------------------------------------
.../apache/jena/tdb2/solver/StageGeneratorDirectTDB.java | 2 +-
.../org/apache/jena/tdb2/store/GraphViewSwitchable.java | 11 +++++++----
2 files changed, 8 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/9a60253c/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/StageGeneratorDirectTDB.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/StageGeneratorDirectTDB.java b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/StageGeneratorDirectTDB.java
index bb9ac10..a4eba73 100644
--- a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/StageGeneratorDirectTDB.java
+++ b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/StageGeneratorDirectTDB.java
@@ -51,7 +51,7 @@ public class StageGeneratorDirectTDB implements StageGenerator
if ( g instanceof GraphViewSwitchable ) {
GraphViewSwitchable gvs = (GraphViewSwitchable)g;
- g = gvs.getGraph();
+ g = gvs.getBaseGraph();
}
if ( ! ( g instanceof GraphTDB ) )
http://git-wip-us.apache.org/repos/asf/jena/blob/9a60253c/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/GraphViewSwitchable.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/GraphViewSwitchable.java b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/GraphViewSwitchable.java
index 2a3fbf5..f008ad9 100644
--- a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/GraphViewSwitchable.java
+++ b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/GraphViewSwitchable.java
@@ -76,17 +76,20 @@ public class GraphViewSwitchable extends GraphView {
return transactionHandler;
}
- /** Return the {@code DatasetGraphSwitchable} we are viewing. */
+ /** Return the {@link DatasetGraphSwitchable} we are viewing. */
@Override
public DatasetGraphSwitchable getDataset() {
return getx();
}
- /** Return the {@code Graph} from the underlying switchable.
+ /** Return the {@code Graph} from the underlying DatasetGraph
* Do not hold onto this reference across switches.
*/
- public Graph getGraph() {
- return getx().getGraph(getGraphName());
+ public Graph getBaseGraph() {
+ if ( getGraphName() == null )
+ return getDSG().getDefaultGraph();
+ else
+ return getDSG().getGraph(getGraphName());
}
// Super uses find. Override to call GraphTDB.size()
[11/27] jena git commit: Use only getW() for the denying write
operations.
Posted by an...@apache.org.
Use only getW() for the denying write operations.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/09f0e8b1
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/09f0e8b1
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/09f0e8b1
Branch: refs/heads/master
Commit: 09f0e8b1c829013e377a42be84a0ce977973ee21
Parents: a17c6dd
Author: Andy Seaborne <an...@apache.org>
Authored: Fri Aug 24 12:02:20 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Fri Aug 24 12:02:20 2018 +0100
----------------------------------------------------------------------
.../jena/sparql/core/DatasetGraphReadOnly.java | 21 +++++++-------------
1 file changed, 7 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/09f0e8b1/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphReadOnly.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphReadOnly.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphReadOnly.java
index dffb52b..06aae4f 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphReadOnly.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphReadOnly.java
@@ -18,8 +18,8 @@
package org.apache.jena.sparql.core;
-import java.util.HashMap ;
import java.util.Map ;
+import java.util.concurrent.ConcurrentHashMap;
import org.apache.jena.atlas.logging.Log ;
import org.apache.jena.graph.Graph ;
@@ -31,6 +31,9 @@ import org.apache.jena.sparql.graph.GraphReadOnly ;
*/
public class DatasetGraphReadOnly extends DatasetGraphWrapper
{
+ // Add a read-only wrapper any graphs returned.
+ // Block write access at getW().
+
public DatasetGraphReadOnly(DatasetGraph dsg) { super(dsg) ; }
private Graph dftGraph = null ;
@@ -50,10 +53,12 @@ public class DatasetGraphReadOnly extends DatasetGraphWrapper
get().begin(mode) ;
}
- private Map<Node, Graph> namedGraphs = new HashMap<>() ;
+ private Map<Node, Graph> namedGraphs = new ConcurrentHashMap<>() ;
@Override
public Graph getGraph(Node graphNode) {
+ // Cache GraphReadOnly wrappers. This also makes == work (a nicety)
+ // if the underlying DatasetGraph isn't changing.
if ( namedGraphs.containsKey(graphNode) ) {
if ( !super.containsGraph(graphNode) ) {
namedGraphs.remove(graphNode) ;
@@ -70,18 +75,6 @@ public class DatasetGraphReadOnly extends DatasetGraphWrapper
return g ;
}
- @Override
- public void setDefaultGraph(Graph g)
- { throw new UnsupportedOperationException("read-only dataset") ; }
-
- @Override
- public void addGraph(Node graphName, Graph graph)
- { throw new UnsupportedOperationException("read-only dataset") ; }
-
- @Override
- public void removeGraph(Node graphName)
- { throw new UnsupportedOperationException("read-only dataset") ; }
-
/** For operations that write the DatasetGraph. */
@Override
protected DatasetGraph getW()