This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git

commit 7b8af45250f4fc87a372ee81c485d30b3878a7ed
Author: Andy Seaborne <[email protected]>
AuthorDate: Wed May 21 20:50:38 2025 +0100

    GH-2805: StatementTerm for jena-permissions
---
 .../java/org/apache/jena/permissions/Factory.java  |   4 +-
 .../permissions/model/SecuredStatementTerm.java    |  28 ++++++
 .../permissions/model/impl/SecuredLiteralImpl.java |  14 ++-
 .../permissions/model/impl/SecuredModelImpl.java   |   4 +-
 .../permissions/model/impl/SecuredRDFNodeImpl.java |  24 ++---
 .../model/impl/SecuredResourceImpl.java            |  27 ++----
 .../model/impl/SecuredStatementImpl.java           |   1 -
 .../model/impl/SecuredStatementTermImpl.java       | 105 +++++++++++++++++++++
 8 files changed, 165 insertions(+), 42 deletions(-)

diff --git 
a/jena-permissions/src/main/java/org/apache/jena/permissions/Factory.java 
b/jena-permissions/src/main/java/org/apache/jena/permissions/Factory.java
index 49178c6f3e..08a71441a8 100644
--- a/jena-permissions/src/main/java/org/apache/jena/permissions/Factory.java
+++ b/jena-permissions/src/main/java/org/apache/jena/permissions/Factory.java
@@ -34,7 +34,7 @@ public class Factory {
 
     /**
      * Create an instance of the SecuredGraph
-     * 
+     *
      * @param securityEvaluator The security evaluator to use
      * @param graphIRI          The IRI for the graph.
      * @param graph             The graph that we are wrapping.
@@ -48,7 +48,7 @@ public class Factory {
 
     /**
      * Get an instance of SecuredModel
-     * 
+     *
      * @param securityEvaluator The security evaluator to use
      * @param modelIRI          The securedModel IRI (graph IRI) to evaluate
      *                          against.
diff --git 
a/jena-permissions/src/main/java/org/apache/jena/permissions/model/SecuredStatementTerm.java
 
b/jena-permissions/src/main/java/org/apache/jena/permissions/model/SecuredStatementTerm.java
new file mode 100644
index 0000000000..74b633c64f
--- /dev/null
+++ 
b/jena-permissions/src/main/java/org/apache/jena/permissions/model/SecuredStatementTerm.java
@@ -0,0 +1,28 @@
+/*
+ * 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.permissions.model;
+
+import org.apache.jena.rdf.model.*;
+
+/**
+ * The interface for secured StatementTerm instances.
+ *
+ * Use a secured Model to create instances.
+ */
+public interface SecuredStatementTerm extends StatementTerm, SecuredRDFNode {
+}
diff --git 
a/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredLiteralImpl.java
 
b/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredLiteralImpl.java
index 06e5bd5a45..2c5be5e4cb 100644
--- 
a/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredLiteralImpl.java
+++ 
b/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredLiteralImpl.java
@@ -25,10 +25,8 @@ import org.apache.jena.permissions.impl.SecuredItemInvoker;
 import org.apache.jena.permissions.model.SecuredLiteral;
 import org.apache.jena.permissions.model.SecuredModel;
 import org.apache.jena.permissions.model.SecuredResource;
-import org.apache.jena.rdf.model.Literal;
-import org.apache.jena.rdf.model.Model;
-import org.apache.jena.rdf.model.RDFVisitor;
-import org.apache.jena.rdf.model.ResourceRequiredException;
+import org.apache.jena.permissions.model.SecuredStatementTerm;
+import org.apache.jena.rdf.model.*;
 import org.apache.jena.shared.AuthenticationRequiredException;
 import org.apache.jena.shared.ReadDeniedException;
 
@@ -100,6 +98,14 @@ public class SecuredLiteralImpl extends SecuredRDFNodeImpl 
implements SecuredLit
         throw new 
ResourceRequiredException(NodeFactory.createLiteralString("Can not read"));
     }
 
+    @Override
+    public SecuredStatementTerm asStatementTerm() {
+        if (canRead()) {
+            throw new StmtTermRequiredException(asNode());
+        }
+        throw new 
StmtTermRequiredException(NodeFactory.createLiteralString("Can not read"));
+    }
+
     /**
      * @sec.graph Read
      * @throws ReadDeniedException
diff --git 
a/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredModelImpl.java
 
b/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredModelImpl.java
index 5b9d762652..c491e125cd 100644
--- 
a/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredModelImpl.java
+++ 
b/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredModelImpl.java
@@ -1345,8 +1345,8 @@ public class SecuredModelImpl extends SecuredItemImpl 
implements SecuredModel {
     }
 
     @Override
-    public RDFNode createStatementTerm(Statement statement) {
-        return SecuredResourceImpl.getInstance(holder.getSecuredItem(), 
holder.getBaseItem().createStatementTerm(statement));
+    public StatementTerm createStatementTerm(Statement statement) {
+        return SecuredStatementTermImpl.getInstance(holder.getSecuredItem(), 
holder.getBaseItem().createStatementTerm(statement));
     }
 
     @Override
diff --git 
a/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredRDFNodeImpl.java
 
b/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredRDFNodeImpl.java
index 203b133c01..09ee7eafe9 100644
--- 
a/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredRDFNodeImpl.java
+++ 
b/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredRDFNodeImpl.java
@@ -6,9 +6,9 @@
  * 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.
@@ -28,10 +28,7 @@ import org.apache.jena.permissions.impl.SecuredItemImpl;
 import org.apache.jena.permissions.model.SecuredModel;
 import org.apache.jena.permissions.model.SecuredRDFNode;
 import 
org.apache.jena.permissions.model.SecuredUnsupportedPolymorphismException;
-import org.apache.jena.rdf.model.Literal;
-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.rdf.model.*;
 import org.apache.jena.shared.AuthenticationRequiredException;
 import org.apache.jena.shared.ReadDeniedException;
 
@@ -40,7 +37,7 @@ import org.apache.jena.shared.ReadDeniedException;
  */
 public abstract class SecuredRDFNodeImpl extends SecuredItemImpl implements 
SecuredRDFNode {
     /**
-     * 
+     *
      * @param securedModel the Secured Model to use.
      * @param rdfNode      the node to secure.
      * @return the secured RDFNode
@@ -49,6 +46,9 @@ public abstract class SecuredRDFNodeImpl extends 
SecuredItemImpl implements Secu
         if (rdfNode instanceof Literal) {
             return SecuredLiteralImpl.getInstance(securedModel, (Literal) 
rdfNode);
         }
+        if (rdfNode instanceof StatementTerm ) {
+            return SecuredStatementTermImpl.getInstance(securedModel, 
(StatementTerm)rdfNode);
+        }
         return SecuredResourceImpl.getInstance(securedModel, (Resource) 
rdfNode);
     }
 
@@ -60,7 +60,7 @@ public abstract class SecuredRDFNodeImpl extends 
SecuredItemImpl implements Secu
 
     /**
      * Constructor
-     * 
+     *
      * @param securedModel the Secured Model to use.
      * @param holder       the item holder that will contain this 
SecuredRDFNode.
      */
@@ -198,8 +198,8 @@ public abstract class SecuredRDFNodeImpl extends 
SecuredItemImpl implements Secu
     }
 
     @Override
-    public boolean isStmtResource() {
-        return holder.getBaseItem().isStmtResource();
+    public boolean isStatementTerm() {
+        return holder.getBaseItem().isStatementTerm();
     }
 
     /**
@@ -208,7 +208,7 @@ public abstract class SecuredRDFNodeImpl extends 
SecuredItemImpl implements Secu
      * asNode, because we allow other implementations of Resource, at least in
      * principle. This is deemed to be a complete and correct interpretation of
      * RDFNode equality, which is why this method has been marked final.
-     * 
+     *
      * @param o An object to test for equality with this node
      * @return True if o is equal to this node.
      * @throws ReadDeniedException
@@ -222,7 +222,7 @@ public abstract class SecuredRDFNodeImpl extends 
SecuredItemImpl implements Secu
 
     /**
      * The hash code of an RDFnode is defined to be the same as the underlying 
node.
-     * 
+     *
      * @return The hashcode as an int
      */
     @Override
diff --git 
a/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredResourceImpl.java
 
b/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredResourceImpl.java
index cbde1532a9..2caf65b862 100644
--- 
a/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredResourceImpl.java
+++ 
b/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredResourceImpl.java
@@ -297,6 +297,12 @@ public class SecuredResourceImpl extends 
SecuredRDFNodeImpl implements SecuredRe
         return holder.getSecuredItem();
     }
 
+    @Override
+    public StatementTerm asStatementTerm() {
+        checkRead();
+        throw new StmtTermRequiredException(asNode());
+    }
+
     @Override
     public SecuredResource begin() {
         holder.getBaseItem().begin();
@@ -505,27 +511,6 @@ public class SecuredResourceImpl extends 
SecuredRDFNodeImpl implements SecuredRe
         return holder.getBaseItem().getURI();
     }
 
-    /**
-     * @sec.graph Read
-     *
-     *            if {@link SecurityEvaluator#isHardReadError()} is true and 
the
-     *            user does not have read access then @{code null} is returned.
-     *
-     * @throws ReadDeniedException
-     * @throws AuthenticationRequiredException if user is not authenticated 
and is
-     *                                         required to be.
-     */
-    @Override
-    public Statement getStmtTerm() {
-        if (checkSoftRead()) {
-            Statement stmt = holder.getBaseItem().getStmtTerm();
-            if (stmt != null && canRead(stmt)) {
-                return SecuredStatementImpl.getInstance(getModel(), stmt);
-            }
-        }
-        return null;
-    }
-
     /**
      * @sec.graph Read
      * @sec.triple Read SecTriple(this,p,o)
diff --git 
a/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredStatementImpl.java
 
b/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredStatementImpl.java
index 59d800280b..4862cabcae 100644
--- 
a/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredStatementImpl.java
+++ 
b/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredStatementImpl.java
@@ -457,7 +457,6 @@ public class SecuredStatementImpl extends SecuredItemImpl 
implements SecuredStat
         checkRead(holder.getBaseItem().asTriple());
         final RDFNode rdfNode = holder.getBaseItem().getObject();
         return SecuredRDFNodeImpl.getInstance(getModel(), rdfNode);
-
     }
 
     /**
diff --git 
a/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredStatementTermImpl.java
 
b/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredStatementTermImpl.java
new file mode 100644
index 0000000000..fac6f7afc4
--- /dev/null
+++ 
b/jena-permissions/src/main/java/org/apache/jena/permissions/model/impl/SecuredStatementTermImpl.java
@@ -0,0 +1,105 @@
+/*
+ * 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.permissions.model.impl;
+
+import org.apache.jena.permissions.impl.ItemHolder;
+import org.apache.jena.permissions.impl.SecuredItemInvoker;
+import org.apache.jena.permissions.model.*;
+import org.apache.jena.rdf.model.*;
+
+/**
+ * Implementation of SecuredStatement to be used by a SecuredItemInvoker proxy.
+ */
+public class SecuredStatementTermImpl extends SecuredRDFNodeImpl implements 
SecuredStatementTerm {
+    /**
+     * get a SecuredStatement
+     *
+     * @param securedModel The secured model that provides the security context
+     * @param stmt         The statement to secure.
+     * @return the SecuredStatement
+     */
+    public static SecuredStatementTerm getInstance(final SecuredModel 
securedModel, final StatementTerm stmtTerm) {
+        if (securedModel == null) {
+            throw new IllegalArgumentException("Secured securedModel may not 
be null");
+        }
+        if (stmtTerm == null) {
+            throw new IllegalArgumentException("StatemenTerm may not be null");
+        }
+
+        final ItemHolder<StatementTerm, SecuredStatementTerm> holder = new 
ItemHolder<>(stmtTerm);
+
+        final SecuredStatementTermImpl checker = new 
SecuredStatementTermImpl(securedModel, holder);
+        // if we are going to create a duplicate proxy, just return this
+        // one.
+        if (stmtTerm instanceof SecuredStatementTerm) {
+            if (checker.isEquivalent((SecuredStatement) stmtTerm)) {
+                return (SecuredStatementTerm) stmtTerm;
+            }
+        }
+        return holder.setSecuredItem(new 
SecuredItemInvoker(holder.getBaseItem().getClass(), checker));
+    }
+
+    // the item holder that contains this SecuredStatement.
+    private final ItemHolder<StatementTerm, SecuredStatementTerm> holder;
+
+    private final SecuredModel securedModel;
+
+    /**
+     * Constructor.
+     *
+     * @param securityEvaluator The security evaluator to use.
+     * @param graphIRI          the graph IRI to verify against.
+     * @param holder            The item holder that will contain this
+     *                          SecuredStatement.
+     */
+    private SecuredStatementTermImpl(final SecuredModel securedModel,
+            final ItemHolder<StatementTerm, SecuredStatementTerm> holder) {
+        super(securedModel, holder);
+        this.holder = holder;
+        this.securedModel = securedModel;
+    }
+
+    @Override
+    public SecuredLiteral asLiteral() {
+        checkRead();
+        throw new LiteralRequiredException(asNode());
+    }
+
+    @Override
+    public SecuredResource asResource() {
+        checkRead();
+        throw new ResourceRequiredException(asNode());
+    }
+
+    @Override
+    public SecuredStatementTerm asStatementTerm() {
+        checkRead();
+        return this;
+    }
+
+    @Override
+    public Statement getStatement() {
+        checkRead();
+        return SecuredStatementImpl.getInstance(securedModel, 
holder.getBaseItem().getStatement());
+    }
+
+    @Override
+    public Object visitWith(RDFVisitor rv) {
+        return rv.visitStmt(this, this.getStatement());
+    }
+}

Reply via email to