Author: jukka
Date: Wed Aug 28 01:31:26 2013
New Revision: 1518045
URL: http://svn.apache.org/r1518045
Log:
OAK-150: Basic JCR LockManager support
Implement lock and unlock in NodeDelegate.
Trim the list of known locking issues.
Modified:
jackrabbit/oak/trunk/oak-jcr/pom.xml
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/lock/LockImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/lock/LockManagerImpl.java
Modified: jackrabbit/oak/trunk/oak-jcr/pom.xml
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/pom.xml?rev=1518045&r1=1518044&r2=1518045&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-jcr/pom.xml Wed Aug 28 01:31:26 2013
@@ -72,122 +72,103 @@
org.apache.jackrabbit.test.api.SerializationTest#testLockExceptionWorkspace
<!-- OAK-127: no session scoped locking -->
org.apache.jackrabbit.test.api.SerializationTest#testLockExceptionSession
<!-- OAK-127: no session scoped locking -->
-
org.apache.jackrabbit.test.api.lock.LockManagerTest#testAddInvalidLockToken
<!-- OAK-150 ... -->
- org.apache.jackrabbit.test.api.lock.LockManagerTest#testLockNonLockable
- org.apache.jackrabbit.test.api.lock.LockTest#testGetNode
org.apache.jackrabbit.test.api.lock.LockTest#testAddRemoveLockToken
+ org.apache.jackrabbit.test.api.lock.LockTest#testOpenScopedLocks
+ org.apache.jackrabbit.test.api.lock.LockTest#testLogout
org.apache.jackrabbit.test.api.lock.LockTest#testNodeLocked
+ org.apache.jackrabbit.test.api.lock.LockTest#testParentChildDeepLock
+ org.apache.jackrabbit.test.api.lock.LockTest#testIsSessionScoped
+ org.apache.jackrabbit.test.api.lock.LockTest#testLockTransfer
+ org.apache.jackrabbit.test.api.lock.LockTest#testRefreshNotLive
+ org.apache.jackrabbit.test.api.lock.LockTest#testCheckedIn
+ org.apache.jackrabbit.test.api.lock.LockTest#testCheckedInUnlock
+
+<!--
+ org.apache.jackrabbit.test.api.lock.LockTest#testGetNode
org.apache.jackrabbit.test.api.lock.LockTest#testGetLockOwnerProperty
org.apache.jackrabbit.test.api.lock.LockTest#testGetLockOwner
org.apache.jackrabbit.test.api.lock.LockTest#testShallowLock
org.apache.jackrabbit.test.api.lock.LockTest#testParentChildLock
- org.apache.jackrabbit.test.api.lock.LockTest#testParentChildDeepLock
org.apache.jackrabbit.test.api.lock.LockTest#testIsDeep
- org.apache.jackrabbit.test.api.lock.LockTest#testIsSessionScoped
- org.apache.jackrabbit.test.api.lock.LockTest#testLogout
- org.apache.jackrabbit.test.api.lock.LockTest#testLockTransfer
- org.apache.jackrabbit.test.api.lock.LockTest#testOpenScopedLocks
org.apache.jackrabbit.test.api.lock.LockTest#testRefresh
- org.apache.jackrabbit.test.api.lock.LockTest#testRefreshNotLive
org.apache.jackrabbit.test.api.lock.LockTest#testGetLock
org.apache.jackrabbit.test.api.lock.LockTest#testMoveLocked
+-->
+
org.apache.jackrabbit.test.api.lock.SetValueLockExceptionTest#testSetValueLockException
+
+ org.apache.jackrabbit.test.api.lock.DeepLockTest#testIsLockOwningSession
+ org.apache.jackrabbit.test.api.lock.DeepLockTest#testIsLockedChild
+ org.apache.jackrabbit.test.api.lock.DeepLockTest#testIsLockedNewChild
+ org.apache.jackrabbit.test.api.lock.DeepLockTest#testGetLockOnChild
+ org.apache.jackrabbit.test.api.lock.DeepLockTest#testGetLockOnNewChild
org.apache.jackrabbit.test.api.lock.DeepLockTest#testParentChildDeepLock
org.apache.jackrabbit.test.api.lock.DeepLockTest#testGetNodeOnLockObtainedFromChild
org.apache.jackrabbit.test.api.lock.DeepLockTest#testGetNodeOnLockObtainedFromNewChild
org.apache.jackrabbit.test.api.lock.DeepLockTest#testDeepLockAboveLockedChild
-
org.apache.jackrabbit.test.api.lock.DeepLockTest#testShallowLockAboveLockedChild
- org.apache.jackrabbit.test.api.lock.DeepLockTest#testRemoveLockedChild
org.apache.jackrabbit.test.api.lock.DeepLockTest#testIsLive
org.apache.jackrabbit.test.api.lock.DeepLockTest#testIsDeep
org.apache.jackrabbit.test.api.lock.DeepLockTest#testIsSessionScoped
- org.apache.jackrabbit.test.api.lock.DeepLockTest#testRefresh
- org.apache.jackrabbit.test.api.lock.DeepLockTest#testRefreshNotLive
- org.apache.jackrabbit.test.api.lock.DeepLockTest#testLockHoldingNode
org.apache.jackrabbit.test.api.lock.DeepLockTest#testNodeIsLocked
org.apache.jackrabbit.test.api.lock.DeepLockTest#testNodeHoldsLocked
- org.apache.jackrabbit.test.api.lock.DeepLockTest#testLockVisibility
- org.apache.jackrabbit.test.api.lock.DeepLockTest#testIsLockOwningSession
+ org.apache.jackrabbit.test.api.lock.DeepLockTest#testRefreshNotLive
+
org.apache.jackrabbit.test.api.lock.DeepLockTest#testRemoveMixLockableFromLockedNode
org.apache.jackrabbit.test.api.lock.DeepLockTest#testGetSecondsRemaining
org.apache.jackrabbit.test.api.lock.DeepLockTest#testGetSecondsRemainingAfterUnlock
+ org.apache.jackrabbit.test.api.lock.DeepLockTest#testUnlockByOtherSession
+ org.apache.jackrabbit.test.api.lock.DeepLockTest#testRemoveLockedChild
+
+<!--
+
org.apache.jackrabbit.test.api.lock.DeepLockTest#testShallowLockAboveLockedChild
+ org.apache.jackrabbit.test.api.lock.DeepLockTest#testRefresh
+ org.apache.jackrabbit.test.api.lock.DeepLockTest#testLockHoldingNode
+ org.apache.jackrabbit.test.api.lock.DeepLockTest#testLockVisibility
org.apache.jackrabbit.test.api.lock.DeepLockTest#testLockExpiration
org.apache.jackrabbit.test.api.lock.DeepLockTest#testOwnerHint
org.apache.jackrabbit.test.api.lock.DeepLockTest#testUnlock
- org.apache.jackrabbit.test.api.lock.DeepLockTest#testUnlockByOtherSession
- org.apache.jackrabbit.test.api.lock.DeepLockTest#testIsLockedChild
- org.apache.jackrabbit.test.api.lock.DeepLockTest#testIsLockedNewChild
org.apache.jackrabbit.test.api.lock.DeepLockTest#testHoldsLockChild
org.apache.jackrabbit.test.api.lock.DeepLockTest#testHoldsLockNewChild
- org.apache.jackrabbit.test.api.lock.DeepLockTest#testGetLockOnChild
- org.apache.jackrabbit.test.api.lock.DeepLockTest#testGetLockOnNewChild
-
org.apache.jackrabbit.test.api.lock.DeepLockTest#testRemoveMixLockableFromLockedNode
+-->
+
org.apache.jackrabbit.test.api.lock.LockManagerTest#testLockTransfer
-
org.apache.jackrabbit.test.api.lock.LockManagerTest#testLockWithPendingChanges
- org.apache.jackrabbit.test.api.lock.LockManagerTest#testNullOwnerHint
- org.apache.jackrabbit.test.api.lock.LockManagerTest#testGetLockTokens
-
org.apache.jackrabbit.test.api.lock.LockManagerTest#testGetLockTokensAfterUnlock
-
org.apache.jackrabbit.test.api.lock.LockManagerTest#testGetLockTokensSessionScoped
- org.apache.jackrabbit.test.api.lock.LockManagerTest#testAddLockToken
-
org.apache.jackrabbit.test.api.lock.LockManagerTest#testAddLockTokenToAnotherSession
+ org.apache.jackrabbit.test.api.lock.LockManagerTest#testLockTransfer2
+ org.apache.jackrabbit.test.api.lock.LockManagerTest#testLockTransfer3
org.apache.jackrabbit.test.api.lock.LockManagerTest#testRemoveLockToken
org.apache.jackrabbit.test.api.lock.LockManagerTest#testRemoveLockToken2
org.apache.jackrabbit.test.api.lock.LockManagerTest#testRemoveLockToken3
+ org.apache.jackrabbit.test.api.lock.LockManagerTest#testNullOwnerHint
+ org.apache.jackrabbit.test.api.lock.LockManagerTest#testAddLockToken
+ org.apache.jackrabbit.test.api.lock.LockManagerTest#testGetLockTokens
org.apache.jackrabbit.test.api.lock.LockManagerTest#testRemoveLockTokenTwice
org.apache.jackrabbit.test.api.lock.LockManagerTest#testAddLockTokenAgain
- org.apache.jackrabbit.test.api.lock.LockManagerTest#testLockTransfer2
- org.apache.jackrabbit.test.api.lock.LockManagerTest#testLockTransfer3
- org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testGetLockToken
+
org.apache.jackrabbit.test.api.lock.LockManagerTest#testAddLockTokenToAnotherSession
+
org.apache.jackrabbit.test.api.lock.LockManagerTest#testLockWithPendingChanges
+ org.apache.jackrabbit.test.api.lock.LockManagerTest#testLockNonLockable
+
org.apache.jackrabbit.test.api.lock.LockManagerTest#testAddInvalidLockToken
<!-- OAK-150 ... -->
+
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testIsLive
- org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testIsDeep
-
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testIsSessionScoped
- org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testRefresh
+ org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testGetLockToken
+
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testIsLockOwningSession
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testRefreshNotLive
-
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testLockHoldingNode
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testNodeIsLocked
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testNodeHoldsLocked
- org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testLockVisibility
-
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testIsLockOwningSession
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testGetSecondsRemaining
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testGetSecondsRemainingAfterUnlock
- org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testLockExpiration
- org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testOwnerHint
- org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testUnlock
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testUnlockByOtherSession
- org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testIsLockedChild
-
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testIsLockedNewChild
- org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testHoldsLockChild
-
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testHoldsLockNewChild
- org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testGetLockOnChild
-
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testGetLockOnNewChild
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testRemoveMixLockableFromLockedNode
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testGetLockToken
+
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testImplicitUnlock
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testImplicitUnlock2
- org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testIsLive
- org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testIsDeep
+
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testIsLockOwningSession
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testIsSessionScoped
- org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testRefresh
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testRefreshNotLive
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testLockHoldingNode
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testNodeIsLocked
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testNodeHoldsLocked
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testLockVisibility
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testIsLockOwningSession
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testGetSecondsRemaining
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testGetSecondsRemainingAfterUnlock
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testLockExpiration
- org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testOwnerHint
- org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testUnlock
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testUnlockByOtherSession
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testIsLockedChild
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testIsLockedNewChild
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testHoldsLockChild
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testHoldsLockNewChild
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testGetLockOnChild
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testGetLockOnNewChild
+ org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testIsLive
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testRemoveMixLockableFromLockedNode
<!-- ... OAK-150 -->
- org.apache.jackrabbit.test.api.lock.LockTest#testCheckedIn
- org.apache.jackrabbit.test.api.lock.LockTest#testCheckedInUnlock
<!-- Lifecycle Mgt : not implemented -->
org.apache.jackrabbit.test.api.LifecycleTest
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java?rev=1518045&r1=1518044&r2=1518045&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
Wed Aug 28 01:31:26 2013
@@ -66,9 +66,12 @@ import javax.jcr.InvalidItemStateExcepti
import javax.jcr.ItemNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.ValueFormatException;
+import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.security.AccessControlException;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
@@ -714,7 +717,61 @@ public class NodeDelegate extends ItemDe
}
}
+ public void lock(boolean isDeep) throws RepositoryException {
+ String path = getPath();
+ Root root = sessionDelegate.getContentSession().getLatestRoot();
+ Tree tree = root.getTree(path);
+ if (tree.hasProperty(JCR_LOCKISDEEP)) {
+ throw new LockException("Node " + path + " is already locked");
+ }
+
+ try {
+ String owner = sessionDelegate.getAuthInfo().getUserID();
+ if (owner == null) {
+ owner = "";
+ }
+ tree.setProperty(JCR_LOCKISDEEP, isDeep);
+ tree.setProperty(JCR_LOCKOWNER, owner);
+ root.commit();
+ } catch (CommitFailedException e) {
+ if (e.isConstraintViolation()) {
+ // TODO: Make lock properties reserved / see nt:unstructured
+ throw new LockException(
+ "Node " + path + " is not lockable", e);
+ } else if (e.isAccessViolation()) {
+ throw new AccessControlException(
+ "Unable to lock node " + path, e);
+ } else {
+ throw new RepositoryException(
+ "Unable to lock node " + path, e);
+ }
+ }
+ }
+
+ public void unlock() throws RepositoryException {
+ String path = getPath();
+
+ Root root = sessionDelegate.getContentSession().getLatestRoot();
+ Tree tree = root.getTree(path);
+ if (!tree.hasProperty(JCR_LOCKISDEEP)) {
+ throw new LockException("Node " + path + " is not locked");
+ }
+
+ try {
+ tree.removeProperty(JCR_LOCKISDEEP);
+ tree.removeProperty(JCR_LOCKOWNER);
+ root.commit();
+ } catch (CommitFailedException e) {
+ if (e.isAccessViolation()) {
+ throw new AccessControlException(
+ "Unable to unlock node " + path, e);
+ } else {
+ throw new RepositoryException(
+ "Unable to unlock node " + path, e);
+ }
+ }
+ }
@Override
public String toString() {
@@ -750,4 +807,5 @@ public class NodeDelegate extends ItemDe
private String getUserID() {
return sessionDelegate.getAuthInfo().getUserID();
}
+
}
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/lock/LockImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/lock/LockImpl.java?rev=1518045&r1=1518044&r2=1518045&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/lock/LockImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/lock/LockImpl.java
Wed Aug 28 01:31:26 2013
@@ -94,7 +94,7 @@ public final class LockImpl implements L
@Override
public boolean isSessionScoped() {
- return true;
+ return false;
}
@Override
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/lock/LockManagerImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/lock/LockManagerImpl.java?rev=1518045&r1=1518044&r2=1518045&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/lock/LockManagerImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/lock/LockManagerImpl.java
Wed Aug 28 01:31:26 2013
@@ -52,7 +52,7 @@ public class LockManagerImpl implements
this.delegate = sessionContext.getSessionDelegate();
}
- @Override
+ @Override @Nonnull
public synchronized String[] getLockTokens() {
return tokens.toArray(new String[tokens.size()]);
}
@@ -91,7 +91,7 @@ public class LockManagerImpl implements
});
}
- @Override
+ @Override @Nonnull
public Lock getLock(String absPath) throws RepositoryException {
NodeDelegate lock = perform(new LockOperation<NodeDelegate>(absPath) {
@Override
@@ -106,23 +106,31 @@ public class LockManagerImpl implements
}
}
- @Override
- @SuppressWarnings("deprecation")
+ @Override @Nonnull
public Lock lock(
- String absPath, boolean isDeep, boolean isSessionScoped,
+ String absPath, final boolean isDeep, boolean isSessionScoped,
long timeoutHint, String ownerInfo) throws RepositoryException {
- return getSession().getNode(absPath).lock(isDeep, isSessionScoped);
+ NodeDelegate lock = perform(new LockOperation<NodeDelegate>(absPath) {
+ @Override
+ protected NodeDelegate perform(NodeDelegate node)
+ throws RepositoryException {
+ node.lock(isDeep);
+ return node;
+ }
+ });
+ return new LockImpl(sessionContext, lock);
}
@Override
- @SuppressWarnings("deprecation")
public void unlock(String absPath) throws RepositoryException {
- getSession().getNode(absPath).unlock();
- }
-
- @Nonnull
- private Session getSession() {
- return sessionContext.getSession();
+ perform(new LockOperation<Void>(absPath) {
+ @Override
+ protected Void perform(NodeDelegate node)
+ throws RepositoryException {
+ node.unlock();
+ return null;
+ }
+ });
}
private <T> T perform(SessionOperation<T> operation)
@@ -149,7 +157,8 @@ public class LockManagerImpl implements
}
}
- protected abstract T perform(NodeDelegate node);
+ protected abstract T perform(NodeDelegate node)
+ throws RepositoryException;
}