jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r986335 [2/2] - in /jackrabbit/branches/2.0/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/ main/java/org/apache/jackrabbit/core/observation/ main/java/org/apache/jackrabbit/core/query/lucene/ main/java/org/apache/jackrabbit/core...
Date Tue, 17 Aug 2010 14:47:31 GMT
Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java Tue Aug 17 14:47:30 2010
@@ -36,6 +36,8 @@ import org.apache.jackrabbit.api.securit
 import org.apache.jackrabbit.api.security.principal.PrincipalManager;
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.id.NodeId;
+import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
 import org.apache.jackrabbit.core.security.authorization.AbstractACLTemplate;
 import org.apache.jackrabbit.core.security.authorization.AccessControlConstants;
 import org.apache.jackrabbit.core.security.authorization.AccessControlEntryImpl;
@@ -76,6 +78,14 @@ class ACLTemplate extends AbstractACLTem
     private final PrivilegeRegistry privilegeRegistry;
 
     /**
+     * The id of the access controlled node or <code>null</code> if this
+     * ACLTemplate isn't created for an existing access controlled node.
+     * Used for the Entry#isLocal(NodeId) call only in order to avoid calls
+     * to {@link javax.jcr.Node#getPath()}.
+     */
+    private final NodeId id;
+
+    /**
      * Construct a new empty {@link ACLTemplate}.
      *
      * @param path path
@@ -88,6 +98,7 @@ class ACLTemplate extends AbstractACLTem
         super(path, valueFactory);
         this.principalMgr = principalMgr;
         this.privilegeRegistry = privilegeRegistry;
+        this.id = null;
     }
 
     /**
@@ -100,13 +111,14 @@ class ACLTemplate extends AbstractACLTem
      */
     ACLTemplate(NodeImpl aclNode, PrivilegeRegistry privilegeRegistry) throws RepositoryException {
         super((aclNode != null) ? aclNode.getParent().getPath() : null, (aclNode != null) ? aclNode.getSession().getValueFactory() : null);
-        if (aclNode == null || !aclNode.isNodeType(AccessControlConstants.NT_REP_ACL)) {
+        if (aclNode == null || !AccessControlConstants.NT_REP_ACL.equals(((NodeTypeImpl)aclNode.getPrimaryNodeType()).getQName())) {
             throw new IllegalArgumentException("Node must be of type 'rep:ACL'");
         }
         SessionImpl sImpl = (SessionImpl) aclNode.getSession();
         principalMgr = sImpl.getPrincipalManager();
-        
+
         this.privilegeRegistry = privilegeRegistry;
+        this.id = aclNode.getParentId();
 
         // load the entries:
         AccessControlManager acMgr = sImpl.getAccessControlManager();
@@ -127,11 +139,10 @@ class ACLTemplate extends AbstractACLTem
                     privs[i] = acMgr.privilegeFromName(privValues[i].getString());
                 }
                 // create a new ACEImpl (omitting validation check)
-                Entry ace = new Entry(
+                Entry ace = createEntry(
                         princ,
                         privs,
-                        aceNode.isNodeType(AccessControlConstants.NT_REP_GRANT_ACE),
-                        valueFactory);
+                        AccessControlConstants.NT_REP_GRANT_ACE.equals(((NodeTypeImpl) aceNode.getPrimaryNodeType()).getQName()));
                 // add the entry
                 internalAdd(ace);
             } catch (RepositoryException e) {
@@ -140,6 +151,18 @@ class ACLTemplate extends AbstractACLTem
         }
     }
 
+    /**
+     * Create a new entry omitting any validation checks.
+     *
+     * @param principal
+     * @param privileges
+     * @param isAllow
+     * @return
+     */
+    Entry createEntry(Principal principal, Privilege[] privileges, boolean isAllow) throws AccessControlException {
+        return new Entry(principal, privileges, isAllow);
+    }
+
     private List<Entry> internalGetEntries(Principal principal) {
         String principalName = principal.getName();
         List entriesPerPrincipal = new ArrayList(2);
@@ -185,7 +208,7 @@ class ACLTemplate extends AbstractACLTem
                     int mergedBits = e.getPrivilegeBits() | entry.getPrivilegeBits();
                     Privilege[] mergedPrivs = privilegeRegistry.getPrivileges(mergedBits);
                     // omit validation check.
-                    entry = new Entry(entry.getPrincipal(), mergedPrivs, entry.isAllow(), valueFactory);
+                    entry = createEntry(entry.getPrincipal(), mergedPrivs, entry.isAllow());
                 } else {
                     complementEntry = e;
                 }
@@ -209,9 +232,9 @@ class ACLTemplate extends AbstractACLTem
                     // replace the existing entry having the privileges adjusted
                     int index = entries.indexOf(complementEntry);
                     entries.remove(complementEntry);
-                    Entry tmpl = new Entry(entry.getPrincipal(),
+                    Entry tmpl = createEntry(entry.getPrincipal(),
                             privilegeRegistry.getPrivileges(resultPrivs),
-                            !entry.isAllow(), valueFactory);
+                            !entry.isAllow());
                     entries.add(index, tmpl);
                 } /* else: does not need to be modified.*/
             }
@@ -231,6 +254,7 @@ class ACLTemplate extends AbstractACLTem
     /**
      * @see AbstractACLTemplate#checkValidEntry(java.security.Principal, javax.jcr.security.Privilege[], boolean, java.util.Map) 
      */
+    @Override
     protected void checkValidEntry(Principal principal, Privilege[] privileges,
                                  boolean isAllow, Map<String, Value> restrictions)
             throws AccessControlException {
@@ -248,20 +272,13 @@ class ACLTemplate extends AbstractACLTem
     /**
      * @see org.apache.jackrabbit.core.security.authorization.AbstractACLTemplate#getEntries()
      */
+    @Override
     protected List<? extends AccessControlEntry> getEntries() {
         return entries;
     }
 
     //--------------------------------------------------< AccessControlList >---
     /**
-     * @see javax.jcr.security.AccessControlList#getAccessControlEntries()
-     */
-    public AccessControlEntry[] getAccessControlEntries() throws RepositoryException {
-        List<? extends AccessControlEntry> l = getEntries();
-        return l.toArray(new AccessControlEntry[l.size()]);
-    }
-
-    /**
      * @see javax.jcr.security.AccessControlList#removeAccessControlEntry(AccessControlEntry)
      */
     public synchronized void removeAccessControlEntry(AccessControlEntry ace)
@@ -297,27 +314,13 @@ class ACLTemplate extends AbstractACLTem
     }
 
     /**
-     * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#isEmpty()
-     */
-    public boolean isEmpty() {
-        return entries.isEmpty();
-    }
-
-    /**
-     * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#size()
-     */
-    public int size() {
-        return getEntries().size();
-    }
-
-    /**
      * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#addEntry(Principal, Privilege[], boolean, Map)
      */
     public boolean addEntry(Principal principal, Privilege[] privileges,
                             boolean isAllow, Map<String, Value> restrictions)
             throws AccessControlException, RepositoryException {
         checkValidEntry(principal, privileges, isAllow, restrictions);
-        Entry ace = new Entry(principal, privileges, isAllow, valueFactory);
+        Entry ace = createEntry(principal, privileges, isAllow);
         return internalAdd(ace);
     }
 
@@ -329,6 +332,7 @@ class ACLTemplate extends AbstractACLTem
      * @return always zero
      * @see Object#hashCode()
      */
+    @Override
     public int hashCode() {
         return 0;
     }
@@ -340,6 +344,7 @@ class ACLTemplate extends AbstractACLTem
      * @return true if the path and the entries are equal; false otherwise.
      * @see Object#equals(Object)
      */
+    @Override
     public boolean equals(Object obj) {
         if (obj == this) {
             return true;
@@ -356,11 +361,20 @@ class ACLTemplate extends AbstractACLTem
     /**
      *
      */
-    static class Entry extends AccessControlEntryImpl {
+    class Entry extends AccessControlEntryImpl {
 
-        Entry(Principal principal, Privilege[] privileges, boolean allow, ValueFactory valueFactory)
+        private Entry(Principal principal, Privilege[] privileges, boolean allow)
                 throws AccessControlException {
             super(principal, privileges, allow, Collections.<String, Value>emptyMap(), valueFactory);
         }
+
+        /**
+         * @param nodeId
+         * @return <code>true</code> if this entry is defined on the node
+         * at <code>nodeId</code>
+         */
+        boolean isLocal(NodeId nodeId) {
+            return id != null && id.equals(nodeId);
+        }
     }
 }

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedProvider.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedProvider.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedProvider.java Tue Aug 17 14:47:30 2010
@@ -25,6 +25,7 @@ import org.apache.jackrabbit.core.securi
 import org.apache.jackrabbit.core.security.authorization.AbstractCompiledPermissions;
 import org.apache.jackrabbit.core.security.authorization.principalbased.ACLProvider;
 import org.apache.jackrabbit.core.ItemImpl;
+import org.apache.jackrabbit.core.id.ItemId;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
 import javax.jcr.security.AccessControlPolicy;
@@ -242,5 +243,13 @@ public class CombinedProvider extends Ab
             }
             super.close();
         }
+
+        /**
+         * @see CompiledPermissions#canRead(Path, ItemId)
+         */
+        public boolean canRead(Path path, ItemId itemId) throws RepositoryException {
+            Path p = (path == null) ? session.getItemManager().getItem(itemId).getPrimaryPath() : path;
+            return grants(p, Permission.READ);
+        }
     }
 }
\ No newline at end of file

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLProvider.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLProvider.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLProvider.java Tue Aug 17 14:47:30 2010
@@ -16,49 +16,46 @@
  */
 package org.apache.jackrabbit.core.security.authorization.principalbased;
 
-import java.security.Principal;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.jcr.Item;
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.Value;
-import javax.jcr.ValueFactory;
-import javax.jcr.observation.Event;
-import javax.jcr.observation.EventIterator;
-import javax.jcr.security.AccessControlEntry;
-import javax.jcr.security.AccessControlException;
-import javax.jcr.security.AccessControlManager;
-import javax.jcr.security.AccessControlPolicy;
-import javax.jcr.security.Privilege;
-
+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.NodeImpl;
 import org.apache.jackrabbit.core.SessionImpl;
-import org.apache.jackrabbit.core.observation.SynchronousEventListener;
+import org.apache.jackrabbit.core.id.ItemId;
 import org.apache.jackrabbit.core.security.SecurityConstants;
 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.AccessControlEntryImpl;
+import org.apache.jackrabbit.core.security.authorization.AccessControlListener;
+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.spi.Path;
-import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
 import org.apache.jackrabbit.util.Text;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import javax.jcr.security.AccessControlEntry;
+import javax.jcr.security.AccessControlException;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.Privilege;
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * <code>CombinedProvider</code>...
  */
@@ -69,31 +66,11 @@ public class ACLProvider extends Abstrac
     // TODO: add means to show effective-policy to a user.
     private static final AccessControlPolicy effectivePolicy = EffectivePrincipalBasedPolicy.getInstance();
 
+    private NodeImpl acRoot;    
     private ACLEditor editor;
 
-    private NodeImpl acRoot;
-
-    //-------------------------------------------------< AccessControlUtils >---
-    /**
-     * @see org.apache.jackrabbit.core.security.authorization.AccessControlUtils#isAcItem(Path)
-     */
-    public boolean isAcItem(Path absPath) throws RepositoryException {
-        Path.Element[] elems = absPath.getElements();
-        for (Path.Element elem : elems) {
-            if (N_POLICY.equals(elem.getName())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * @see org.apache.jackrabbit.core.security.authorization.AccessControlUtils#isAcItem(ItemImpl)
-     */
-    public boolean isAcItem(ItemImpl item) throws RepositoryException {
-        NodeImpl n = ((item.isNode()) ? (NodeImpl) item : (NodeImpl) item.getParent());
-        return n.isNodeType(NT_REP_ACL) || n.isNodeType(NT_REP_ACE);
-    }
+    private EntriesCache entriesCache;
+    private int readBits;
 
     //----------------------------------------------< AccessControlProvider >---
     /**
@@ -114,6 +91,9 @@ public class ACLProvider extends Abstrac
         }
 
         editor = new ACLEditor(session, resolver.getQPath(acRoot.getPath()));
+        entriesCache = new EntriesCache(session, editor, acRoot.getPath());
+        readBits = PrivilegeRegistry.getBits(new Privilege[] {session.getAccessControlManager().privilegeFromName(Privilege.JCR_READ)});
+
         // TODO: replace by configurable default policy (see JCR-2331)
         if (!configuration.containsKey(PARAM_OMIT_DEFAULT_PERMISSIONS)) {
             try {
@@ -169,6 +149,12 @@ public class ACLProvider extends Abstrac
             log.debug("... policy for principal  '"+principal.getName()+"'  already present.");
         }
     }
+    
+    @Override
+    public void close() {
+        super.close();        
+        entriesCache.close();
+    }
 
     /**
      * @see org.apache.jackrabbit.core.security.authorization.AccessControlProvider#getEffectivePolicies(Path)
@@ -181,7 +167,7 @@ public class ACLProvider extends Abstrac
            entries, returning the principal-based policy at 'absPath' (which for
            most nodes in the repository isn't available anyway) doesn't
            provide the desired information.
-           As tmp. solution some default policy is returned indicating.
+           As tmp. solution some default policy is returned instead.
            TODO: add proper evaluation and return a set of ACLs that take effect on the node at abs path
         */
         return new AccessControlPolicy[] {effectivePolicy};
@@ -215,7 +201,7 @@ public class ACLProvider extends Abstrac
         } else if (isReadOnly(principals)) {
             return getReadOnlyPermissions();
         } else {
-            return new ACLProvider.CompiledPermissionImpl(principals);
+            return new CompiledPermissionImpl(principals);
         }
     }
 
@@ -227,8 +213,8 @@ public class ACLProvider extends Abstrac
         if (isAdminOrSystem(principals)) {
             return true;
         } else {
-            CompiledPermissions cp = new CompiledPermissionImpl(principals, false);
-            return cp.grants(PathFactoryImpl.getInstance().getRootPath(), Permission.READ);
+            CompiledPermissionImpl cp = new CompiledPermissionImpl(principals, false);
+            return cp.canRead(((NodeImpl) session.getRootNode()).getPrimaryPath());
         }
     }
 
@@ -237,12 +223,17 @@ public class ACLProvider extends Abstrac
      *
      */
     private class CompiledPermissionImpl extends AbstractCompiledPermissions
-            implements SynchronousEventListener {
+            implements AccessControlListener {
 
         private final Set<Principal> principals;
         private final Set<String> acPaths;
         private List<AccessControlEntry> entries;
 
+        private boolean canReadAll;
+
+        private final Map<ItemId, Boolean> readCache = new LRUMap(2000);
+        private final Object monitor = new Object();
+
         /**
          * @param principals the underlying principals
          * @throws RepositoryException if an error occurs
@@ -260,16 +251,43 @@ public class ACLProvider extends Abstrac
 
             this.principals = principals;
             acPaths = new HashSet<String>(principals.size());
-            entries = reload();
+            reload();
 
-            // TODO: describe
             if (listenToEvents) {
-                int events = Event.PROPERTY_CHANGED | Event.PROPERTY_ADDED |
-                        Event.PROPERTY_REMOVED | Event.NODE_ADDED | Event.NODE_REMOVED;
-                String[] ntNames = new String[] {
-                        session.getJCRName(NT_REP_ACE)
-                };
-                observationMgr.addEventListener(this, events, acRoot.getPath(), true, null, ntNames, false);
+                /*
+                 Make sure this AclPermission recalculates the permissions if
+                 any ACL concerning it is modified.
+                 */
+                 entriesCache.addListener(this);
+            }
+        }
+               
+        /**
+         * @throws RepositoryException if an error occurs
+         */
+        private void reload() throws RepositoryException {
+            // reload the paths
+            acPaths.clear();
+            for (Principal p : principals) {
+                acPaths.add(editor.getPathToAcNode(p));
+            }
+
+            // and retrieve the entries from the entry-collector.
+            entries = entriesCache.getEntries(principals);
+            
+            // in addition: trivial check if read access is deny somewhere
+            // as as shortcut in #canRead(Path)
+            canReadAll = canRead(session.getQPath("/"));            
+            if (canReadAll) {
+                for (AccessControlEntry entry : entries) {
+                    AccessControlEntryImpl ace = (AccessControlEntryImpl) entry;
+                    if (!ace.isAllow() && ((ace.getPrivilegeBits() & readBits) == readBits)) {
+                        // found an ace that defines read deny for a sub tree
+                        // -> canReadAll is false.
+                        canReadAll = false;
+                        break;
+                    }
+                }
             }
         }
 
@@ -287,32 +305,22 @@ public class ACLProvider extends Abstrac
             String jcrPath = session.getJCRPath(absPath);
 
             // retrieve principal-based permissions and privileges
-            Result result;
-            if (session.itemExists(jcrPath)) {
-                Item item = session.getItem(jcrPath);
-                result = getResult(item, item.getPath(), isAcItem);
-            } else {
-                result = getResult(null, jcrPath, isAcItem);
-            }
-            return result;
+            return buildResult(jcrPath, isAcItem);
         }
 
 
         /**
          * Loop over all entries and evaluate allows/denies for those matching
          * the given jcrPath.
-         *
-         * @param target Existing target item for which the permissions will be
-         * evaluated or <code>null</code>.
+         * 
          * @param targetPath Path used for the evaluation; pointing to an
          * existing or non-existing item.
          * @param isAcItem the item
          * @return the result
          * @throws RepositoryException if an error occurs
          */
-        private Result getResult(Item target,
-                                 String targetPath,
-                                 boolean isAcItem) throws RepositoryException {
+        private Result buildResult(String targetPath,
+                                   boolean isAcItem) throws RepositoryException {
             int allows = Permission.NONE;
             int denies = Permission.NONE;
             int allowPrivileges = PrivilegeRegistry.NO_PRIVILEGE;
@@ -337,7 +345,7 @@ public class ACLProvider extends Abstrac
                     }
                 }
 
-                boolean matches = (target != null) ? entr.matches(target) : entr.matches(targetPath);
+                boolean matches = entr.matches(targetPath);
                 if (matches) {
                     if (entr.isAllow()) {
                         allowPrivileges |= Permission.diff(privs, denyPrivileges);
@@ -359,84 +367,63 @@ public class ACLProvider extends Abstrac
          */
         @Override
         public void close() {
-            try {
-                observationMgr.removeEventListener(this);
-            } catch (RepositoryException e) {
-                log.debug("Unable to unregister listener: ", e.getMessage());
-            }
+            entriesCache.removeListener(this);
             super.close();
         }
 
-        //--------------------------------------------------< EventListener >---
         /**
-         * @see javax.jcr.observation.EventListener#onEvent(EventIterator)
+         * @see CompiledPermissions#canRead(Path, ItemId)
          */
-        public synchronized void onEvent(EventIterator events) {
+        public boolean canRead(Path path, ItemId itemId) throws RepositoryException {
+            boolean canRead;
+            if (path == null) {
+                // only itemId: try to avoid expensive resolution from itemID to path
+                synchronized (monitor) {
+                    if (readCache.containsKey(itemId)) {
+                        // id has been evaluated before -> shortcut
+                        canRead = readCache.get(itemId);
+                    } else {
+                        canRead = canRead(session.getHierarchyManager().getPath(itemId));
+                        readCache.put(itemId, canRead);
+                        return canRead;
+                    }
+                }
+            } else {
+                // path param present:
+                canRead = canRead(path);
+            }
+            return canRead;
+        }
+
+        private boolean canRead(Path path) throws RepositoryException {
+            // first try if reading non-ac-items was always granted -> no eval
+            // otherwise evaluate the permissions.
+            return (canReadAll && !isAcItem(path)) || grants(path, Permission.READ);
+        }
+
+        //------------------------------------------< AccessControlListener >---
+        /**
+         * @see AccessControlListener#acModified(org.apache.jackrabbit.core.security.authorization.AccessControlModifications)
+         */
+        public void acModified(AccessControlModifications modifications) {
             try {
                 boolean reload = false;
-                while (events.hasNext() && !reload) {
-                    Event ev = events.nextEvent();
-                    String path = ev.getPath();
-                    // only invalidate cache if any of the events affects the
-                    // nodes defining permissions for the principals.
-                    switch (ev.getType()) {
-                        case Event.NODE_ADDED:
-                        case Event.NODE_REMOVED:
-                        case Event.NODE_MOVED:
-                            reload = acPaths.contains(Text.getRelativeParent(path, 2));
-                            break;
-                        case Event.PROPERTY_ADDED:
-                        case Event.PROPERTY_CHANGED:
-                        case Event.PROPERTY_REMOVED:
-                            reload = acPaths.contains(Text.getRelativeParent(path, 3));
-                            break;
-
-                        default:
-                            // illegal event-type: should never occur. ignore
-                            break;
-                    }
+                Iterator keys = modifications.getNodeIdentifiers().iterator();
+                while (keys.hasNext() && !reload) {
+                    String path = keys.next().toString();
+                    reload = acPaths.contains(path);
                 }
                 // eventually reload the ACL and clear the cache
                 if (reload) {
                     clearCache();
-                    // reload the acl
-                    entries = reload();
+                    // reload the ac-path list and the list of aces
+                    reload();
                 }
             } catch (RepositoryException e) {
                 // should never get here
                 log.warn("Internal error: ", e.getMessage());
             }
         }
-
-        /**
-         *
-         * @return the aces
-         * @throws RepositoryException if an error occurs
-         */
-        private List<AccessControlEntry> reload() throws RepositoryException {
-            // reload the paths
-            acPaths.clear();
-
-            // acNodes must be ordered in the same order as the principals
-            // in order to obtain proper acl-evaluation in case the given
-            // principal-set is ordered.
-            List<AccessControlEntry> allACEs = new ArrayList<AccessControlEntry>();
-            // build acl-hierarchy assuming that principal-order determines the
-            // acl-inheritance.
-            for (Principal p : principals) {
-                ACLTemplate acl = editor.getACL(p);
-                if (acl == null || acl.isEmpty()) {
-                    acPaths.add(editor.getPathToAcNode(p));
-                } else {
-                    // retrieve the ACEs from the node
-                    AccessControlEntry[] aces = acl.getAccessControlEntries();
-                    allACEs.addAll(Arrays.asList(aces));
-                    acPaths.add(acl.getPath());
-                }
-            }
-
-            return allACEs;
-        }
     }
 
     //--------------------------------------------------------------------------

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java Tue Aug 17 14:47:30 2010
@@ -155,6 +155,7 @@ class ACLTemplate extends AbstractACLTem
     /**
      * @see AbstractACLTemplate#checkValidEntry(java.security.Principal, javax.jcr.security.Privilege[], boolean, java.util.Map)
      */
+    @Override
     protected void checkValidEntry(Principal principal, Privilege[] privileges,
                                  boolean isAllow, Map<String, Value> restrictions)
             throws AccessControlException {
@@ -171,6 +172,7 @@ class ACLTemplate extends AbstractACLTem
     /**
      * @see org.apache.jackrabbit.core.security.authorization.AbstractACLTemplate#getEntries() 
      */
+    @Override
     protected List<? extends AccessControlEntry> getEntries() {
         return entries;
     }
@@ -197,20 +199,6 @@ class ACLTemplate extends AbstractACLTem
     }
 
     /**
-     * @see JackrabbitAccessControlList#isEmpty()
-     */
-    public boolean isEmpty() {
-        return entries.isEmpty();
-    }
-
-    /**
-     * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#size()
-     */
-    public int size() {
-        return entries.size();
-    }
-
-    /**
      * Known restrictions are:
      * <pre>
      *   rep:nodePath  (mandatory) value-type: PATH
@@ -241,14 +229,6 @@ class ACLTemplate extends AbstractACLTem
 
     //--------------------------------------------------< AccessControlList >---
     /**
-     * @see javax.jcr.security.AccessControlList#getAccessControlEntries()
-     */
-    public AccessControlEntry[] getAccessControlEntries()
-            throws RepositoryException {
-        return entries.toArray(new AccessControlEntry[entries.size()]);
-    }
-
-    /**
      * @see javax.jcr.security.AccessControlList#removeAccessControlEntry(AccessControlEntry)
      */
     public void removeAccessControlEntry(AccessControlEntry ace)
@@ -269,6 +249,7 @@ class ACLTemplate extends AbstractACLTem
      * @return always zero
      * @see Object#hashCode()
      */
+    @Override
     public int hashCode() {
         return 0;
     }
@@ -280,6 +261,7 @@ class ACLTemplate extends AbstractACLTem
      * @return true if the path and the entries are equal; false otherwise.
      * @see Object#equals(Object)
      */
+    @Override
     public boolean equals(Object obj) {
         if (obj == this) {
             return true;
@@ -305,7 +287,7 @@ class ACLTemplate extends AbstractACLTem
         private final String nodePath;
 
         /**
-         * Globbing pattern
+         * Globing pattern
          */
         private final GlobPattern pattern;
 

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/GlobPattern.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/GlobPattern.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/GlobPattern.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/GlobPattern.java Tue Aug 17 14:47:30 2010
@@ -36,9 +36,19 @@ class GlobPattern {
     public static final String WILDCARD_ALL = "*";
 
     private final String pattern;
+    private final char[] patternChars;
+
+    private final boolean matchesAll;
+    private final boolean containsWildcard;
 
     private GlobPattern(String pattern)  {
         this.pattern = pattern;
+
+        matchesAll = WILDCARD_ALL.equals(pattern);
+        containsWildcard = pattern.indexOf(ALL) > -1;
+
+        patternChars = pattern.toCharArray();
+
     }
 
     static GlobPattern create(String pattern) {
@@ -50,17 +60,17 @@ class GlobPattern {
 
     boolean matches(String toMatch) {
         // shortcut
-        if (WILDCARD_ALL.equals(pattern)) {
+        if (matchesAll) {
             return true;
         }
         if (toMatch == null) {
             return false;
         }
 
-        if (containsWildCard()) {
-            return matches(pattern, toMatch);
+        if (containsWildcard) {
+            return matches(patternChars, toMatch.toCharArray());
         } else {
-            return pattern.equals(toMatch) || Text.isDescendant(pattern, toMatch);
+            return Text.isDescendantOrEqual(pattern, toMatch);
         }
     }
 
@@ -74,21 +84,13 @@ class GlobPattern {
         }
     }
 
-    private boolean containsWildCard() {
+    private static boolean matches(char[] patternChars, char[] toMatch) {
         // TODO: add proper impl
-        return pattern.indexOf(ALL) > -1;
-    }
-
-    private static boolean matches(String pattern, String toMatch) {
-        // TODO: add proper impl
-        char[] c1 = pattern.toCharArray();
-        char[] c2 = toMatch.toCharArray();
-
-        for (int i = 0; i < c1.length; i++) {
-            if (c1[i] == ALL) {
+        for (int i = 0; i < patternChars.length; i++) {
+            if (patternChars[i] == ALL) {
                 return true;
             }
-            if (i >= c2.length || c1[i] != c2[i]) {
+            if (i >= toMatch.length || patternChars[i] != toMatch[i]) {
                 return false;
             }
         }
@@ -101,6 +103,7 @@ class GlobPattern {
     /**
      * @see Object#hashCode()
      */
+    @Override
     public int hashCode() {
         return pattern.hashCode();
     }
@@ -108,6 +111,7 @@ class GlobPattern {
     /**
      * @see Object#toString()
      */
+    @Override
     public String toString() {
         return pattern;
     }
@@ -115,6 +119,7 @@ class GlobPattern {
     /**
      * @see Object#equals(Object)
      */
+    @Override
     public boolean equals(Object obj) {
         if (obj == this) {
             return true;

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java Tue Aug 17 14:47:30 2010
@@ -167,7 +167,7 @@ public class SimpleAccessManager extends
         return internalIsGranted(parentPath, permissions);
     }
 
-    public boolean canRead(Path itemPath) throws RepositoryException {
+    public boolean canRead(Path itemPath, ItemId itemId) throws RepositoryException {
         return true;
     }
 

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleLoginModule.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleLoginModule.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleLoginModule.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleLoginModule.java Tue Aug 17 14:47:30 2010
@@ -41,6 +41,7 @@ public class SimpleLoginModule extends A
     /**
      * @see AbstractLoginModule#doInit(javax.security.auth.callback.CallbackHandler, javax.jcr.Session, java.util.Map)
      */
+    @Override
     protected void doInit(CallbackHandler callbackHandler, Session session, Map options) throws LoginException {
         // nothing to do
         log.debug("init: SimpleLoginModule. Done.");
@@ -49,6 +50,7 @@ public class SimpleLoginModule extends A
     /**
      * @see AbstractLoginModule#impersonate(java.security.Principal, javax.jcr.Credentials)
      */
+    @Override
     protected boolean impersonate(Principal principal, Credentials credentials) throws RepositoryException, LoginException {
         if (principal instanceof Group) {
             return false;
@@ -60,6 +62,7 @@ public class SimpleLoginModule extends A
     /**
      * @see AbstractLoginModule#getAuthentication(java.security.Principal, javax.jcr.Credentials)
      */
+    @Override
     protected Authentication getAuthentication(Principal principal, Credentials creds) throws RepositoryException {
         if (principal instanceof Group) {
             return null;
@@ -86,6 +89,7 @@ public class SimpleLoginModule extends A
      *
      * @see AbstractLoginModule#getPrincipal(Credentials)
      */
+    @Override
     protected Principal getPrincipal(Credentials credentials) {
         String userId = getUserID(credentials);
         Principal principal = principalProvider.getPrincipal(userId);

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java Tue Aug 17 14:47:30 2010
@@ -24,6 +24,7 @@ import org.apache.jackrabbit.api.securit
 import org.apache.jackrabbit.core.ItemImpl;
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.id.ItemId;
 import org.apache.jackrabbit.core.observation.SynchronousEventListener;
 import org.apache.jackrabbit.core.security.authorization.AbstractAccessControlProvider;
 import org.apache.jackrabbit.core.security.authorization.AbstractCompiledPermissions;
@@ -192,8 +193,9 @@ public class UserAccessControlProvider e
             ItemBasedPrincipal userPrincipal = getUserPrincipal(principals);
             NodeImpl userNode = getUserNode(userPrincipal);
             if (userNode == null) {
-                // no 'user' within set of principals -> READ-only
-                return getReadOnlyPermissions();
+                // no 'user' within set of principals -> no permissions in the
+                // security workspace.
+                return CompiledPermissions.NO_PERMISSION;
             } else {
                 return new CompiledPermissionsImpl(principals, userNode.getPath());
             }
@@ -335,7 +337,7 @@ public class UserAccessControlProvider e
                 // no Node corresponding to user for which the permissions are
                 // calculated -> no permissions/privileges.
                 log.debug("No node at " + userNodePath);
-                return new Result(Permission.NONE, Permission.NONE, PrivilegeRegistry.NO_PRIVILEGE, PrivilegeRegistry.NO_PRIVILEGE);
+                return Result.EMPTY;
             }
 
             // no explicit denied permissions:
@@ -440,8 +442,7 @@ public class UserAccessControlProvider e
          */
         public boolean grants(Path absPath, int permissions) throws RepositoryException {
             if (permissions == Permission.READ) {
-                // read is always granted
-                return true;
+                return canReadAll();
             }
             // otherwise: retrieve from cache (or build)
             return super.grants(absPath, permissions);
@@ -451,7 +452,16 @@ public class UserAccessControlProvider e
          * @see CompiledPermissions#canReadAll()
          */
         public boolean canReadAll() throws RepositoryException {
-            return true;
+            // for consistency with 'grants(Path, int) this method only returns
+            // true if there exists a node for 'userNodePath'
+            return session.nodeExists(userNodePath);
+        }
+
+        /**
+         * @see CompiledPermissions#canRead(Path, ItemId)
+         */
+        public boolean canRead(Path path, ItemId itemId) throws RepositoryException {
+            return canReadAll();
         }
 
         //--------------------------------------------------< EventListener >---

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/AccessManagerTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/AccessManagerTest.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/AccessManagerTest.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/AccessManagerTest.java Tue Aug 17 14:47:30 2010
@@ -21,6 +21,8 @@ import org.apache.jackrabbit.core.ItemIm
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.id.PropertyId;
 import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.PropertyImpl;
 import org.apache.jackrabbit.core.security.authorization.Permission;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
@@ -280,4 +282,51 @@ public class AccessManagerTest extends A
             s.logout();
         }
     }
+
+    public void testCanReadPathId() throws Exception {
+        Session s = getHelper().getReadOnlySession();
+        try {
+            AccessManager acMgr = getAccessManager(s);
+
+            ItemId id = ((NodeImpl) testRootNode).getId();
+            Path path = ((NodeImpl) testRootNode).getPrimaryPath();
+            assertTrue(acMgr.canRead(null, id));
+            assertTrue(acMgr.canRead(path, null));
+            assertTrue(acMgr.canRead(path, id));
+
+            id = ((PropertyImpl) testRootNode.getProperty(jcrPrimaryType)).getId();
+            path = ((PropertyImpl) testRootNode.getProperty(jcrPrimaryType)).getPrimaryPath();
+            assertTrue(acMgr.canRead(null, id));
+            assertTrue(acMgr.canRead(path, null));
+            assertTrue(acMgr.canRead(path, id));
+
+        } finally {
+            s.logout();
+        }
+
+    }
+
+    public void testCanReadNewId() throws Exception {
+        Session s = getHelper().getReadOnlySession();
+        try {
+            NodeImpl n = (NodeImpl) testRootNode.addNode(nodeName1);
+            PropertyImpl p = (PropertyImpl) n.setProperty(propertyName1, "somevalue");
+            try {
+                AccessManager acMgr = getAccessManager(s);
+                acMgr.canRead(null, n.getId());
+                fail("expected repositoryexception");
+            } catch (RepositoryException e) {
+                // success
+            }
+            try {
+                AccessManager acMgr = getAccessManager(s);
+                acMgr.canRead(null, p.getId());
+                fail("expected repositoryexception");
+            } catch (RepositoryException e) {
+                // success
+            }
+        } finally {
+            s.logout();
+        }
+    }
 }
\ No newline at end of file

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEntryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEntryTest.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEntryTest.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEntryTest.java Tue Aug 17 14:47:30 2010
@@ -37,6 +37,7 @@ public abstract class AbstractEntryTest 
 
     protected Principal testPrincipal;
 
+    @Override
     protected void setUp() throws Exception {
         super.setUp();
         testPrincipal = new Principal() {

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractWriteTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractWriteTest.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractWriteTest.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractWriteTest.java Tue Aug 17 14:47:30 2010
@@ -63,6 +63,7 @@ public abstract class AbstractWriteTest 
     // TODO: test AC for moved node
     // TODO: test AC for moved AC-controlled node
 
+    @Override
     protected void setUp() throws Exception {
         super.setUp();
 
@@ -85,6 +86,7 @@ public abstract class AbstractWriteTest 
         siblingPath = n2.getPath();
     }
 
+    @Override
     protected void tearDown() throws Exception {
         try {
             if (testGroup != null && testUser != null) {
@@ -1035,6 +1037,33 @@ public abstract class AbstractWriteTest 
         n.orderBefore(Text.getName(childNPath), Text.getName(childNPath2));
         testSession.save();
     }
+    
+    /**
+     * Test case for JCR-2420
+     *
+     * @throws Exception
+     * @see <a href="https://issues.apache.org/jira/browse/JCR-2420">JCR-2420</a>
+     */
+    public void testRemovalJCR242() throws Exception {
+        Privilege[] allPriv = privilegesFromNames(new String[] {Privilege.JCR_ALL});
+
+        /* grant ALL privilege for testUser at 'path' */
+        givePrivileges(path, testUser.getPrincipal(), allPriv, getRestrictions(superuser, path));
+        /* grant ALL privilege for testUser at 'childNPath' */
+        givePrivileges(childNPath, testUser.getPrincipal(), allPriv, getRestrictions(superuser, childNPath));
+
+        Session testSession = getTestSession();
+        AccessControlManager acMgr = testSession.getAccessControlManager();
+
+        assertTrue(acMgr.hasPrivileges(path, allPriv));
+        assertTrue(acMgr.hasPrivileges(childNPath, allPriv));
+
+        assertTrue(testSession.hasPermission(childNPath, Session.ACTION_REMOVE));
+
+        Node child = testSession.getNode(childNPath);
+        child.remove();
+        testSession.save();
+    }
 
     private static Node findPolicyNode(Node start) throws RepositoryException {
         Node policyNode = null;

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/EntryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/EntryTest.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/EntryTest.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/EntryTest.java Tue Aug 17 14:47:30 2010
@@ -17,9 +17,16 @@
 package org.apache.jackrabbit.core.security.authorization.acl;
 
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlEntry;
+import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.security.authorization.AbstractEntryTest;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
+import org.apache.jackrabbit.test.NotExecutableException;
 
 import javax.jcr.RepositoryException;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.AccessControlPolicyIterator;
 import javax.jcr.security.Privilege;
 import java.security.Principal;
 
@@ -28,8 +35,54 @@ import java.security.Principal;
  */
 public class EntryTest extends AbstractEntryTest {
 
+    private ACLTemplate acl;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        SessionImpl s = (SessionImpl) superuser;
+
+        acl = new ACLTemplate(testPath, s.getPrincipalManager(), new PrivilegeRegistry(s), s.getValueFactory());
+    }
+
+    @Override
     protected JackrabbitAccessControlEntry createEntry(Principal principal, Privilege[] privileges, boolean isAllow)
             throws RepositoryException {
-        return new ACLTemplate.Entry(principal, privileges, isAllow, superuser.getValueFactory());
+        return acl.createEntry(principal, privileges, isAllow);
+    }
+
+    public void testIsLocal() throws NotExecutableException, RepositoryException {
+        ACLTemplate.Entry entry = (ACLTemplate.Entry) createEntry(new String[] {Privilege.JCR_READ}, true);
+
+        // false since acl has been created from path only -> no id
+        assertFalse(entry.isLocal(((NodeImpl) testRootNode).getNodeId()));
+        // false since internal id is null -> will never match.
+        assertFalse(entry.isLocal(new NodeId()));
+    }
+
+    public void testIsLocal2()  throws NotExecutableException, RepositoryException {
+        String path = testRootNode.getPath();
+        AccessControlPolicy[] acls = acMgr.getPolicies(path);
+        if (acls.length == 0) {
+            AccessControlPolicyIterator it = acMgr.getApplicablePolicies(path);
+            if (!it.hasNext()) {
+                throw new NotExecutableException();
+            }
+            acMgr.setPolicy(path, it.nextAccessControlPolicy());
+            acls = acMgr.getPolicies(path);
+        }
+
+        assertTrue(acls[0] instanceof ACLTemplate);
+
+        ACLTemplate acl = (ACLTemplate) acls[0];
+        assertEquals(path, acl.getPath());       
+
+        ACLTemplate.Entry entry = acl.createEntry(testPrincipal, new Privilege[] {acMgr.privilegeFromName(Privilege.JCR_READ)}, true);
+
+        // node is must be present + must match to testrootnodes id.
+        assertTrue(entry.isLocal(((NodeImpl) testRootNode).getNodeId()));
+        // but not to a random id.
+        assertFalse(entry.isLocal(new NodeId()));
     }
 }
\ No newline at end of file

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/TestAll.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/TestAll.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/TestAll.java Tue Aug 17 14:47:30 2010
@@ -39,6 +39,7 @@ public class TestAll extends TestCase {
 
         suite.addTestSuite(ACLTemplateTest.class);
         suite.addTestSuite(EntryTest.class);
+        suite.addTestSuite(EntryCollectorTest.class);
 
         suite.addTestSuite(ReadTest.class);
         suite.addTestSuite(WriteTest.class);

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/WriteTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/WriteTest.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/WriteTest.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/WriteTest.java Tue Aug 17 14:47:30 2010
@@ -46,14 +46,17 @@ import java.util.UUID;
  */
 public class WriteTest extends AbstractWriteTest {
 
+    @Override
     protected boolean isExecutable() {
         return EvaluationUtil.isExecutable(acMgr);
     }
 
+    @Override
     protected JackrabbitAccessControlList getPolicy(AccessControlManager acM, String path, Principal principal) throws RepositoryException, AccessDeniedException, NotExecutableException {
         return EvaluationUtil.getPolicy(acM, path, principal);
     }
 
+    @Override
     protected Map<String, Value> getRestrictions(Session s, String path) {
         return Collections.emptyMap();
     }

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/WriteTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/WriteTest.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/WriteTest.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/WriteTest.java Tue Aug 17 14:47:30 2010
@@ -20,6 +20,8 @@ import org.apache.jackrabbit.api.securit
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
 import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
 import org.apache.jackrabbit.test.NotExecutableException;
 import org.slf4j.Logger;
@@ -56,6 +58,21 @@ public class WriteTest extends org.apach
         }
     }
 
+    protected boolean isExecutable() {
+        try {
+            AccessControlPolicy[] rootPolicies = acMgr.getPolicies("/");
+            if (rootPolicies.length > 0) {
+                return true;
+            }
+            if (acMgr.getApplicablePolicies("/").hasNext()) {
+                return true;
+            }
+        } catch (RepositoryException e) {
+            // ignore
+        }
+        return false;
+    }
+
     private JackrabbitAccessControlList getPrincipalBasedPolicy(AccessControlManager acM, String path, Principal principal) throws RepositoryException, AccessDeniedException, NotExecutableException {
         if (acM instanceof JackrabbitAccessControlManager) {
             AccessControlPolicy[] tmpls = ((JackrabbitAccessControlManager) acM).getApplicablePolicies(principal);
@@ -174,4 +191,57 @@ public class WriteTest extends org.apach
         assertFalse(testSession.hasPermission(childNPath+"/anyproperty", javax.jcr.Session.ACTION_SET_PROPERTY));
         assertFalse(testAcMgr.hasPrivileges(childNPath, modPropPrivs));
     }
+
+    public void testCanReadOnCombinedPolicies() throws RepositoryException, NotExecutableException {
+        Group testGroup = getTestGroup();
+        Session testSession = getTestSession();
+        /*
+          precondition:
+          testuser must have READ-only permission on test-node and below
+        */
+        checkReadOnly(path);
+
+        Privilege[] readPrivs = privilegesFromName(Privilege.JCR_READ);
+        // nodebased: remove READ privilege for 'testUser' at 'path'
+        withdrawPrivileges(path, readPrivs, getRestrictions(superuser, path));
+        // principalbased: add READ privilege for 'testGroup'
+        givePrivileges(path, testGroup.getPrincipal(), readPrivs, getPrincipalBasedRestrictions(path), false);
+        /*
+         expected result:
+         - nodebased wins over principalbased -> READ is denied
+         */
+        NodeId nodeId = ((NodeImpl) superuser.getNode(path)).getNodeId();
+        assertFalse(((SessionImpl) testSession).getAccessManager().canRead(null, nodeId));
+
+        /* allow again on child N -> should be allowed */
+        givePrivileges(childNPath, testGroup.getPrincipal(), readPrivs, getPrincipalBasedRestrictions(path), false);
+
+        NodeId childId = ((NodeImpl) superuser.getNode(childNPath)).getNodeId();
+        assertTrue(((SessionImpl) testSession).getAccessManager().canRead(null, childId));
+
+        // remove the nodebased policy
+        JackrabbitAccessControlList policy = getPolicy(acMgr, path, testUser.getPrincipal());
+        acMgr.removePolicy(policy.getPath(), policy);
+        superuser.save();
+
+        /*
+         expected result:
+         - READ privilege is present again.
+         */
+        assertTrue(((SessionImpl) testSession).getAccessManager().canRead(null, nodeId));
+
+        // nodebased: remove READ privilege for 'testUser' at 'path'
+        givePrivileges(path, readPrivs, getRestrictions(superuser, path));
+        // principalbased: add READ privilege for 'testGroup'
+        withdrawPrivileges(path, testGroup.getPrincipal(), readPrivs, getPrincipalBasedRestrictions(path), false);
+        /*
+         expected result:
+         - nodebased wins over principalbased -> READ is allowed
+         */
+        assertTrue(((SessionImpl) testSession).getAccessManager().canRead(null, nodeId));
+
+        /* allow again on child N -> should be allowed */
+        withdrawPrivileges(childNPath, testGroup.getPrincipal(), readPrivs, getPrincipalBasedRestrictions(path), false);
+        assertFalse(((SessionImpl) testSession).getAccessManager().canRead(null, childId));
+    }
 }
\ No newline at end of file

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/EntryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/EntryTest.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/EntryTest.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/EntryTest.java Tue Aug 17 14:47:30 2010
@@ -47,6 +47,7 @@ public class EntryTest extends AbstractE
     private String nodePath;
     private String glob;
 
+    @Override
     protected void setUp() throws Exception {
         super.setUp();
 
@@ -64,6 +65,7 @@ public class EntryTest extends AbstractE
         acl = new ACLTemplate(testPrincipal, testPath, (SessionImpl) superuser, superuser.getValueFactory());
     }
 
+    @Override
     protected JackrabbitAccessControlEntry createEntry(Principal principal, Privilege[] privileges, boolean isAllow)
             throws RepositoryException {
         return (JackrabbitAccessControlEntry) acl.createEntry(principal, privileges, isAllow, restrictions);

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/TestAll.java?rev=986335&r1=986334&r2=986335&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/TestAll.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/TestAll.java Tue Aug 17 14:47:30 2010
@@ -49,6 +49,8 @@ public class TestAll extends TestCase {
 
         suite.addTestSuite(UserImporterTest.class);
 
+        suite.addTestSuite(UserAccessControlProviderTest.class);        
+
         return suite;
     }
 }



Mime
View raw message