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 2009/01/08 12:52:45 UTC

svn commit: r732693 [3/6] - in /jackrabbit/trunk: jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jsr283/security/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ jackra...

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/AuthorizableImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/AuthorizableImpl.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/AuthorizableImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/AuthorizableImpl.java Thu Jan  8 03:52:38 2009
@@ -305,7 +305,7 @@
             return true;
         } catch (RepositoryException e) {
             // revert all pending changes and rethrow.
-            log.error("Error while editing group membership:", e.getMessage());
+            log.warn("Error while editing group membership:", e.getMessage());
             getSession().refresh(false);
             throw e;
         }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java Thu Jan  8 03:52:38 2009
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.core.security.user;
 
 import org.apache.jackrabbit.api.jsr283.security.AccessControlPolicy;
+import org.apache.jackrabbit.api.jsr283.security.Privilege;
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.core.ItemImpl;
@@ -189,7 +190,7 @@
                 // no 'user' within set of principals -> READ-only
                 return getReadOnlyPermissions();
             } else {
-                return new CompiledPermissionsImpl(principals, userNode);
+                return new CompiledPermissionsImpl(principals, userNode.getPath());
             }
         }
     }
@@ -251,6 +252,11 @@
         }
     }
 
+    private int getPrivilegeBits(String privName) throws RepositoryException {
+        Privilege[] privs = new Privilege[] {session.getAccessControlManager().privilegeFromName(privName)};
+        return PrivilegeRegistry.getBits(privs);
+    }
+
     private static boolean containsGroup(Set principals, String groupName) {
         for (Iterator it = principals.iterator(); it.hasNext() && groupName != null;) {
             Principal p = (Principal) it.next();
@@ -289,13 +295,13 @@
     private class CompiledPermissionsImpl extends AbstractCompiledPermissions
             implements SynchronousEventListener {
 
-        private final NodeImpl userNode;
+        private final String userNodePath;
 
         private boolean isUserAdmin;
         private boolean isGroupAdmin;
 
-        protected CompiledPermissionsImpl(Set principals, NodeImpl userNode) throws RepositoryException {
-            this.userNode = userNode;
+        protected CompiledPermissionsImpl(Set principals, String userNodePath) throws RepositoryException {
+            this.userNodePath = userNodePath;
             isUserAdmin = containsGroup(principals, userAdminGroup);
             isGroupAdmin = containsGroup(principals, groupAdminGroup);
 
@@ -308,6 +314,22 @@
          * @see AbstractCompiledPermissions#buildResult(Path)
          */
         protected Result buildResult(Path path) throws RepositoryException {
+            NodeImpl userNode = null;
+            try {
+                if (session.nodeExists(userNodePath)) {
+                    userNode = (NodeImpl) session.getNode(userNodePath);
+                }
+            } catch (RepositoryException e) {
+                // ignore
+            }
+
+            if (userNode == null) {
+                // no Node corresponding to user for which the permissions are
+                // calculated -> no permissions/priviles.
+                log.debug("No node at " + userNodePath);
+                return new Result(Permission.NONE, Permission.NONE, PrivilegeRegistry.NO_PRIVILEGE, PrivilegeRegistry.NO_PRIVILEGE);
+            }
+
             // no explicit denied permissions:
             int denies = Permission.NONE;
             // default allow permission and default privileges
@@ -317,7 +339,7 @@
             // Generally, privileges can only be determined for existing nodes.
             boolean calcPrivs = session.nodeExists(resolver.getJCRPath(path.getNormalizedPath()));
             if (calcPrivs) {
-                privs = PrivilegeRegistry.READ;
+                privs = getPrivilegeBits(Privilege.JCR_READ);
             } else {
                 privs = PrivilegeRegistry.NO_PRIVILEGE;
             }
@@ -370,23 +392,32 @@
                             3) special treatment for rep:group property which can
                                only be modified by group-administrators
                             */
+                            Path aPath = session.getQPath(authN.getPath());
                             if (requiredGroups) {
                                 // principals contain 'user-admin'
                                 // -> user can modify items below the user-node except rep:group.
                                 // principals contains 'user-admin' + 'group-admin'
                                 // -> user can modify rep:group property as well.
-                                allows = Permission.ALL;
+                                if (path.equals(aPath)) {
+                                    allows |= (Permission.ADD_NODE | Permission.REMOVE_PROPERTY | Permission.SET_PROPERTY);
+                                } else {
+                                    allows |= Permission.ALL;
+                                }
                                 if (calcPrivs) {
                                     // grant WRITE privilege
                                     // note: ac-read/modification is not included
-                                    privs |= PrivilegeRegistry.WRITE;
+                                    //       remove_node is not included
+                                    privs |= getPrivilegeBits(PrivilegeRegistry.REP_WRITE);
+                                    if (!path.equals(aPath)) {
+                                       privs |= getPrivilegeBits(Privilege.JCR_REMOVE_NODE);
+                                    }
                                 }
                             } else if (userNode.isSame(node) && (!isGroupProp || isGroupAdmin)) {
                                 // user can only read && write his own props
                                 // except for the rep:group property.
                                 allows |= (Permission.SET_PROPERTY | Permission.REMOVE_PROPERTY);
                                 if (calcPrivs) {
-                                    privs |= PrivilegeRegistry.MODIFY_PROPERTIES;
+                                    privs |= getPrivilegeBits(Privilege.JCR_MODIFY_PROPERTIES);
                                 }
                             } // else some other node below but not U-admin -> read-only.
                             break;
@@ -406,7 +437,7 @@
                                 if (calcPrivs) {
                                     // grant WRITE privilege
                                     // note: ac-read/modification is not included
-                                    privs |= PrivilegeRegistry.WRITE;
+                                    privs |= getPrivilegeBits(PrivilegeRegistry.REP_WRITE);
                                 }
                             }
                     }
@@ -419,7 +450,7 @@
                 if (isGroupAdmin) {
                     allows = Permission.ALL;
                     if (calcPrivs) {
-                        privs |= PrivilegeRegistry.WRITE;
+                        privs |= getPrivilegeBits(PrivilegeRegistry.REP_WRITE);
                     }
                 }
             } // else outside of user/group tree -> read only.
@@ -473,7 +504,7 @@
                     String repGroups = session.getJCRName(UserConstants.P_GROUPS);
                     // TODO: add better evaluation.
                     if (repGroups.equals(Text.getName(evPath)) &&
-                            userNode.getPath().equals(Text.getRelativeParent(evPath, 1))) {
+                            userNodePath.equals(Text.getRelativeParent(evPath, 1))) {
                         // recalculate the is...Admin flags
                         switch (ev.getType()) {
                             case Event.PROPERTY_REMOVED:
@@ -482,15 +513,17 @@
                                 break;
                             case Event.PROPERTY_ADDED:
                             case Event.PROPERTY_CHANGED:
-                                Value[] vs = session.getProperty(evPath).getValues();
-                                String princName = session.getJCRName(P_PRINCIPAL_NAME);
-                                for (int i = 0; i < vs.length; i++) {
-                                    Node groupNode = session.getNodeByUUID(vs[i].getString());
-                                    String pName = groupNode.getProperty(princName).getString();
-                                    if (userAdminGroup.equals(pName)) {
-                                        isUserAdmin = true;
-                                    } else if (groupAdminGroup.equals(pName)) {
-                                        isGroupAdmin = true;
+                                if (session.propertyExists(evPath)) {
+                                    Value[] vs = session.getProperty(evPath).getValues();
+                                    String princName = session.getJCRName(P_PRINCIPAL_NAME);
+                                    for (int i = 0; i < vs.length; i++) {
+                                        Node groupNode = session.getNodeByUUID(vs[i].getString());
+                                        String pName = groupNode.getProperty(princName).getString();
+                                        if (userAdminGroup.equals(pName)) {
+                                            isUserAdmin = true;
+                                        } else if (groupAdminGroup.equals(pName)) {
+                                            isGroupAdmin = true;
+                                        }
                                     }
                                 }
                                 break;
@@ -508,4 +541,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java Thu Jan  8 03:52:38 2009
@@ -71,6 +71,7 @@
     private final Map idPathMap = new LRUMap(1000);
 
     public UserManagerImpl(SessionImpl session, String adminId) throws RepositoryException {
+        super(false);
         this.session = session;
         this.adminId = adminId;
 
@@ -222,7 +223,7 @@
             setSecurityProperty(userNode, P_PRINCIPAL_NAME, getValue(principal.getName()));
             parent.save();
 
-            log.info("User created: " + userID + "; " + userNode.getPath());
+            log.debug("User created: " + userID + "; " + userNode.getPath());
             return createUser(userNode);
         } catch (RepositoryException e) {
             // something went wrong -> revert changes and rethrow
@@ -274,7 +275,7 @@
             setSecurityProperty(groupNode, P_PRINCIPAL_NAME, getValue(principal.getName()));
             parent.save();
 
-            log.info("Group created: " + groupID + "; " + groupNode.getPath());
+            log.debug("Group created: " + groupID + "; " + groupNode.getPath());
 
             return createGroup(groupNode);
         } catch (RepositoryException e) {

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java Thu Jan  8 03:52:38 2009
@@ -31,8 +31,6 @@
 import javax.jcr.ReferentialIntegrityException;
 import javax.jcr.PropertyType;
 
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.IdentityHashMap;

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java Thu Jan  8 03:52:38 2009
@@ -16,21 +16,23 @@
  */
 package org.apache.jackrabbit.core.version;
 
-import org.apache.jackrabbit.core.ItemManager;
 import org.apache.jackrabbit.core.AbstractNodeData;
+import org.apache.jackrabbit.core.ItemManager;
 import org.apache.jackrabbit.core.NodeId;
-import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.NodeImpl;
-import org.apache.jackrabbit.spi.commons.conversion.NameException;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.security.authorization.Permission;
 import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.commons.conversion.NameException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.jcr.InvalidItemStateException;
 import javax.jcr.Item;
+import javax.jcr.NodeIterator;
 import javax.jcr.RepositoryException;
 import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.NodeIterator;
-import javax.jcr.InvalidItemStateException;
+import javax.jcr.ItemNotFoundException;
 import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.version.Version;
 import javax.jcr.version.VersionException;
@@ -51,10 +53,7 @@
      * Create a new instance of this class.
      * @param itemMgr item manager
      * @param session session
-     * @param id node id
-     * @param state node state
-     * @param definition node definition
-     * @param listeners life cycle listeners
+     * @param data
      */
     public VersionHistoryImpl(ItemManager itemMgr, SessionImpl session, AbstractNodeData data) {
         super(itemMgr, session, data);
@@ -132,6 +131,8 @@
     public void addVersionLabel(String versionName, String label, boolean move)
             throws VersionException, RepositoryException {
         try {
+            // check permissions
+            checkVersionManagementPermission();
             session.getVersionManager().setVersionLabel(
                     this, session.getQName(versionName),
                     session.getQName(label), move);
@@ -145,8 +146,9 @@
      */
     public void removeVersionLabel(String label) throws RepositoryException {
         try {
-            Version existing = session.getVersionManager().setVersionLabel(
-                    this, null, session.getQName(label), true);
+            // check permissions
+            checkVersionManagementPermission();
+            Version existing = session.getVersionManager().setVersionLabel(this, null, session.getQName(label), true);
             if (existing == null) {
                 throw new VersionException("No version with label '" + label + "' exists in this version history.");
             }
@@ -215,8 +217,9 @@
             throws UnsupportedRepositoryOperationException, VersionException,
             RepositoryException {
         try {
-            session.getVersionManager().removeVersion(
-                    this, session.getQName(versionName));
+            // check permissions
+            checkVersionManagementPermission();
+            session.getVersionManager().removeVersion(this, session.getQName(versionName));
         } catch (NameException e) {
             throw new RepositoryException(e);
         }
@@ -247,6 +250,19 @@
     }
 
     /**
+     * 
+     * @return
+     * @throws RepositoryException
+     */
+    private void checkVersionManagementPermission() throws RepositoryException {
+        try {
+            session.getAccessManager().checkPermission(getPrimaryPath(), Permission.VERSION_MNGMT);
+        } catch (ItemNotFoundException e) {
+            // ignore.
+        }
+    }
+    
+    /**
      * Checks if the given version belongs to this history
      *
      * @param version

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java Thu Jan  8 03:52:38 2009
@@ -19,6 +19,7 @@
 import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.security.authorization.Permission;
 import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
@@ -27,6 +28,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.jcr.AccessDeniedException;
 import javax.jcr.ImportUUIDBehavior;
 import javax.jcr.ItemExistsException;
 import javax.jcr.ItemNotFoundException;
@@ -65,7 +67,7 @@
      * @param importTargetNode
      * @param session
      * @param uuidBehavior     any of the constants declared by
-     *                         {@link ImportUUIDBehavior}
+     *                         {@link javax.jcr.ImportUUIDBehavior}
      */
     public SessionImporter(NodeImpl importTargetNode,
                            SessionImpl session,
@@ -184,6 +186,13 @@
             log.debug("Skipping node: " + nodeName);
             return;
         }
+
+        // make sure the editing session is allowed create nodes with a
+        // specified node type (and ev. mixins)
+        if (!session.getAccessManager().isGranted(session.getQPath(parent.getPath()), nodeName, Permission.NODE_TYPE_MNGMT)) {
+            throw new AccessDeniedException("Insufficient permission.");
+        }
+
         if (parent.hasNode(nodeName)) {
             // a node with that name already exists...
             NodeImpl existing = parent.getNode(nodeName);

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/AbstractLockTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/AbstractLockTest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/AbstractLockTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/AbstractLockTest.java Thu Jan  8 03:52:38 2009
@@ -108,9 +108,6 @@
         assertTrue("Seconds remaining must be a positive long or 0.", lock.getSecondsRemaining() >= 0);
     }
 
-
-
-
     public void testRemoveMixLockableFromLockedNode() throws RepositoryException {
         try {
             lockedNode.removeMixin(mixLockable);

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/DeepLockTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/DeepLockTest.java?rev=732693&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/DeepLockTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/DeepLockTest.java Thu Jan  8 03:52:38 2009
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.api.jsr283.lock;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.lock.LockException;
+
+/** <code>DeepLockTest</code>... */
+public class DeepLockTest extends AbstractJCRTest {
+
+    private static Logger log = LoggerFactory.getLogger(DeepLockTest.class);
+
+    protected Node lockedNode;
+    protected Node childNode;
+    protected Lock lock;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        lockedNode = testRootNode.addNode(nodeName1, testNodeType);
+        lockedNode.addMixin(mixLockable);
+        childNode = lockedNode.addNode(nodeName2, testNodeType);
+        testRootNode.save();
+
+        // TODO: remove cast
+        // TODO: replace by LockManager#lock call
+        lock = (Lock) lockedNode.lock(true, true);
+    }
+
+    protected void tearDown() throws Exception {
+        // make sure all locks are removed
+        try {
+            lockedNode.unlock();
+        } catch (RepositoryException e) {
+            // ignore
+        }
+        super.tearDown();
+    }
+
+    // TODO: replace locking calls by LockManager#...
+
+    public void testNewBelowDeepLock() throws RepositoryException {
+        Node newNode = lockedNode.addNode(nodeName3);
+        assertTrue(newNode.isLocked());
+    }
+
+    public void testLockHoldingNode() throws RepositoryException {
+        assertTrue("Lock.getNode() must be lockholding node.", lock.getNode().isSame(lockedNode));
+    }
+
+    public void testLockIsDeep() throws RepositoryException {
+        assertTrue("Lock.isDeep() if lock has been created deeply.", lock.isDeep());
+    }
+
+    public void testNodeIsLocked() throws RepositoryException {
+        assertTrue("Creating a deep lock must create a lock on the lock-holding node", lockedNode.isLocked());
+        assertTrue("Creating a deep lock must create a lock on the lock-holding node", lockedNode.holdsLock());
+    }
+
+    public void testIsLockedChild() throws RepositoryException {
+        assertTrue("Child node below deep lock must be locked", childNode.isLocked());
+    }
+
+    public void testIsLockedNewChild() throws RepositoryException {
+        Node newChild = lockedNode.addNode(nodeName3, testNodeType);
+        assertTrue("Child node below deep lock must be locked even if it is NEW",
+                newChild.isLocked());
+    }
+
+    public void testNotHoldsLockChild() throws RepositoryException {
+        assertFalse("Child node below deep lock must not be lock holder",
+                childNode.holdsLock());
+    }
+
+    public void testGetLockOnChild() throws RepositoryException {
+        // get lock must succeed even if child is not lockable.
+        javax.jcr.lock.Lock lock = childNode.getLock();
+        assertNotNull(lock);
+        assertTrue("Lock.getNode() must return the lock holding node",
+                lockedNode.isSame(lock.getNode()));
+    }
+
+    public void testGetLockOnNewChild() throws RepositoryException {
+        // get lock must succeed even if child is not lockable.
+        Node newChild = lockedNode.addNode(nodeName3, testNodeType);
+        javax.jcr.lock.Lock lock = newChild.getLock();
+        assertNotNull(lock);
+        assertTrue("Lock.getNode() must return the lock holding node",
+                lockedNode.isSame(lock.getNode()));
+    }
+
+    public void testGetNodeOnLockObtainedFromChild() throws RepositoryException {
+        javax.jcr.lock.Lock lock = childNode.getLock();
+        assertTrue("Lock.getNode() must return the lock holding node even if lock is obtained from child node.", lock.getNode().isSame(lockedNode));
+    }
+
+    public void testGetNodeOnLockObtainedFromNewChild() throws RepositoryException {
+        Node newChild = lockedNode.addNode(nodeName3, testNodeType);
+        javax.jcr.lock.Lock lock = newChild.getLock();
+        assertTrue("Lock.getNode() must return the lock holding node even if lock is obtained from child node.", lock.getNode().isSame(lockedNode));
+    }
+
+    public void testParentChildDeepLock() throws RepositoryException {
+        childNode.addMixin(mixLockable);
+        testRootNode.save();
+
+        // try to lock child node
+        try {
+            childNode.lock(false, false);
+            fail("child node is already locked by deep lock on parent.");
+        } catch (LockException e) {
+            // ok
+        }
+    }
+
+    public void testDeepLockAboveLockedChild() throws RepositoryException, NotExecutableException {
+        try {
+            Node parent = lockedNode.getParent();
+            if (!parent.isNodeType(mixLockable)) {
+                try {
+                    parent.addMixin(mixLockable);
+                    parent.save();
+                } catch (RepositoryException e) {
+                    throw new NotExecutableException();
+                }
+            }
+
+            parent.lock(true, true);
+            fail("Creating a deep lock on a parent of a locked node must fail.");
+        } catch (LockException e) {
+            // expected
+        }
+    }
+
+    public void testShallowLockAboveLockedChild() throws RepositoryException, NotExecutableException {
+        Node parent = lockedNode.getParent();
+        try {
+            if (!parent.isNodeType(mixLockable)) {
+                try {
+                    parent.addMixin(mixLockable);
+                    parent.save();
+                } catch (RepositoryException e) {
+                    throw new NotExecutableException();
+                }
+            }
+
+            // creating a shallow lock on the parent must succeed.
+            parent.lock(false, true);
+        } finally {
+            parent.unlock();
+        }
+    }
+
+    public void testRemoveLockedChild() throws RepositoryException {
+        Session otherSession = helper.getReadWriteSession();
+        try {
+            Node child = (Node) otherSession.getItem(childNode.getPath());
+            child.remove();
+            otherSession.save();
+            fail("A node below a deeply locked node cannot be removed by another Session.");
+        } catch (LockException e) {
+            // success
+        } finally {
+            otherSession.logout();
+        }
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/DeepLockTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/DeepLockTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/LockManagerTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/LockManagerTest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/LockManagerTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/LockManagerTest.java Thu Jan  8 03:52:38 2009
@@ -19,7 +19,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.jackrabbit.test.AbstractJCRTest;
-import org.apache.jackrabbit.test.NotExecutableException;
 
 /** <code>LockManagerTest</code>... */
 public class LockManagerTest extends AbstractJCRTest {

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/OpenScopedLockTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/OpenScopedLockTest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/OpenScopedLockTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/OpenScopedLockTest.java Thu Jan  8 03:52:38 2009
@@ -18,8 +18,6 @@
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.apache.jackrabbit.test.AbstractJCRTest;
-import org.apache.jackrabbit.test.NotExecutableException;
 
 /** <code>OpenScopedLockTest</code>... */
 public class OpenScopedLockTest extends AbstractLockTest {

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/SessionScopedLockTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/SessionScopedLockTest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/SessionScopedLockTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/SessionScopedLockTest.java Thu Jan  8 03:52:38 2009
@@ -18,15 +18,6 @@
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.apache.jackrabbit.test.AbstractJCRTest;
-import org.apache.jackrabbit.test.NotExecutableException;
-
-import javax.jcr.lock.LockException;
-import javax.jcr.AccessDeniedException;
-import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.Node;
 
 /** <code>SessionScopedLockTest</code>... */
 public class SessionScopedLockTest extends AbstractLockTest {
@@ -47,5 +38,4 @@
     public void testGetLockToken() {
         assertNull("A session scoped lock may never expose the token.", lock.getLockToken());
     }
-
 }
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/TestAll.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/TestAll.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/TestAll.java Thu Jan  8 03:52:38 2009
@@ -35,6 +35,7 @@
         suite.addTestSuite(LockManagerTest.class);
         suite.addTestSuite(OpenScopedLockTest.class);
         suite.addTestSuite(SessionScopedLockTest.class);
+        suite.addTestSuite(DeepLockTest.class);
         */
 
         return suite;

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/security/AccessControlListTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/security/AccessControlListTest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/security/AccessControlListTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/security/AccessControlListTest.java Thu Jan  8 03:52:38 2009
@@ -16,24 +16,24 @@
  */
 package org.apache.jackrabbit.api.jsr283.security;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.jackrabbit.test.NotExecutableException;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.security.TestPrincipal;
+import org.apache.jackrabbit.test.NotExecutableException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import javax.jcr.AccessDeniedException;
 import javax.jcr.Node;
-import javax.jcr.Session;
 import javax.jcr.RepositoryException;
-import javax.jcr.AccessDeniedException;
-import java.util.Iterator;
-import java.util.Arrays;
-import java.util.List;
+import javax.jcr.Session;
+import java.security.Principal;
+import java.security.acl.Group;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
-import java.security.Principal;
-import java.security.acl.Group;
 
 /**
  * <code>AccessControlEntryTest</code>...
@@ -88,7 +88,6 @@
 
     protected void tearDown() throws Exception {
         try {
-            // TODO: review if correct.
             // restore original entries (remove others).
             AccessControlList list = getList(acMgr, path);
             AccessControlEntry[] entries = list.getAccessControlEntries();
@@ -98,10 +97,15 @@
                     list.removeAccessControlEntry(ace);
                 }
             }
-            list.addAccessControlEntry(testPrincipal, (Privilege[]) privilegesToRestore.toArray(new Privilege[privilegesToRestore.size()]));
-            superuser.save();
+            if (!privilegesToRestore.isEmpty()) {
+                list.addAccessControlEntry(testPrincipal, (Privilege[]) privilegesToRestore.toArray(new Privilege[privilegesToRestore.size()]));
+            }
+            if (list.getAccessControlEntries().length > 0 && acMgr.getPolicies(path).length > 0) {
+                acMgr.setPolicy(path, list);
+                superuser.save();                
+            }
         } catch (Exception e) {
-            AccessControlListTest.log.error("Unexpected error while removing test entries.", e);
+            log.warn("Unexpected error while removing test entries.", e);
         }
         super.tearDown();
     }
@@ -215,6 +219,30 @@
         }
     }
 
+    public void testAddAbstractPrivilege() throws NotExecutableException, RepositoryException {
+        checkCanModifyAc(path);
+
+        Privilege abstractPriv = null;
+        Privilege[] allPrivs = acMgr.privilegeFromName(Privilege.JCR_ALL).getAggregatePrivileges();
+        for (int i = 0; i < allPrivs.length; i++) {
+            if (allPrivs[i].isAbstract()) {
+                abstractPriv = allPrivs[i];
+                break;
+            }
+        }
+        if (abstractPriv == null) {
+            throw new NotExecutableException("No abstract privilege found.");
+        }
+
+        AccessControlList acl = getList(acMgr, path);
+        try {
+            acl.addAccessControlEntry(testPrincipal, new Privilege[] {abstractPriv});
+            fail("Adding an ACE with an abstract privilege must fail.");
+        } catch (AccessControlException e) {
+            // success
+        }
+    }
+
     public void testAddPrivilegesPresentInEntries() throws NotExecutableException, RepositoryException {
         checkCanModifyAc(path);
 

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java Thu Jan  8 03:52:38 2009
@@ -24,6 +24,8 @@
 import javax.jcr.Session;
 import javax.jcr.RepositoryException;
 import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.InvalidItemStateException;
 import javax.jcr.version.VersionException;
 import javax.jcr.version.Version;
 import javax.jcr.lock.Lock;
@@ -88,7 +90,7 @@
     }
 
     /**
-     * @see junit.framework#runTest
+     * @see junit.framework.TestCase#runTest
      *
      * Make sure that tested repository supports transactions
      */
@@ -746,38 +748,39 @@
      */
     public void testLockCommit() throws Exception {
         Session other = helper.getSuperuserSession();
+        try {
+            // add node that is both lockable and referenceable, save
+            Node n = testRootNode.addNode(nodeName1);
+            n.addMixin(mixLockable);
+            n.addMixin(mixReferenceable);
+            testRootNode.save();
 
-        // add node that is both lockable and referenceable, save
-        Node n = testRootNode.addNode(nodeName1);
-        n.addMixin(mixLockable);
-        n.addMixin(mixReferenceable);
-        testRootNode.save();
-
-        // reference node in second session
-        Node nOther = other.getNodeByUUID(n.getUUID());
-
-        // verify node is not locked in either session
-        assertFalse("Node not locked in session 1", n.isLocked());
-        assertFalse("Node not locked in session 2", nOther.isLocked());
-
-        // get user transaction object, start and lock node
-        UserTransaction utx = new UserTransactionImpl(superuser);
-        utx.begin();
-        n.lock(false, true);
-
-        // verify node is locked in first session only
-        assertTrue("Node locked in session 1", n.isLocked());
-        assertFalse("Node not locked in session 2", nOther.isLocked());
+            // reference node in second session
+            Node nOther = other.getNodeByUUID(n.getUUID());
 
-        // commit in first session
-        utx.commit();
+            // verify node is not locked in either session
+            assertFalse("Node not locked in session 1", n.isLocked());
+            assertFalse("Node not locked in session 2", nOther.isLocked());
+
+            // get user transaction object, start and lock node
+            UserTransaction utx = new UserTransactionImpl(superuser);
+            utx.begin();
+            n.lock(false, true);
+
+            // verify node is locked in first session only
+            assertTrue("Node locked in session 1", n.isLocked());
+            assertFalse("Node not locked in session 2", nOther.isLocked());
 
-        // verify node is locked in both sessions
-        assertTrue("Node locked in session 1", n.isLocked());
-        assertTrue("Node locked in session 2", nOther.isLocked());
+            // commit in first session
+            utx.commit();
 
-        // logout
-        other.logout();
+            // verify node is locked in both sessions
+            assertTrue("Node locked in session 1", n.isLocked());
+            assertTrue("Node locked in session 2", nOther.isLocked());
+        } finally {
+            // logout
+            other.logout();
+        }
     }
 
     /**
@@ -787,38 +790,41 @@
      */
     public void testLockRollback() throws Exception {
         Session other = helper.getSuperuserSession();
+        try {
+            // add node that is both lockable and referenceable, save
+            Node n = testRootNode.addNode(nodeName1);
+            n.addMixin(mixLockable);
+            n.addMixin(mixReferenceable);
+            testRootNode.save();
 
-        // add node that is both lockable and referenceable, save
-        Node n = testRootNode.addNode(nodeName1);
-        n.addMixin(mixLockable);
-        n.addMixin(mixReferenceable);
-        testRootNode.save();
-
-        // reference node in second session
-        Node nOther = other.getNodeByUUID(n.getUUID());
-
-        // verify node is not locked in either session
-        assertFalse("Node not locked in session 1", n.isLocked());
-        assertFalse("Node not locked in session 2", nOther.isLocked());
-
-        // get user transaction object, start and lock node
-        UserTransaction utx = new UserTransactionImpl(superuser);
-        utx.begin();
-        n.lock(false, true);
-
-        // verify node is locked in first session only
-        assertTrue("Node locked in session 1", n.isLocked());
-        assertFalse("Node not locked in session 2", nOther.isLocked());
-
-        // rollback in first session
-        utx.rollback();
-
-        // verify node is not locked in either session
-        assertFalse("Node not locked in session 1", n.isLocked());
-        assertFalse("Node not locked in session 2", nOther.isLocked());
+            // reference node in second session
+            Node nOther = other.getNodeByUUID(n.getUUID());
 
-        // logout
-        other.logout();
+            // verify node is not locked in either session
+            assertFalse("Node not locked in session 1", n.isLocked());
+            assertFalse("Node not locked in session 2", nOther.isLocked());
+
+            // get user transaction object, start and lock node
+            UserTransaction utx = new UserTransactionImpl(superuser);
+            utx.begin();
+            n.lock(false, true);
+
+            // verify node is locked in first session only
+            assertTrue("Node locked in session 1", n.isLocked());
+            assertFalse("Node not locked in session 2", nOther.isLocked());
+            assertFalse("Node not locked in session 2", nOther.hasProperty(jcrLockOwner));
+
+            // rollback in first session
+            utx.rollback();
+
+            // verify node is not locked in either session
+            assertFalse("Node not locked in session 1", n.isLocked());
+            assertFalse("Node not locked in session 2", nOther.isLocked());
+            assertFalse("Node not locked in session 2", nOther.hasProperty(jcrlockIsDeep));
+        } finally {
+            // logout
+            other.logout();
+        }
     }
 
     /**
@@ -828,46 +834,50 @@
      */
     public void testLockTwice() throws Exception {
         Session other = helper.getSuperuserSession();
+        try {
+            // add node that is both lockable and referenceable, save
+            Node n = testRootNode.addNode(nodeName1);
+            n.addMixin(mixLockable);
+            n.addMixin(mixReferenceable);
+            testRootNode.save();
 
-        // add node that is both lockable and referenceable, save
-        Node n = testRootNode.addNode(nodeName1);
-        n.addMixin(mixLockable);
-        n.addMixin(mixReferenceable);
-        testRootNode.save();
-
-        // reference node in second session
-        Node nOther = other.getNodeByUUID(n.getUUID());
-
-        // verify node is not locked in either session
-        assertFalse("Node not locked in session 1", n.isLocked());
-        assertFalse("Node not locked in session 2", nOther.isLocked());
-
-        // get user transaction object, start and lock node
-        UserTransaction utx = new UserTransactionImpl(superuser);
-        utx.begin();
-        n.lock(false, true);
+            // reference node in second session
+            Node nOther = other.getNodeByUUID(n.getUUID());
 
-        // lock node in non-transactional session, too
-        nOther.lock(false, true);
+            // verify node is not locked in either session
+            assertFalse("Node not locked in session 1", n.isLocked());
+            assertFalse("Node not locked in session 2", nOther.isLocked());
+
+            // get user transaction object, start and lock node
+            UserTransaction utx = new UserTransactionImpl(superuser);
+            utx.begin();
+            n.lock(false, true);
+
+            // lock node in non-transactional session, too
+            nOther.lock(false, true);
+
+            // verify node is locked in both sessions
+            assertTrue("Node locked in session 1", n.isLocked());
+            assertTrue("Node locked in session 2", nOther.isLocked());
+            assertTrue("Node locked in session 2", nOther.hasProperty(jcrLockOwner));
+
+            // assertion: commit must fail since node has already been locked
+            try {
+                utx.commit();
+                fail("Commit succeeds with double locking");
+            } catch (RollbackException e) {
+                /* expected */
+            }
 
-        // verify node is locked in both sessions
-        assertTrue("Node locked in session 1", n.isLocked());
-        assertTrue("Node locked in session 2", nOther.isLocked());
+            // verify node is locked in both sessions
+            assertTrue("Node locked in session 1", n.isLocked());
+            assertTrue("Node locked in session 2", nOther.isLocked());
+            assertTrue("Node locked in session 2", nOther.hasProperty(jcrlockIsDeep));
 
-        // assertion: commit must fail since node has already been locked
-        try {
-            utx.commit();
-            fail("Commit succeeds with double locking");
-        } catch (RollbackException e) {
-            /* expected */
+        } finally {
+            // logout
+            other.logout();
         }
-
-        // verify node is locked in both sessions
-        assertTrue("Node locked in session 1", n.isLocked());
-        assertTrue("Node locked in session 2", nOther.isLocked());
-
-        // logout
-        other.logout();
     }
 
     /**
@@ -986,6 +996,126 @@
         assertTrue("Lock live", lock.isLive());
     }
 
+    /**
+     * Test correct behaviour of lock related properties within transaction.
+     *
+     * @throws Exception
+     */
+    public void testLockProperties() throws Exception {
+        Node n = testRootNode.addNode(nodeName1);
+        n.addMixin(mixLockable);
+        n.addMixin(mixReferenceable);
+        testRootNode.save();
+
+        // get user transaction object, start and lock node
+        UserTransaction utx = new UserTransactionImpl(superuser);
+        utx.begin();
+        Lock lock = n.lock(false, true);
+
+        // verify that the lock properties have been created and are neither
+        // NEW nor MODIFIED.
+        assertTrue(n.hasProperty(jcrLockOwner));
+        Property lockOwner = n.getProperty(jcrLockOwner);
+        assertFalse(lockOwner.isNew());
+        assertFalse(lockOwner.isModified());
+
+        assertTrue(n.hasProperty(jcrlockIsDeep));
+        Property lockIsDeep = n.getProperty(jcrlockIsDeep);
+        assertFalse(lockIsDeep.isNew());
+        assertFalse(lockIsDeep.isModified());
+
+        // rollback
+        utx.rollback();
+
+        // verify that the lock properties have been removed again.
+        assertFalse(n.hasProperty(jcrLockOwner));
+        try {
+            lockOwner.getPath();
+            fail("jcr:lockIsDeep property must have been invalidated.");
+        } catch (InvalidItemStateException e) {
+            // success
+        }
+        assertFalse(n.hasProperty(jcrlockIsDeep));
+        try {
+            lockIsDeep.getPath();
+            fail("jcr:lockIsDeep property must have been invalidated.");
+        } catch (InvalidItemStateException e) {
+            // success
+        }
+    }
+
+    /**
+     * Test correct behaviour of lock related properties within transaction.
+     *
+     * @throws Exception
+     */
+    public void testLockProperties2() throws Exception {
+        // add node that is both lockable and referenceable, save
+        Node n = testRootNode.addNode(nodeName1);
+        n.addMixin(mixLockable);
+        n.addMixin(mixReferenceable);
+        testRootNode.save();
+
+        Lock lock = n.lock(false, true);
+
+        // get user transaction object, start
+        UserTransaction utx = new UserTransactionImpl(superuser);
+        utx.begin();
+
+        // verify that the lock properties are present
+        assertTrue(n.hasProperty(jcrLockOwner));
+        assertTrue(n.hasProperty(jcrlockIsDeep));
+
+        // unlock
+        n.unlock();
+
+        // verify that the lock properties have been removed.
+        assertFalse(n.hasProperty(jcrLockOwner));
+        assertFalse(n.hasProperty(jcrlockIsDeep));
+
+        // rollback
+        utx.rollback();
+
+        // verify lock is live again -> properties must be present
+        assertTrue(n.hasProperty(jcrLockOwner));
+        assertTrue(n.hasProperty(jcrlockIsDeep));
+    }
+
+    /**
+     * Test visibility of lock properties by another session.
+     */
+    public void testLockProperties3() throws Exception {
+        // add node that is both lockable and referenceable, save
+        Node n = testRootNode.addNode(nodeName1);
+        n.addMixin(mixLockable);
+        n.addMixin(mixReferenceable);
+        testRootNode.save();
+
+        Lock lock = n.lock(false, true);
+
+        // get user transaction object, start
+        UserTransaction utx = new UserTransactionImpl(superuser);
+        utx.begin();
+
+        // unlock
+        n.unlock();
+
+        Node n2 = (Node) otherSuperuser.getItem(n.getPath());
+        assertTrue(n2.isLocked());
+        assertTrue(n2.hasProperty(jcrLockOwner));
+        assertTrue(n2.hasProperty(jcrlockIsDeep));
+        Lock lock2 = n2.getLock();
+
+        // rollback
+        utx.commit();
+
+        n2.refresh(false);
+        assertFalse(lock2.isLive());
+        assertFalse(n2.isLocked());
+        assertFalse(n2.hasProperty(jcrLockOwner));
+        assertFalse(n2.hasProperty(jcrlockIsDeep));
+    }
+
     //-----------------------------------------------------------< versioning >
 
     /**

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/SimpleEventListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/SimpleEventListener.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/SimpleEventListener.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/SimpleEventListener.java Thu Jan  8 03:52:38 2009
@@ -50,10 +50,10 @@
     /**
      * {@inheritDoc}
      */
-    public void externalLock(NodeId nodeId, boolean isDeep, String userId)
+    public void externalLock(NodeId nodeId, boolean isDeep, String lockOwner)
             throws RepositoryException {
 
-        clusterEvents.add(new LockEvent(nodeId, isDeep, userId));
+        clusterEvents.add(new LockEvent(nodeId, isDeep, lockOwner));
     }
 
     /**

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/daily/DailyIntegrationTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/daily/DailyIntegrationTest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/daily/DailyIntegrationTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/daily/DailyIntegrationTest.java Thu Jan  8 03:52:38 2009
@@ -29,6 +29,8 @@
 import org.apache.jackrabbit.core.ConcurrentVersioningWithTransactionsTest;
 import org.apache.jackrabbit.core.LockTest;
 import org.apache.jackrabbit.core.ReadVersionsWhileModified;
+import org.apache.jackrabbit.core.lock.ConcurrentLockingTest;
+import org.apache.jackrabbit.core.lock.ConcurrentLockingWithTransactionsTest;
 
 /**
  * Contains tests that are run on a daily basis.
@@ -52,6 +54,8 @@
         suite.addTestSuite(ConcurrentCheckinMixedTransactionTest.class);
         suite.addTestSuite(LockTest.class);
         suite.addTestSuite(ReadVersionsWhileModified.class);
+        suite.addTestSuite(ConcurrentLockingTest.class);
+        suite.addTestSuite(ConcurrentLockingWithTransactionsTest.class);
 
         return suite;
     }

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingTest.java?rev=732693&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingTest.java Thu Jan  8 03:52:38 2009
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.lock;
+
+import org.apache.jackrabbit.core.AbstractConcurrencyTest;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Node;
+import javax.jcr.lock.Lock;
+
+/**
+ * <code>ConcurrentLockingTest</code> contains test cases that run lock
+ * operations with concurrent threads.
+ */
+public class ConcurrentLockingTest extends AbstractConcurrencyTest {
+
+    /**
+     * The number of threads.
+     */
+    private static final int CONCURRENCY = 10;
+
+    /**
+     * The total number of operations to execute. E.g. number of lock
+     * performed by the threads.
+     */
+    private static final int NUM_OPERATIONS = 200;
+
+    public void testConcurrentLockUnlock() throws RepositoryException {
+        runTask(new Task() {
+            public void execute(Session session, Node test) throws RepositoryException {
+                Node n = test.addNode("test");
+                n.addMixin(mixLockable);
+                session.save();
+
+                for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
+                    n.lock(false, true);
+                    n.unlock();
+                }
+            }
+        }, CONCURRENCY);
+    }
+
+    public void testConcurrentCreateAndLockUnlock() throws RepositoryException {
+        runTask(new Task() {
+            public void execute(Session session, Node test) throws RepositoryException {
+                // add versionable nodes
+                for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
+                    Node n = test.addNode("test" + i);
+                    n.addMixin(mixLockable);
+                    session.save();
+                    Lock l = n.lock(false, true);
+                    l.refresh();
+                    n.unlock();
+                }
+            }
+        }, CONCURRENCY);
+    }
+
+    public void testConcurrentLock() throws RepositoryException {
+        runTask(new Task() {
+            public void execute(Session session, Node test) throws RepositoryException {
+                Node n = test.addNode("test");
+                n.addMixin(mixLockable);
+                session.save();
+
+                for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
+                    if (n.isLocked()) {
+                        n.unlock();
+                    }
+                    n.lock(false, true);
+                }
+            }
+        }, CONCURRENCY);
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingWithTransactionsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingWithTransactionsTest.java?rev=732693&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingWithTransactionsTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingWithTransactionsTest.java Thu Jan  8 03:52:38 2009
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.lock;
+
+import org.apache.jackrabbit.core.state.StaleItemStateException;
+import org.apache.jackrabbit.core.AbstractConcurrencyTest;
+import org.apache.jackrabbit.core.UserTransactionImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.lock.Lock;
+import javax.transaction.UserTransaction;
+
+/** <code>ConcurrentLockingWithTransactionsTest</code>... */
+public class ConcurrentLockingWithTransactionsTest extends AbstractConcurrencyTest {
+
+    private static Logger log = LoggerFactory.getLogger(ConcurrentLockingWithTransactionsTest.class);
+
+    /**
+     * The number of threads.
+     */
+    private static final int CONCURRENCY = 100;
+
+    /**
+     * The total number of operations to execute. E.g. number of locking operations
+     * performed by the threads.
+     */
+    private static final int NUM_OPERATIONS = 100;
+
+    public void testConcurrentRefreshInTransaction()
+            throws RepositoryException {
+        runTask(new Task() {
+            public void execute(Session session, Node test)
+                    throws RepositoryException {
+                int i = 0;
+                try {
+                    Node n = test.addNode("test");
+                    n.addMixin(mixLockable);
+                    session.save();
+                    for (i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
+                        Lock lock = n.lock(false, true);
+
+                        final UserTransaction utx = new UserTransactionImpl(test.getSession());
+                        utx.begin();
+                        lock.refresh();
+                        utx.commit();
+
+                        n.unlock();
+                    }
+                } catch (Exception e) {
+                    final String threadName = Thread.currentThread().getName();
+                    final Throwable deepCause = getLevel2Cause(e);
+                    if (deepCause != null && deepCause instanceof StaleItemStateException) {
+                        // ignore
+                    } else {
+                        throw new RepositoryException(threadName + ", i=" + i + ":" + e.getClass().getName(), e);
+                    }
+                }
+            }
+        }, CONCURRENCY);
+    }
+
+    public void testConcurrentCreateAndLockUnLockInTransaction()
+            throws RepositoryException {
+        runTask(new Task() {
+            public void execute(Session session, Node test)
+                    throws RepositoryException {
+                // add versionable nodes
+                for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
+                    try {
+                        final UserTransaction utx = new UserTransactionImpl(test.getSession());
+                        utx.begin();
+                        Node n = test.addNode("test" + i);
+                        n.addMixin(mixLockable);
+                        session.save();
+                        Lock l = n.lock(false, true);
+                        n.unlock();
+                        utx.commit();
+                    } catch (Exception e) {
+                        final String threadName = Thread.currentThread().getName();
+                        final Throwable deepCause = getLevel2Cause(e);
+                        if (deepCause != null && deepCause instanceof StaleItemStateException) {
+                            // ignore
+                        } else {
+                            throw new RepositoryException(threadName + ", i=" + i + ":" + e.getClass().getName(), e);
+                        }
+                    }
+                }
+            }
+        }, CONCURRENCY);
+    }
+
+    private static Throwable getLevel2Cause(Throwable t) {
+        Throwable result = null;
+        try {
+            result = t.getCause().getCause();
+        } catch (NullPointerException npe) {
+            // ignore, we have no deep cause
+        }
+        return result;
+
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingWithTransactionsTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingWithTransactionsTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ExtendedLockingTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ExtendedLockingTest.java?rev=732693&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ExtendedLockingTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ExtendedLockingTest.java Thu Jan  8 03:52:38 2009
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.lock;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.lock.Lock;
+import java.util.List;
+import java.util.Arrays;
+
+/**
+ * <code>ExtendedLockingTest</code>...
+ */
+public class ExtendedLockingTest extends AbstractJCRTest {
+
+    public void testRemoveMixLockableFromLockedNode() throws RepositoryException {
+
+        Node n = testRootNode.addNode(nodeName1);
+        n.addMixin(mixLockable);
+        testRootNode.save();
+
+        Lock l = n.lock(true, true);
+
+        try {
+            n.removeMixin(mixLockable);
+            n.save();
+            fail("Removing mix:lockable from a locked node must fail.");
+        } catch (ConstraintViolationException e) {
+            // success
+        } finally {
+            if (n.isLocked()) {
+                n.unlock();
+            }
+        }
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ExtendedLockingTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ExtendedLockingTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/TestAll.java?rev=732693&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/TestAll.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/TestAll.java Thu Jan  8 03:52:38 2009
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.lock;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite that includes all testcases for package org.apache.jackrabbit.core.lock.
+ */
+public class TestAll extends TestCase {
+
+    /**
+     * Returns a <code>Test</code> suite that executes all tests inside this
+     * package.
+     *
+     * @return a <code>Test</code> suite that executes all tests inside this
+     *         package.
+     */
+    public static Test suite() {
+        TestSuite suite = new TestSuite("org.apache.jackrabbit.core.lock tests");
+
+        suite.addTestSuite(ExtendedLockingTest.class);
+
+        return suite;
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/TestAll.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/TestAll.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplateTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplateTest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplateTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplateTest.java Thu Jan  8 03:52:38 2009
@@ -110,8 +110,8 @@
                 public boolean isAllow() {
                     return false;
                 }
-                public int getPrivilegeBits() {
-                    return PrivilegeRegistry.READ;
+                public int getPrivilegeBits() throws RepositoryException, NotExecutableException {
+                    return PrivilegeRegistry.getBits(privilegesFromName(Privilege.JCR_READ));
                 }
                 public String[] getRestrictionNames() {
                     return new String[0];
@@ -182,11 +182,13 @@
 
     public void testEffect() throws RepositoryException, NotExecutableException {
         JackrabbitAccessControlList pt = createEmptyTemplate(getTestPath());
-        pt.addAccessControlEntry(testPrincipal, privilegesFromName(Privilege.JCR_READ));
+        Privilege[] read = privilegesFromName(Privilege.JCR_READ);
+        Privilege[] modProp = privilegesFromName(Privilege.JCR_MODIFY_PROPERTIES);
+
+        pt.addAccessControlEntry(testPrincipal, read);
 
         // add deny entry for mod_props
-        assertTrue(pt.addEntry(testPrincipal, privilegesFromName(Privilege.JCR_MODIFY_PROPERTIES),
-                false, null));
+        assertTrue(pt.addEntry(testPrincipal, modProp, false, null));
 
         // test net-effect
         int allows = PrivilegeRegistry.NO_PRIVILEGE;
@@ -195,7 +197,7 @@
         for (int i = 0; i < entries.length; i++) {
             AccessControlEntry ace = entries[i];
             if (testPrincipal.equals(ace.getPrincipal()) && ace instanceof JackrabbitAccessControlEntry) {
-                int entryBits = ((JackrabbitAccessControlEntry) ace).getPrivilegeBits();
+                int entryBits = PrivilegeRegistry.getBits(ace.getPrivileges());
                 if (((JackrabbitAccessControlEntry) ace).isAllow()) {
                     allows |= Permission.diff(entryBits, denies);
                 } else {
@@ -203,8 +205,8 @@
                 }
             }
         }
-        assertEquals(PrivilegeRegistry.READ, allows);
-        assertEquals(PrivilegeRegistry.MODIFY_PROPERTIES, denies);
+        assertEquals(PrivilegeRegistry.getBits(read), allows);
+        assertEquals(PrivilegeRegistry.getBits(modProp), denies);
     }
 
     public void testEffect2() throws RepositoryException, NotExecutableException {
@@ -221,7 +223,7 @@
         for (int i = 0; i < entries.length; i++) {
             AccessControlEntry ace = entries[i];
             if (testPrincipal.equals(ace.getPrincipal()) && ace instanceof JackrabbitAccessControlEntry) {
-                int entryBits = ((JackrabbitAccessControlEntry) ace).getPrivilegeBits();
+                int entryBits = PrivilegeRegistry.getBits(ace.getPrivileges());
                 if (((JackrabbitAccessControlEntry) ace).isAllow()) {
                     allows |= Permission.diff(entryBits, denies);
                 } else {
@@ -231,7 +233,7 @@
         }
 
         assertEquals(PrivilegeRegistry.NO_PRIVILEGE, allows);
-        assertEquals(PrivilegeRegistry.READ, denies);
+        assertEquals(PrivilegeRegistry.getBits(privilegesFromName(Privilege.JCR_READ)), denies);
     }
 
     public void testRemoveEntry() throws RepositoryException,

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEntryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEntryTest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEntryTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEntryTest.java Thu Jan  8 03:52:38 2009
@@ -72,12 +72,14 @@
     public void testGetPrivilegeBits() throws RepositoryException, NotExecutableException {
         JackrabbitAccessControlEntry tmpl = createEntry(new String[] {Privilege.JCR_READ}, true);
 
-        int privs = tmpl.getPrivilegeBits();
-        assertTrue(privs == PrivilegeRegistry.READ);
-
-        tmpl = createEntry(new String[] {Privilege.JCR_WRITE}, true);
-        privs = tmpl.getPrivilegeBits();
-        assertTrue(privs == PrivilegeRegistry.WRITE);
+        int privs = PrivilegeRegistry.getBits(tmpl.getPrivileges());
+        assertEquals(1, tmpl.getPrivileges().length);
+        assertEquals(getAccessControlManager(superuser).privilegeFromName(Privilege.JCR_READ),
+                tmpl.getPrivileges()[0]);
+
+        tmpl = createEntry(new String[] {PrivilegeRegistry.REP_WRITE}, true);
+        assertEquals(getAccessControlManager(superuser).privilegeFromName(PrivilegeRegistry.REP_WRITE),
+                tmpl.getPrivileges()[0]);
     }
 
     public void testGetPrivileges() throws RepositoryException, NotExecutableException {
@@ -87,14 +89,14 @@
         assertNotNull(privs);
         assertEquals(1, privs.length);
         assertEquals(privs[0], acMgr.privilegeFromName(Privilege.JCR_READ));
-        assertTrue(PrivilegeRegistry.getBits(privs) == entry.getPrivilegeBits());
+        assertTrue(PrivilegeRegistry.getBits(privs) == PrivilegeRegistry.getBits(entry.getPrivileges()));
 
-        entry = createEntry(new String[] {Privilege.JCR_WRITE}, true);
+        entry = createEntry(new String[] {PrivilegeRegistry.REP_WRITE}, true);
         privs = entry.getPrivileges();
         assertNotNull(privs);
         assertEquals(1, privs.length);
-        assertEquals(privs[0], acMgr.privilegeFromName(Privilege.JCR_WRITE));
-        assertTrue(PrivilegeRegistry.getBits(privs) == entry.getPrivilegeBits());
+        assertEquals(privs[0], acMgr.privilegeFromName(PrivilegeRegistry.REP_WRITE));
+        assertTrue(PrivilegeRegistry.getBits(privs) == PrivilegeRegistry.getBits(entry.getPrivileges()));
 
         entry = createEntry(new String[] {Privilege.JCR_ADD_CHILD_NODES,
                 Privilege.JCR_REMOVE_CHILD_NODES}, true);
@@ -107,7 +109,7 @@
                 Privilege.JCR_REMOVE_CHILD_NODES
         });
         assertEquals(Arrays.asList(param), Arrays.asList(privs));
-        assertEquals(PrivilegeRegistry.getBits(privs), entry.getPrivilegeBits());
+        assertEquals(PrivilegeRegistry.getBits(privs), PrivilegeRegistry.getBits(entry.getPrivileges()));
     }
 
     public void testEquals() throws RepositoryException, NotExecutableException  {
@@ -157,7 +159,7 @@
         }
         // ACE template with different privileges and 'allows
         try {
-            otherAces.add(createEntry(new String[] {Privilege.JCR_WRITE}, false));
+            otherAces.add(createEntry(new String[] {PrivilegeRegistry.REP_WRITE}, false));
         } catch (RepositoryException e) {
         }
 
@@ -169,8 +171,8 @@
             public boolean isAllow() {
                 return true;
             }
-            public int getPrivilegeBits() {
-                return PrivilegeRegistry.ALL;
+            public int getPrivilegeBits() throws AccessControlException {
+                return PrivilegeRegistry.getBits(privs);
             }
             public String[] getRestrictionNames() {
                 return new String[0];