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/09 16:18:31 UTC

svn commit: r733059 - in /jackrabbit/trunk: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/ jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/ jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ jackrabbit-jcr-tes...

Author: angela
Date: Fri Jan  9 07:18:31 2009
New Revision: 733059

URL: http://svn.apache.org/viewvc?rev=733059&view=rev
Log:
JCR-1590 - JSR 283: Locking

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/AbstractLockTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/DeepLockTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/LockManagerTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/SessionScopedLockTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/TestAll.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java
    jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/RepositoryStub.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockImpl.java?rev=733059&r1=733058&r2=733059&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockImpl.java Fri Jan  9 07:18:31 2009
@@ -116,7 +116,7 @@
         if (!isLive()) {
             throw new LockException("Lock is not live any more.");
         }
-        if (getLockToken() == null) {
+        if (!isLockOwningSession()) {
             throw new LockException("Session does not hold lock.");
         }
         // make sure the current session has sufficient privileges to refresh

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java?rev=733059&r1=733058&r2=733059&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java Fri Jan  9 07:18:31 2009
@@ -92,7 +92,14 @@
          islocked = true. therefore, the shortcut for NEW nodes that was
          present with NodeImpl.isLocked before cannot be applied any more.
          */
-        return systemLockMgr.isLocked(node);
+        if (node.isNew()) {
+            while (node.isNew()) {
+                node = (NodeImpl) node.getParent();
+            }
+            return systemLockMgr.isLocked(node) && systemLockMgr.getLock(node).isDeep();
+        } else {
+            return systemLockMgr.isLocked(node);
+        }
     }
 
     /**
@@ -102,7 +109,19 @@
             UnsupportedRepositoryOperationException, LockException,
             AccessDeniedException, RepositoryException {
         NodeImpl node = (NodeImpl) session.getNode(absPath);
-        return (Lock) systemLockMgr.getLock(node);
+        if (node.isNew()) {
+            while (node.isNew()) {
+                node = (NodeImpl) node.getParent();
+            }
+            Lock l = (Lock) systemLockMgr.getLock(node);
+            if (l.isDeep()) {
+                return l;
+            } else {
+                throw new LockException("Node not locked: " + node);
+            }
+        } else {
+            return (Lock) systemLockMgr.getLock(node);
+        }
     }
 
     /**
@@ -157,6 +176,13 @@
         session.getAccessManager().checkPermission(session.getQPath(node.getPath()), Permission.LOCK_MNGMT);
 
         synchronized (systemLockMgr) {
+            // basic checks if unlock can be called on the node.
+            if (!systemLockMgr.holdsLock(node)) {
+                throw new LockException("Node not locked: " + node);
+            }
+            if (!systemLockMgr.isLockHolder(session, node)) {
+                throw new LockException("Node not locked by session: " + node);
+            }
             systemLockMgr.unlock(node);
         }
     }

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=733059&r1=733058&r2=733059&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 Fri Jan  9 07:18:31 2009
@@ -19,26 +19,26 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.RepositoryStub;
+import org.apache.jackrabbit.test.NotExecutableException;
+import org.apache.jackrabbit.core.WorkspaceImpl;
 
 import javax.jcr.Node;
 import javax.jcr.Session;
 import javax.jcr.RepositoryException;
+import javax.jcr.lock.LockException;
 import javax.jcr.nodetype.ConstraintViolationException;
-import java.util.List;
-import java.util.Arrays;
 
 /** <code>AbstractLockTest</code>... */
 public abstract class AbstractLockTest extends AbstractJCRTest {
 
     private static Logger log = LoggerFactory.getLogger(AbstractLockTest.class);
 
+    protected LockManager lockMgr;
     protected Node lockedNode;
     protected Node childNode;
     protected Lock lock;
 
-    protected abstract boolean isSessionScoped();
-    protected abstract boolean isDeep();
-
     protected void setUp() throws Exception {
         super.setUp();
 
@@ -47,21 +47,51 @@
         childNode = lockedNode.addNode(nodeName2, testNodeType);
         testRootNode.save();
 
-        // TODO: remove cast
-        // TODO: replace by LockManager#lock call
-        lock = (Lock) lockedNode.lock(isDeep(), isSessionScoped());
+        lockMgr = getLockManager(testRootNode.getSession());
+        lock = lockMgr.lock(lockedNode.getPath(), isDeep(), isSessionScoped(), getTimeoutHint(), getLockOwner());
     }
 
     protected void tearDown() throws Exception {
-        // make sure all locks are removed
-        try {
-            lockedNode.unlock();
-        } catch (RepositoryException e) {
-            // ignore
+        // release the lock created during setup
+        if (lockMgr != null && lockedNode != null) {
+            try {
+                lockMgr.unlock(lockedNode.getPath());
+            } catch (RepositoryException e) {
+                // ignore
+            }
         }
         super.tearDown();
     }
 
+    protected abstract boolean isSessionScoped();
+    protected abstract boolean isDeep();
+
+    protected long getTimeoutHint() throws RepositoryException {
+        String timoutStr = getProperty(RepositoryStub.PROP_LOCK_TIMEOUT);
+        long hint = Long.MAX_VALUE;
+        if (timoutStr != null) {
+            try {
+                hint = Long.parseLong(timoutStr);
+            } catch (NumberFormatException e) {
+                log.warn(e.getMessage());
+            }
+        }
+        return hint;
+    }
+
+    protected String getLockOwner() throws RepositoryException {
+        String ownerStr = getProperty(RepositoryStub.PROP_LOCK_OWNER);
+        if (ownerStr == null) {
+            ownerStr = superuser.getUserID();
+        }
+        return ownerStr;
+    }
+
+    private static LockManager getLockManager(Session session) throws RepositoryException {
+        // TODO: rm cast and adjust call as soon as 283 is released
+        return ((WorkspaceImpl) session.getWorkspace()).get283LockManager();
+    }
+
     /**
      *
      */
@@ -69,6 +99,20 @@
         assertEquals("Lock.isDeep must be consistent with lock call.", isDeep(), lock.isDeep());
     }
 
+    public void testLockHoldingNode() throws RepositoryException {
+        assertTrue("Lock.getNode() must be lockholding node.", lock.getNode().isSame(lockedNode));
+    }
+
+    public void testNodeIsLocked() throws RepositoryException {
+        assertTrue("Node must be locked after lock creation.", lockedNode.isLocked());
+        assertTrue("Node must be locked after lock creation.", lockMgr.isLocked(lockedNode.getPath()));
+    }
+
+    public void testNodeHoldsLocked() throws RepositoryException {
+        assertTrue("Node must hold lock after lock creation.", lockedNode.holdsLock());
+        assertTrue("Node must hold lock after lock creation.", lockMgr.holdsLock(lockedNode.getPath()));
+    }
+    
     /**
      *
      */
@@ -83,11 +127,15 @@
     public void testIsLockOwningSession() throws RepositoryException {
         assertTrue("Session must be lock owner", lock.isLockOwningSession());
         assertTrue("Session must be lock owner", ((Lock) lockedNode.getLock()).isLockOwningSession());
+        assertTrue("Session must be lock owner", lockMgr.getLock(lockedNode.getPath()).isLockOwningSession());
 
         Session otherSession = helper.getReadOnlySession();
         try {
             Lock lck = (Lock) ((Node) otherSession.getItem(lockedNode.getPath())).getLock();
             assertFalse("Session must not be lock owner", lck.isLockOwningSession());
+
+            Lock lck2 = getLockManager(otherSession).getLock(lockedNode.getPath());
+            assertFalse("Session must not be lock owner", lck2.isLockOwningSession());
         } finally {
             otherSession.logout();
         }
@@ -96,6 +144,10 @@
         try {
             Lock lck = (Lock) ((Node) otherAdmin.getItem(lockedNode.getPath())).getLock();
             assertFalse("Other Session for the same userID must not be lock owner", lck.isLockOwningSession());
+
+            Lock lck2 = getLockManager(otherAdmin).getLock(lockedNode.getPath());
+            assertFalse("Other Session for the same userID must not be lock owner", lck2.isLockOwningSession());
+
         } finally {
             otherAdmin.logout();
         }
@@ -108,6 +160,104 @@
         assertTrue("Seconds remaining must be a positive long or 0.", lock.getSecondsRemaining() >= 0);
     }
 
+    public void testUnlockByOtherSession() throws RepositoryException, NotExecutableException {
+        Session otherSession = helper.getReadWriteSession();
+        try {
+            getLockManager(otherSession).unlock(lockedNode.getPath());
+            fail("Another session must not be allowed to unlock.");
+        } catch (LockException e) {
+            // success
+            // make sure the node is still locked and the lock properties are
+            // still present.
+            assertTrue(lockMgr.isLocked(lockedNode.getPath()));
+            assertTrue(lockedNode.hasProperty(jcrlockIsDeep));
+            assertTrue(lockedNode.hasProperty(jcrLockOwner));
+        } finally {
+            otherSession.logout();
+        }
+    }
+
+    public void testIsLockedChild() throws RepositoryException {
+        assertEquals("Child node must be locked according to isDeep flag.", isDeep(), childNode.isLocked());
+        assertEquals("Child node must be locked according to isDeep flag.", isDeep(), lockMgr.isLocked(childNode.getPath()));
+    }
+
+    public void testIsLockedNewChild() throws RepositoryException {
+        Node newChild = lockedNode.addNode(nodeName3, testNodeType);
+        assertEquals("New child node must be locked according to isDeep flag.", isDeep(),
+                newChild.isLocked());
+        assertEquals("New child node must be locked according to isDeep flag.", isDeep(),
+                lockMgr.isLocked(newChild.getPath()));
+    }
+
+    public void testHoldsLockChild() throws RepositoryException {
+        assertFalse("Child node below a locked node must never be lock holder",
+                childNode.holdsLock());
+        assertFalse("Child node below a locked node must never be lock holder",
+                lockMgr.holdsLock(childNode.getPath()));
+    }
+
+    public void testHoldsLockNewChild() throws RepositoryException {
+        Node newChild = lockedNode.addNode(nodeName3, testNodeType);
+        assertFalse("Child node below a locked node must never be lock holder",
+                newChild.holdsLock());
+        assertFalse("Child node below a locked node must never be lock holder",
+                lockMgr.holdsLock(newChild.getPath()));
+    }
+
+    public void testGetLockOnChild() throws RepositoryException {
+        if (isDeep()) {
+            // 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()));
+
+            Lock lock2 = lockMgr.getLock(childNode.getPath());
+            assertNotNull(lock2);
+            assertTrue("Lock.getNode() must return the lock holding node", lockedNode.isSame(lock2.getNode()));
+        } else {
+            try {
+                childNode.getLock();
+                fail("Node.getLock() must throw if node is not locked.");
+            } catch (LockException e) {
+                // success
+            }
+            try {
+                lockMgr.getLock(childNode.getPath());
+                fail("LockManager.getLock(String) must throw if node is not locked.");
+            } catch (LockException e) {
+                // success
+            }
+        }
+    }
+
+    public void testGetLockOnNewChild() throws RepositoryException {
+        Node newChild = lockedNode.addNode(nodeName3, testNodeType);
+        if (isDeep()) {
+            // get lock must succeed even if child is not lockable.
+            javax.jcr.lock.Lock lock = newChild.getLock();
+            assertNotNull(lock);
+            assertTrue("Lock.getNode() must return the lock holding node", lockedNode.isSame(lock.getNode()));
+
+            Lock lock2 = lockMgr.getLock(newChild.getPath());
+            assertNotNull(lock2);
+            assertTrue("Lock.getNode() must return the lock holding node", lockedNode.isSame(lock2.getNode()));
+        } else {
+            try {
+                newChild.getLock();
+                fail("Node.getLock() must throw if node is not locked.");
+            } catch (LockException e) {
+                // success
+            }
+            try {
+                lockMgr.getLock(newChild.getPath());
+                fail("LockManager.getLock(String) must throw if node is not locked.");
+            } catch (LockException e) {
+                // success
+            }
+        }
+    }
+
     public void testRemoveMixLockableFromLockedNode() throws RepositoryException {
         try {
             lockedNode.removeMixin(mixLockable);
@@ -118,8 +268,7 @@
             String msg = "Lock should have been released.";
             assertFalse(msg, lock.isLive());
             assertFalse(msg, lockedNode.isLocked());
-            List tokens = Arrays.asList(superuser.getLockTokens());
-            assertFalse(msg, tokens.contains(lock.getLockToken()));
+            assertFalse(msg, lockMgr.isLocked(lockedNode.getPath()));
 
             assertFalse(msg, lockedNode.hasProperty(jcrLockOwner));
             assertFalse(msg, lockedNode.hasProperty(jcrlockIsDeep));
@@ -130,8 +279,8 @@
             String msg = "Lock must still be live.";
             assertTrue(msg, lock.isLive());
             assertTrue(msg, lockedNode.isLocked());
-            List tokens = Arrays.asList(superuser.getLockTokens());
-            assertTrue(tokens.contains(lock.getLockToken()));
+            assertTrue(msg, lockMgr.isLocked(lockedNode.getPath()));
+
             assertTrue(msg, lockedNode.hasProperty(jcrLockOwner));
             assertTrue(msg, lockedNode.hasProperty(jcrlockIsDeep));
         } finally {

Modified: 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=733059&r1=733058&r2=733059&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/DeepLockTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/DeepLockTest.java Fri Jan  9 07:18:31 2009
@@ -16,7 +16,6 @@
  */
 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;
@@ -27,87 +26,16 @@
 import javax.jcr.lock.LockException;
 
 /** <code>DeepLockTest</code>... */
-public class DeepLockTest extends AbstractJCRTest {
+public class DeepLockTest extends AbstractLockTest {
 
     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()));
+    protected boolean isSessionScoped() {
+        return true;
     }
 
-    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()));
+    protected boolean isDeep() {
+        return true;
     }
 
     public void testGetNodeOnLockObtainedFromChild() throws RepositoryException {
@@ -132,44 +60,63 @@
         } catch (LockException e) {
             // ok
         }
+
+        try {
+            lockMgr.lock(childNode.getPath(), false, false, getTimeoutHint(), getLockOwner());
+            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();
-                }
+        Node parent = lockedNode.getParent();
+        if (!parent.isNodeType(mixLockable)) {
+            try {
+                parent.addMixin(mixLockable);
+                parent.save();
+            } catch (RepositoryException e) {
+                throw new NotExecutableException();
             }
+        }
 
+        try {
             parent.lock(true, true);
             fail("Creating a deep lock on a parent of a locked node must fail.");
         } catch (LockException e) {
             // expected
         }
+        try {
+            lockMgr.lock(parent.getPath(), true, true, getTimeoutHint(), getLockOwner());
+            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();
-                }
+        if (!parent.isNodeType(mixLockable)) {
+            try {
+                parent.addMixin(mixLockable);
+                parent.save();
+            } catch (RepositoryException e) {
+                throw new NotExecutableException();
             }
+        }
 
+        try {
             // creating a shallow lock on the parent must succeed.
             parent.lock(false, true);
         } finally {
             parent.unlock();
         }
+        try {
+            // creating a shallow lock on the parent must succeed.
+            lockMgr.lock(parent.getPath(), false, true, getTimeoutHint(), getLockOwner());
+        } finally {
+            parent.unlock();
+        }
     }
 
     public void testRemoveLockedChild() throws RepositoryException {

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=733059&r1=733058&r2=733059&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 Fri Jan  9 07:18:31 2009
@@ -19,13 +19,69 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+import org.apache.jackrabbit.core.WorkspaceImpl;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.lock.LockException;
 
 /** <code>LockManagerTest</code>... */
 public class LockManagerTest extends AbstractJCRTest {
 
     private static Logger log = LoggerFactory.getLogger(LockManagerTest.class);
 
-    // TODO - timeout hint
-    // TODO - ownerInfo hint
-    
+    protected LockManager lockMgr;
+    protected Node testNode;
+    protected String testPath;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        testNode = testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+        testPath = testNode.getPath();
+
+        // TODO: rm cast and adjust call as soon as 283 is released
+        lockMgr = ((WorkspaceImpl) superuser.getWorkspace()).get283LockManager();
+    }
+
+    protected void tearDown() throws Exception  {
+        if (lockMgr != null && lockMgr.holdsLock(testPath)) {
+            lockMgr.unlock(testPath);
+        }
+        super.tearDown();
+    }
+
+    public void testLockNonLockable() throws NotExecutableException, RepositoryException {
+        if (testNode.isNodeType(mixLockable)) {
+            throw new NotExecutableException();
+        }
+        try {
+            lockMgr.lock(testPath, true, true, Long.MAX_VALUE, superuser.getUserID());
+            fail("Attempt to lock a non-lockable node must throw LockException.");
+        } catch (LockException e) {
+            // success
+        }
+    }
+
+    public void testLockWithPendingChanges() throws RepositoryException {
+        // transient modification
+        testNode.addNode(nodeName2);
+        try {
+            lockMgr.lock(testPath, true, true, Long.MAX_VALUE, superuser.getUserID());
+            fail("Attempt to lock a node with transient modifications must throw InvalidItemStateException.");
+        } catch (InvalidItemStateException e) {
+            // success
+        }
+    }
+
+    public void testNullOwnerHint() throws RepositoryException {
+        testNode.addMixin(mixLockable);
+        testRootNode.save();
+
+        Lock l = lockMgr.lock(testPath, true, true, Long.MAX_VALUE, null);
+        assertNotNull(l.getLockOwner());
+    }
 }
\ No newline at end of file

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=733059&r1=733058&r2=733059&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 Fri Jan  9 07:18:31 2009
@@ -33,9 +33,13 @@
     }
 
     /**
-     * 
+     * {@link org.apache.jackrabbit.api.jsr283.lock.Lock#getLockToken()} must
+     * always return <code>null</code> for session scoped locks.
      */
+    /*
+    TODO: uncomment as soon as 283 lock token handing is in effect
     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=733059&r1=733058&r2=733059&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 Fri Jan  9 07:18:31 2009
@@ -30,13 +30,10 @@
     public static Test suite() {
         TestSuite suite = new TestSuite("org.apache.jackrabbit.api.jsr283.lock tests");
 
-        /*
-        // TODO uncomment as soon as 283 lock impl is completed.
         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/core/XATest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java?rev=733059&r1=733058&r2=733059&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 Fri Jan  9 07:18:31 2009
@@ -90,7 +90,7 @@
     }
 
     /**
-     * @see junit.framework.TestCase#runTest
+     * @see junit.framework.TestCase#runTest()
      *
      * Make sure that tested repository supports transactions
      */
@@ -1057,32 +1057,37 @@
         testRootNode.save();
 
         Lock lock = n.lock(false, true);
+        try {
+            // get user transaction object, start
+            UserTransaction utx = new UserTransactionImpl(superuser);
+            utx.begin();
 
-        // 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 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));
 
-        // verify that the lock properties have been removed.
-        assertFalse(n.hasProperty(jcrLockOwner));
-        assertFalse(n.hasProperty(jcrlockIsDeep));
-
-        // rollback
-        utx.rollback();
+            // rollback
+            utx.rollback();
 
-        // verify lock is live again -> properties must be present
-        assertTrue(n.hasProperty(jcrLockOwner));
-        assertTrue(n.hasProperty(jcrlockIsDeep));
+            // verify lock is live again -> properties must be present
+            assertTrue(n.hasProperty(jcrLockOwner));
+            assertTrue(n.hasProperty(jcrlockIsDeep));
+        } finally {
+            n.unlock();
+        }
     }
 
     /**
      * Test visibility of lock properties by another session.
+     *
+     * @throws Exception
      */
     public void testLockProperties3() throws Exception {
         // add node that is both lockable and referenceable, save
@@ -1106,9 +1111,10 @@
         assertTrue(n2.hasProperty(jcrlockIsDeep));
         Lock lock2 = n2.getLock();
 
-        // rollback
+        // complete transaction
         utx.commit();
 
+        // unlock must now be visible to other session
         n2.refresh(false);
         assertFalse(lock2.isLive());
         assertFalse(n2.isLocked());

Modified: jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/RepositoryStub.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/RepositoryStub.java?rev=733059&r1=733058&r2=733059&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/RepositoryStub.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/RepositoryStub.java Fri Jan  9 07:18:31 2009
@@ -79,6 +79,16 @@
 
     public static final String PROP_NAMESPACES = "namespaces";
 
+    /**
+     * @since JCR 2.0
+     */
+    public static final String PROP_LOCK_TIMEOUT = "lock.timeout";
+
+    /**
+     * @since JCR 2.0
+     */
+    public static final String PROP_LOCK_OWNER = "lock.owner";
+
     protected final Properties environment;
 
     protected SimpleCredentials superuser;