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/12/15 13:21:00 UTC

svn commit: r1049520 - in /jackrabbit/trunk/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/security/authorization/ main/java/org/apache/jackrabbit/core/security/authorization/acl/ test/java/org/apache/jackrabbit/core/security/authorization/ ...

Author: angela
Date: Wed Dec 15 12:20:59 2010
New Revision: 1049520

URL: http://svn.apache.org/viewvc?rev=1049520&view=rev
Log:
JCR-2841 - Avoid path resolution in case of non-wildcard ACEs (follow-up to JCR-2573)

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CompiledPermissionsImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/EntryFilterImpl.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEvaluationTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractWriteTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/ReadTest.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryImpl.java?rev=1049520&r1=1049519&r2=1049520&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryImpl.java Wed Dec 15 12:20:59 2010
@@ -167,6 +167,16 @@ public abstract class AccessControlEntry
     }
 
     /**
+     * Returns <code>true</code> if this ACE defines any restriction.
+     *
+     * @return <code>true</code> if this ACE defines any restriction;
+     * <code>false</code> otherwise.
+     */
+    public boolean hasRestrictions() {
+        return !restrictions.isEmpty();
+    }
+
+    /**
      * Returns the restrictions defined for this entry.
      *
      * @return the restrictions defined for this entry.

Modified: 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=1049520&r1=1049519&r2=1049520&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CompiledPermissionsImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CompiledPermissionsImpl.java Wed Dec 15 12:20:59 2010
@@ -218,7 +218,7 @@ class CompiledPermissionsImpl extends Ab
         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;
+        boolean canRead = false;
         synchronized (monitor) {
             if (readCache.containsKey(id)) {
                 canRead = readCache.get(id);
@@ -226,11 +226,36 @@ class CompiledPermissionsImpl extends Ab
                 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);
+                boolean isAcItem = util.isAcItem(node);
+                EntryFilterImpl filter;
+                if (path == null) {
+                    filter = new EntryFilterImpl(principalNames, id, session);
+                } else {
+                    filter = new EntryFilterImpl(principalNames, path, session);
+                }
+
+                if (isAcItem) {
+                    /* item defines ac content -> regular evaluation */
+                    Result result = buildResult(node, isExistingNode, util.isAcItem(node), filter);
+                    canRead = result.grants(Permission.READ);
+                } else {
+                    /*
+                     simplified evaluation focusing on READ permission. this allows
+                     to omit evaluation of parent node permissions that are
+                     required when calculating the complete set of permissions
+                     (see special treatment of remove, create or ac-specific
+                      permissions).
+                     */
+                    for (AccessControlEntry accessControlEntry : entryCollector.collectEntries(node, filter)) {
+                        ACLTemplate.Entry ace = (ACLTemplate.Entry) accessControlEntry;
+                        int entryBits = ace.getPrivilegeBits();
+                        if ((entryBits & Permission.READ) == Permission.READ) {
+                            canRead = ace.isAllow();
+                            break;
+                        }
+                    }
+                }
                 readCache.put(id, canRead);
             }
         }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/EntryFilterImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/EntryFilterImpl.java?rev=1049520&r1=1049519&r2=1049520&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/EntryFilterImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/EntryFilterImpl.java Wed Dec 15 12:20:59 2010
@@ -16,19 +16,21 @@
  */
 package org.apache.jackrabbit.core.security.authorization.acl;
 
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.id.ItemId;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.commons.conversion.PathResolver;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.jcr.NamespaceException;
+import javax.jcr.RepositoryException;
 import javax.jcr.security.AccessControlEntry;
 import java.security.acl.Group;
 import java.util.Collection;
 import java.util.List;
 
 /**
- * <code>PrincipalEntryFilter</code>...
+ * <code>EntryFilterImpl</code>...
  */
 class EntryFilterImpl implements EntryFilter {
 
@@ -38,15 +40,27 @@ class EntryFilterImpl implements EntryFi
     private static final Logger log = LoggerFactory.getLogger(EntryFilterImpl.class);
 
     private final Collection<String> principalNames;
-    private final Path path;
-    private final PathResolver resolver;
+    private final PathProvider pathProvider;
 
     private String itemPath;
 
-    EntryFilterImpl(Collection<String> principalNames, Path path, PathResolver resolver) {
+    EntryFilterImpl(Collection<String> principalNames, final ItemId id, final SessionImpl sessionImpl) {
         this.principalNames = principalNames;
-        this.path = path;
-        this.resolver = resolver;
+        this.pathProvider = new PathProvider() {
+            public String getPath() throws RepositoryException {
+                Path p = sessionImpl.getHierarchyManager().getPath(id);
+                return sessionImpl.getJCRPath(p);
+            }
+        };
+    }
+
+    EntryFilterImpl(Collection<String> principalNames, final Path absPath, final PathResolver pathResolver) {
+        this.principalNames = principalNames;
+        this.pathProvider = new PathProvider() {
+            public String getPath() throws RepositoryException {
+                return pathResolver.getJCRPath(absPath);
+            }
+        };
     }
 
     /**
@@ -88,7 +102,8 @@ class EntryFilterImpl implements EntryFi
 
     private boolean matches(AccessControlEntry ace) {
         if (principalNames == null || principalNames.contains(ace.getPrincipal().getName())) {
-            if (((ACLTemplate.Entry) ace).getRestrictions().isEmpty()) {
+            ACLTemplate.Entry entry = (ACLTemplate.Entry) ace;
+            if (!entry.hasRestrictions()) {
                 // short cut: there is no glob-restriction -> the entry matches
                 // because it is either defined on the node or inherited.
                 return true;
@@ -96,8 +111,8 @@ class EntryFilterImpl implements EntryFi
                 // there is a glob-restriction: check if the target path matches
                 // this entry.
                 try {
-                    return ((ACLTemplate.Entry) ace).matches(getPath());
-                } catch (NamespaceException e) {
+                    return entry.matches(getPath());
+                } catch (RepositoryException e) {
                     log.error("Cannot determine ACE match.", e);
                 }
             }
@@ -107,10 +122,21 @@ class EntryFilterImpl implements EntryFi
         return false;
     }
 
-    String getPath() throws NamespaceException {
+    String getPath() throws RepositoryException {
         if (itemPath == null) {
-            itemPath = resolver.getJCRPath(path);
+            itemPath = pathProvider.getPath();
         }
         return itemPath;
     }
+
+    //--------------------------------------------------------------------------
+    /**
+     * Interface for lazy calculation of the JCR path used for evaluation of ACE
+     * matching in case of entries defining restriction(s).
+     */
+    private interface PathProvider {
+
+        String getPath() throws RepositoryException;
+
+    }
 }
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEvaluationTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEvaluationTest.java?rev=1049520&r1=1049519&r2=1049520&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEvaluationTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEvaluationTest.java Wed Dec 15 12:20:59 2010
@@ -18,9 +18,11 @@ package org.apache.jackrabbit.core.secur
 
 import org.apache.jackrabbit.api.JackrabbitSession;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.core.security.TestPrincipal;
 import org.apache.jackrabbit.test.NotExecutableException;
 import org.apache.jackrabbit.test.api.security.AbstractAccessControlTest;
 import org.slf4j.Logger;
@@ -49,6 +51,8 @@ public abstract class AbstractEvaluation
     private String uid;
     protected User testUser;
     protected Credentials creds;
+
+    protected Group testGroup;    
     
     private Session testSession;
     private AccessControlManager testAccessControlManager;
@@ -81,32 +85,41 @@ public abstract class AbstractEvaluation
 
     @Override
     protected void tearDown() throws Exception {
-        for (String path : toClear) {
-            try {
-                AccessControlPolicy[] policies = acMgr.getPolicies(path);
-                for (AccessControlPolicy policy : policies) {
-                    acMgr.removePolicy(path, policy);
+        try {
+            for (String path : toClear) {
+                try {
+                    AccessControlPolicy[] policies = acMgr.getPolicies(path);
+                    for (AccessControlPolicy policy : policies) {
+                        acMgr.removePolicy(path, policy);
+                    }
+                    superuser.save();
+                } catch (RepositoryException e) {
+                    // log error and ignore
+                    log.debug(e.getMessage());
                 }
-                superuser.save();
-            } catch (RepositoryException e) {
-                // log error and ignore
-                log.debug(e.getMessage());
             }
-        }
 
-        if (testSession != null && testSession.isLive()) {
-            testSession.logout();
-        }
-        if (uid != null) {
-            Authorizable a = getUserManager(superuser).getAuthorizable(uid);
-            if (a != null) {
-                a.remove();
-                if (!getUserManager(superuser).isAutoSave()) {
-                    superuser.save();
+            if (testSession != null && testSession.isLive()) {
+                testSession.logout();
+            }
+            if (testGroup != null && testUser != null) {
+                if (testGroup.isDeclaredMember(testUser)) {
+                    testGroup.removeMember(testUser);
                 }
+                testGroup.remove();
             }
+            if (uid != null) {
+                Authorizable a = getUserManager(superuser).getAuthorizable(uid);
+                if (a != null) {
+                    a.remove();
+                }
+            }
+            if (!getUserManager(superuser).isAutoSave() && superuser.hasPendingChanges()) {
+                superuser.save();
+            }
+        } finally {
+            super.tearDown();
         }
-        super.tearDown();
     }
 
     protected static UserManager getUserManager(Session session) throws
@@ -135,6 +148,20 @@ public abstract class AbstractEvaluation
         return testAccessControlManager;
     }
     
+    protected Group getTestGroup() throws RepositoryException, NotExecutableException {
+        if (testGroup == null) {
+            // create the testGroup
+            Principal principal = new TestPrincipal("testGroup" + UUID.randomUUID());
+            UserManager umgr = getUserManager(superuser);
+            testGroup = umgr.createGroup(principal);
+            testGroup.addMember(testUser);
+            if (!umgr.isAutoSave() && superuser.hasPendingChanges()) {
+                superuser.save();
+            }
+        }
+        return testGroup;
+    }
+    
     protected Node getTestNode() throws RepositoryException {
         if (trn == null) {
             trn = (Node) getTestSession().getItem(testRootNode.getPath());

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractWriteTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractWriteTest.java?rev=1049520&r1=1049519&r2=1049520&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractWriteTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractWriteTest.java Wed Dec 15 12:20:59 2010
@@ -55,8 +55,6 @@ public abstract class AbstractWriteTest 
 
     protected static final long DEFAULT_WAIT_TIMEOUT = 5000;
 
-    protected Group testGroup;
-
     protected String path;
     protected String childNPath;
     protected String childNPath2;
@@ -90,35 +88,6 @@ public abstract class AbstractWriteTest 
         siblingPath = n2.getPath();
     }
 
-    @Override
-    protected void tearDown() throws Exception {
-        try {
-            if (testGroup != null && testUser != null) {
-                testGroup.removeMember(testUser);
-                testGroup.remove();
-                if (!getUserManager(superuser).isAutoSave() && superuser.hasPendingChanges()) {
-                    superuser.save();
-                }
-            }
-        } finally {
-            super.tearDown();
-        }
-    }
-
-    protected Group getTestGroup() throws RepositoryException, NotExecutableException {
-        if (testGroup == null) {
-            // create the testGroup
-            Principal principal = new TestPrincipal("testGroup" + UUID.randomUUID());
-            UserManager umgr = getUserManager(superuser);
-            testGroup = umgr.createGroup(principal);
-            testGroup.addMember(testUser);
-            if (!umgr.isAutoSave() && superuser.hasPendingChanges()) {
-                superuser.save();
-            }
-        }
-        return testGroup;
-    }
-
     public void testGrantedPermissions() throws RepositoryException, AccessDeniedException, NotExecutableException {
         /* precondition:
            testuser must have READ-only permission on test-node and below
@@ -1095,7 +1064,7 @@ public abstract class AbstractWriteTest 
 
         // permissions defined @ path
         // restriction: grants write priv to all nodeName3 children
-        Map<String, Value> restrictions = new HashMap(getRestrictions(superuser, path));        
+        Map<String, Value> restrictions = new HashMap<String, Value>(getRestrictions(superuser, path));
         restrictions.put(AccessControlConstants.P_GLOB.toString(), vf.createValue("/*"+nodeName3));
         givePrivileges(path, write, restrictions);
 
@@ -1136,7 +1105,7 @@ public abstract class AbstractWriteTest 
         Privilege[] addNode = privilegesFromName(Privilege.JCR_ADD_CHILD_NODES);
         Privilege[] rmNode = privilegesFromName(Privilege.JCR_REMOVE_NODE);
 
-        Map<String, Value> restrictions = new HashMap(getRestrictions(superuser, path));
+        Map<String, Value> restrictions = new HashMap<String, Value>(getRestrictions(superuser, path));
 
         // permissions defined @ path
         // restriction: grants write-priv to nodeName3 grand-children but not direct nodeName3 children.
@@ -1177,7 +1146,7 @@ public abstract class AbstractWriteTest 
         Privilege[] addNode = privilegesFromName(Privilege.JCR_ADD_CHILD_NODES);
         String writeActions = Session.ACTION_ADD_NODE +","+Session.ACTION_REMOVE +","+ Session.ACTION_SET_PROPERTY;
 
-        Map<String, Value> restrictions = new HashMap(getRestrictions(superuser, path));
+        Map<String, Value> restrictions = new HashMap<String, Value>(getRestrictions(superuser, path));
 
         // permissions defined @ path
         // restriction: allows write to nodeName3 children
@@ -1219,7 +1188,7 @@ public abstract class AbstractWriteTest 
         Privilege[] write = privilegesFromName(PrivilegeRegistry.REP_WRITE);
         Privilege[] addNode = privilegesFromName(Privilege.JCR_ADD_CHILD_NODES);
 
-        Map<String, Value> restrictions = new HashMap(getRestrictions(superuser, path));
+        Map<String, Value> restrictions = new HashMap<String, Value>(getRestrictions(superuser, path));
         restrictions.put(AccessControlConstants.P_GLOB.toString(), vf.createValue("/*"+nodeName3));
         givePrivileges(path, write, restrictions);
 
@@ -1256,7 +1225,7 @@ public abstract class AbstractWriteTest 
         Privilege[] write = privilegesFromName(PrivilegeRegistry.REP_WRITE);
         Privilege[] addNode = privilegesFromName(Privilege.JCR_ADD_CHILD_NODES);
 
-        Map<String, Value> restrictions = new HashMap(getRestrictions(superuser, path));
+        Map<String, Value> restrictions = new HashMap<String, Value>(getRestrictions(superuser, path));
         restrictions.put(AccessControlConstants.P_GLOB.toString(), vf.createValue(""));
         givePrivileges(path, write, restrictions);
 

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/ReadTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/ReadTest.java?rev=1049520&r1=1049519&r2=1049520&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/ReadTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/ReadTest.java Wed Dec 15 12:20:59 2010
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.core.security.authorization.acl;
 
+import org.apache.jackrabbit.api.JackrabbitSession;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
 import org.apache.jackrabbit.core.security.authorization.AbstractEvaluationTest;
 import org.apache.jackrabbit.core.security.authorization.AccessControlConstants;
@@ -42,6 +43,7 @@ public class ReadTest extends AbstractEv
     private String path;
     private String childNPath;
 
+    @Override
     protected void setUp() throws Exception {
         super.setUp();
 
@@ -54,14 +56,17 @@ public class ReadTest extends AbstractEv
         childNPath = cn1.getPath();
     }
 
+    @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();
     }
@@ -85,6 +90,220 @@ public class ReadTest extends AbstractEv
         n.getDefinition();
     }
 
+    public void testDenyUserAllowGroup() throws Exception {
+        Privilege[] privileges = privilegesFromName(Privilege.JCR_READ);
+        Principal group = getTestGroup().getPrincipal();
+
+        /*
+         deny READ privilege for testUser at 'path'
+         */
+        withdrawPrivileges(path, testUser.getPrincipal(), privileges, getRestrictions(superuser, path));
+        /*
+         allow READ privilege for group at 'path'
+         */
+        givePrivileges(path, group, privileges, getRestrictions(superuser, path));
+
+        Session testSession = getTestSession();
+        assertFalse(testSession.nodeExists(path));
+    }
+
+    public void testAllowGroupDenyUser() throws Exception {
+        Privilege[] privileges = privilegesFromName(Privilege.JCR_READ);
+        Principal group = getTestGroup().getPrincipal();
+
+        /*
+        allow READ privilege for group at 'path'
+        */
+        givePrivileges(path, group, privileges, getRestrictions(superuser, path));
+        /*
+        deny READ privilege for testUser at 'path'
+        */
+        withdrawPrivileges(path, testUser.getPrincipal(), privileges, getRestrictions(superuser, path));
+
+        Session testSession = getTestSession();
+        assertFalse(testSession.nodeExists(path));
+    }
+
+    public void testAllowUserDenyGroup() throws Exception {
+        Privilege[] privileges = privilegesFromName(Privilege.JCR_READ);
+        Principal group = getTestGroup().getPrincipal();
+
+        /*
+         allow READ privilege for testUser at 'path'
+         */
+        givePrivileges(path, testUser.getPrincipal(), privileges, getRestrictions(superuser, path));
+        /*
+         deny READ privilege for group at 'path'
+         */
+        withdrawPrivileges(path, group, privileges, getRestrictions(superuser, path));
+
+        Session testSession = getTestSession();
+        assertTrue(testSession.nodeExists(path));
+    }
+
+    public void testDenyGroupAllowUser() throws Exception {
+        Privilege[] privileges = privilegesFromName(Privilege.JCR_READ);
+        Principal group = getTestGroup().getPrincipal();
+
+        /*
+         deny READ privilege for group at 'path'
+         */
+        withdrawPrivileges(path, group, privileges, getRestrictions(superuser, path));
+
+        /*
+         allow READ privilege for testUser at 'path'
+         */
+        givePrivileges(path, testUser.getPrincipal(), privileges, getRestrictions(superuser, path));
+
+        Session testSession = getTestSession();
+        assertTrue(testSession.nodeExists(path));
+    }
+
+    public void testDenyGroupAllowEveryone() throws Exception {
+        Privilege[] privileges = privilegesFromName(Privilege.JCR_READ);
+        Principal group = getTestGroup().getPrincipal();
+        Principal everyone = ((JackrabbitSession) superuser).getPrincipalManager().getEveryone();
+
+        /*
+         deny READ privilege for group at 'path'
+         */
+        withdrawPrivileges(path, group, privileges, getRestrictions(superuser, path));
+
+        /*
+         allow READ privilege for everyone at 'path'
+         */
+        givePrivileges(path, everyone, privileges, getRestrictions(superuser, path));
+
+        Session testSession = getTestSession();
+        assertTrue(testSession.nodeExists(path));
+    }
+
+    public void testAllowEveryoneDenyGroup() throws Exception {
+        Privilege[] privileges = privilegesFromName(Privilege.JCR_READ);
+        Principal group = getTestGroup().getPrincipal();
+        Principal everyone = ((JackrabbitSession) superuser).getPrincipalManager().getEveryone();
+
+        /*
+         allow READ privilege for everyone at 'path'
+         */
+        givePrivileges(path, everyone, privileges, getRestrictions(superuser, path));
+
+        /*
+         deny READ privilege for group at 'path'
+         */
+        withdrawPrivileges(path, group, privileges, getRestrictions(superuser, path));
+
+        Session testSession = getTestSession();
+        assertFalse(testSession.nodeExists(path));
+    }
+
+    public void testDenyGroupPathAllowEveryoneChildPath() throws Exception {
+        Privilege[] privileges = privilegesFromName(Privilege.JCR_READ);
+        Principal group = getTestGroup().getPrincipal();
+        Principal everyone = ((JackrabbitSession) superuser).getPrincipalManager().getEveryone();
+
+        /*
+         deny READ privilege for group at 'path'
+         */
+        withdrawPrivileges(path, group, privileges, getRestrictions(superuser, path));
+
+        /*
+         allow READ privilege for everyone at 'childNPath'
+         */
+        givePrivileges(path, everyone, privileges, getRestrictions(superuser, childNPath));
+
+        Session testSession = getTestSession();
+        assertTrue(testSession.nodeExists(childNPath));
+    }
+
+    public void testAllowEveryonePathDenyGroupChildPath() throws Exception {
+        Privilege[] privileges = privilegesFromName(Privilege.JCR_READ);
+        Principal group = getTestGroup().getPrincipal();
+        Principal everyone = ((JackrabbitSession) superuser).getPrincipalManager().getEveryone();
+
+        /*
+         allow READ privilege for everyone at 'path'
+         */
+        givePrivileges(path, everyone, privileges, getRestrictions(superuser, path));
+
+        /*
+         deny READ privilege for group at 'childNPath'
+         */
+        withdrawPrivileges(path, group, privileges, getRestrictions(superuser, childNPath));
+
+        Session testSession = getTestSession();
+        assertFalse(testSession.nodeExists(childNPath));
+    }
+
+    public void testAllowUserPathDenyGroupChildPath() throws Exception {
+        Privilege[] privileges = privilegesFromName(Privilege.JCR_READ);
+        Principal group = getTestGroup().getPrincipal();
+
+        /*
+         allow READ privilege for testUser at 'path'
+         */
+        givePrivileges(path, testUser.getPrincipal(), privileges, getRestrictions(superuser, path));
+        /*
+         deny READ privilege for group at 'childPath'
+         */
+        withdrawPrivileges(path, group, privileges, getRestrictions(superuser, childNPath));
+
+        Session testSession = getTestSession();
+        assertTrue(testSession.nodeExists(childNPath));
+    }
+
+    public void testDenyGroupPathAllowUserChildPath() throws Exception {
+        Privilege[] privileges = privilegesFromName(Privilege.JCR_READ);
+        Principal group = getTestGroup().getPrincipal();
+
+        /*
+         deny READ privilege for group at 'path'
+         */
+        withdrawPrivileges(path, group, privileges, getRestrictions(superuser, path));
+
+        /*
+         allow READ privilege for testUser at 'childNPath'
+         */
+        givePrivileges(path, testUser.getPrincipal(), privileges, getRestrictions(superuser, childNPath));
+
+        Session testSession = getTestSession();
+        assertTrue(testSession.nodeExists(childNPath));
+    }
+
+    public void testDenyUserPathAllowGroupChildPath() throws Exception {
+        Privilege[] privileges = privilegesFromName(Privilege.JCR_READ);
+        Principal group = getTestGroup().getPrincipal();
+
+        /*
+         deny READ privilege for testUser at 'path'
+         */
+        withdrawPrivileges(path, testUser.getPrincipal(), privileges, getRestrictions(superuser, path));
+        /*
+         allow READ privilege for group at 'childNPath'
+         */
+        givePrivileges(path, group, privileges, getRestrictions(superuser, childNPath));
+
+        Session testSession = getTestSession();
+        assertFalse(testSession.nodeExists(childNPath));
+    }
+
+    public void testAllowGroupPathDenyUserChildPath() throws Exception {
+        Privilege[] privileges = privilegesFromName(Privilege.JCR_READ);
+        Principal group = getTestGroup().getPrincipal();
+
+        /*
+        allow READ privilege for everyone at 'path'
+        */
+        givePrivileges(path, group, privileges, getRestrictions(superuser, path));
+        /*
+        deny READ privilege for testUser at 'childNPath'
+        */
+        withdrawPrivileges(path, testUser.getPrincipal(), privileges, getRestrictions(superuser, childNPath));
+
+        Session testSession = getTestSession();
+        assertFalse(testSession.nodeExists(childNPath));
+    }
+
     public void testGlobRestriction() throws Exception {
         Session testSession = getTestSession();
         AccessControlManager testAcMgr = getTestACManager();
@@ -96,13 +315,9 @@ public class ReadTest extends AbstractEv
         checkReadOnly(path);
         checkReadOnly(childNPath);
 
-        Node child = superuser.getNode(childNPath).addNode(nodeName3);
-        superuser.save();
-        String childchildPath = child.getPath();
-
         Privilege[] read = privilegesFromName(Privilege.JCR_READ);
 
-        Map<String, Value> restrictions = new HashMap(getRestrictions(superuser, path));
+        Map<String, Value> restrictions = new HashMap<String, Value>(getRestrictions(superuser, path));
         restrictions.put(AccessControlConstants.P_GLOB.toString(), vf.createValue("*/"+jcrPrimaryType));
 
         withdrawPrivileges(path, read, restrictions);