Map<String, List<NodeKey>> lockedNodesByWorkspaceName = new HashMap<>();
// Iterate over the locks ...
MutableCachedNode locksNode = systemContent.mutableLocksNode();
for (ChildReference ref : locksNode.getChildReferences(systemSession)) {
NodeKey lockKey = ref.getKey();
CachedNode lockNode = systemSession.getNode(lockKey);
if (lockNode == null) {
//it may happen that another thread has performed a session.logout which means the lock might have been removed
continue;
}
ModeShapeLock lock = new ModeShapeLock(lockNode, systemSession);
NodeKey lockedNodeKey = lock.getLockedNodeKey();
if (lock.isSessionScoped() && activeSessionIds.contains(lock.getLockingSessionId())) {
//for active session locks belonging to the sessions of this process, we want to extend the expiration date
//so that other processes in a cluster can tell that this lock is still active
MutableCachedNode mutableLockNode = systemSession.mutable(lockKey);
Property prop = propertyFactory.create(ModeShapeLexicon.EXPIRATION_DATE, newExpiration);
mutableLockNode.setProperty(systemSession, prop);
//reflect the change in the expiry date in the internal map
this.locksByNodeKey.replace(lockedNodeKey, lock.withExpiryTime(newExpiration));
continue;
}
//if it's not an active session lock, we always check the expiry date
DateTime expirationDate = firstDate(lockNode.getProperty(ModeShapeLexicon.EXPIRATION_DATE, systemSession));
if (expirationDate.isBefore(now)) {
//remove the lock from the system area
systemContent.removeLock(lock);
//register the target node which needs cleaning
List<NodeKey> lockedNodes = lockedNodesByWorkspaceName.get(lock.getWorkspaceName());
if (lockedNodes == null) {
lockedNodes = new ArrayList<>();
lockedNodesByWorkspaceName.put(lock.getWorkspaceName(), lockedNodes);
}
lockedNodes.add(lockedNodeKey);
}
}
//persist all the changes to the locks from the system area
systemSession.save();
//update each of nodes which has been unlocked
for (String workspaceName : lockedNodesByWorkspaceName.keySet()) {
SessionCache internalSession = repository.repositoryCache().createSession(context, workspaceName, false);
for (NodeKey lockedNodeKey : lockedNodesByWorkspaceName.get(workspaceName)) {
//clear the internal cache
this.locksByNodeKey.remove(lockedNodeKey);
CachedNode lockedNode = internalSession.getWorkspace().getNode(lockedNodeKey);
if (lockedNode != null) {
MutableCachedNode mutableLockedNode = internalSession.mutable(lockedNodeKey);
mutableLockedNode.removeProperty(internalSession, JcrLexicon.LOCK_IS_DEEP);
mutableLockedNode.removeProperty(internalSession, JcrLexicon.LOCK_OWNER);
mutableLockedNode.unlock();