I believe there is a bug in the LockManagerImpl class with regard to
LockToken management. The problem is that the LockInfo listener of the
Session is lost. I believe the LockManagerImpl::lockTokenAdded method
sets the lockHolder to the session, but doesn't add the LockInfo as a
listener of the session to clear out the lockHolder when the session is
logging out.
if (info.getLockHolder() == null) {
info.setLockHolder(session);
} else {
should be
if (info.getLockHolder() == null) {
session.addListener(info); //info must be a
LockInfo, not an AbstraceLockInfo
info.setLockHolder(session);
} else {
similarly for LockManagerImpl::lockTokenRemoved....it should remove the
LockInfo from the session listener list.
Normally the listener is added in LockManagerImpl::internalLock, however
when the lock token is added to another session, the internalLock method
is not invoked.
Here is a testcase that should evoke the exception....the exception should
occur on the setProperty in session3.
try {
//Register the repository in JNDI
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.jackrabbit.core.jndi.provider.DummyInitialContextFactory");
env.put(Context.PROVIDER_URL, "localhost");
InitialContext ctx = new InitialContext(env);
RegistryHelper.registerRepository(ctx, "localRep", "repository.xml",
".", false);
Repository rep = (Repository)ctx.lookup("localRep");
String userid = "user";
String password = "password";
String nodeName = "testLockTokens";
Session session1 = rep.login(new SimpleCredentials(userid,
password.toCharArray()));
Node root = session1.getRootNode();
Node testNode = root.addNode(nodeName, "nt:unstructured");
testNode.addMixin("mix:lockable");
testNode.setProperty("foo", "session1");
session1.save();
Lock lock = testNode.lock(false, false);
String token = lock.getLockToken();
session1.logout();
Session session2 = rep.login(new SimpleCredentials(userid,
password.toCharArray()));
session2.addLockToken(token);
root = session2.getRootNode();
testNode = root.getNode(nodeName);
testNode.setProperty("foo", "session2");
session2.save();
session2.logout();
Session session3 = rep.login(new SimpleCredentials(userid,
password.toCharArray()));
session3.addLockToken(token);
root = session3.getRootNode();
testNode = root.getNode(nodeName);
testNode.setProperty("foo", "session3");
session3.save();
session3.logout();
Session session4 = rep.login(new SimpleCredentials(userid,
password.toCharArray()));
root = session4.getRootNode();
testNode = root.getNode(nodeName);
testNode.remove();
session4.save();
} catch (Exception e){
e.printStackTrace();
}
David