Author: jukka
Date: Wed Aug 28 01:34:28 2013
New Revision: 1518049
URL: http://svn.apache.org/r1518049
Log:
OAK-150: Basic JCR LockManager support
Improved tracking of session and open scoped locks and lock tokens
Better interaction between versioning and locking (it's possible to checkin a
locked node, not checkout)
Trimmed list of known TCK issues
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionConstants.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionEditor.java
jackrabbit/oak/trunk/oak-jcr/pom.xml
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ItemImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.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
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/VersionManagerImpl.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionConstants.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionConstants.java?rev=1518049&r1=1518048&r2=1518049&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionConstants.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionConstants.java
Wed Aug 28 01:34:28 2013
@@ -19,9 +19,12 @@ package org.apache.jackrabbit.oak.plugin
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Set;
import org.apache.jackrabbit.JcrConstants;
+import com.google.common.collect.ImmutableSet;
+
/**
* VersionConstants... TODO
*/
@@ -128,6 +131,10 @@ public interface VersionConstants extend
JCR_VERSIONHISTORY
));
+ Set<String> LOCK_PROPERTY_NAMES = ImmutableSet.of(
+ JCR_LOCKISDEEP,
+ JCR_LOCKOWNER);
+
Collection<String> VERSION_NODE_NAMES =
Collections.unmodifiableList(Arrays.asList(
JCR_ACTIVITIES,
JCR_CONFIGURATIONS,
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionEditor.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionEditor.java?rev=1518049&r1=1518048&r2=1518049&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionEditor.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionEditor.java
Wed Aug 28 01:34:28 2013
@@ -144,7 +144,7 @@ class VersionEditor implements Editor {
public void propertyDeleted(PropertyState before)
throws CommitFailedException {
if (wasReadOnly) {
- if (!isVersionProperty(before)) {
+ if (!isVersionProperty(before) && !isLockProperty(before)) {
throwCheckedIn("Cannot delete property on checked in node");
}
}
@@ -188,6 +188,10 @@ class VersionEditor implements Editor {
.contains(state.getName());
}
+ private boolean isLockProperty(PropertyState state) {
+ return VersionConstants.LOCK_PROPERTY_NAMES.contains(state.getName());
+ }
+
/**
* @return {@code true} if this node <b>was</b> checked in. That is,
* this method checks the base state for the jcr:isCheckedOut
Modified: jackrabbit/oak/trunk/oak-jcr/pom.xml
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/pom.xml?rev=1518049&r1=1518048&r2=1518049&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-jcr/pom.xml Wed Aug 28 01:34:28 2013
@@ -72,63 +72,28 @@
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.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#testAddRemoveLockToken
org.apache.jackrabbit.test.api.lock.LockTest#testCheckedIn
+ org.apache.jackrabbit.test.api.lock.LockTest#testOpenScopedLocks
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#testIsDeep
- org.apache.jackrabbit.test.api.lock.LockTest#testRefresh
- org.apache.jackrabbit.test.api.lock.LockTest#testGetLock
- org.apache.jackrabbit.test.api.lock.LockTest#testMoveLocked
--->
+ org.apache.jackrabbit.test.api.lock.LockTest#testLogout
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#testShallowLockAboveLockedChild
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#testIsLive
- org.apache.jackrabbit.test.api.lock.DeepLockTest#testIsDeep
+ org.apache.jackrabbit.test.api.lock.DeepLockTest#testRemoveLockedChild
org.apache.jackrabbit.test.api.lock.DeepLockTest#testIsSessionScoped
- org.apache.jackrabbit.test.api.lock.DeepLockTest#testNodeIsLocked
- org.apache.jackrabbit.test.api.lock.DeepLockTest#testNodeHoldsLocked
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#testIsLockOwningSession
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#testHoldsLockChild
- org.apache.jackrabbit.test.api.lock.DeepLockTest#testHoldsLockNewChild
--->
+
org.apache.jackrabbit.test.api.lock.DeepLockTest#testGetSecondsRemainingAfterUnlock
org.apache.jackrabbit.test.api.lock.LockManagerTest#testLockTransfer
org.apache.jackrabbit.test.api.lock.LockManagerTest#testLockTransfer2
@@ -136,39 +101,25 @@
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#testLockWithPendingChanges
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#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#testGetLockToken
-
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testIsLockOwningSession
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testRefreshNotLive
- org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testNodeIsLocked
-
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testNodeHoldsLocked
-
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testGetSecondsRemaining
-
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testGetSecondsRemainingAfterUnlock
+
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testIsLockOwningSession
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testUnlockByOtherSession
-
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testRemoveMixLockableFromLockedNode
+
org.apache.jackrabbit.test.api.lock.OpenScopedLockTest#testGetSecondsRemainingAfterUnlock
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testImplicitUnlock
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testImplicitUnlock2
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testIsLockOwningSession
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testIsSessionScoped
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testRefreshNotLive
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testNodeIsLocked
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testNodeHoldsLocked
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testGetSecondsRemaining
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testGetSecondsRemainingAfterUnlock
+
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testIsLockOwningSession
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testUnlockByOtherSession
- org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testIsLive
-
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testRemoveMixLockableFromLockedNode
<!-- ... OAK-150 -->
+
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testGetSecondsRemainingAfterUnlock
+
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testImplicitUnlock
+
org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testImplicitUnlock2
<!-- Lifecycle Mgt : not implemented -->
org.apache.jackrabbit.test.api.LifecycleTest
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ItemImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ItemImpl.java?rev=1518049&r1=1518048&r2=1518049&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ItemImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ItemImpl.java
Wed Aug 28 01:34:28 2013
@@ -39,6 +39,7 @@ import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
+import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.ItemDefinition;
import javax.jcr.version.VersionManager;
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java?rev=1518049&r1=1518048&r2=1518049&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java
Wed Aug 28 01:34:28 2013
@@ -17,10 +17,13 @@
package org.apache.jackrabbit.oak.jcr;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Sets.newHashSet;
+import static com.google.common.collect.Sets.newTreeSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
@@ -89,6 +92,12 @@ public class SessionContext implements N
private PrivilegeManager privilegeManager;
private ObservationManagerImpl observationManager;
+ /** Paths (tokens) of all open scoped locks held by this session. */
+ private final Set<String> openScopedLocks = newTreeSet();
+
+ /** Paths of all session scoped locks held by this session. */
+ private final Set<String> sessionScopedLocks = newHashSet();
+
public SessionContext(
@Nonnull RepositoryImpl repository, @Nonnull Whiteboard whiteboard,
Map<String, Object> attributes, @Nonnull final SessionDelegate
delegate) {
@@ -244,6 +253,14 @@ public class SessionContext implements N
return observationManager;
}
+ public Set<String> getOpenScopedLocks() {
+ return openScopedLocks;
+ }
+
+ public Set<String> getSessionScopedLocks() {
+ return sessionScopedLocks;
+ }
+
//-----------------------------------------------------< NamePathMapper
>---
@Override
@@ -335,6 +352,7 @@ public class SessionContext implements N
//-----------------------------------------------------------< internal
>---
void dispose() {
+ getWorkspace().getLockManager().unlockAllSessionScopedLocks();
if (observationManager != null) {
observationManager.dispose();
}
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java?rev=1518049&r1=1518048&r2=1518049&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java
Wed Aug 28 01:34:28 2013
@@ -61,7 +61,7 @@ public class WorkspaceImpl implements Ja
private final SessionContext sessionContext;
private final SessionDelegate sessionDelegate;
private final QueryManagerImpl queryManager;
- private final LockManager lockManager;
+ private final LockManagerImpl lockManager;
private final VersionManagerImpl versionManager;
private final ReadWriteNodeTypeManager nodeTypeManager;
@@ -182,7 +182,7 @@ public class WorkspaceImpl implements Ja
}
@Override
- public LockManager getLockManager() {
+ public LockManagerImpl getLockManager() {
return lockManager;
}
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=1518049&r1=1518048&r2=1518049&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:34:28 2013
@@ -89,7 +89,12 @@ public final class LockImpl implements L
return safePerform(new NodeOperation<String>(delegate) {
@Override
public String perform() throws RepositoryException {
- return node.getPath();
+ String token = node.getPath();
+ if (context.getOpenScopedLocks().contains(token)) {
+ return token;
+ } else {
+ return null;
+ }
}
});
}
@@ -105,12 +110,25 @@ public final class LockImpl implements L
@Override
public boolean isSessionScoped() {
- return false;
+ return safePerform(new NodeOperation<Boolean>(delegate) {
+ @Override
+ public Boolean perform() throws RepositoryException {
+ String path = node.getPath();
+ return context.getSessionScopedLocks().contains(path);
+ }
+ });
}
@Override
public boolean isLockOwningSession() {
- return true;
+ return safePerform(new NodeOperation<Boolean>(delegate) {
+ @Override
+ public Boolean perform() throws RepositoryException {
+ String path = node.getPath();
+ return context.getSessionScopedLocks().contains(path)
+ || context.getOpenScopedLocks().contains(path);
+ }
+ });
}
@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=1518049&r1=1518048&r2=1518049&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:34:28 2013
@@ -16,8 +16,7 @@
*/
package org.apache.jackrabbit.oak.jcr.lock;
-import static com.google.common.collect.Sets.newTreeSet;
-
+import java.util.Iterator;
import java.util.Set;
import javax.annotation.Nonnull;
@@ -33,6 +32,8 @@ import org.apache.jackrabbit.oak.jcr.Ses
import org.apache.jackrabbit.oak.jcr.delegate.NodeDelegate;
import org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate;
import org.apache.jackrabbit.oak.jcr.operation.SessionOperation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Simple lock manager implementation that just keeps track of a set of lock
@@ -41,31 +42,63 @@ import org.apache.jackrabbit.oak.jcr.ope
*/
public class LockManagerImpl implements LockManager {
+ /** Logger instance */
+ private static final Logger log =
+ LoggerFactory.getLogger(LockManagerImpl.class);
+
private final SessionContext sessionContext;
private final SessionDelegate delegate;
- private final Set<String> tokens = newTreeSet();
-
public LockManagerImpl(SessionContext sessionContext) {
this.sessionContext = sessionContext;
this.delegate = sessionContext.getSessionDelegate();
}
@Override @Nonnull
- public synchronized String[] getLockTokens() {
- return tokens.toArray(new String[tokens.size()]);
+ public String[] getLockTokens() throws RepositoryException {
+ return perform(new SessionOperation<String[]>() {
+ @Override @Nonnull
+ public String[] perform() {
+ Set<String> tokens = sessionContext.getOpenScopedLocks();
+ return tokens.toArray(new String[tokens.size()]);
+ }
+ });
}
@Override
- public synchronized void addLockToken(String lockToken) {
- tokens.add(lockToken);
+ public void addLockToken(final String lockToken)
+ throws RepositoryException {
+ try {
+ perform(new LockOperation<String>(sessionContext, lockToken) {
+ @Override
+ protected String perform(NodeDelegate node)
+ throws LockException {
+ if (node.holdsLock(false)) {
+ String token = node.getPath();
+ sessionContext.getOpenScopedLocks().add(token);
+ return null;
+ } else {
+ throw new LockException(
+ "Invalid lock token: " + lockToken);
+ }
+ }
+ });
+ } catch (IllegalArgumentException e) { // TODO: better exception
+ throw new LockException("Invalid lock token: " + lockToken);
+ }
}
@Override
- public synchronized void removeLockToken(String lockToken)
- throws LockException {
- if (!tokens.remove(lockToken)) {
+ public void removeLockToken(final String lockToken)
+ throws RepositoryException {
+ if (!perform(new SessionOperation<Boolean>() {
+ @Override @Nonnull
+ public Boolean perform() {
+ // TODO: name mapping?
+ return sessionContext.getOpenScopedLocks().remove(lockToken);
+ }
+ })) {
throw new LockException(
"Lock token " + lockToken + " is not held by this
session");
}
@@ -109,9 +142,9 @@ public class LockManagerImpl implements
@Override @Nonnull
public Lock lock(
- String absPath, final boolean isDeep, boolean isSessionScoped,
+ String absPath, final boolean isDeep, final boolean
isSessionScoped,
long timeoutHint, String ownerInfo) throws RepositoryException {
- NodeDelegate lock = perform(
+ return new LockImpl(sessionContext, perform(
new LockOperation<NodeDelegate>(sessionContext, absPath) {
@Override
protected NodeDelegate perform(NodeDelegate node)
@@ -121,14 +154,16 @@ public class LockManagerImpl implements
"Unable to lock a node with pending
changes");
}
node.lock(isDeep);
+ String path = node.getPath();
+ if (isSessionScoped) {
+ sessionContext.getSessionScopedLocks().add(path);
+ } else {
+ sessionContext.getOpenScopedLocks().add(path);
+ }
session.refresh(true);
return node;
}
- });
- if (!isSessionScoped) {
- addLockToken(absPath);
- }
- return new LockImpl(sessionContext, lock);
+ }));
}
@Override
@@ -137,13 +172,48 @@ public class LockManagerImpl implements
@Override
protected Void perform(NodeDelegate node)
throws RepositoryException {
- node.unlock();
- session.refresh(true);
- return null;
+ String path = node.getPath();
+ if (sessionContext.getSessionScopedLocks().contains(path)
+ || sessionContext.getOpenScopedLocks().contains(path))
{
+ node.unlock();
+ sessionContext.getSessionScopedLocks().remove(path);
+ sessionContext.getOpenScopedLocks().remove(path);
+ session.refresh(true);
+ return null;
+ } else {
+ throw new LockException("Not an owner of the lock " +
path);
+ }
}
});
}
+ public void unlockAllSessionScopedLocks() {
+ try {
+ perform(new SessionOperation<Void>() {
+ @Override
+ public Void perform() throws RepositoryException {
+ SessionDelegate delegate =
sessionContext.getSessionDelegate();
+ Iterator<String> iterator =
+ sessionContext.getSessionScopedLocks().iterator();
+ while (iterator.hasNext()) {
+ NodeDelegate node = delegate.getNode(iterator.next());
+ if (node != null) {
+ try {
+ node.unlock();
+ } catch (RepositoryException e) {
+ log.warn("Failed to clean up a session scoped
lock", e);
+ }
+ }
+ iterator.remove();
+ }
+ return null;
+ }
+ });
+ } catch (RepositoryException e) {
+ log.warn("Unexpected repository exception", e);
+ }
+ }
+
private <T> T perform(SessionOperation<T> operation)
throws RepositoryException {
return delegate.perform(operation);
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/VersionManagerImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/VersionManagerImpl.java?rev=1518049&r1=1518048&r2=1518049&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/VersionManagerImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/VersionManagerImpl.java
Wed Aug 28 01:34:28 2013
@@ -352,7 +352,6 @@ public class VersionManagerImpl implemen
if (nodeDelegate == null) {
throw new PathNotFoundException(absPath);
}
- checkNotLocked(absPath);
return new
VersionImpl(versionManagerDelegate.checkin(nodeDelegate), sessionContext);
}
});