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/11/17 17:20:41 UTC

[15/34] jena git commit: JENA-1594: Add filtering for all operations.

JENA-1594: Add filtering for all operations.

Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/34b89a6a
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/34b89a6a
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/34b89a6a

Branch: refs/heads/master
Commit: 34b89a6a83789bdb552919730bb2e2c975741b50
Parents: 1b5463f
Author: Andy Seaborne <an...@apache.org>
Authored: Fri Nov 2 17:15:04 2018 +0000
Committer: Andy Seaborne <an...@apache.org>
Committed: Tue Nov 13 15:39:14 2018 +0000

----------------------------------------------------------------------
 .../fuseki/access/AssemblerAccessDataset.java   | 13 ++--
 .../jena/fuseki/access/DataAccessCtl.java       | 34 +++++-----
 .../access/DatasetGraphAccessControl.java       |  7 ++
 .../fuseki/access/Filtered_REST_Quads_RW.java   | 49 ++++++++++++++
 .../fuseki/access/Filtered_SPARQL_GSP_RW.java   | 49 ++++++++++++++
 .../fuseki/access/Filtered_SPARQL_Update.java   | 14 ++--
 .../fuseki/access/Filtered_SPARQL_Upload.java   | 49 ++++++++++++++
 .../org/apache/jena/fuseki/jetty/JettyLib.java  | 16 ++++-
 .../apache/jena/fuseki/server/FusekiVocab.java  | 71 ++++++++++----------
 9 files changed, 236 insertions(+), 66 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/34b89a6a/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 b379e2a..67ccec1 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
@@ -48,16 +48,17 @@ public class AssemblerAccessDataset extends AssemblerBase {
         RDFNode rnDataset = root.getProperty(VocabSecurity.pDataset).getObject();
         
         AuthorizationService sr = (AuthorizationService)a.open(rnRegistry.asResource()) ;
-        Dataset ds = (Dataset)a.open(rnDataset.asResource()) ;
+        DatasetGraph dsgBase = ((Dataset)a.open(rnDataset.asResource())).asDatasetGraph();
         
-        DatasetGraph dsg = new DatasetGraphAccessControl(ds.asDatasetGraph(), sr);
-        ds = DatasetFactory.wrap(dsg);
+        DatasetGraph dsg = new DatasetGraphAccessControl(dsgBase, sr);
         
         // Add marker
         // ds.getContext().set(DataAccessCtl.symControlledAccess, true);
-        // Add security registry : if this dadaset is wrapped then this means the AuthorizationService is still accessible.
-        ds.getContext().set(DataAccessCtl.symAuthorizationService, sr);
-        return ds;
+        
+        // Add security registry : if this dataset is wrapped then this means the AuthorizationService is still accessible.
+        // But adding to DatasetGraphAccessControl (currently) pushes it down to the wrapped base DSG. 
+        //dsg.getContext().set(DataAccessCtl.symAuthorizationService, sr);
+        return DatasetFactory.wrap(dsg);
     }
     
 }

http://git-wip-us.apache.org/repos/asf/jena/blob/34b89a6a/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 2da63fe..78a4647 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
@@ -120,10 +120,10 @@ public class DataAccessCtl {
         builder.registerOperation(Operation.GSP_R, new Filtered_SPARQL_GSP_R(determineUser));
         builder.registerOperation(Operation.Quads_R, new Filtered_REST_Quads_R(determineUser));
         
-        // Block updates
+        // Block updates (can just not register these operations).
         builder.registerOperation(Operation.Update, WebContent.contentTypeSPARQLUpdate, new Filtered_SPARQL_Update(determineUser));
-        builder.registerOperation(Operation.GSP_RW, null);
-        builder.registerOperation(Operation.Quads_RW, null);
+        builder.registerOperation(Operation.GSP_RW, new Filtered_SPARQL_GSP_RW(determineUser));
+        builder.registerOperation(Operation.Quads_RW, new Filtered_REST_Quads_RW(determineUser));
         return builder;
     }
 
@@ -139,22 +139,26 @@ public class DataAccessCtl {
          */
         // The mapping operation to handler is in the ServiceDispatchRegistry and is per
         // server (per servlet context). "registerOrReplace" might be a better name,
-        ActionService queryServletAccessFilter = new Filtered_SPARQL_QueryDataset(determineUser);
         ServletContext cxt = server.getServletContext();
         ServiceDispatchRegistry reg = ServiceDispatchRegistry.get(cxt);
         
-        if ( reg.isRegistered(Operation.Query) )
-            reg.register(Operation.Query, WebContent.contentTypeSPARQLQuery, queryServletAccessFilter);
-        if ( reg.isRegistered(Operation.GSP_R) )
-            reg.register(Operation.GSP_R, null, new Filtered_SPARQL_GSP_R(determineUser));
-        if ( reg.isRegistered(Operation.Quads_R) )
-            reg.register(Operation.Quads_R, null, new Filtered_REST_Quads_R(determineUser));
-        
+        resetOperation(reg, Operation.Query, WebContent.contentTypeSPARQLQuery, new Filtered_SPARQL_QueryDataset(determineUser));
+        resetOperation(reg, Operation.GSP_R, null, new Filtered_SPARQL_GSP_R(determineUser));
+        resetOperation(reg, Operation.Quads_R, null, new Filtered_REST_Quads_R(determineUser));
+
         // Block updates
-        //reg.register(Operation.Update, WebContent.contentTypeSPARQLUpdate, new Filtered_SPARQL_Update(determineUser));
-        reg.unregister(Operation.Update);
-        reg.unregister(Operation.GSP_RW);
-        reg.unregister(Operation.Quads_RW);
+        resetOperation(reg, Operation.Update, WebContent.contentTypeSPARQLUpdate, new Filtered_SPARQL_Update(determineUser));
+        resetOperation(reg, Operation.GSP_RW, null, new Filtered_SPARQL_GSP_RW(determineUser));
+        resetOperation(reg, Operation.Quads_RW, null, new Filtered_SPARQL_Update(determineUser));
+        
+//        reg.unregister(Operation.Update);
+//        reg.unregister(Operation.GSP_RW);
+//        reg.unregister(Operation.Quads_RW);
+    }
+    
+    private static void resetOperation(ServiceDispatchRegistry reg, Operation operation, String contentType, ActionService service) {
+        if ( reg.isRegistered(operation) )
+            reg.register(operation, contentType, service);
     }
     
     /**

http://git-wip-us.apache.org/repos/asf/jena/blob/34b89a6a/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 2ccd538..44a8147 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
@@ -37,6 +37,13 @@ public class DatasetGraphAccessControl extends DatasetGraphWrapper {
         return registry;
     }
 
+    // XXX Settings will be pushed down to the wrapped dataset.
+    // A problem for DataAccessCtl.symAuthorizationService.
+//    @Override
+//    public Context getContext() {
+//        return super.getContext();
+//    }
+    
     /**
      * Return the underlying {@code DatasetGraph}. If the argument is not a
      * {@code DatasetGraphAccessControl}, return the argument.

http://git-wip-us.apache.org/repos/asf/jena/blob/34b89a6a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_RW.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_RW.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_RW.java
new file mode 100644
index 0000000..d074f82
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_REST_Quads_RW.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.function.Function;
+
+import org.apache.jena.fuseki.servlets.HttpAction;
+import org.apache.jena.fuseki.servlets.REST_Quads_R;
+import org.apache.jena.fuseki.servlets.REST_Quads_RW;
+import org.apache.jena.fuseki.servlets.ServletOps;
+import org.apache.jena.sparql.core.DatasetGraph;
+
+/**
+ * Filter for {@link REST_Quads_R} that inserts a security filter on read-access to the
+ * {@link DatasetGraph}.
+ */
+public class Filtered_REST_Quads_RW extends REST_Quads_RW {
+    
+    private final Function<HttpAction, String> requestUser;
+    
+    public Filtered_REST_Quads_RW(Function<HttpAction, String> determineUser) {
+        this.requestUser = determineUser; 
+    }
+
+    @Override
+    protected void validate(HttpAction action) {
+        super.validate(action);
+        DatasetGraph dsg = action.getDataset();
+        if ( ! DataAccessCtl.isAccessControlled(dsg) )
+            return;
+        ServletOps.errorBadRequest("REST update of the dataset not supported");
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/34b89a6a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_RW.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_RW.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_RW.java
new file mode 100644
index 0000000..cedd7c0
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_GSP_RW.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.function.Function;
+
+import org.apache.jena.fuseki.servlets.HttpAction;
+import org.apache.jena.fuseki.servlets.REST_Quads_R;
+import org.apache.jena.fuseki.servlets.SPARQL_GSP_RW;
+import org.apache.jena.fuseki.servlets.ServletOps;
+import org.apache.jena.sparql.core.DatasetGraph;
+
+/**
+ * Filter for {@link REST_Quads_R} that inserts a security filter on read-access to the
+ * {@link DatasetGraph}.
+ */
+public class Filtered_SPARQL_GSP_RW extends SPARQL_GSP_RW {
+    
+    private final Function<HttpAction, String> requestUser;
+    
+    public Filtered_SPARQL_GSP_RW(Function<HttpAction, String> determineUser) {
+        this.requestUser = determineUser; 
+    }
+
+    @Override
+    protected void validate(HttpAction action) {
+        super.validate(action);
+        DatasetGraph dsg = action.getDataset();
+        if ( ! DataAccessCtl.isAccessControlled(dsg) )
+            return;
+        ServletOps.errorBadRequest("SPARQL Graph Store Protocol update not supported");
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/34b89a6a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_Update.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_Update.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_Update.java
index 9ca0294..8249a70 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_Update.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_Update.java
@@ -40,32 +40,30 @@ public class Filtered_SPARQL_Update extends SPARQL_Update {
     protected void validate(HttpAction action) {
         super.validate(action);
         
-        DatasetGraph dsg = action.getActiveDSG() ;
+        DatasetGraph dsg = action.getDataset();
         if ( ! DataAccessCtl.isAccessControlled(dsg) )
             return;
-        
-        ServletOps.errorBadRequest("SPARQL Update no supported");
+        ServletOps.errorBadRequest("SPARQL Update not supported");
     }
     
     @Override
     protected void perform(HttpAction action) {
-        DatasetGraph dsg = action.getActiveDSG() ;
+        DatasetGraph dsg = action.getDataset() ;
         if ( ! DataAccessCtl.isAccessControlled(dsg) ) {
             super.perform(action);
             return;
         }
-        
-        ServletOps.errorBadRequest("SPARQL Update no supported");
+        ServletOps.errorBadRequest("SPARQL Update not supported");
     }
     
     @Override
     protected void execute(HttpAction action, InputStream input) {
-        DatasetGraph dsg = action.getActiveDSG() ;
+        DatasetGraph dsg = action.getDataset() ;
         if ( ! DataAccessCtl.isAccessControlled(dsg) ) {
             super.execute(action, input);
             return;
         }
-        ServletOps.errorBadRequest("SPARQL Update no supported");
+        ServletOps.errorBadRequest("SPARQL Update not supported");
     }
 }
 

http://git-wip-us.apache.org/repos/asf/jena/blob/34b89a6a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_Upload.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_Upload.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_Upload.java
new file mode 100644
index 0000000..5e7b654
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/Filtered_SPARQL_Upload.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.function.Function;
+
+import org.apache.jena.fuseki.servlets.HttpAction;
+import org.apache.jena.fuseki.servlets.REST_Quads_R;
+import org.apache.jena.fuseki.servlets.SPARQL_Upload;
+import org.apache.jena.fuseki.servlets.ServletOps;
+import org.apache.jena.sparql.core.DatasetGraph;
+
+/**
+ * Filter for {@link REST_Quads_R} that inserts a security filter on read-access to the
+ * {@link DatasetGraph}.
+ */
+public class Filtered_SPARQL_Upload extends SPARQL_Upload {
+    
+    private final Function<HttpAction, String> requestUser;
+    
+    public Filtered_SPARQL_Upload(Function<HttpAction, String> determineUser) {
+        this.requestUser = determineUser; 
+    }
+
+    @Override
+    protected void validate(HttpAction action) {
+        super.validate(action);
+        DatasetGraph dsg = action.getDataset();
+        if ( ! DataAccessCtl.isAccessControlled(dsg) )
+            return;
+        ServletOps.errorBadRequest("Upload not supported");
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/34b89a6a/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 43d84d0..616fbb7 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
@@ -146,14 +146,26 @@ public class JettyLib {
         Objects.requireNonNull(password);
         Objects.requireNonNull(role);
         UserStore userStore = new UserStore();
+        addUser(userStore, user, password, role);
+        try { userStore.start(); }
+        catch (Exception ex) { throw new RuntimeException("UserStore", ex); }
+        return userStore;
+    }
+    public static UserStore addUser(UserStore userStore, String user, String password) {
+        return addUser(userStore, user, password, "**");
+    }
+
+    /** Make a {@link UserStore} for a single user,password,role*/
+    public static UserStore addUser(UserStore userStore, String user, String password, String role) {
         String[] roles = role == null ? null : new String[]{role};
         Credential cred  = new Password(password);
         userStore.addUser(user, cred, roles);
-        try { userStore.start(); }
-        catch (Exception ex) { throw new RuntimeException("UserStore", ex); }
         return userStore;
+
     }
     
+    
+    
     /** Add or append a {@link Handler} to a Jetty {@link Server}. */
     public static void addHandler(Server server, Handler handler) {
         final Handler currentHandler = server.getHandler();

http://git-wip-us.apache.org/repos/asf/jena/blob/34b89a6a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java
index a705a22..f6ebca3 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java
@@ -18,61 +18,62 @@
 
 package org.apache.jena.fuseki.server;
 
-import org.apache.jena.fuseki.FusekiException ;
-import org.apache.jena.iri.IRI ;
-import org.apache.jena.rdf.model.* ;
-import org.apache.jena.riot.system.IRIResolver ;
+import org.apache.jena.fuseki.FusekiException;
+import org.apache.jena.iri.IRI;
+import org.apache.jena.rdf.model.*;
+import org.apache.jena.riot.system.IRIResolver;
 
 public class FusekiVocab
 {
-    public static String NS = "http://jena.apache.org/fuseki#" ;
-    private static Model model = ModelFactory.createDefaultModel() ;
+    public static String NS = "http://jena.apache.org/fuseki#";
+    private static Model model = ModelFactory.createDefaultModel();
 
-    public static final Resource tServer = resource("Server") ;
+    public static final Resource tServer            = resource("Server");
 
-    public static final Resource fusekiService = resource("Service") ;
+    public static final Resource fusekiService      = resource("Service");
 
-    public static final Property pServices = property("services") ;
-    public static final Property pServiceName = property("name") ;
+    public static final Property pServices          = property("services");
+    public static final Property pServiceName       = property("name");
+    public static final Property pAllowedUsers      = property("allowedUsers");
     
-    public static final Property pServiceQueryEP               = property("serviceQuery") ;
-    public static final Property pServiceUpdateEP              = property("serviceUpdate") ;
-    public static final Property pServiceUploadEP              = property("serviceUpload") ;
-    public static final Property pServiceReadWriteGraphStoreEP = property("serviceReadWriteGraphStore") ;
-    public static final Property pServiceReadGraphStoreEP      = property("serviceReadGraphStore") ;
-    public static final Property pServiceReadWriteQuadsEP      = property("serviceReadWriteQuads") ;
-    public static final Property pServiceReadQuadsEP           = property("serviceReadQuads") ;
+    public static final Property pServiceQueryEP                = property("serviceQuery");
+    public static final Property pServiceUpdateEP               = property("serviceUpdate");
+    public static final Property pServiceUploadEP               = property("serviceUpload");
+    public static final Property pServiceReadWriteGraphStoreEP  = property("serviceReadWriteGraphStore");
+    public static final Property pServiceReadGraphStoreEP       = property("serviceReadGraphStore");
+    public static final Property pServiceReadWriteQuadsEP       = property("serviceReadWriteQuads");
+    public static final Property pServiceReadQuadsEP            = property("serviceReadQuads");
 
-    public static final Property pAllowTimeoutOverride = property("allowTimeoutOverride");
-    public static final Property pMaximumTimeoutOverride = property("maximumTimeoutOverride");
+    public static final Property pAllowTimeoutOverride          = property("allowTimeoutOverride");
+    public static final Property pMaximumTimeoutOverride        = property("maximumTimeoutOverride");
     
     // Internal
     
-    private static final String stateNameActive      = DataServiceStatus.ACTIVE.name ;
-    private static final String stateNameOffline     = DataServiceStatus.OFFLINE.name ;
-    private static final String stateNameClosing     = DataServiceStatus.CLOSING.name ;
-    private static final String stateNameClosed      = DataServiceStatus.CLOSED.name ;
+    private static final String stateNameActive     = DataServiceStatus.ACTIVE.name;
+    private static final String stateNameOffline    = DataServiceStatus.OFFLINE.name;
+    private static final String stateNameClosing    = DataServiceStatus.CLOSING.name;
+    private static final String stateNameClosed     = DataServiceStatus.CLOSED.name;
     
-    public static final Resource stateActive        = resource(stateNameActive) ;
-    public static final Resource stateOffline       = resource(stateNameOffline) ;
-    public static final Resource stateClosing       = resource(stateNameClosing) ;
-    public static final Resource stateClosed        = resource(stateNameClosed) ;
+    public static final Resource stateActive        = resource(stateNameActive);
+    public static final Resource stateOffline       = resource(stateNameOffline);
+    public static final Resource stateClosing       = resource(stateNameClosing);
+    public static final Resource stateClosed        = resource(stateNameClosed);
     
-    public static final Property pStatus = property("status") ;
+//    public static final Property pStatus            = property("status");
 
-    private static Resource resource(String localname) { return model.createResource(iri(localname)) ; }
-    private static Property property(String localname) { return model.createProperty(iri(localname)) ; }
+    private static Resource resource(String localname) { return model.createResource(iri(localname)); }
+    private static Property property(String localname) { return model.createProperty(iri(localname)); }
         
     private static String iri(String localname)
     {
-        String uri = NS+localname ;
-        IRI iri = IRIResolver.parseIRI(uri) ;
+        String uri = NS+localname;
+        IRI iri = IRIResolver.parseIRI(uri);
         if ( iri.hasViolation(true) )
-            throw new FusekiException("Bad IRI: "+iri) ;
+            throw new FusekiException("Bad IRI: "+iri);
         if ( ! iri.isAbsolute() )
-            throw new FusekiException("Bad IRI: "+iri) ;
+            throw new FusekiException("Bad IRI: "+iri);
         
-        return uri ;
+        return uri;
     }
 }