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 2015/04/24 14:20:15 UTC
[17/24] jena git commit: Module jena-seurity becomes jena-permissions
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/main/java/org/apache/jena/security/model/impl/SecuredStatementImpl.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/main/java/org/apache/jena/security/model/impl/SecuredStatementImpl.java b/jena-permissions/src/main/java/org/apache/jena/security/model/impl/SecuredStatementImpl.java
new file mode 100644
index 0000000..9981b00
--- /dev/null
+++ b/jena-permissions/src/main/java/org/apache/jena/security/model/impl/SecuredStatementImpl.java
@@ -0,0 +1,560 @@
+/*
+ * 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.security.model.impl;
+
+import org.apache.jena.graph.NodeFactory ;
+import org.apache.jena.graph.Triple ;
+import org.apache.jena.rdf.model.* ;
+import org.apache.jena.security.impl.ItemHolder ;
+import org.apache.jena.security.impl.SecuredItemImpl ;
+import org.apache.jena.security.impl.SecuredItemInvoker ;
+import org.apache.jena.security.model.* ;
+import org.apache.jena.shared.PropertyNotFoundException ;
+
+/**
+ * Implementation of SecuredStatement to be used by a SecuredItemInvoker proxy.
+ */
+public class SecuredStatementImpl extends SecuredItemImpl implements
+ SecuredStatement
+{
+ /**
+ * get a SecuredStatement
+ *
+ * @param securedModel
+ * The secured model that provides the security context
+ * @param stmt
+ * The statement to secure.
+ * @return the SecuredStatement
+ */
+ public static SecuredStatement getInstance(
+ final SecuredModel securedModel, final Statement stmt )
+ {
+ if (securedModel == null)
+ {
+ throw new IllegalArgumentException(
+ "Secured securedModel may not be null");
+ }
+ if (stmt == null)
+ {
+ throw new IllegalArgumentException("Statement may not be null");
+ }
+
+ final ItemHolder<Statement, SecuredStatement> holder = new ItemHolder<Statement, SecuredStatement>(
+ stmt);
+
+ final SecuredStatementImpl checker = new SecuredStatementImpl(
+ securedModel, holder);
+ // if we are going to create a duplicate proxy, just return this
+ // one.
+ if (stmt instanceof SecuredStatement)
+ {
+ if (checker.isEquivalent((SecuredStatement) stmt))
+ {
+ return (SecuredStatement) stmt;
+ }
+ }
+ return holder.setSecuredItem(new SecuredItemInvoker(holder
+ .getBaseItem().getClass(), checker));
+ }
+
+ // the item holder that contains this SecuredStatement.
+ private final ItemHolder<Statement, SecuredStatement> 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 SecuredStatementImpl( final SecuredModel securedModel,
+ final ItemHolder<Statement, SecuredStatement> holder )
+ {
+ super(securedModel, holder);
+ this.holder = holder;
+ this.securedModel = securedModel;
+ }
+
+ @Override
+ public Triple asTriple()
+ {
+ checkRead();
+ final Triple retval = holder.getBaseItem().asTriple();
+ checkRead(retval);
+ return retval;
+ }
+
+ @Override
+ public boolean canCreate()
+ {
+ return super.canCreate() ? canCreate(holder.getBaseItem()) : false;
+ }
+
+ @Override
+ public boolean canDelete()
+ {
+ return super.canDelete() ? canDelete(holder.getBaseItem()) : false;
+ }
+
+ @Override
+ public boolean canRead()
+ {
+ return super.canRead() ? canRead(holder.getBaseItem()) : false;
+ }
+
+ @Override
+ public SecuredStatement changeLiteralObject( final boolean o )
+ {
+ checkUpdate();
+ final Triple base = holder.getBaseItem().asTriple();
+ final Triple newBase = getNewTriple(base, o);
+ checkUpdate(base, newBase);
+ return SecuredStatementImpl.getInstance(getModel(), holder
+ .getBaseItem().changeLiteralObject(o));
+ }
+
+ @Override
+ public SecuredStatement changeLiteralObject( final char o )
+ {
+ checkUpdate();
+ final Triple base = holder.getBaseItem().asTriple();
+ final Triple newBase = getNewTriple(base, o);
+ checkUpdate(base, newBase);
+ return SecuredStatementImpl.getInstance(getModel(), holder
+ .getBaseItem().changeLiteralObject(o));
+ }
+
+ @Override
+ public SecuredStatement changeLiteralObject( final double o )
+ {
+ checkUpdate();
+ final Triple base = holder.getBaseItem().asTriple();
+ final Triple newBase = getNewTriple(base, o);
+ checkUpdate(base, newBase);
+ return SecuredStatementImpl.getInstance(getModel(), holder
+ .getBaseItem().changeLiteralObject(o));
+ }
+
+ @Override
+ public SecuredStatement changeLiteralObject( final float o )
+ {
+ checkUpdate();
+ final Triple base = holder.getBaseItem().asTriple();
+ final Triple newBase = getNewTriple(base, o);
+ checkUpdate(base, newBase);
+ return SecuredStatementImpl.getInstance(getModel(), holder
+ .getBaseItem().changeLiteralObject(o));
+ }
+
+ @Override
+ public SecuredStatement changeLiteralObject( final int o )
+ {
+ checkUpdate();
+ final Triple base = holder.getBaseItem().asTriple();
+ final Triple newBase = getNewTriple(base, o);
+ checkUpdate(base, newBase);
+ return SecuredStatementImpl.getInstance(getModel(), holder
+ .getBaseItem().changeLiteralObject(o));
+ }
+
+ @Override
+ public SecuredStatement changeLiteralObject( final long o )
+ {
+ checkUpdate();
+ final Triple base = holder.getBaseItem().asTriple();
+ final Triple newBase = getNewTriple(base, o);
+ checkUpdate(base, newBase);
+ return SecuredStatementImpl.getInstance(getModel(), holder
+ .getBaseItem().changeLiteralObject(o));
+ }
+
+ @Override
+ public SecuredStatement changeObject( final RDFNode o )
+ {
+ checkUpdate();
+ final Triple base = holder.getBaseItem().asTriple();
+ final Triple newBase = new Triple(base.getSubject(),
+ base.getPredicate(), o.asNode());
+ checkUpdate(base, newBase);
+ return SecuredStatementImpl.getInstance(getModel(), holder
+ .getBaseItem().changeObject(o));
+ }
+
+ @Override
+ public SecuredStatement changeObject( final String o )
+ {
+ checkUpdate();
+ final Triple base = holder.getBaseItem().asTriple();
+ final Triple newBase = getNewTriple(base, o);
+ checkUpdate(base, newBase);
+ return SecuredStatementImpl.getInstance(getModel(), holder
+ .getBaseItem().changeObject(o));
+ }
+
+ @Override
+ public SecuredStatement changeObject( final String o,
+ final boolean wellFormed )
+ {
+ checkUpdate();
+ final Triple base = holder.getBaseItem().asTriple();
+ final Triple newBase = new Triple(base.getSubject(),
+ base.getPredicate(), NodeFactory.createLiteral(o, "", wellFormed));
+ checkUpdate(base, newBase);
+ return SecuredStatementImpl.getInstance(getModel(), holder
+ .getBaseItem().changeObject(o));
+ }
+
+ @Override
+ public SecuredStatement changeObject( final String o, final String l )
+ {
+ checkUpdate();
+ final Triple base = holder.getBaseItem().asTriple();
+ final Triple newBase = new Triple(base.getSubject(),
+ base.getPredicate(), NodeFactory.createLiteral(o, l, false));
+ checkUpdate(base, newBase);
+ return SecuredStatementImpl.getInstance(getModel(), holder
+ .getBaseItem().changeObject(o, l));
+ }
+
+ @Override
+ public SecuredStatement changeObject( final String o, final String l,
+ final boolean wellFormed )
+ {
+ checkUpdate();
+ final Triple base = holder.getBaseItem().asTriple();
+ final Triple newBase = new Triple(base.getSubject(),
+ base.getPredicate(), NodeFactory.createLiteral(o, l, wellFormed));
+ checkUpdate(base, newBase);
+ return SecuredStatementImpl.getInstance(getModel(), holder
+ .getBaseItem().changeObject(o, l, wellFormed));
+ }
+
+ @Override
+ public SecuredReifiedStatement createReifiedStatement()
+ {
+ checkUpdate();
+ checkCreateReified(null,
+ SecuredItemImpl.convert(holder.getBaseItem().asTriple()));
+ return SecuredReifiedStatementImpl.getInstance(getModel(), holder
+ .getBaseItem().createReifiedStatement());
+ }
+
+ @Override
+ public SecuredReifiedStatement createReifiedStatement( final String uri )
+ {
+ checkUpdate();
+ checkCreateReified(uri,
+ SecuredItemImpl.convert(holder.getBaseItem().asTriple()));
+ return SecuredReifiedStatementImpl.getInstance(getModel(), holder
+ .getBaseItem().createReifiedStatement(uri));
+ }
+
+ @Override
+ public SecuredAlt getAlt()
+ {
+ return SecuredAltImpl.getInstance(getModel(), holder.getBaseItem()
+ .getAlt());
+ }
+
+ @Override
+ public SecuredBag getBag()
+ {
+ return SecuredBagImpl.getInstance(getModel(), holder.getBaseItem()
+ .getBag());
+ }
+
+ @Override
+ public boolean getBoolean()
+ {
+ checkRead();
+ checkRead(holder.getBaseItem().asTriple());
+ return holder.getBaseItem().getBoolean();
+ }
+
+ @Override
+ public byte getByte()
+ {
+ checkRead();
+ checkRead(holder.getBaseItem().asTriple());
+ return holder.getBaseItem().getByte();
+ }
+
+ @Override
+ public char getChar()
+ {
+ checkRead();
+ checkRead(holder.getBaseItem().asTriple());
+ return holder.getBaseItem().getChar();
+
+ }
+
+ @Override
+ public double getDouble()
+ {
+ checkRead();
+ checkRead(holder.getBaseItem().asTriple());
+ return holder.getBaseItem().getDouble();
+ }
+
+ @Override
+ public float getFloat()
+ {
+ checkRead();
+ checkRead(holder.getBaseItem().asTriple());
+ return holder.getBaseItem().getFloat();
+ }
+
+ @Override
+ public int getInt()
+ {
+ checkRead();
+ checkRead(holder.getBaseItem().asTriple());
+ return holder.getBaseItem().getInt();
+ }
+
+ @Override
+ public String getLanguage()
+ {
+ checkRead();
+ checkRead(holder.getBaseItem().asTriple());
+ return holder.getBaseItem().getLiteral().getLanguage();
+ }
+
+ @Override
+ public SecuredLiteral getLiteral()
+ {
+ return SecuredLiteralImpl.getInstance(getModel(), holder.getBaseItem()
+ .getLiteral());
+ }
+
+ @Override
+ public long getLong()
+ {
+ checkRead();
+ checkRead(holder.getBaseItem().asTriple());
+ return holder.getBaseItem().getLong();
+ }
+
+ @Override
+ public SecuredModel getModel()
+ {
+ return securedModel;
+ }
+
+ private Triple getNewTriple( final Triple t, final Object o )
+ {
+ return new Triple(t.getSubject(), t.getPredicate(),
+ NodeFactory.createLiteral(String.valueOf(o), "", false));
+ }
+
+ @Override
+ public SecuredRDFNode getObject()
+ {
+ checkRead();
+ checkRead(holder.getBaseItem().asTriple());
+ final RDFNode rdfNode = holder.getBaseItem().getObject();
+ return SecuredRDFNodeImpl.getInstance(getModel(), rdfNode);
+
+ }
+
+ @Override
+ public SecuredProperty getPredicate()
+ {
+ return SecuredPropertyImpl.getInstance(getModel(), holder.getBaseItem()
+ .getPredicate());
+ }
+
+ @Override
+ public SecuredStatement getProperty( final Property p )
+ {
+ final StmtIterator s = holder
+ .getBaseItem()
+ .getModel()
+ .listStatements(holder.getBaseItem().getObject().asResource(),
+ p, (RDFNode) null);
+ final SecuredStatementIterator iter = new SecuredStatementIterator(
+ getModel(), s);
+ try
+ {
+ if (iter.hasNext())
+ {
+ return SecuredStatementImpl
+ .getInstance(getModel(), iter.next());
+ }
+ else
+ {
+ throw new PropertyNotFoundException(p);
+ }
+ }
+ finally
+ {
+ iter.close();
+ }
+ }
+
+ @Override
+ public SecuredResource getResource()
+ {
+ return SecuredResourceImpl.getInstance(getModel(), holder.getBaseItem()
+ .getResource());
+ }
+
+ @Override
+ @Deprecated
+ public SecuredResource getResource( final ResourceF f )
+ {
+ return SecuredResourceImpl.getInstance(getModel(), holder.getBaseItem()
+ .getResource(f));
+ }
+
+ @Override
+ public SecuredSeq getSeq()
+ {
+ return SecuredSeqImpl.getInstance(getModel(), holder.getBaseItem()
+ .getSeq());
+ }
+
+ @Override
+ public short getShort()
+ {
+ checkRead();
+ checkRead(holder.getBaseItem().asTriple());
+ return holder.getBaseItem().getShort();
+ }
+
+ @Override
+ public SecuredStatement getStatementProperty( final Property p )
+ {
+ final RSIterator rsIter = holder.getBaseItem().listReifiedStatements();
+ try
+ {
+ while (rsIter.hasNext())
+ {
+ final ReifiedStatement s = rsIter.next();
+ if (s.hasProperty(p))
+ {
+ return SecuredStatementImpl.getInstance(getModel(),
+ s.getProperty(p));
+ }
+ }
+ throw new PropertyNotFoundException(p);
+ }
+ finally
+ {
+ rsIter.close();
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ if (canRead() && canRead(holder.getBaseItem().asTriple()))
+ {
+ return holder.getBaseItem().toString();
+ }
+ else
+ {
+ return super.toString();
+ }
+ }
+
+ @Override
+ public String getString()
+ { return getLiteral().getLexicalForm(); }
+
+ @Override
+ public SecuredResource getSubject()
+ {
+ return SecuredResourceImpl.getInstance(getModel(), holder.getBaseItem()
+ .getSubject());
+ }
+
+ @Override
+ public boolean hasWellFormedXML()
+ {
+ checkRead();
+ checkRead(holder.getBaseItem().asTriple());
+ return holder.getBaseItem().getLiteral().isWellFormedXML();
+ }
+
+ @Override
+ public boolean isReified()
+ {
+ checkRead();
+ checkRead(holder.getBaseItem().asTriple());
+ return holder.getBaseItem().isReified();
+ }
+
+ @Override
+ public RSIterator listReifiedStatements()
+ {
+ checkRead();
+ checkRead(holder.getBaseItem().asTriple());
+ return new SecuredRSIterator(getModel(), holder.getBaseItem()
+ .listReifiedStatements());
+ }
+
+ @Override
+ public SecuredStatement remove()
+ {
+ checkUpdate();
+ checkDelete(holder.getBaseItem());
+ holder.getBaseItem().remove();
+ return holder.getSecuredItem();
+ }
+
+ @Override
+ public void removeReification()
+ {
+ checkUpdate();
+ if (!canDelete(Triple.ANY))
+ {
+ StmtIterator iter = null;
+ final RSIterator rsIter = holder.getBaseItem()
+ .listReifiedStatements();
+ try
+ {
+ while (rsIter.hasNext())
+ {
+ final ReifiedStatement stmt = rsIter.next();
+ iter = stmt.listProperties();
+ while (iter.hasNext())
+ {
+ final Statement s = iter.next();
+ checkDelete(s);
+ }
+ }
+ }
+ finally
+ {
+ rsIter.close();
+ if (iter != null)
+ {
+ iter.close();
+ }
+ }
+ }
+ holder.getBaseItem().removeReification();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/main/java/org/apache/jena/security/model/impl/SecuredStatementIterator.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/main/java/org/apache/jena/security/model/impl/SecuredStatementIterator.java b/jena-permissions/src/main/java/org/apache/jena/security/model/impl/SecuredStatementIterator.java
new file mode 100644
index 0000000..6066da7
--- /dev/null
+++ b/jena-permissions/src/main/java/org/apache/jena/security/model/impl/SecuredStatementIterator.java
@@ -0,0 +1,148 @@
+/*
+ * 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.security.model.impl;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.apache.jena.rdf.model.Statement ;
+import org.apache.jena.rdf.model.StmtIterator ;
+import org.apache.jena.security.SecurityEvaluator.Action;
+import org.apache.jena.security.model.SecuredModel;
+import org.apache.jena.security.model.SecuredStatement;
+import org.apache.jena.security.utils.PermStatementFilter;
+import org.apache.jena.util.iterator.ExtendedIterator ;
+import org.apache.jena.util.iterator.Filter ;
+import org.apache.jena.util.iterator.Map1 ;
+
+/**
+ * A secured StatementIterator implementation
+ */
+public class SecuredStatementIterator implements StmtIterator
+{
+
+ private class PermStatementMap implements Map1<Statement, Statement>
+ {
+ private final SecuredModel securedModel;
+
+ public PermStatementMap( final SecuredModel securedModel )
+ {
+ this.securedModel = securedModel;
+ }
+
+ @Override
+ public SecuredStatement map1( final Statement o )
+ {
+ return SecuredStatementImpl.getInstance(securedModel, o);
+ }
+ }
+
+ private final ExtendedIterator<Statement> iter;
+
+ /**
+ * Constructor.
+ *
+ * @param securedModel
+ * The item providing the security context.
+ * @param wrapped
+ * The iterator to wrap.
+ */
+ public SecuredStatementIterator( final SecuredModel securedModel,
+ final ExtendedIterator<Statement> wrapped )
+ {
+ final PermStatementFilter filter = new PermStatementFilter(
+ new Action[] { Action.Read }, securedModel);
+ final PermStatementMap map1 = new PermStatementMap(securedModel);
+ iter = wrapped.filterKeep(filter).mapWith(map1);
+ }
+
+ @Override
+ public <X extends Statement> ExtendedIterator<Statement> andThen(
+ final Iterator<X> other )
+ {
+ return iter.andThen(other);
+ }
+
+ @Override
+ public void close()
+ {
+ iter.close();
+ }
+
+ @Override
+ public ExtendedIterator<Statement> filterDrop( final Filter<Statement> f )
+ {
+ return iter.filterDrop(f);
+ }
+
+ @Override
+ public ExtendedIterator<Statement> filterKeep( final Filter<Statement> f )
+ {
+ return iter.filterKeep(f);
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ return iter.hasNext();
+ }
+
+ @Override
+ public <U> ExtendedIterator<U> mapWith( final Map1<Statement, U> map1 )
+ {
+ return iter.mapWith(map1);
+ }
+
+ @Override
+ public Statement next()
+ {
+ return iter.next();
+ }
+
+ @Override
+ public Statement nextStatement() throws NoSuchElementException
+ {
+ return next();
+ }
+
+ @Override
+ public void remove()
+ {
+ iter.remove();
+ }
+
+ @Override
+ public Statement removeNext()
+ {
+ return iter.removeNext();
+ }
+
+ @Override
+ public List<Statement> toList()
+ {
+ return iter.toList();
+ }
+
+ @Override
+ public Set<Statement> toSet()
+ {
+ return iter.toSet();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/main/java/org/apache/jena/security/package-info.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/main/java/org/apache/jena/security/package-info.java b/jena-permissions/src/main/java/org/apache/jena/security/package-info.java
new file mode 100644
index 0000000..359dc3b
--- /dev/null
+++ b/jena-permissions/src/main/java/org/apache/jena/security/package-info.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+/**
+ * JenaSecurity is a SecurityEvaluator interface and a set of dynamic proxies that apply that
+ * interface to Jena Graphs, Models, and associated methods and classes.
+ * <p>
+ * The SecurityEvaluator class must be implemented. This class provides the interface to the
+ * authentication results (e.g. <code>getPrincipal()</code>) and the authorization system.
+ * </p><p>
+ * <ul>
+ * <li>
+ * Create a SecuredGraph by calling <code>Factory.getInstance( SecurityEvaluator, String, Graph );</code>
+ * </li><li>
+ * Create a SecuredModel by calling <code>Factory.getInstance( SecurityEvaluator, String, Model )</code>
+ * </li><li>
+ * It is not recommended that you create a model by calling the Jena <code>ModelFactory.createModelForGraph( SecuredGraph )</code>
+ * See Overview for discussion.
+ * </li>
+ * </ul>
+ * </p><p>
+ * <em>NOTES:</em>
+ * <ul>
+ * <li>See SecurityEvaluator documentation for description of cascading security checks</li>
+ * <li>Secured methods are annotated with:
+ * @sec.graph for permissions required on the graph to execute the method.
+ * @sec.triple for permissions required on the associated triples (if any) to execute the method.
+ * </li>
+ * <li>It is possible to implement a SecurityEvaluator that does not enforce security at the triple
+ * level. See SecurityEvaluator documentation for details</li>
+ * </ul>
+ * </p>
+ */
+package org.apache.jena.security;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/main/java/org/apache/jena/security/query/SecuredQueryEngine.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/main/java/org/apache/jena/security/query/SecuredQueryEngine.java b/jena-permissions/src/main/java/org/apache/jena/security/query/SecuredQueryEngine.java
new file mode 100644
index 0000000..1afec86
--- /dev/null
+++ b/jena-permissions/src/main/java/org/apache/jena/security/query/SecuredQueryEngine.java
@@ -0,0 +1,152 @@
+/*
+ * 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.security.query;
+
+import java.security.Principal;
+import java.util.Set;
+
+import org.apache.jena.graph.Graph ;
+import org.apache.jena.query.Query ;
+import org.apache.jena.security.SecurityEvaluator;
+import org.apache.jena.security.SecurityEvaluator.SecNode;
+import org.apache.jena.security.SecurityEvaluator.SecNode.Type;
+import org.apache.jena.security.graph.SecuredGraph;
+import org.apache.jena.security.query.rewriter.OpRewriter;
+import org.apache.jena.sparql.algebra.Op ;
+import org.apache.jena.sparql.core.DatasetGraph ;
+import org.apache.jena.sparql.engine.binding.Binding ;
+import org.apache.jena.sparql.engine.main.QueryEngineMain ;
+import org.apache.jena.sparql.util.Context ;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SecuredQueryEngine extends QueryEngineMain
+{
+ private static Logger LOG = LoggerFactory
+ .getLogger(SecuredQueryEngine.class);
+
+ private SecurityEvaluator securityEvaluator;
+ private SecNode graphIRI;
+
+ /*
+ * public SecuredQueryEngine( Op op, DatasetGraph dataset, Binding input,
+ * Context context )
+ * {
+ * super(op, dataset, input, context);
+ * setGraphIRI( dataset );
+ * }
+ */
+ public SecuredQueryEngine( final Query query, final DatasetGraph dataset,
+ final Binding input, final Context context )
+ {
+ super(query, dataset, input, context);
+ setGraphIRI(dataset);
+ }
+
+ public SecurityEvaluator getSecurityEvaluator()
+ {
+ return securityEvaluator;
+ }
+
+ @Override
+ protected Op modifyOp( final Op op )
+ {
+ final OpRewriter rewriter = new OpRewriter(securityEvaluator, graphIRI);
+ SecuredQueryEngine.LOG.debug("Before: {}", op);
+ op.visit(rewriter);
+ Op result = rewriter.getResult();
+ result = result == null ? op : result;
+ SecuredQueryEngine.LOG.debug("After: {}", result);
+ result = super.modifyOp(result);
+ SecuredQueryEngine.LOG.debug("After Optimize: {}", result);
+ return result;
+ }
+
+ private void setGraphIRI( final DatasetGraph dataset )
+ {
+ final Graph g = dataset.getDefaultGraph();
+ if (g instanceof SecuredGraph)
+ {
+ final SecuredGraph sg = (SecuredGraph) g;
+ graphIRI = sg.getModelNode();
+ this.securityEvaluator = sg.getSecurityEvaluator();
+ }
+ else
+ {
+ graphIRI = new SecNode(Type.URI, "urn:x-arq:DefaultGraph");
+ this.securityEvaluator = new SecurityEvaluator() {
+
+ @Override
+ public boolean evaluate( final Object principal, final Action action,
+ final SecNode graphIRI )
+ {
+ return true;
+ }
+
+ @Override
+ public boolean evaluate( final Object principal, final Action action,
+ final SecNode graphIRI, final SecTriple triple )
+ {
+ return true;
+ }
+
+ @Override
+ public boolean evaluate( final Object principal, final Set<Action> action,
+ final SecNode graphIRI )
+ {
+ return true;
+ }
+
+ @Override
+ public boolean evaluate( final Object principal, final Set<Action> action,
+ final SecNode graphIRI, final SecTriple triple )
+ {
+ return true;
+ }
+
+ @Override
+ public boolean evaluateAny( final Object principal, final Set<Action> action,
+ final SecNode graphIRI )
+ {
+ return true;
+ }
+
+ @Override
+ public boolean evaluateAny( final Object principal, final Set<Action> action,
+ final SecNode graphIRI, final SecTriple triple )
+ {
+ return true;
+ }
+
+ @Override
+ public boolean evaluateUpdate( final Object principal, final SecNode graphIRI,
+ final SecTriple from, final SecTriple to )
+ {
+ return true;
+ }
+
+ @Override
+ public Principal getPrincipal()
+ {
+ return null;
+ }
+ };
+
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/main/java/org/apache/jena/security/query/SecuredQueryEngineConfig.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/main/java/org/apache/jena/security/query/SecuredQueryEngineConfig.java b/jena-permissions/src/main/java/org/apache/jena/security/query/SecuredQueryEngineConfig.java
new file mode 100644
index 0000000..479814b
--- /dev/null
+++ b/jena-permissions/src/main/java/org/apache/jena/security/query/SecuredQueryEngineConfig.java
@@ -0,0 +1,29 @@
+/*
+ * 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.security.query;
+
+import org.apache.jena.sparql.util.Context ;
+
+public class SecuredQueryEngineConfig
+{
+
+ public void initializeContext(Context context)
+ {
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/main/java/org/apache/jena/security/query/SecuredQueryEngineFactory.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/main/java/org/apache/jena/security/query/SecuredQueryEngineFactory.java b/jena-permissions/src/main/java/org/apache/jena/security/query/SecuredQueryEngineFactory.java
new file mode 100644
index 0000000..41988b2
--- /dev/null
+++ b/jena-permissions/src/main/java/org/apache/jena/security/query/SecuredQueryEngineFactory.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jena.security.query;
+
+import org.apache.jena.graph.Graph ;
+import org.apache.jena.query.Query ;
+import org.apache.jena.security.SecurityEvaluator;
+import org.apache.jena.security.graph.SecuredGraph;
+import org.apache.jena.sparql.ARQInternalErrorException ;
+import org.apache.jena.sparql.algebra.Op ;
+import org.apache.jena.sparql.core.DatasetGraph ;
+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.engine.binding.Binding ;
+import org.apache.jena.sparql.util.Context ;
+
+public class SecuredQueryEngineFactory implements QueryEngineFactory
+{
+ private boolean silentService = true;
+ private SecuredQueryEngineConfig cfgResource;
+ private SecurityEvaluator securityEvaluator;
+
+ private static SecuredQueryEngineFactory factory = new SecuredQueryEngineFactory();
+
+ static public SecuredQueryEngineFactory getFactory() {
+ return factory;
+ }
+
+ static public void register() {
+ QueryEngineRegistry.addFactory(factory);
+ }
+
+ static public void unregister() {
+ QueryEngineRegistry.removeFactory(factory);
+ }
+
+ public SecurityEvaluator getSecurityEvaluator() {
+ return securityEvaluator;
+ }
+
+ public void setSecurityEvaluator(SecurityEvaluator securityEvaluator) {
+ this.securityEvaluator = securityEvaluator;
+ }
+
+ public boolean isSilentService() {
+ return silentService;
+ }
+
+ public void setSilentService(boolean silentService) {
+ this.silentService = silentService;
+ }
+
+ public void setSecuredQueryEngineConfig(SecuredQueryEngineConfig cfgResource) {
+ this.cfgResource = cfgResource;
+
+ }
+
+ /**
+ * Only accept a secured dataset
+ */
+ @Override
+ public boolean accept(Query query, DatasetGraph dataset, Context context) {
+ Graph g = dataset.getDefaultGraph();
+ return g instanceof SecuredGraph;
+ }
+
+ @Override
+ public Plan create(Query query, DatasetGraph dataset, Binding initial,
+ Context context) {
+ // set up the context
+ if (cfgResource != null) {
+ cfgResource.initializeContext( context );
+ }
+
+ // Create a query engine instance.
+ SecuredQueryEngine engine = new SecuredQueryEngine(query, dataset,
+ initial, context);
+ return engine.getPlan();
+ }
+
+ @Override
+ public boolean accept(Op op, DatasetGraph dataset, Context context) { // Refuse
+ // to
+ // accept
+ // algebra
+ // expressions
+ // directly.
+ return false;
+ }
+
+ @Override
+ public Plan create(Op op, DatasetGraph dataset, Binding inputBinding,
+ Context context) { // Should not be called because acceept/Op is
+ // false
+ throw new ARQInternalErrorException(this.getClass().getSimpleName()
+ + ": factory called directly with an algebra expression");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/main/java/org/apache/jena/security/query/rewriter/OpRewriter.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/main/java/org/apache/jena/security/query/rewriter/OpRewriter.java b/jena-permissions/src/main/java/org/apache/jena/security/query/rewriter/OpRewriter.java
new file mode 100644
index 0000000..1cd59c1
--- /dev/null
+++ b/jena-permissions/src/main/java/org/apache/jena/security/query/rewriter/OpRewriter.java
@@ -0,0 +1,592 @@
+/*
+ * 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.security.query.rewriter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.jena.graph.Node ;
+import org.apache.jena.graph.Triple ;
+import org.apache.jena.security.AccessDeniedException;
+import org.apache.jena.security.SecurityEvaluator;
+import org.apache.jena.security.SecurityEvaluator.Action;
+import org.apache.jena.security.SecurityEvaluator.SecNode;
+import org.apache.jena.security.SecurityEvaluator.SecTriple;
+import org.apache.jena.security.impl.SecuredItemImpl;
+import org.apache.jena.sparql.algebra.Op ;
+import org.apache.jena.sparql.algebra.OpVisitor ;
+import org.apache.jena.sparql.algebra.op.* ;
+import org.apache.jena.sparql.core.BasicPattern ;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class rewrites the query by examining each operation in the algebra
+ * returned by the Jena SPARQL parser.
+ * <p>
+ * This implementation inserts security evaluator checks where necessary.
+ * </p>
+ */
+public class OpRewriter implements OpVisitor
+{
+ private static Logger LOG = LoggerFactory.getLogger(OpRewriter.class);
+ private OpSequence result;
+ private final SecNode graphIRI;
+ private final SecurityEvaluator securityEvaluator;
+ // if true the restricted data are silently ignored.
+ // default false
+ private final boolean silentFail;
+
+ /**
+ * Constructor
+ * @param securityEvaluator The security evaluator to use
+ * @param graphIRI The IRI for the default graph.
+ */
+ public OpRewriter( final SecurityEvaluator securityEvaluator,
+ final SecNode graphIRI )
+ {
+ this.securityEvaluator = securityEvaluator;
+ this.graphIRI = graphIRI;
+ this.silentFail = false;
+ reset();
+ }
+
+ /**
+ * Constructor
+ * @param securityEvaluator The security evaluator to use
+ * @param graphIRI The IRI for the default graph.
+ */
+ public OpRewriter( final SecurityEvaluator securityEvaluator,
+ final String graphIRI )
+ {
+ this(securityEvaluator, new SecNode(SecNode.Type.URI, graphIRI));
+ }
+
+ /**
+ * Add the operation to the result.
+ * @param op the operation to add.
+ */
+ private void addOp( final Op op )
+ {
+ result.add(op);
+ }
+
+ /**
+ * Get the result of the rewrite.
+ * @return the resulting operator
+ */
+ public Op getResult()
+ {
+ if (result.size() == 0)
+ {
+ return OpNull.create();
+ }
+ if (result.size() == 1)
+ {
+ return result.get(0);
+ }
+ return result;
+
+ }
+
+ /**
+ * Register variables.
+ *
+ * Registers n as a variable if it is one.
+ *
+ * @param n the node to check
+ * @param variables the list of variable nodes
+ * @Return n for chaining.
+ */
+ private Node registerVariables( final Node n, final List<Node> variables )
+ {
+ if (n.isVariable() && !variables.contains(n))
+ {
+ variables.add(n);
+ }
+ return n;
+ }
+
+ /**
+ * Reset the rewriter to the initial state.
+ * @return this rewriter for chaining.
+ */
+ public OpRewriter reset()
+ {
+ result = OpSequence.create();
+ return this;
+ }
+
+ /**
+ * Register all the variables in the triple.
+ * @param t the triple to register.
+ * @param variables The list of variables.
+ * @return t for chaining
+ */
+ private Triple registerBGPTriple( final Triple t,
+ final List<Node> variables )
+ {
+ registerVariables(t.getSubject(), variables);
+ registerVariables(t.getPredicate(), variables);
+ registerVariables(t.getObject(), variables);
+ return t;
+ }
+
+ /**
+ * Rewrites the subop of op1 and returns the result.
+ *
+ * @param op1
+ * @return the rewritten op.
+ */
+ private Op rewriteOp1( final Op1 op1 )
+ {
+ final OpRewriter rewriter = new OpRewriter(securityEvaluator, graphIRI);
+ op1.getSubOp().visit(rewriter);
+ return rewriter.getResult();
+ }
+
+ /**
+ * rewrites the left and right parts of the op2 the left part is
+ * returned the right part is placed in the rewriter
+ *
+ * @param op2
+ * @param rewriter
+ * @return the rewritten op.
+ */
+ private Op rewriteOp2( final Op2 op2, final OpRewriter rewriter )
+ {
+ op2.getLeft().visit(rewriter.reset());
+ final Op left = rewriter.getResult();
+ op2.getRight().visit(rewriter.reset());
+ return left;
+ }
+
+ /**
+ * rewrite source to dest and returns dest
+ *
+ * @param source
+ * @param dest
+ * @return the rewritten op.
+ */
+ private OpN rewriteOpN( final OpN source, final OpN dest )
+ {
+ final OpRewriter rewriter = new OpRewriter(securityEvaluator, graphIRI);
+ for (final Op o : source.getElements())
+ {
+ o.visit(rewriter.reset());
+ dest.add(rewriter.getResult());
+ }
+ return dest;
+ }
+
+ /**
+ * rewrites the subop of assign.
+ */
+ @Override
+ public void visit( final OpAssign opAssign )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpAssign"); }
+ addOp(OpAssign.assign(rewriteOp1(opAssign), opAssign.getVarExprList()));
+ }
+
+ @Override
+ public void visit( final OpBGP opBGP )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpBGP"); }
+ Object principal = securityEvaluator.getPrincipal();
+ if (!securityEvaluator.evaluate(principal, Action.Read, graphIRI))
+ {
+ if (silentFail)
+ {
+ return;
+ }
+ else
+ {
+ throw new AccessDeniedException(graphIRI, Action.Read);
+ }
+ }
+
+ // if the user can read any triple just add the opBGP
+ if (securityEvaluator.evaluate(principal, Action.Read, graphIRI, SecTriple.ANY))
+ {
+ addOp(opBGP);
+ }
+ else
+ {
+ // add security filtering to the resulting triples
+ final List<Triple> newBGP = new ArrayList<Triple>();
+ final List<Node> variables = new ArrayList<Node>();
+ // register all variables
+ for (final Triple t : opBGP.getPattern().getList())
+ {
+ newBGP.add(registerBGPTriple(t, variables));
+ }
+ // create the security function.
+ final SecuredFunction secFunc = new SecuredFunction(graphIRI,
+ securityEvaluator, variables, newBGP);
+ // create the filter
+ Op filter = OpFilter.filter(secFunc, new OpBGP(BasicPattern.wrap(newBGP)));
+ // add the filter
+ addOp(filter);
+ }
+ }
+
+ /**
+ * Rewrite left and right
+ */
+ @Override
+ public void visit( final OpConditional opCondition )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpConditional"); }
+ final OpRewriter rewriter = new OpRewriter(securityEvaluator, graphIRI);
+ addOp(new OpConditional(rewriteOp2(opCondition, rewriter),
+ rewriter.getResult()));
+ }
+
+ /**
+ * returns the dsNames
+ */
+ @Override
+ public void visit( final OpDatasetNames dsNames )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpDatasetName"); }
+ addOp(dsNames);
+ }
+
+ /**
+ * Rewrite left and right
+ */
+ @Override
+ public void visit( final OpDiff opDiff )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpDiff"); }
+ final OpRewriter rewriter = new OpRewriter(securityEvaluator, graphIRI);
+ addOp(OpDiff.create(rewriteOp2(opDiff, rewriter), rewriter.getResult()));
+ }
+
+ /**
+ * Rewrite sequence elements
+ */
+ @Override
+ public void visit( final OpDisjunction opDisjunction )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpDisjunction"); }
+ addOp(rewriteOpN(opDisjunction, OpDisjunction.create()));
+ }
+
+ /**
+ * rewrites the subop of distinct
+ */
+ @Override
+ public void visit( final OpDistinct opDistinct )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpDistinct"); }
+ addOp(new OpDistinct(rewriteOp1(opDistinct)));
+ }
+
+ /**
+ * Returns the Ext
+ */
+ @Override
+ public void visit( final OpExt opExt )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpExt"); }
+ addOp(opExt);
+ }
+
+ /**
+ * rewrites the subop of extend.
+ */
+ @Override
+ public void visit( final OpExtend opExtend )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpExtend"); }
+ addOp(OpExtend.extend(rewriteOp1(opExtend), opExtend.getVarExprList()));
+ }
+
+ /**
+ * rewrites the subop of filter.
+ */
+ @Override
+ public void visit( final OpFilter opFilter )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpFilter"); }
+ addOp(OpFilter.filter(opFilter.getExprs(), rewriteOp1(opFilter)));
+ }
+
+ /**
+ * rewrites the subop of graph.
+ */
+ @Override
+ public void visit( final OpGraph opGraph )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpGraph"); }
+ final OpRewriter rewriter = new OpRewriter(securityEvaluator,
+ SecuredItemImpl.convert(opGraph.getNode()));
+ opGraph.getSubOp().visit(rewriter);
+ addOp(new OpGraph(opGraph.getNode(), rewriter.getResult()));
+ }
+
+ /**
+ * rewrites the subop of group.
+ */
+ @Override
+ public void visit( final OpGroup opGroup )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpGroup"); }
+ addOp(new OpGroup(rewriteOp1(opGroup), opGroup.getGroupVars(),
+ opGroup.getAggregators()));
+ }
+
+ /**
+ * Parses the joins and recursively calls the left and right parts
+ */
+ @Override
+ public void visit( final OpJoin opJoin )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpJoin"); }
+ final OpRewriter rewriter = new OpRewriter(securityEvaluator, graphIRI);
+ addOp(OpJoin.create(rewriteOp2(opJoin, rewriter), rewriter.getResult()));
+ }
+
+ /**
+ * returns the label
+ */
+ @Override
+ public void visit( final OpLabel opLabel )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpLabel"); }
+ addOp(opLabel);
+ }
+
+ /**
+ * Parses the joins and recursively calls the left and right parts
+ */
+ @Override
+ public void visit( final OpLeftJoin opLeftJoin )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpLeftJoin"); }
+ final OpRewriter rewriter = new OpRewriter(securityEvaluator, graphIRI);
+ addOp(OpLeftJoin.create(rewriteOp2(opLeftJoin, rewriter),
+ rewriter.getResult(), opLeftJoin.getExprs()));
+ }
+
+ /**
+ * rewrites the subop of list.
+ */
+ @Override
+ public void visit( final OpList opList )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpList"); }
+ addOp(new OpList(rewriteOp1(opList)));
+ }
+
+ /**
+ * Rewrite left and right
+ */
+ @Override
+ public void visit( final OpMinus opMinus )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpMinus"); }
+ final OpRewriter rewriter = new OpRewriter(securityEvaluator, graphIRI);
+ addOp(OpMinus.create(rewriteOp2(opMinus, rewriter),
+ rewriter.getResult()));
+ }
+
+ /**
+ * returns the null
+ */
+ @Override
+ public void visit( final OpNull opNull )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpNull"); }
+ addOp(opNull);
+ }
+
+ /**
+ * rewrites the subop of order.
+ */
+ @Override
+ public void visit( final OpOrder opOrder )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpOrder"); }
+ addOp(new OpOrder(rewriteOp1(opOrder), opOrder.getConditions()));
+ }
+
+ /**
+ * Returns the path
+ */
+ @Override
+ public void visit( final OpPath opPath )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpPath"); }
+ addOp(opPath);
+ }
+
+ /**
+ * rewrites the subop of proc.
+ */
+ @Override
+ public void visit( final OpProcedure opProc )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpProc"); }
+ if (opProc.getProcId() != null)
+ {
+ addOp(new OpProcedure(opProc.getProcId(), opProc.getArgs(),
+ rewriteOp1(opProc)));
+ }
+ else
+ {
+ addOp(new OpProcedure(opProc.getURI(), opProc.getArgs(),
+ rewriteOp1(opProc)));
+ }
+ }
+
+ /**
+ * rewrites the subop of project.
+ */
+ @Override
+ public void visit( final OpProject opProject )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpProject"); }
+ addOp(new OpProject(rewriteOp1(opProject), opProject.getVars()));
+ }
+
+ /**
+ * rewrites the subop of propFunc.
+ */
+ @Override
+ public void visit( final OpPropFunc opPropFunc )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpPropFunc"); }
+ addOp(new OpPropFunc(opPropFunc.getProperty(),
+ opPropFunc.getSubjectArgs(), opPropFunc.getObjectArgs(),
+ rewriteOp1(opPropFunc)));
+ }
+
+ /**
+ * Returns the quad
+ */
+ @Override
+ public void visit( final OpQuad opQuad )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpQuad"); }
+ addOp(opQuad);
+ }
+
+ /**
+ * Returns the quadpattern
+ */
+ @Override
+ public void visit( final OpQuadPattern quadPattern )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpQuadPattern"); }
+ addOp(quadPattern);
+ }
+
+ /**
+ * rewrites the subop of reduced.
+ */
+ @Override
+ public void visit( final OpReduced opReduced )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpReduced"); }
+ addOp(OpReduced.create(rewriteOp1(opReduced)));
+ }
+
+ /**
+ * Rewrite sequence elements
+ */
+ @Override
+ public void visit( final OpSequence opSequence )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpSequence"); }
+ addOp(rewriteOpN(opSequence, OpSequence.create()));
+ }
+
+ /**
+ * returns the service
+ */
+ @Override
+ public void visit( final OpService opService )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting opService"); }
+ addOp(opService);
+ }
+
+ /**
+ * rewrites the subop of slice
+ *
+ * This also handles the limit case
+ */
+ @Override
+ public void visit( final OpSlice opSlice )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpSlice"); }
+ addOp(opSlice);
+ }
+
+ /**
+ * returns the table
+ */
+ @Override
+ public void visit( final OpTable opTable )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpTable"); }
+ addOp(opTable);
+ }
+
+ /**
+ * rewrites the subop of top.
+ */
+ @Override
+ public void visit( final OpTopN opTop )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpTop"); }
+ addOp(new OpTopN(rewriteOp1(opTop), opTop.getLimit(),
+ opTop.getConditions()));
+ }
+
+ /**
+ * Converts to BGP
+ */
+ @Override
+ public void visit( final OpTriple opTriple )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpTriple"); }
+ visit(opTriple.asBGP());
+ }
+
+ /**
+ * Rewrite left and right
+ */
+ @Override
+ public void visit( final OpUnion opUnion )
+ {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpUnion"); }
+ final OpRewriter rewriter = new OpRewriter(securityEvaluator, graphIRI);
+ addOp(OpUnion.create(rewriteOp2(opUnion, rewriter),
+ rewriter.getResult()));
+ }
+
+ @Override
+ public void visit(OpQuadBlock quadBlock) {
+ if (LOG.isDebugEnabled()) { LOG.debug( "Starting visiting OpQuadBlock"); }
+ addOp(quadBlock);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/main/java/org/apache/jena/security/query/rewriter/SecuredFunction.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/main/java/org/apache/jena/security/query/rewriter/SecuredFunction.java b/jena-permissions/src/main/java/org/apache/jena/security/query/rewriter/SecuredFunction.java
new file mode 100644
index 0000000..b765061
--- /dev/null
+++ b/jena-permissions/src/main/java/org/apache/jena/security/query/rewriter/SecuredFunction.java
@@ -0,0 +1,138 @@
+/*
+ * 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.security.query.rewriter;
+
+import java.util.List;
+
+import org.apache.jena.graph.Node ;
+import org.apache.jena.graph.Triple ;
+import org.apache.jena.security.SecurityEvaluator;
+import org.apache.jena.security.SecurityEvaluator.Action;
+import org.apache.jena.security.SecurityEvaluator.SecNode;
+import org.apache.jena.security.SecurityEvaluator.SecTriple;
+import org.apache.jena.security.impl.SecuredItemImpl;
+import org.apache.jena.sparql.core.Var ;
+import org.apache.jena.sparql.engine.binding.Binding ;
+import org.apache.jena.sparql.expr.* ;
+import org.apache.jena.sparql.function.FunctionEnv ;
+import org.apache.jena.sparql.graph.NodeTransform ;
+
+public class SecuredFunction extends ExprFunctionN
+{
+ private final SecurityEvaluator securityEvaluator;
+ private final List<Node> variables;
+ private final List<Triple> bgp;
+ private final SecNode graphIRI;
+
+ private static ExprList createArgs( List<Node> variables )
+ {
+ ExprList retval = new ExprList();
+ for (Node n : variables )
+ {
+ retval.add( new ExprVar( n ));
+ }
+ return retval;
+ }
+
+ public SecuredFunction( final SecNode graphIRI,
+ final SecurityEvaluator securityEvaluator,
+ final List<Node> variables, final List<Triple> bgp )
+ {
+ super(String.format("<java:%s>", SecuredFunction.class.getName() ), createArgs( variables));
+ //,
+ // new ElementTriplesBlock( BasicPattern.wrap(bgp) ),
+ // new OpBGP( BasicPattern.wrap(bgp) )
+ // );
+ this.securityEvaluator = securityEvaluator;
+ this.variables = variables;
+ this.bgp = bgp;
+ this.graphIRI = graphIRI;
+ }
+
+ private boolean checkAccess( Binding values )
+ {
+ Object principal = securityEvaluator.getPrincipal();
+ for (final Triple t : bgp)
+ {
+ final SecTriple secT = createSecTriple(t, values);
+ if (!securityEvaluator.evaluate(principal, Action.Read, graphIRI, secT))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private SecTriple createSecTriple( final Triple t, final Binding values )
+ {
+ int idx = variables.indexOf(t.getSubject());
+
+ final SecNode s = SecuredItemImpl.convert(idx ==-1 ? t.getSubject()
+ : values.get(Var.alloc( variables.get(idx))));
+
+ idx = variables.indexOf(t.getPredicate());
+ final SecNode p = SecuredItemImpl.convert(idx == -1 ? t
+ .getPredicate()
+ : values.get(Var.alloc( variables.get(idx))));
+ idx = variables.indexOf(t.getObject());
+ final SecNode o = SecuredItemImpl.convert(idx == -1 ? t.getObject()
+ : values.get(Var.alloc( variables.get(idx))));
+ return new SecTriple(s, p, o);
+ }
+
+
+ @Override
+ public Expr copySubstitute( Binding binding )
+ {
+ return this;
+ }
+
+ @Override
+ public Expr applyNodeTransform( NodeTransform transform )
+ {
+ return this;
+ }
+
+ @Override
+ public void visit( ExprVisitor visitor )
+ {
+ visitor.visit( this );
+ }
+
+ @Override
+ public NodeValue eval( List<NodeValue> args )
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Expr copy( ExprList newArgs )
+ {
+ return this;
+ }
+
+ @Override
+ protected NodeValue evalSpecial( Binding binding, FunctionEnv env )
+ {
+ return NodeValue.booleanReturn( checkAccess( binding ));
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/main/java/org/apache/jena/security/utils/ContainerFilter.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/main/java/org/apache/jena/security/utils/ContainerFilter.java b/jena-permissions/src/main/java/org/apache/jena/security/utils/ContainerFilter.java
new file mode 100644
index 0000000..d49792f
--- /dev/null
+++ b/jena-permissions/src/main/java/org/apache/jena/security/utils/ContainerFilter.java
@@ -0,0 +1,48 @@
+/*
+ * 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.security.utils;
+
+import org.apache.jena.rdf.model.Property ;
+import org.apache.jena.rdf.model.Statement ;
+import org.apache.jena.util.iterator.Filter ;
+import org.apache.jena.vocabulary.RDF ;
+
+public class ContainerFilter extends Filter<Statement>
+{
+
+ @Override
+ public boolean accept( final Statement o )
+ {
+ final Property p = o.getPredicate();
+ if (p.getNameSpace().equals(RDF.getURI())
+ && p.getLocalName().startsWith("_"))
+ {
+ try
+ {
+ Integer.parseInt(p.getLocalName().substring(1));
+ return true;
+ }
+ catch (final NumberFormatException e)
+ {
+ // acceptable;
+ }
+ }
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/main/java/org/apache/jena/security/utils/PermStatementFilter.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/main/java/org/apache/jena/security/utils/PermStatementFilter.java b/jena-permissions/src/main/java/org/apache/jena/security/utils/PermStatementFilter.java
new file mode 100644
index 0000000..b2217a1
--- /dev/null
+++ b/jena-permissions/src/main/java/org/apache/jena/security/utils/PermStatementFilter.java
@@ -0,0 +1,164 @@
+/*
+ * 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.security.utils;
+
+import java.util.Collection;
+import java.util.Set;
+
+import org.apache.jena.rdf.model.Statement ;
+import org.apache.jena.security.SecurityEvaluator;
+import org.apache.jena.security.SecurityEvaluator.Action;
+import org.apache.jena.security.SecurityEvaluator.SecNode;
+import org.apache.jena.security.impl.SecuredItem;
+import org.apache.jena.security.impl.SecuredItemImpl;
+import org.apache.jena.util.iterator.Filter ;
+
+/**
+ * A filter for to filter ExtendedIterators on Statements.
+ * This filter removes any triple that the user can not perform all
+ * the actions on.
+ */
+public class PermStatementFilter extends Filter<Statement>
+{
+ private final SecurityEvaluator evaluator;
+ private final SecNode modelNode;
+ private final Set<Action> actions;
+ private final Object principal;
+
+ /**
+ * Creates a filter that requires that the user have all the permissions
+ * listed in the actions parameter
+ *
+ * @param action
+ * The action the user must be permitted to perform.
+ * @param securedItem
+ * The secured item that secures this iterator.
+ */
+ public PermStatementFilter( final Action action,
+ final SecuredItem securedItem )
+ {
+ this.modelNode = securedItem.getModelNode();
+ this.actions = SecurityEvaluator.Util.asSet(new Action[] { action });
+ this.evaluator = securedItem.getSecurityEvaluator();
+ this.principal = evaluator.getPrincipal();
+ }
+
+ /**
+ * Creates a filter that requires that the user have all the permissions
+ * listed in the actions parameter
+ *
+ * @param action
+ * The action the user must be permitted to perform.
+ * @param securedItem
+ * The secured item that secures this iterator.
+ * @param evaluator
+ * The security evaluator to evaluate the security queries.
+ */
+ public PermStatementFilter( final Action action,
+ final SecuredItem securedItem, final SecurityEvaluator evaluator )
+ {
+ this.modelNode = securedItem.getModelNode();
+ this.actions = SecurityEvaluator.Util.asSet(new Action[] { action });
+ this.evaluator = evaluator;
+ this.principal = evaluator.getPrincipal();
+ }
+
+ /**
+ * Creates a filter that requires that the user have all the permissions
+ * listed in the actions parameter
+ *
+ * @param actions
+ * The actions the user must be permitted to perform.
+ * @param securedItem
+ * The secured item that secures this iterator.
+ */
+ public PermStatementFilter( final Action[] actions,
+ final SecuredItem securedItem )
+ {
+ this.modelNode = securedItem.getModelNode();
+ this.actions = SecurityEvaluator.Util.asSet(actions);
+ this.evaluator = securedItem.getSecurityEvaluator();
+ this.principal = evaluator.getPrincipal();
+ }
+
+ /**
+ * Creates a filter that requires that the user have all the permissions
+ * listed in the actions parameter
+ *
+ * @param actions
+ * The actions the user must be permitted to perform.
+ * @param securedItem
+ * The secured item that secures this iterator.
+ * @param evaluator
+ * The security evaluator to evaluate the security queries.
+ */
+ public PermStatementFilter( final Action[] actions,
+ final SecuredItem securedItem, final SecurityEvaluator evaluator )
+ {
+ this.modelNode = securedItem.getModelNode();
+ this.actions = SecurityEvaluator.Util.asSet(actions);
+ this.evaluator = evaluator;
+ this.principal = evaluator.getPrincipal();
+ }
+
+ /**
+ * Creates a filter that requires that the user have all the permissions
+ * listed in the actions parameter
+ *
+ * @param actions
+ * The actions the user must be permitted to perform.
+ * @param securedItem
+ * The secured item that secures this iterator.
+ */
+ public PermStatementFilter( final Collection<Action> actions,
+ final SecuredItem securedItem )
+ {
+ this.modelNode = securedItem.getModelNode();
+ this.actions = SecurityEvaluator.Util.asSet(actions);
+ this.evaluator = securedItem.getSecurityEvaluator();
+ this.principal = evaluator.getPrincipal();
+ }
+
+ /**
+ * Creates a filter that requires that the user have all the permissions
+ * listed in the actions parameter
+ *
+ * @param actions
+ * The actions the user must be permitted to perform.
+ * @param securedItem
+ * The secured item that secures this iterator.
+ * @param evaluator
+ * The security evaluator to evaluate the security queries.
+ */
+ public PermStatementFilter( final Collection<Action> actions,
+ final SecuredItem securedItem, final SecurityEvaluator evaluator )
+ {
+ this.modelNode = securedItem.getModelNode();
+ this.actions = SecurityEvaluator.Util.asSet(actions);
+ this.evaluator = evaluator;
+ this.principal = evaluator.getPrincipal();
+ }
+
+ @Override
+ public boolean accept( final Statement s )
+ {
+ return evaluator.evaluateAny(principal, actions, modelNode,
+ SecuredItemImpl.convert(s.asTriple()));
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/main/java/org/apache/jena/security/utils/PermTripleFilter.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/main/java/org/apache/jena/security/utils/PermTripleFilter.java b/jena-permissions/src/main/java/org/apache/jena/security/utils/PermTripleFilter.java
new file mode 100644
index 0000000..5f6cfa1
--- /dev/null
+++ b/jena-permissions/src/main/java/org/apache/jena/security/utils/PermTripleFilter.java
@@ -0,0 +1,163 @@
+/*
+ * 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.security.utils;
+
+import java.util.Collection;
+import java.util.Set;
+
+import org.apache.jena.graph.Triple ;
+import org.apache.jena.security.SecurityEvaluator;
+import org.apache.jena.security.SecurityEvaluator.Action;
+import org.apache.jena.security.SecurityEvaluator.SecNode;
+import org.apache.jena.security.impl.SecuredItem;
+import org.apache.jena.security.impl.SecuredItemImpl;
+import org.apache.jena.util.iterator.Filter ;
+
+/**
+ * A filter for to filter ExtendedIterators on Triples.
+ * This filter removes any triple that the user can not perform all
+ * the actions on.
+ */
+public class PermTripleFilter extends Filter<Triple>
+{
+ private final SecurityEvaluator evaluator;
+ private final SecNode modelNode;
+ private final Set<Action> actions;
+ private final Object principal;
+
+ /**
+ * Creates a filter that requires that the user have all the permissions
+ * listed in the actions parameter
+ *
+ * @param action
+ * The action the user must be permitted to perform.
+ * @param securedItem
+ * The secured item that secures this iterator.
+ */
+ public PermTripleFilter( final Action action, final SecuredItem securedItem )
+ {
+ this.modelNode = securedItem.getModelNode();
+ this.actions = SecurityEvaluator.Util.asSet(new Action[] { action });
+ this.evaluator = securedItem.getSecurityEvaluator();
+ this.principal = evaluator.getPrincipal();
+ }
+
+ /**
+ * Creates a filter that requires that the user have all the permissions
+ * listed in the actions parameter
+ *
+ * @param action
+ * The action the user must be permitted to perform.
+ * @param securedItem
+ * The secured item that secures this iterator.
+ * @param evaluator
+ * The security evaluator to evaluate the security queries.
+ */
+ public PermTripleFilter( final Action action,
+ final SecuredItem securedItem, final SecurityEvaluator evaluator )
+ {
+ this.modelNode = securedItem.getModelNode();
+ this.actions = SecurityEvaluator.Util.asSet(new Action[] { action });
+ this.evaluator = evaluator;
+ this.principal = evaluator.getPrincipal();
+ }
+
+ /**
+ * Creates a filter that requires that the user have all the permissions
+ * listed in the actions parameter
+ *
+ * @param actions
+ * The actions the user must be permitted to perform.
+ * @param securedItem
+ * The secured item that secures this iterator.
+ */
+ public PermTripleFilter( final Action[] actions,
+ final SecuredItem securedItem )
+ {
+ this.modelNode = securedItem.getModelNode();
+ this.actions = SecurityEvaluator.Util.asSet(actions);
+ this.evaluator = securedItem.getSecurityEvaluator();
+ this.principal = evaluator.getPrincipal();
+ }
+
+ /**
+ * Creates a filter that requires that the user have all the permissions
+ * listed in the actions parameter
+ *
+ * @param actions
+ * The actions the user must be permitted to perform.
+ * @param securedItem
+ * The secured item that secures this iterator.
+ * @param evaluator
+ * The security evaluator to evaluate the security queries.
+ */
+ public PermTripleFilter( final Action[] actions,
+ final SecuredItem securedItem, final SecurityEvaluator evaluator )
+ {
+ this.modelNode = securedItem.getModelNode();
+ this.actions = SecurityEvaluator.Util.asSet(actions);
+ this.evaluator = evaluator;
+ this.principal = evaluator.getPrincipal();
+ }
+
+ /**
+ * Creates a filter that requires that the user have all the permissions
+ * listed in the actions parameter
+ *
+ * @param actions
+ * The actions the user must be permitted to perform.
+ * @param securedItem
+ * The secured item that secures this iterator.
+ */
+ public PermTripleFilter( final Collection<Action> actions,
+ final SecuredItem securedItem )
+ {
+ this.modelNode = securedItem.getModelNode();
+ this.actions = SecurityEvaluator.Util.asSet(actions);
+ this.evaluator = securedItem.getSecurityEvaluator();
+ this.principal = evaluator.getPrincipal();
+ }
+
+ /**
+ * Creates a filter that requires that the user have all the permissions
+ * listed in the actions parameter
+ *
+ * @param actions
+ * The actions the user must be permitted to perform.
+ * @param securedItem
+ * The secured item that secures this iterator.
+ * @param evaluator
+ * The security evaluator to evaluate the security queries.
+ */
+ public PermTripleFilter( final Collection<Action> actions,
+ final SecuredItem securedItem, final SecurityEvaluator evaluator )
+ {
+ this.modelNode = securedItem.getModelNode();
+ this.actions = SecurityEvaluator.Util.asSet(actions);
+ this.evaluator = evaluator;
+ this.principal = evaluator.getPrincipal();
+ }
+
+ @Override
+ public boolean accept( final Triple t )
+ {
+ return evaluator.evaluateAny(principal, actions, modelNode,
+ SecuredItemImpl.convert(t));
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/main/java/org/apache/jena/security/utils/RDFListIterator.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/main/java/org/apache/jena/security/utils/RDFListIterator.java b/jena-permissions/src/main/java/org/apache/jena/security/utils/RDFListIterator.java
new file mode 100644
index 0000000..9c86b95
--- /dev/null
+++ b/jena-permissions/src/main/java/org/apache/jena/security/utils/RDFListIterator.java
@@ -0,0 +1,79 @@
+/*
+ * 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.security.utils;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.apache.jena.rdf.model.RDFList ;
+import org.apache.jena.vocabulary.RDF ;
+
+public class RDFListIterator implements Iterator<RDFList>
+{
+ private RDFList current;
+ private Boolean found;
+
+ public RDFListIterator( final RDFList start )
+ {
+ this.current = start;
+ }
+
+ private boolean endOfList()
+ {
+ return current.equals(RDF.nil);
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ if ((found == null) && !endOfList())
+ {
+ found = !endOfList();
+ }
+ return found == null ? false : found;
+ }
+
+ private void incrementCurrent()
+ {
+ if (!endOfList())
+ {
+ current = current.getRequiredProperty(RDF.rest).getResource()
+ .as(RDFList.class);
+ }
+ }
+
+ @Override
+ public RDFList next()
+ {
+ if (hasNext())
+ {
+ found = null;
+ final RDFList retval = current;
+ incrementCurrent();
+ return retval;
+ }
+ throw new NoSuchElementException();
+ }
+
+ @Override
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/main/java/org/apache/jena/security/utils/RDFListSecFilter.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/main/java/org/apache/jena/security/utils/RDFListSecFilter.java b/jena-permissions/src/main/java/org/apache/jena/security/utils/RDFListSecFilter.java
new file mode 100644
index 0000000..3127c4f
--- /dev/null
+++ b/jena-permissions/src/main/java/org/apache/jena/security/utils/RDFListSecFilter.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.security.utils;
+
+import java.util.Set;
+
+import org.apache.jena.rdf.model.RDFList ;
+import org.apache.jena.rdf.model.Statement ;
+import org.apache.jena.security.SecurityEvaluator;
+import org.apache.jena.security.SecurityEvaluator.Action;
+import org.apache.jena.security.impl.SecuredItem;
+import org.apache.jena.security.impl.SecuredItemImpl;
+import org.apache.jena.util.iterator.Filter ;
+import org.apache.jena.vocabulary.RDF ;
+
+public class RDFListSecFilter<T extends RDFList> extends Filter<T>
+{
+ private final SecuredItem securedItem;
+ private final Set<Action> perms;
+ private final Object principal;
+
+ public RDFListSecFilter( final SecuredItem securedItem, final Action perm )
+ {
+ this(securedItem, SecurityEvaluator.Util.asSet(new Action[] { perm }));
+ }
+
+ public RDFListSecFilter( final SecuredItem securedItem,
+ final Set<Action> perms )
+ {
+ this.securedItem = securedItem;
+ this.perms = perms;
+ this.principal = securedItem.getSecurityEvaluator().getPrincipal();
+ }
+
+ @Override
+ public boolean accept( final RDFList o )
+ {
+ final Statement s = o.getRequiredProperty(RDF.first);
+ return securedItem.getSecurityEvaluator().evaluate(principal, perms,
+ securedItem.getModelNode(),
+ SecuredItemImpl.convert(s.asTriple()));
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/main/overview.html
----------------------------------------------------------------------
diff --git a/jena-permissions/src/main/overview.html b/jena-permissions/src/main/overview.html
new file mode 100644
index 0000000..561c53a
--- /dev/null
+++ b/jena-permissions/src/main/overview.html
@@ -0,0 +1,83 @@
+<html>
+<body>
+ <p>JenaSecurity is a SecurityEvaluator interface and a set of
+ dynamic proxies that apply that interface to Jena Graphs, Models, and
+ associated methods and classes.</p>
+ <p>
+ The SecurityEvaluator class must be implemented. This class provides
+ the interface to the authentication results (e.g.
+ <code>getPrincipal()</code>
+ ) and the authorization system.
+ </p>
+ <p>
+ <ul>
+ <li>Create a SecuredGraph by calling <code>Factory.getInstance(
+ SecurityEvaluator, String, Graph );</code>
+ </li>
+ <li>Create a SecuredModel by calling <code>Factory.getInstance(
+ SecurityEvaluator, String, Model )</code>
+ </li>
+ <li>It is not recommended that you use the Jena <code>ModelFactory.createModelForGraph(
+ SecuredGraph )</code> See Differences Between Graph and Model below for
+ reasons.
+ </li>
+ </ul>
+ </p>
+ <p>
+ <ul>
+ <li>See SecurityEvaluator documentation for description of
+ cascading security checks</li>
+ <li>Secured methods are annotated with: @sec.graph for
+ permissions required on the graph to execute the method.
+ @sec.triple for permissions required on the associated triples
+ (if any) to execute the method.</li>
+ <li>It is possible to implement a SecurityEvaluator that does not
+ enforce security at the triple level. See SecurityEvaluator
+ documentation for details</li>
+ </ul>
+ </p>
+ <h2>
+ Differences Between
+ <code>Graph</code>
+ and
+ <code>Model</code>
+ </h2>
+ <p>
+ The Graph interface does not have the concept of "update". Thus all
+ updates are implemented as a delete and an insert. The Model interface
+ does have the concept of update as evidenced by the
+ <code>replace()</code>
+ method in the
+ <code>RDFList</code>
+ class. This difference means that a
+ <code>Model</code>
+ created by calling
+ <code>ModelFactory.createModelForGraph( SecuredGraph )</code>
+ will yield a model that evaluates
+ <code>Update</code>
+ actions differently from one created with
+ <Code>Factory.getInstance( SecurityEvaluator, modelIRI, model)</Code>
+ .
+ <ul>
+ <li>Models created by the Jena ModelFactory will require that the
+ user have both delete and create permissions on the underlying graph
+ to perform the update. And will delete the existing triple before
+ attempting to create the new one. Since the graph interface does not
+ have visibility to the model's request for update these are, to the
+ graph, separate events. It is possible that the delete may succeed
+ while the create fails.</li>
+ <li>Models created by the JenaSecurity Factory will require that
+ the user have update permissions on the underlying model to perform
+ the update. As long as the user has the update permission on the
+ graph, and the triple where required, the update is performed as a
+ single event.</li>
+ </ul>
+ This is the well documented case of differences between the two secured
+ model creation methods. For this reason it is recommended that the
+ model be created with the
+ <code>Factory.getInsance()</code>
+ method.
+ </p>
+
+</body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/test/java/org/apache/jena/security/EqualityTester.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/test/java/org/apache/jena/security/EqualityTester.java b/jena-permissions/src/test/java/org/apache/jena/security/EqualityTester.java
new file mode 100644
index 0000000..4b1d882
--- /dev/null
+++ b/jena-permissions/src/test/java/org/apache/jena/security/EqualityTester.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.security;
+
+import org.junit.Assert;
+
+public class EqualityTester
+{
+
+ public static void testEquality( final String label, final Object o1,
+ final Object o2 )
+ {
+ Assert.assertEquals(label, o1, o2);
+ Assert.assertEquals(label + " inverse", o2, o1);
+ Assert.assertEquals(label + " hashCode", o1.hashCode(), o2.hashCode());
+ }
+
+ public static void testInequality( final String label, final Object o1,
+ final Object o2 )
+ {
+ if ((o1 == null) && (o2 == null))
+ {
+ Assert.fail(label + ": both arguments are null");
+ }
+ if ((o1 == null) || (o2 == null))
+ {
+ return;
+ }
+ Assert.assertFalse(label, o2.equals(o1));
+ Assert.assertFalse(label, o1.equals(o2));
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/test/java/org/apache/jena/security/MockPrefixMapping.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/test/java/org/apache/jena/security/MockPrefixMapping.java b/jena-permissions/src/test/java/org/apache/jena/security/MockPrefixMapping.java
new file mode 100644
index 0000000..5db2402
--- /dev/null
+++ b/jena-permissions/src/test/java/org/apache/jena/security/MockPrefixMapping.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.security;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.jena.shared.PrefixMapping ;
+
+public class MockPrefixMapping implements PrefixMapping
+{
+
+ @Override
+ public String expandPrefix( final String prefixed )
+ {
+ return prefixed;
+ }
+
+ @Override
+ public Map<String, String> getNsPrefixMap()
+ {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public String getNsPrefixURI( final String prefix )
+ {
+ return null;
+ }
+
+ @Override
+ public String getNsURIPrefix( final String uri )
+ {
+ return null;
+ }
+
+ @Override
+ public PrefixMapping lock()
+ {
+ return this;
+ }
+
+ @Override
+ public String qnameFor( final String uri )
+ {
+ return null;
+ }
+
+ @Override
+ public PrefixMapping removeNsPrefix( final String prefix )
+ {
+ return this;
+ }
+
+ @Override
+ public boolean samePrefixMappingAs( final PrefixMapping other )
+ {
+ return false;
+ }
+
+ @Override
+ public PrefixMapping setNsPrefix( final String prefix, final String uri )
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public PrefixMapping setNsPrefixes( final Map<String, String> map )
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public PrefixMapping setNsPrefixes( final PrefixMapping other )
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String shortForm( final String uri )
+ {
+ return uri;
+ }
+
+ @Override
+ public PrefixMapping withDefaultMappings( final PrefixMapping map )
+ {
+ throw new UnsupportedOperationException();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/b712fb28/jena-permissions/src/test/java/org/apache/jena/security/MockSecurityEvaluator.java
----------------------------------------------------------------------
diff --git a/jena-permissions/src/test/java/org/apache/jena/security/MockSecurityEvaluator.java b/jena-permissions/src/test/java/org/apache/jena/security/MockSecurityEvaluator.java
new file mode 100644
index 0000000..797bdf0
--- /dev/null
+++ b/jena-permissions/src/test/java/org/apache/jena/security/MockSecurityEvaluator.java
@@ -0,0 +1,228 @@
+/*
+ * 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.security;
+
+import java.security.Principal;
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.jena.rdf.model.Resource ;
+import org.apache.jena.security.SecurityEvaluator;
+
+public class MockSecurityEvaluator implements SecurityEvaluator
+{
+
+ private final boolean loggedIn;
+ private final boolean create;
+ private final boolean read;
+ private final boolean update;
+ private final boolean delete;
+ private final boolean forceTripleChecks;
+
+ public static MockSecurityEvaluator getInstance()
+ {
+ return new MockSecurityEvaluator( true, true, true, true, true, true );
+ }
+
+
+ public MockSecurityEvaluator( final boolean loggedIn, final boolean create,
+ final boolean read, final boolean update, final boolean delete,
+ final boolean forceTripleChecks )
+ {
+ this.loggedIn = loggedIn;
+ this.create = create;
+ this.read = read;
+ this.update = update;
+ this.delete = delete;
+ this.forceTripleChecks = forceTripleChecks;
+ }
+
+ public boolean evaluate( final Action action )
+ {
+ switch (action)
+ {
+ case Read:
+ return read;
+ case Create:
+ return create;
+ case Update:
+ return update;
+ case Delete:
+ return delete;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Answers the question. can the logged in user perform action on the
+ * object.
+ *
+ * if there is no logged in user then anonymous access is assumed.
+ *
+ * @param action
+ * @param object
+ * @return boolean
+ */
+ public boolean evaluate( final Action action, final Resource object )
+ {
+
+ return evaluate(action);
+ }
+
+ @Override
+ public boolean evaluate( final Object principal, final Action action, final SecNode uri )
+ {
+ return evaluate(action);
+ }
+
+ @Override
+ public boolean evaluate( final Object principal, final Action action, final SecNode graphIRI,
+ final SecTriple triple )
+ {
+ if (forceTripleChecks)
+ {
+ if (triple.getSubject().equals(SecNode.ANY)
+ || triple.getPredicate().equals(SecNode.ANY)
+ || triple.getObject().equals(SecNode.ANY))
+ {
+ return false;
+ }
+ }
+ return evaluate(action);
+ }
+
+ public boolean evaluate( final Action[] actions )
+ {
+ for (final Action a : actions)
+ {
+ if (!evaluate(a))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean evaluate( final Set<Action> action )
+ {
+ boolean result = true;
+ for (final Action a : action)
+ {
+ result &= evaluate(a);
+ }
+ return result;
+ }
+
+ public boolean evaluate( final Set<Action> action, final Resource object )
+ {
+ boolean result = true;
+ for (final Action a : action)
+ {
+ result &= evaluate(a);
+ }
+ return result;
+ }
+
+ @Override
+ public boolean evaluate( final Object principal, final Set<Action> action, final SecNode uri )
+ {
+ return evaluate(action);
+ }
+
+ @Override
+ public boolean evaluate( final Object principal, final Set<Action> action, final SecNode graphIRI,
+ final SecTriple triple )
+ {
+ for (final Action a : action)
+ {
+ if (!evaluate(a))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean evaluateAny( final Object principal, final Set<Action> action, final SecNode graphIRI )
+ {
+ for (final Action a : action)
+ {
+ if (evaluate(a))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean evaluateAny( final Object principal, final Set<Action> action,
+ final SecNode graphIRI, final SecTriple triple )
+ {
+ return evaluateAny( principal, action, graphIRI);
+ }
+
+ @Override
+ public boolean evaluateUpdate( final Object principal, final SecNode graphIRI,
+ final SecTriple from, final SecTriple to )
+ {
+ return evaluate(Action.Update);
+ }
+
+ public Set<Action> getPermissions( final Resource resourceID )
+ {
+ return Collections.emptySet();
+ }
+
+ public Set<Action> getPermissions( final SecNode uri )
+ {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Principal getPrincipal()
+ {
+ if (loggedIn)
+ {
+ return new Principal() {
+
+ @Override
+ public String getName()
+ {
+ return "TestingPrincipal";
+ }
+ };
+ }
+ return null;
+ }
+
+ public boolean isLoggedIn()
+ {
+ return loggedIn;
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("C:%s R:%s U:%s D:%s force:%s", create, read,
+ update, delete, forceTripleChecks);
+ }
+
+}