You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2010/10/15 10:28:54 UTC
svn commit: r1022857 - in
/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization:
./ acl/ principalbased/
Author: angela
Date: Fri Oct 15 08:28:53 2010
New Revision: 1022857
URL: http://svn.apache.org/viewvc?rev=1022857&view=rev
Log:
minor improvement
Added:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CompiledPermissionsImpl.java (with props)
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplate.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLProvider.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CachingEntryCollector.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/EntryCollector.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/EntriesCache.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplate.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplate.java?rev=1022857&r1=1022856&r2=1022857&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplate.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplate.java Fri Oct 15 08:28:53 2010
@@ -78,7 +78,7 @@ public abstract class AbstractACLTemplat
* @return the list of entries.
* @see #orderBefore(AccessControlEntry, AccessControlEntry)
*/
- protected abstract List<? extends AccessControlEntry> getEntries();
+ protected abstract List<AccessControlEntry> getEntries();
//--------------------------------------< JackrabbitAccessControlPolicy >---
/**
@@ -120,7 +120,7 @@ public abstract class AbstractACLTemplat
return;
}
- List entries = getEntries();
+ List<AccessControlEntry> entries = getEntries();
int index = (destEntry == null) ? entries.size()-1 : entries.indexOf(destEntry);
if (index < 0) {
throw new AccessControlException("destEntry not contained in this AccessControlList");
@@ -151,4 +151,4 @@ public abstract class AbstractACLTemplat
throws AccessControlException, RepositoryException {
return addEntry(principal, privileges, true, Collections.<String, Value>emptyMap());
}
-}
\ No newline at end of file
+}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLProvider.java?rev=1022857&r1=1022856&r2=1022857&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLProvider.java Fri Oct 15 08:28:53 2010
@@ -16,26 +16,17 @@
*/
package org.apache.jackrabbit.core.security.authorization.acl;
-import org.apache.commons.collections.map.LRUMap;
import org.apache.jackrabbit.api.security.principal.PrincipalManager;
-import org.apache.jackrabbit.core.ItemImpl;
-import org.apache.jackrabbit.core.ItemManager;
import org.apache.jackrabbit.core.NodeImpl;
import org.apache.jackrabbit.core.SessionImpl;
-import org.apache.jackrabbit.core.id.ItemId;
import org.apache.jackrabbit.core.id.NodeId;
-import org.apache.jackrabbit.core.id.PropertyId;
import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
import org.apache.jackrabbit.core.security.SecurityConstants;
-import org.apache.jackrabbit.core.security.authorization.AccessControlListener;
import org.apache.jackrabbit.core.security.authorization.AbstractAccessControlProvider;
-import org.apache.jackrabbit.core.security.authorization.AbstractCompiledPermissions;
import org.apache.jackrabbit.core.security.authorization.AccessControlConstants;
import org.apache.jackrabbit.core.security.authorization.AccessControlEditor;
-import org.apache.jackrabbit.core.security.authorization.AccessControlModifications;
import org.apache.jackrabbit.core.security.authorization.CompiledPermissions;
import org.apache.jackrabbit.core.security.authorization.Permission;
-import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
import org.apache.jackrabbit.core.security.authorization.UnmodifiableAccessControlList;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.Path;
@@ -52,7 +43,6 @@ import javax.jcr.Session;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
-import javax.jcr.security.AccessControlEntry;
import javax.jcr.security.AccessControlList;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.AccessControlPolicy;
@@ -60,7 +50,6 @@ import javax.jcr.security.Privilege;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -95,11 +84,6 @@ public class ACLProvider extends Abstrac
private static final Logger log = LoggerFactory.getLogger(ACLProvider.class);
/**
- * the system acl editor.
- */
- private ACLEditor systemEditor;
-
- /**
* The node id of the root node
*/
private NodeId rootNodeId;
@@ -123,7 +107,7 @@ public class ACLProvider extends Abstrac
// minimal protection on the root node.
NodeImpl root = (NodeImpl) session.getRootNode();
rootNodeId = root.getNodeId();
- systemEditor = new ACLEditor(systemSession, this);
+ ACLEditor systemEditor = new ACLEditor(systemSession, this);
// TODO: replace by configurable default policy (see JCR-2331)
boolean initializedWithDefaults = !configuration.containsKey(PARAM_OMIT_DEFAULT_PERMISSIONS);
@@ -231,7 +215,7 @@ public class ACLProvider extends Abstrac
} else if (isReadOnly(principals)) {
return getReadOnlyPermissions();
} else {
- return new AclPermissions(principals);
+ return new CompiledPermissionsImpl(principals, session, entryCollector, this, true);
}
}
@@ -243,8 +227,12 @@ public class ACLProvider extends Abstrac
if (isAdminOrSystem(principals)) {
return true;
} else {
- CompiledPermissions cp = new AclPermissions(principals, false);
- return cp.canRead(null, rootNodeId);
+ CompiledPermissions cp = new CompiledPermissionsImpl(principals, session, entryCollector, this, false);
+ try {
+ return cp.canRead(null, rootNodeId);
+ } finally {
+ cp.close();
+ }
}
}
@@ -257,55 +245,13 @@ public class ACLProvider extends Abstrac
* @param systemSession The system session to create the entry collector for.
* @return A new instance of <code>CachingEntryCollector</code>.
* @throws RepositoryException If an error occurs.
- * @see #retrieveResultEntries(NodeImpl, EntryFilter)
*/
protected EntryCollector createEntryCollector(SessionImpl systemSession) throws RepositoryException {
- return new CachingEntryCollector(systemSession, systemEditor, rootNodeId);
- }
-
- /**
- * Retrieve an iterator of <code>AccessControlEntry</code> to be evaluated
- * upon {@link AbstractCompiledPermissions#buildResult}.
- *
- * @param node Target node.
- * @param filter The entry filter used to collect the access control entries.
- * @return an iterator of <code>AccessControlEntry</code>.
- * @throws RepositoryException If an error occurs.
- */
- protected Iterator<AccessControlEntry> retrieveResultEntries(NodeImpl node, EntryFilter filter) throws RepositoryException {
- Iterator<AccessControlEntry> itr = entryCollector.collectEntries(node, filter).iterator();
- return itr;
+ return new CachingEntryCollector(systemSession, rootNodeId);
}
//------------------------------------------------------------< private >---
/**
- * Returns the given <code>targetNode</code> unless the node itself stores
- * access control information in which case it's nearest non-ac-parent is
- * searched and returned.
- *
- * @param targetNode The node for which AC information needs to be retrieved.
- * @param isAcItem true if the specified target node defines access control
- * content; false otherwise.
- * @return the given <code>targetNode</code> or the nearest non-ac-parent
- * in case the <code>targetNode</code> itself defines access control content.
- * @throws RepositoryException if an error occurs
- */
- private NodeImpl getNode(NodeImpl targetNode, boolean isAcItem) throws RepositoryException {
- NodeImpl node;
- if (isAcItem) {
- Name ntName = ((NodeTypeImpl) targetNode.getPrimaryNodeType()).getQName();
- if (ntName.equals(NT_REP_ACL)) {
- node = (NodeImpl) targetNode.getParent();
- } else {
- node = (NodeImpl) targetNode.getParent().getParent();
- }
- } else {
- node = targetNode;
- }
- return node;
- }
-
- /**
* Recursively collects all ACLs that are effective on the specified node.
*
* @param node the Node to collect the ACLs for, which must NOT be part of the
@@ -397,189 +343,30 @@ public class ACLProvider extends Abstrac
return node.hasNode(N_POLICY) && node.isNodeType(NT_REP_ACCESS_CONTROLLABLE);
}
- //------------------------------------------------< CompiledPermissions >---
/**
+ * Returns the given <code>targetNode</code> unless the node itself stores
+ * access control information in which case it's nearest non-ac-parent is
+ * searched and returned.
*
+ * @param targetNode The node for which AC information needs to be retrieved.
+ * @param isAcItem true if the specified target node defines access control
+ * content; false otherwise.
+ * @return the given <code>targetNode</code> or the nearest non-ac-parent
+ * in case the <code>targetNode</code> itself defines access control content.
+ * @throws RepositoryException if an error occurs
*/
- private class AclPermissions extends AbstractCompiledPermissions implements AccessControlListener {
-
- private final List<String> principalNames;
- // TODO find optimal cache size and ev. make it configurable (see also JCR-2573).
- private final Map<ItemId, Boolean> readCache = new LRUMap(5000);
- private final Object monitor = new Object();
-
- private AclPermissions(Set<Principal> principals) throws RepositoryException {
- this(principals, true);
- }
-
- private AclPermissions(Set<Principal> principals, boolean listenToEvents) throws RepositoryException {
- principalNames = new ArrayList<String>(principals.size());
- for (Principal princ : principals) {
- principalNames.add(princ.getName());
- }
-
- if (listenToEvents) {
- /*
- Make sure this AclPermission recalculates the permissions if
- any ACL concerning it is modified.
- */
- entryCollector.addListener(this);
- }
- }
-
- private Result buildResult(NodeImpl node, boolean isExistingNode, boolean isAcItem, EntryFilterImpl filter) throws RepositoryException {
- // retrieve all ACEs at path or at the direct ancestor of path that
- // apply for the principal names.
- Iterator<AccessControlEntry> entries = retrieveResultEntries(getNode(node, isAcItem), filter);
-
- /*
- Calculate privileges and permissions:
- Since the ACEs only define privileges on a node and do not allow
- to add additional restrictions, the permissions can be determined
- without taking the given target name or target item into account.
- */
- int allows = Permission.NONE;
- int denies = Permission.NONE;
-
- int allowPrivileges = PrivilegeRegistry.NO_PRIVILEGE;
- int denyPrivileges = PrivilegeRegistry.NO_PRIVILEGE;
- int parentAllows = PrivilegeRegistry.NO_PRIVILEGE;
- int parentDenies = PrivilegeRegistry.NO_PRIVILEGE;
-
- String parentPath = Text.getRelativeParent(filter.getPath(), 1);
-
- while (entries.hasNext()) {
- ACLTemplate.Entry ace = (ACLTemplate.Entry) entries.next();
- /*
- Determine if the ACE also takes effect on the parent:
- Some permissions (e.g. add-node or removal) must be determined
- from privileges defined for the parent.
- A 'local' entry defined on the target node never effects the
- parent. For inherited ACEs determine if the ACE matches the
- parent path.
- */
- int entryBits = ace.getPrivilegeBits();
- boolean isLocal = isExistingNode && ace.isLocal(node.getNodeId());
- boolean matchesParent = (!isLocal && ace.matches(parentPath));
- if (matchesParent) {
- if (ace.isAllow()) {
- parentAllows |= Permission.diff(entryBits, parentDenies);
- } else {
- parentDenies |= Permission.diff(entryBits, parentAllows);
- }
- }
- if (ace.isAllow()) {
- allowPrivileges |= Permission.diff(entryBits, denyPrivileges);
- int permissions = PrivilegeRegistry.calculatePermissions(allowPrivileges, parentAllows, true, isAcItem);
- allows |= Permission.diff(permissions, denies);
- } else {
- denyPrivileges |= Permission.diff(entryBits, allowPrivileges);
- int permissions = PrivilegeRegistry.calculatePermissions(denyPrivileges, parentDenies, false, isAcItem);
- denies |= Permission.diff(permissions, allows);
- }
- }
- return new Result(allows, denies, allowPrivileges, denyPrivileges);
- }
-
- //------------------------------------< AbstractCompiledPermissions >---
- /**
- * @see AbstractCompiledPermissions#buildResult(Path)
- */
- @Override
- protected Result buildResult(Path absPath) throws RepositoryException {
- boolean existingNode = false;
- NodeImpl node;
-
- ItemManager itemMgr = session.getItemManager();
- try {
- ItemImpl item = itemMgr.getItem(absPath);
- if (item.isNode()) {
- node = (NodeImpl) item;
- existingNode = true;
- } else {
- node = (NodeImpl) item.getParent();
- }
- } catch (RepositoryException e) {
- // path points to a non-persisted item.
- // -> find the nearest persisted node starting from the root.
- Path.Element[] elems = absPath.getElements();
- NodeImpl parent = (NodeImpl) session.getRootNode();
- for (int i = 1; i < elems.length - 1; i++) {
- Name name = elems[i].getName();
- int index = elems[i].getIndex();
- if (!parent.hasNode(name, index)) {
- // last persisted node reached
- break;
- }
- parent = parent.getNode(name, index);
-
- }
- node = parent;
- }
-
- if (node == null) {
- // should never get here
- throw new ItemNotFoundException("Item out of hierarchy.");
- }
-
- boolean isAcItem = isAcItem(absPath);
- return buildResult(node, existingNode, isAcItem, new EntryFilterImpl(principalNames, absPath, session));
- }
-
- /**
- * @see AbstractCompiledPermissions#clearCache()
- */
- @Override
- protected void clearCache() {
- synchronized (monitor) {
- readCache.clear();
- }
- super.clearCache();
- }
-
- //--------------------------------------------< CompiledPermissions >---
- /**
- * @see CompiledPermissions#close()
- */
- @Override
- public void close() {
- entryCollector.removeListener(this);
- super.close();
- }
-
- /**
- * @see CompiledPermissions#canRead(Path, ItemId)
- */
- public boolean canRead(Path path, ItemId itemId) throws RepositoryException {
- ItemId id = (itemId == null) ? session.getHierarchyManager().resolvePath(path) : itemId;
- // no extra check for existence as method may only be called for existing items.
- boolean isExistingNode = id.denotesNode();
- boolean canRead;
- synchronized (monitor) {
- if (readCache.containsKey(id)) {
- canRead = readCache.get(id);
- } else {
- ItemManager itemMgr = session.getItemManager();
- NodeId nodeId = (isExistingNode) ? (NodeId) id : ((PropertyId) id).getParentId();
- NodeImpl node = (NodeImpl) itemMgr.getItem(nodeId);
- // TODO: check again if retrieving the path can be avoided
- Path absPath = (path == null) ? session.getHierarchyManager().getPath(id) : path;
- Result result = buildResult(node, isExistingNode, isAcItem(node), new EntryFilterImpl(principalNames, absPath, session));
-
- canRead = result.grants(Permission.READ);
- readCache.put(id, canRead);
- }
+ static NodeImpl getNode(NodeImpl targetNode, boolean isAcItem) throws RepositoryException {
+ NodeImpl node;
+ if (isAcItem) {
+ Name ntName = ((NodeTypeImpl) targetNode.getPrimaryNodeType()).getQName();
+ if (ntName.equals(NT_REP_ACL)) {
+ node = (NodeImpl) targetNode.getParent();
+ } else {
+ node = (NodeImpl) targetNode.getParent().getParent();
}
- return canRead;
- }
-
- //----------------------------------------< ACLModificationListener >---
- /**
- * @see org.apache.jackrabbit.core.security.authorization.AccessControlListener#acModified(AccessControlModifications)
- */
- public void acModified(AccessControlModifications modifications) {
- // ignore the details of the modifications and clear all caches.
- clearCache();
+ } else {
+ node = targetNode;
}
+ return node;
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java?rev=1022857&r1=1022856&r2=1022857&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java Fri Oct 15 08:28:53 2010
@@ -67,7 +67,7 @@ class ACLTemplate extends AbstractACLTem
/**
* List containing the entries of this ACL Template.
*/
- private final List<Entry> entries = new ArrayList<Entry>();
+ private final List<AccessControlEntry> entries = new ArrayList<AccessControlEntry>();
/**
* The principal manager used for validation checks
@@ -197,9 +197,9 @@ class ACLTemplate extends AbstractACLTem
private List<Entry> internalGetEntries(Principal principal) {
String principalName = principal.getName();
List<Entry> entriesPerPrincipal = new ArrayList<Entry>(2);
- for (Entry entry : entries) {
+ for (AccessControlEntry entry : entries) {
if (principalName.equals(entry.getPrincipal().getName())) {
- entriesPerPrincipal.add(entry);
+ entriesPerPrincipal.add((Entry) entry);
}
}
return entriesPerPrincipal;
@@ -311,7 +311,7 @@ class ACLTemplate extends AbstractACLTem
* @see org.apache.jackrabbit.core.security.authorization.AbstractACLTemplate#getEntries()
*/
@Override
- protected List<? extends AccessControlEntry> getEntries() {
+ protected List<AccessControlEntry> getEntries() {
return entries;
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CachingEntryCollector.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CachingEntryCollector.java?rev=1022857&r1=1022856&r2=1022857&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CachingEntryCollector.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CachingEntryCollector.java Fri Oct 15 08:28:53 2010
@@ -52,13 +52,12 @@ class CachingEntryCollector extends Entr
/**
*
* @param systemSession
- * @param systemEditor
* @param rootID
* @throws RepositoryException
*/
@SuppressWarnings("unchecked")
- CachingEntryCollector(SessionImpl systemSession, ACLEditor systemEditor, NodeId rootID) throws RepositoryException {
- super(systemSession, systemEditor, rootID);
+ CachingEntryCollector(SessionImpl systemSession, NodeId rootID) throws RepositoryException {
+ super(systemSession, rootID);
cache = new LRUMap(1000);
}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CompiledPermissionsImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CompiledPermissionsImpl.java?rev=1022857&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CompiledPermissionsImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CompiledPermissionsImpl.java Fri Oct 15 08:28:53 2010
@@ -0,0 +1,237 @@
+/*
+ * 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.jackrabbit.core.security.authorization.acl;
+
+import org.apache.commons.collections.map.LRUMap;
+import org.apache.jackrabbit.core.ItemImpl;
+import org.apache.jackrabbit.core.ItemManager;
+import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.id.ItemId;
+import org.apache.jackrabbit.core.id.NodeId;
+import org.apache.jackrabbit.core.id.PropertyId;
+import org.apache.jackrabbit.core.security.authorization.AbstractCompiledPermissions;
+import org.apache.jackrabbit.core.security.authorization.AccessControlListener;
+import org.apache.jackrabbit.core.security.authorization.AccessControlModifications;
+import org.apache.jackrabbit.core.security.authorization.AccessControlUtils;
+import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.util.Text;
+
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.security.AccessControlEntry;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <code>CompiledPermissionsImpl</code>...
+ */
+class CompiledPermissionsImpl extends AbstractCompiledPermissions implements AccessControlListener {
+
+ private final List<String> principalNames;
+ private final SessionImpl session;
+ private final EntryCollector entryCollector;
+ private final AccessControlUtils util;
+
+ private final Map<ItemId, Boolean> readCache = new LRUMap(5000);
+ private final Object monitor = new Object();
+
+ CompiledPermissionsImpl(Set<Principal> principals, SessionImpl session,
+ EntryCollector entryCollector, AccessControlUtils util,
+ boolean listenToEvents) throws RepositoryException {
+ this.session = session;
+ this.entryCollector = entryCollector;
+ this.util = util;
+
+ principalNames = new ArrayList<String>(principals.size());
+ for (Principal princ : principals) {
+ principalNames.add(princ.getName());
+ }
+
+ if (listenToEvents) {
+ /*
+ Make sure this AclPermission recalculates the permissions if
+ any ACL concerning it is modified.
+ */
+ entryCollector.addListener(this);
+ }
+ }
+
+ private Result buildResult(NodeImpl node, boolean isExistingNode, boolean isAcItem, EntryFilterImpl filter) throws RepositoryException {
+ // retrieve all ACEs at path or at the direct ancestor of path that
+ // apply for the principal names.
+ NodeImpl n = ACLProvider.getNode(node, isAcItem);
+ Iterator<AccessControlEntry> entries = entryCollector.collectEntries(n, filter).iterator();
+
+ /*
+ Calculate privileges and permissions:
+ Since the ACEs only define privileges on a node and do not allow
+ to add additional restrictions, the permissions can be determined
+ without taking the given target name or target item into account.
+ */
+ int allows = Permission.NONE;
+ int denies = Permission.NONE;
+
+ int allowPrivileges = PrivilegeRegistry.NO_PRIVILEGE;
+ int denyPrivileges = PrivilegeRegistry.NO_PRIVILEGE;
+ int parentAllows = PrivilegeRegistry.NO_PRIVILEGE;
+ int parentDenies = PrivilegeRegistry.NO_PRIVILEGE;
+
+ String parentPath = Text.getRelativeParent(filter.getPath(), 1);
+
+ while (entries.hasNext()) {
+ ACLTemplate.Entry ace = (ACLTemplate.Entry) entries.next();
+ /*
+ Determine if the ACE also takes effect on the parent:
+ Some permissions (e.g. add-node or removal) must be determined
+ from privileges defined for the parent.
+ A 'local' entry defined on the target node never effects the
+ parent. For inherited ACEs determine if the ACE matches the
+ parent path.
+ */
+ int entryBits = ace.getPrivilegeBits();
+ boolean isLocal = isExistingNode && ace.isLocal(node.getNodeId());
+ boolean matchesParent = (!isLocal && ace.matches(parentPath));
+ if (matchesParent) {
+ if (ace.isAllow()) {
+ parentAllows |= Permission.diff(entryBits, parentDenies);
+ } else {
+ parentDenies |= Permission.diff(entryBits, parentAllows);
+ }
+ }
+ if (ace.isAllow()) {
+ allowPrivileges |= Permission.diff(entryBits, denyPrivileges);
+ int permissions = PrivilegeRegistry.calculatePermissions(allowPrivileges, parentAllows, true, isAcItem);
+ allows |= Permission.diff(permissions, denies);
+ } else {
+ denyPrivileges |= Permission.diff(entryBits, allowPrivileges);
+ int permissions = PrivilegeRegistry.calculatePermissions(denyPrivileges, parentDenies, false, isAcItem);
+ denies |= Permission.diff(permissions, allows);
+ }
+ }
+ return new Result(allows, denies, allowPrivileges, denyPrivileges);
+ }
+
+ //------------------------------------< AbstractCompiledPermissions >---
+ /**
+ * @see AbstractCompiledPermissions#buildResult(org.apache.jackrabbit.spi.Path)
+ */
+ @Override
+ protected Result buildResult(Path absPath) throws RepositoryException {
+ boolean existingNode = false;
+ NodeImpl node;
+
+ ItemManager itemMgr = session.getItemManager();
+ try {
+ ItemImpl item = itemMgr.getItem(absPath);
+ if (item.isNode()) {
+ node = (NodeImpl) item;
+ existingNode = true;
+ } else {
+ node = (NodeImpl) item.getParent();
+ }
+ } catch (RepositoryException e) {
+ // path points to a non-persisted item.
+ // -> find the nearest persisted node starting from the root.
+ Path.Element[] elems = absPath.getElements();
+ NodeImpl parent = (NodeImpl) session.getRootNode();
+ for (int i = 1; i < elems.length - 1; i++) {
+ Name name = elems[i].getName();
+ int index = elems[i].getIndex();
+ if (!parent.hasNode(name, index)) {
+ // last persisted node reached
+ break;
+ }
+ parent = parent.getNode(name, index);
+
+ }
+ node = parent;
+ }
+
+ if (node == null) {
+ // should never get here
+ throw new ItemNotFoundException("Item out of hierarchy.");
+ }
+
+ boolean isAcItem = util.isAcItem(absPath);
+ return buildResult(node, existingNode, isAcItem, new EntryFilterImpl(principalNames, absPath, session));
+ }
+
+ /**
+ * @see AbstractCompiledPermissions#clearCache()
+ */
+ @Override
+ protected void clearCache() {
+ synchronized (monitor) {
+ readCache.clear();
+ }
+ super.clearCache();
+ }
+
+ //--------------------------------------------< CompiledPermissions >---
+ /**
+ * @see org.apache.jackrabbit.core.security.authorization.CompiledPermissions#close()
+ */
+ @Override
+ public void close() {
+ entryCollector.removeListener(this);
+ // NOTE: do not logout shared session.
+ super.close();
+ }
+
+ /**
+ * @see org.apache.jackrabbit.core.security.authorization.CompiledPermissions#canRead(Path, ItemId)
+ */
+ public boolean canRead(Path path, ItemId itemId) throws RepositoryException {
+ ItemId id = (itemId == null) ? session.getHierarchyManager().resolvePath(path) : itemId;
+ // no extra check for existence as method may only be called for existing items.
+ boolean isExistingNode = id.denotesNode();
+ boolean canRead;
+ synchronized (monitor) {
+ if (readCache.containsKey(id)) {
+ canRead = readCache.get(id);
+ } else {
+ ItemManager itemMgr = session.getItemManager();
+ NodeId nodeId = (isExistingNode) ? (NodeId) id : ((PropertyId) id).getParentId();
+ NodeImpl node = (NodeImpl) itemMgr.getItem(nodeId);
+ // TODO: check again if retrieving the path can be avoided
+ Path absPath = (path == null) ? session.getHierarchyManager().getPath(id) : path;
+ Result result = buildResult(node, isExistingNode, util.isAcItem(node), new EntryFilterImpl(principalNames, absPath, session));
+
+ canRead = result.grants(Permission.READ);
+ readCache.put(id, canRead);
+ }
+ }
+ return canRead;
+ }
+
+ //----------------------------------------< ACLModificationListener >---
+ /**
+ * @see org.apache.jackrabbit.core.security.authorization.AccessControlListener#acModified(org.apache.jackrabbit.core.security.authorization.AccessControlModifications)
+ */
+ public void acModified(AccessControlModifications modifications) {
+ // ignore the details of the modifications and clear all caches.
+ clearCache();
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CompiledPermissionsImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CompiledPermissionsImpl.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/EntryCollector.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/EntryCollector.java?rev=1022857&r1=1022856&r2=1022857&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/EntryCollector.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/EntryCollector.java Fri Oct 15 08:28:53 2010
@@ -22,6 +22,7 @@ import org.apache.jackrabbit.core.id.Nod
import org.apache.jackrabbit.core.security.authorization.AccessControlConstants;
import org.apache.jackrabbit.core.security.authorization.AccessControlModifications;
import org.apache.jackrabbit.core.security.authorization.AccessControlObserver;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
import org.apache.jackrabbit.util.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,7 +34,6 @@ import javax.jcr.observation.EventIterat
import javax.jcr.observation.ObservationManager;
import javax.jcr.security.AccessControlEntry;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
@@ -51,25 +51,36 @@ public class EntryCollector extends Acce
* logger instance
*/
private static final Logger log = LoggerFactory.getLogger(EntryCollector.class);
-
+
+ /**
+ * The system session used to register an event listener and process the
+ * events as well as collect AC entries.
+ */
protected final SessionImpl systemSession;
+
+ /**
+ * The root id.
+ */
protected final NodeId rootID;
+
+ private final PrivilegeRegistry privilegeRegistry;
- private final ACLEditor systemEditor;
-
+ /**
+ * Standard JCR name form of the {@link #N_POLICY} constant.
+ */
private final String repPolicyName;
/**
*
* @param systemSession
- * @param systemEditor
* @param rootID
* @throws RepositoryException
*/
- protected EntryCollector(SessionImpl systemSession, ACLEditor systemEditor, NodeId rootID) throws RepositoryException {
+ protected EntryCollector(SessionImpl systemSession, NodeId rootID) throws RepositoryException {
this.systemSession = systemSession;
- this.systemEditor = systemEditor;
this.rootID = rootID;
+
+ privilegeRegistry = new PrivilegeRegistry(systemSession);
repPolicyName = systemSession.getJCRName(N_POLICY);
ObservationManager observationMgr = systemSession.getWorkspace().getObservationManager();
@@ -95,6 +106,7 @@ public class EntryCollector extends Acce
* Release all resources contained by this instance. It will no longer be
* used. This implementation only stops listening to ac modification events.
*/
+ @Override
protected void close() {
super.close();
try {
@@ -126,7 +138,7 @@ public class EntryCollector extends Acce
next = getParentId(next);
}
- List<AccessControlEntry> entries = new ArrayList(userAces.size() + groupAces.size());
+ List<AccessControlEntry> entries = new ArrayList<AccessControlEntry>(userAces.size() + groupAces.size());
entries.addAll(userAces);
entries.addAll(groupAces);
@@ -147,7 +159,7 @@ public class EntryCollector extends Acce
if (ACLProvider.isAccessControlled(node)) {
// collect the aces of that node.
NodeImpl aclNode = node.getNode(N_POLICY);
- entries = Arrays.asList(systemEditor.getACL(aclNode).getAccessControlEntries());
+ entries = new ACLTemplate(aclNode, privilegeRegistry).getEntries();
} else {
// not access controlled
entries = Collections.emptyList();
@@ -288,7 +300,7 @@ public class EntryCollector extends Acce
if (!modMap.isEmpty()) {
// notify listeners and eventually clean up internal caches.
- notifyListeners(new AccessControlModifications(modMap));
+ notifyListeners(new AccessControlModifications<NodeId>(modMap));
}
}
}
\ No newline at end of file
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java?rev=1022857&r1=1022856&r2=1022857&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java Fri Oct 15 08:28:53 2010
@@ -185,7 +185,7 @@ class ACLTemplate extends AbstractACLTem
* @see org.apache.jackrabbit.core.security.authorization.AbstractACLTemplate#getEntries()
*/
@Override
- protected List<? extends AccessControlEntry> getEntries() {
+ protected List<AccessControlEntry> getEntries() {
return entries;
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/EntriesCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/EntriesCache.java?rev=1022857&r1=1022856&r2=1022857&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/EntriesCache.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/EntriesCache.java Fri Oct 15 08:28:53 2010
@@ -100,6 +100,7 @@ class EntriesCache extends AccessControl
* Release all resources contained by this instance. It will no longer be
* used. This implementation only stops listening to ac modification events.
*/
+ @Override
protected void close() {
super.close();
try {
@@ -110,7 +111,7 @@ class EntriesCache extends AccessControl
}
List<AccessControlEntry> getEntries(Collection<Principal> principals) throws RepositoryException {
- Object key = getCacheKey(principals);
+ String key = getCacheKey(principals);
List<AccessControlEntry> entries;
synchronized (monitor) {
entries = cache.get(key);
@@ -134,7 +135,7 @@ class EntriesCache extends AccessControl
return entries;
}
- private static Object getCacheKey(Collection<Principal> principals) {
+ private static String getCacheKey(Collection<Principal> principals) {
StringBuilder sb = new StringBuilder();
for (Principal p : principals) {
sb.append(p.getName()).append('/');
@@ -219,7 +220,7 @@ class EntriesCache extends AccessControl
synchronized (monitor) {
cache.clear();
}
- notifyListeners(new AccessControlModifications(modMap));
+ notifyListeners(new AccessControlModifications<String>(modMap));
}
}
}