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: &#64;sec.graph for
+			permissions required on the graph to execute the method.
+			&#64;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);
+	}
+
+}