Due to the limitations you brought up, we decided to use a super-user-like (un)locker session, always open during the app lifecycle, from a singleton, and the rest of the classes ask the class owning that (un)locker session to manage (lock, unlock, retrieve lock info) locks.
It's not a very elegant solution, but it works for us... You can take a look at: http://trac.calenco.com/browser/trunk/calenco-storage/src/main/java/com/calenco/storage/PooledRepoManager.java and: http://trac.calenco.com/browser/trunk/calenco-storage/src/main/java/com/calenco/storage/LockTokenGenerator.java Hope this helps. On Fri, May 13, 2011 at 3:43 AM, Kamil Nezval <[email protected]> wrote: > Hi, > > I'm trying to implement a "stealing" of a node's lock - one user will be > able to unlock the nodes locked by other users. According to the JCR 2.0 > specification it should be possible to assign a lock to a current session > using LockManager.addLockToken() method: > > "If the implementation does not support simultaneous lock ownership this > method will > transfer ownership of the lock corresponding to the specified lockToken to > the > current session, otherwise the current session will become an additional > owner of > that lock." > > So I've tried something like this: > > String nodePath = node.getPath(); > LockManager lockManager = jcrSession.getWorkspace().getLockManager(); > Lock nodeLock = lockManager.getLock(nodePath); > String lockToken = nodeLock.getLockToken(); > lockManager.addLockToken(lockToken); > lockManager.unlock(nodePath); > lockManager.lock(nodePath, false, false, 1000, jcrSession.getUserID()); > > But it doesn't work ("Cannot add lock token: lock already held by other > session." exception). I've looked into a source code and it looks like the > implementation doesn't follow the specification at all, see the code bellow > (LockManagerImpl.java): > > public void addLockToken(SessionImpl session, String lt) throws > LockException, RepositoryException { > try { > NodeId id = LockInfo.parseLockToken(lt); > > NodeImpl node = (NodeImpl) > sysSession.getItemManager().getItem(id); > Path path = node.getPrimaryPath(); > PathMap.Element<LockInfo> element = lockMap.map(path, true); > if (element != null) { > LockInfo info = element.get(); > if (info != null) { > if (info.isLockHolder(session)) { > // nothing to do > } else if (info.getLockHolder() == null) { > info.setLockHolder(session); > if (info instanceof InternalLockInfo) { > session.addListener((InternalLockInfo) info); > } > } else { > String msg = "Cannot add lock token: lock already > held by other session."; > log.warn(msg); > info.throwLockException(msg, session); > } > } > } > // inform SessionLockManager > getSessionLockManager(session).lockTokenAdded(lt); > } catch (IllegalArgumentException e) { > String msg = "Bad lock token: " + e.getMessage(); > log.warn(msg); > throw new LockException(msg); > } > } > > And it is also not possible to get a lock token if the current user is not > the lock holder (LockImpl.java): > > public String getLockToken() { > if (!info.isSessionScoped() && info.isLockHolder(node.getSession())) > { > return info.getLockToken(); > } else { > return null; > } > } > > So my question is whether it is somehow possible to implement a > "lock-stealing" as described above. > > Thanks in advance. > > Regards > > Kamil > > > -- Fabián Mandelbaum IS Engineer
