2011/5/13 Fabián Mandelbaum <[email protected]>: > Hello Stefan, > > how will your proposal work with long-lived (a.k.a. not session-scoped) > tokens? > > A common scenario in web applications is that the client issuing the > lock request is not always able to save (cache, keep, whatever one > wants to call it) the lock tokens, and thus would not be able to pass > the token around like you suggest (it's not uncommon that a user > closes the web browser tab or window that had the client application > running onto, and away goes the lock tokens that client could have > saved...). It's common for the web application backend to maintain a > pool of JCR sessions, thus you cannot guarantee that you'll have > access to the session that locked the item (thus the lock token is > 'lost' somehow...) > > Hope to have been clear :-)
absolutely ;) if you need to be able to 'break' somebody else's lock you could e.g. override the following method: o.a.jackrabbit.core..lock.checkUnlock(LockInfo info, Session session) that way you can implement some sort of lock administrator session which is able to unlock any open-scoped lock. note that you'd have to subclass RepositoryImpl as well. cheers stefan > > On Fri, May 13, 2011 at 9:24 AM, Stefan Guggisberg > <[email protected]> wrote: >> On Fri, May 13, 2011 at 8: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. >> >> i prefer the term "transferring lock ownership"... >> >>> 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, >> >> the implementation is spec-compliant. the javadoc [1] clearly states >> that a LockException is thrown >> >> "if the specified lock token is already held by another Session and >> the implementation does not support simultaneous ownership of >> open-scoped locks." >> >> before adding the token to the new session you have to remove the token >> from the other session. >> >> cheers >> stefan >> >> [1] >> http://www.day.com/maven/jsr170/javadocs/jcr-2.0/javax/jcr/lock/LockManager.html#addLockToken(java.lang.String) >> >>> 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 >
