/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.jena.permissions.model.impl; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.apache.jena.graph.Node; import org.apache.jena.graph.Triple; import org.apache.jena.permissions.SecurityEvaluator.Action; import org.apache.jena.permissions.impl.ItemHolder; import org.apache.jena.permissions.impl.SecuredItemInvoker; import org.apache.jena.permissions.model.SecuredContainer; import org.apache.jena.permissions.model.SecuredModel; import org.apache.jena.permissions.utils.ContainerFilter; import org.apache.jena.permissions.utils.PermStatementFilter; import org.apache.jena.rdf.model.*; import org.apache.jena.shared.AddDeniedException; import org.apache.jena.shared.AuthenticationRequiredException; import org.apache.jena.shared.DeleteDeniedException; import org.apache.jena.shared.ReadDeniedException; import org.apache.jena.shared.UpdateDeniedException; import org.apache.jena.util.iterator.ExtendedIterator; import org.apache.jena.util.iterator.WrappedIterator; import org.apache.jena.vocabulary.RDF; /** * Implementation of SecuredContainer to be used by a SecuredItemInvoker proxy. */ public class SecuredContainerImpl extends SecuredResourceImpl implements SecuredContainer { /** * Constructor * * @param securedModel * the Secured Model to use. * @param container * The container to secure. * @return The SecuredResource */ public static SecuredContainer getInstance(final SecuredModel securedModel, final Container container) { if (securedModel == null) { throw new IllegalArgumentException( "Secured securedModel may not be null"); } if (container == null) { throw new IllegalArgumentException("Container may not be null"); } // check that resource has a securedModel. Container goodContainer = container; if (goodContainer.getModel() == null) { container.asNode(); goodContainer = securedModel.createBag(); } final ItemHolder<Container, SecuredContainer> holder = new ItemHolder<Container, SecuredContainer>( goodContainer); final SecuredContainerImpl checker = new SecuredContainerImpl( securedModel, holder); // if we are going to create a duplicate proxy, just return this // one. if (goodContainer instanceof SecuredContainer) { if (checker.isEquivalent((SecuredContainer) goodContainer)) { return (SecuredContainer) goodContainer; } } return holder.setSecuredItem(new SecuredItemInvoker(container .getClass(), checker)); } // the item holder that contains this SecuredContainer. private final ItemHolder<? extends Container, ? extends SecuredContainer> holder; /** * Constructor * * @param securedModel * the Secured Model to use. * @param holder * The item holder that will contain this SecuredContainer */ protected SecuredContainerImpl( final SecuredModel securedModel, final ItemHolder<? extends Container, ? extends SecuredContainer> holder) { super(securedModel, holder); this.holder = holder; // listener=new ChangeListener(); // holder.getBaseItem().getModel().register(listener); } protected RDFNode asObject(Object o) { return o instanceof RDFNode ? (RDFNode) o : ResourceFactory .createTypedLiteral(o); } protected RDFNode asLiteral(String o, String l) { return holder.getBaseItem().getModel().createLiteral(o, l); } @Override public SecuredContainer add(final boolean o) throws AddDeniedException, UpdateDeniedException, AuthenticationRequiredException { return add(asObject(o)); } @Override public SecuredContainer add(final char o) throws AddDeniedException, UpdateDeniedException, AuthenticationRequiredException { return add(asObject(o)); } @Override public SecuredContainer add(final double o) throws AddDeniedException, UpdateDeniedException, AuthenticationRequiredException { return add(asObject(o)); } @Override public SecuredContainer add(final float o) throws AddDeniedException, UpdateDeniedException, AuthenticationRequiredException { return add(asObject(o)); } @Override public SecuredContainer add(final long o) throws AddDeniedException, UpdateDeniedException, AuthenticationRequiredException { return add(asObject(o)); } @Override public SecuredContainer add(final Object o) throws AddDeniedException, UpdateDeniedException, AuthenticationRequiredException { return add(asObject(o)); } @Override public SecuredContainer add(final RDFNode o) throws AddDeniedException, UpdateDeniedException, AuthenticationRequiredException { checkUpdate(); final int pos = holder.getBaseItem().size(); checkAdd(pos, o.asNode()); holder.getBaseItem().add(o); return holder.getSecuredItem(); } @Override public SecuredContainer add(final String o) throws AddDeniedException, UpdateDeniedException, AuthenticationRequiredException { return add(asLiteral(o, "")); } @Override public SecuredContainer add(final String o, final String l) throws AddDeniedException, UpdateDeniedException, AuthenticationRequiredException { return add(asLiteral(o, l)); } protected void checkAdd(final int pos, final Literal literal) throws AddDeniedException, UpdateDeniedException, AuthenticationRequiredException { checkAdd(pos, literal.asNode()); } protected void checkAdd(final int pos, final Node node) throws AddDeniedException, UpdateDeniedException, AuthenticationRequiredException { checkCreate(new Triple(holder.getBaseItem().asNode(), RDF.li(pos) .asNode(), node)); } @Override public boolean contains(final boolean o) throws ReadDeniedException, AuthenticationRequiredException { return contains(asObject(o)); } @Override public boolean contains(final char o) throws ReadDeniedException, AuthenticationRequiredException { return contains(asObject(o)); } @Override public boolean contains(final double o) throws ReadDeniedException, AuthenticationRequiredException { return contains(asObject(o)); } @Override public boolean contains(final float o) throws ReadDeniedException, AuthenticationRequiredException { return contains(asObject(o)); } @Override public boolean contains(final long o) throws ReadDeniedException, AuthenticationRequiredException { return contains(asObject(o)); } @Override public boolean contains(final Object o) throws ReadDeniedException, AuthenticationRequiredException { return contains(asObject(o)); } @Override public boolean contains(final RDFNode o) throws ReadDeniedException, AuthenticationRequiredException { // iterator check reads final SecuredNodeIterator<RDFNode> iter = iterator(); while (iter.hasNext()) { if (iter.next().asNode().equals(o.asNode())) { return true; } } return false; } @Override public boolean contains(final String o) throws ReadDeniedException, AuthenticationRequiredException { return contains(asLiteral(o, "")); } @Override public boolean contains(final String o, final String l) throws ReadDeniedException, AuthenticationRequiredException { return contains(asLiteral(o, l)); } protected int getAddIndex() { int pos = -1; final ExtendedIterator<Statement> iter = holder.getBaseItem() .listProperties(); try { while (iter.hasNext()) { pos = Math.max(pos, getIndex(iter.next().getPredicate())); } } finally { iter.close(); } return pos + 1; } protected static int getIndex(final Property p) { if (p.getNameSpace().equals(RDF.getURI()) && p.getLocalName().startsWith("_")) { try { return Integer.parseInt(p.getLocalName().substring(1)); } catch (final NumberFormatException e) { // acceptable; } } return -1; } protected ExtendedIterator<Statement> getStatementIterator(final Action perm) { return holder.getBaseItem().listProperties() .filterKeep(new ContainerFilter()) .filterKeep(new PermStatementFilter(perm, this)); } protected ExtendedIterator<Statement> getStatementIterator( final Set<Action> perm) { return holder.getBaseItem().listProperties() .filterKeep(new ContainerFilter()) .filterKeep(new PermStatementFilter(perm, this)); } @Override public boolean isAlt() { return holder.getBaseItem().isAlt(); } @Override public boolean isBag() { return holder.getBaseItem().isBag(); } @Override public boolean isSeq() { return holder.getBaseItem().isSeq(); } @Override public SecuredNodeIterator<RDFNode> iterator() { // listProperties calls checkRead(); SecuredStatementIterator iter = listProperties(); try { SortedSet<Statement> result = new TreeSet<Statement>( new ContainerComparator()); while (iter.hasNext()) { Statement stmt = iter.next(); if (stmt.getPredicate().getOrdinal() > 0) { result.add(stmt); } } return new SecuredNodeIterator<RDFNode>(getModel(), new StatementRemovingIterator(result.iterator()) .mapWith(s -> s.getObject())); } finally { iter.close(); } } @Override public SecuredNodeIterator<RDFNode> iterator(final Set<Action> perms) { checkRead(); final Set<Action> permsCopy = new HashSet<Action>(perms); permsCopy.add(Action.Read); final ExtendedIterator<RDFNode> ni = getStatementIterator(perms) .mapWith(o -> o.getObject()); return new SecuredNodeIterator<RDFNode>(getModel(), ni); } @Override public SecuredContainer remove(final Statement s) throws UpdateDeniedException, DeleteDeniedException, AuthenticationRequiredException { checkUpdate(); checkDelete(s.asTriple()); holder.getBaseItem().remove(s); return holder.getSecuredItem(); } @Override public int size() throws ReadDeniedException, AuthenticationRequiredException { checkRead(); return holder.getBaseItem().size(); } static class ContainerComparator implements Comparator<Statement> { @Override public int compare(Statement arg0, Statement arg1) { return Integer.valueOf(arg0.getPredicate().getOrdinal()).compareTo( arg1.getPredicate().getOrdinal()); } } static class StatementRemovingIterator extends WrappedIterator<Statement> { private Statement stmt; public StatementRemovingIterator(Iterator<? extends Statement> base) { super(base); } @Override public Statement next() { stmt = super.next(); return stmt; } @Override public void remove() { stmt.remove(); super.remove(); } } }