You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2009/05/20 18:58:07 UTC
svn commit: r776766 - in /jackrabbit/branches/1.x: ./
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/
jackrabbit-core/src/test/java/org/apache/jackrabbit/core/
Author: jukka
Date: Wed May 20 16:58:06 2009
New Revision: 776766
URL: http://svn.apache.org/viewvc?rev=776766&view=rev
Log:
1.x: Merged revision 775868 (JCR-1634)
Modified:
jackrabbit/branches/1.x/ (props changed)
jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java
jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java
jackrabbit/branches/1.x/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java
Propchange: jackrabbit/branches/1.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed May 20 16:58:06 2009
@@ -1 +1 @@
-/jackrabbit/trunk:770143-773197,773483,773525-773554,773584,773588,773828,773835-775756,775833,775836,775840,775981,775986,776036,776256,776310,776313,776321-776322,776332,776356-776357,776362,776373,776650-776693,776737
+/jackrabbit/trunk:770143-773197,773483,773525-773554,773584,773588,773828,773835-775756,775833,775836,775840,775868,775981,775986,776036,776256,776310,776313,776321-776322,776332,776356-776357,776362,776373,776650-776693,776737
Modified: jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java?rev=776766&r1=776765&r2=776766&view=diff
==============================================================================
--- jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java (original)
+++ jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java Wed May 20 16:58:06 2009
@@ -20,10 +20,12 @@
import org.apache.jackrabbit.core.NodeImpl;
import org.apache.jackrabbit.core.SessionImpl;
import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.WorkspaceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.RepositoryException;
+import javax.jcr.Workspace;
import javax.jcr.lock.LockException;
import java.util.Map;
import java.util.HashMap;
@@ -263,16 +265,66 @@
/**
* Add lock token to this environment.
+ * @param session
* @param lt lock token
+ * @throws RepositoryException
*/
- public void addLockToken(String lt) {
+ public void addLockToken(SessionImpl session, String lt) throws RepositoryException {
+ try {
+ LockToken lockToken = LockToken.parse(lt);
+ NodeImpl node = (NodeImpl) session.getItemManager().getItem(lockToken.getId());
+ AbstractLockInfo info = getLockInfo(node);
+ if (info != null) {
+ if (info.getLockHolder() == null) {
+ info.setLockHolder(session);
+ } else {
+ String msg = "Cannot add lock token: lock already held by other session.";
+ log.warn(msg);
+ throw new LockException(msg);
+ }
+ }
+ // inform SessionLockManager
+ getSessionLockManager(session).lockTokenAdded(lt);
+ } catch (IllegalArgumentException e) {
+ String msg = "Bad lock token: " + e.getMessage();
+ log.warn(msg);
+ throw new LockException(msg);
+ }
}
/**
* Remove lock token from this environment.
+ * @param session
* @param lt lock token
+ * @throws RepositoryException
*/
- public void removeLockToken(String lt) {
+ public void removeLockToken(SessionImpl session, String lt) throws RepositoryException {
+ try {
+ LockToken lockToken = LockToken.parse(lt);
+
+ NodeImpl node = (NodeImpl) session.getItemManager().getItem(lockToken.getId());
+ AbstractLockInfo info = getLockInfo(node);
+ if (info != null) {
+ if (session == info.getLockHolder()) {
+ info.setLockHolder(null);
+ } else {
+ String msg = "Cannot remove lock token: lock held by other session.";
+ log.warn(msg);
+ throw new LockException(msg);
+ }
+ }
+ // inform SessionLockManager
+ getSessionLockManager(session).lockTokenRemoved(lt);
+ } catch (IllegalArgumentException e) {
+ String msg = "Bad lock token: " + e.getMessage();
+ log.warn(msg);
+ throw new LockException(msg);
+ }
+ }
+
+ static SessionLockManager getSessionLockManager(SessionImpl session) throws RepositoryException {
+ WorkspaceImpl wsp = (WorkspaceImpl) session.getWorkspace();
+ return (SessionLockManager) wsp.getLockManager();
}
/**
@@ -437,7 +489,12 @@
if (isUnlock) {
lockMgr.internalUnlock(node);
} else {
- lockMgr.internalLock(node, deep, sessionScoped, getSecondsRemaining(), lockOwner);
+ AbstractLockInfo internalLock = lockMgr.internalLock(node, deep, sessionScoped, getSecondsRemaining(), lockOwner);
+ AbstractLockInfo xaEnvLock = getLockInfo(node);
+ // Check if the lockToken has been removed in the transaction ...
+ if (xaEnvLock != null && xaEnvLock.getLockHolder() == null) {
+ internalLock.setLockHolder(null);
+ }
}
}
Modified: jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java?rev=776766&r1=776765&r2=776766&view=diff
==============================================================================
--- jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java (original)
+++ jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java Wed May 20 16:58:06 2009
@@ -205,7 +205,7 @@
*/
public void lockTokenAdded(SessionImpl session, String lt) throws RepositoryException {
if (isInXA()) {
- xaEnv.addLockToken(lt);
+ xaEnv.addLockToken(session, lt);
} else {
lockMgr.lockTokenAdded(session, lt);
}
@@ -216,7 +216,7 @@
*/
public void lockTokenRemoved(SessionImpl session, String lt) throws RepositoryException {
if (isInXA()) {
- xaEnv.removeLockToken(lt);
+ xaEnv.removeLockToken(session, lt);
} else {
lockMgr.lockTokenRemoved(session, lt);
}
Modified: jackrabbit/branches/1.x/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.x/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java?rev=776766&r1=776765&r2=776766&view=diff
==============================================================================
--- jackrabbit/branches/1.x/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java (original)
+++ jackrabbit/branches/1.x/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java Wed May 20 16:58:06 2009
@@ -29,6 +29,7 @@
import javax.jcr.version.VersionException;
import javax.jcr.version.Version;
import javax.jcr.lock.Lock;
+import javax.jcr.lock.LockException;
import javax.transaction.UserTransaction;
import javax.transaction.RollbackException;
import java.util.StringTokenizer;
@@ -787,6 +788,48 @@
}
/**
+ * Test locking and unlocking behavior in transaction
+ * @throws Exception
+ */
+ public void testLockUnlockCommit() 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();
+
+ // 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());
+
+ n.unlock();
+ // commit in first session
+ utx.commit();
+
+ // verify node is locked in both sessions
+ assertFalse("Node locked in session 1", n.isLocked());
+ assertFalse("Node locked in session 2", nOther.isLocked());
+ } finally {
+ // logout
+ other.logout();
+ }
+ }
+
+ /**
* Test locking a node in one session. Verify that node is not locked
* in session after rollback.
* @throws Exception
@@ -920,7 +963,78 @@
assertTrue(nOther2.isLocked());
utx.commit();
+
+ }
+
+ /**
+ * Test add and remove lock tokens in a transaction
+ * @throws Exception
+ */
+ public void testAddRemoveLockToken() throws Exception {
+ // create new node and lock it
+ UserTransaction utx = new UserTransactionImpl(superuser);
+ utx.begin();
+
+ // add node that is both lockable and referenceable, save
+ Node rootNode = superuser.getRootNode();
+ Node n = rootNode.addNode(nodeName1);
+ n.addMixin(mixLockable);
+ n.addMixin(mixReferenceable);
+ rootNode.save();
+
+ String uuid = n.getUUID();
+
+ // lock this new node
+ Lock lock = n.lock(true, false);
+ String lockToken = lock.getLockToken();
+
+ // assert: session must get a non-null lock token
+ assertNotNull("session must get a non-null lock token", lockToken);
+
+ // assert: session must hold lock token
+ assertTrue("session must hold lock token", containsLockToken(superuser, lockToken));
+
+ superuser.removeLockToken(lockToken);
+ assertNull("session must get a null lock token", lock.getLockToken());
+
+ // commit
+ utx.commit();
+
+ // refresh Lock Info
+ lock = n.getLock();
+
+ assertNull("session must get a null lock token", lock.getLockToken());
+ Session other = helper.getSuperuserSession();
+ // start new Transaction and try to add lock token
+ utx = new UserTransactionImpl(other);
+ utx.begin();
+
+ Node otherNode = other.getNodeByUUID(uuid);
+ assertTrue("Node not locked", otherNode.isLocked());
+ try {
+ otherNode.setProperty(propertyName1, "foo");
+ fail("Lock exception should be thrown");
+ } catch (LockException e) {
+ // expected
+ }
+
+ // add lock token
+ other.addLockToken(lockToken);
+
+ // refresh Lock Info
+ lock = otherNode.getLock();
+
+ // assert: session must hold lock token
+ assertTrue("session must hold lock token", containsLockToken(other, lock.getLockToken()));
+
+ otherNode.unlock();
+
+ assertFalse("Node is locked", otherNode.isLocked());
+
+ otherNode.setProperty(propertyName1, "foo");
+ other.save();
+ utx.commit();
}
/**
@@ -1628,4 +1742,18 @@
utx.commit();
}
+
+ /**
+ * Return a flag indicating whether the indicated session contains
+ * a specific lock token
+ */
+ private boolean containsLockToken(Session session, String lockToken) {
+ String[] lt = session.getLockTokens();
+ for (int i = 0; i < lt.length; i++) {
+ if (lt[i].equals(lockToken)) {
+ return true;
+ }
+ }
+ return false;
+ }
}