diff --git a/source/java/org/alfresco/repo/webdav/LockInfo.java b/source/java/org/alfresco/repo/webdav/LockInfo.java index d1a118e98d..cf8b15a1b0 100644 --- a/source/java/org/alfresco/repo/webdav/LockInfo.java +++ b/source/java/org/alfresco/repo/webdav/LockInfo.java @@ -22,9 +22,13 @@ import java.io.Serializable; import java.util.Date; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** - * Class to represent a WebDAV lock info + * Class to represent a WebDAV lock info. Instances of this class are accessible + * my multiple threads as they are kept in the {@link LockStore}. Clients of this + * class are expected to synchronise externally using the provided + * ReentrantReadWriteLock (use {@link #getRWLock()}). * * @author Ivan Rybnikov * @@ -33,6 +37,8 @@ public final class LockInfo implements Serializable { private static final long serialVersionUID = 1L; + private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); + // Exclusive lock token private String exclusiveLockToken = null; @@ -73,6 +79,20 @@ public final class LockInfo implements Serializable this.depth = depth; } + /** + * Retrieves the {@link ReentrantReadWriteLock} associated with this LockInfo. This is + * to allow client code to protect against invalid concurrent access to the state of + * this class. + *

+ * Not to be confused with WebDAV locks. + * + * @return + */ + public ReentrantReadWriteLock getRWLock() + { + return rwLock; + } + /** * Returns true if node has shared or exclusive locks * @@ -294,15 +314,23 @@ public final class LockInfo implements Serializable } /** - * Sets the expiry date/time to lockTimeout seconds into the future. + * Sets the expiry date/time to lockTimeout seconds into the future. Provide + * a lockTimeout of WebDAV.TIMEOUT_INFINITY for never expires. * * @param lockTimeout */ public void setTimeoutSeconds(int lockTimeout) { - int timeoutMillis = (lockTimeout * 60 * 1000); - Date now = new Date(); - Date nextExpiry = new Date(now.getTime() + timeoutMillis); - setExpires(nextExpiry); + if (lockTimeout == WebDAV.TIMEOUT_INFINITY) + { + setExpires(null); + } + else + { + int timeoutMillis = (lockTimeout * 60 * 1000); + Date now = new Date(); + Date nextExpiry = new Date(now.getTime() + timeoutMillis); + setExpires(nextExpiry); + } } } diff --git a/source/java/org/alfresco/repo/webdav/LockMethod.java b/source/java/org/alfresco/repo/webdav/LockMethod.java index 8552df1e2b..9ba07c4729 100644 --- a/source/java/org/alfresco/repo/webdav/LockMethod.java +++ b/source/java/org/alfresco/repo/webdav/LockMethod.java @@ -336,25 +336,39 @@ public class LockMethod extends WebDAVMethod m_response.setStatus(HttpServletResponse.SC_CREATED); } - - // Check if this is a new lock or a lock refresh if (hasLockToken()) { - this.lockInfo = checkNode(lockNodeInfo); - // If a request body is not defined and "If" header is sent we have createExclusive as false, - // but we need to check a previous LOCK was an exclusive. I.e. get the property for node. It - // is already has got in a checkNode method, so we need just get a scope from lockInfo. - // This particular case was raised as ALF-4008. - this.createExclusive = WebDAV.XML_EXCLUSIVE.equals(this.lockInfo.getScope()); - // Refresh an existing lock - refreshLock(lockNodeInfo, userName); + lockInfo = checkNode(lockNodeInfo); + lockInfo.getRWLock().writeLock().lock(); + try + { + // If a request body is not defined and "If" header is sent we have createExclusive as false, + // but we need to check a previous LOCK was an exclusive. I.e. get the property for node. It + // is already has got in a checkNode method, so we need just get a scope from lockInfo. + // This particular case was raised as ALF-4008. + this.createExclusive = WebDAV.XML_EXCLUSIVE.equals(this.lockInfo.getScope()); + // Refresh an existing lock + refreshLock(lockNodeInfo, userName); + } + finally + { + lockInfo.getRWLock().writeLock().unlock(); + } } else { - this.lockInfo = checkNode(lockNodeInfo, true, this.createExclusive); - // Create a new lock - createLock(lockNodeInfo, userName); + lockInfo = checkNode(lockNodeInfo, true, createExclusive); + lockInfo.getRWLock().writeLock().lock(); + try + { + // Create a new lock + createLock(lockNodeInfo, userName); + } + finally + { + lockInfo.getRWLock().writeLock().unlock(); + } } @@ -391,30 +405,38 @@ public class LockMethod extends WebDAVMethod // Create Lock token lockToken = WebDAV.makeLockToken(lockNode.getNodeRef(), userName); - if (createExclusive) + lockInfo.getRWLock().writeLock().lock(); + try { - // Lock the node - lockInfo.setTimeoutSeconds(getLockTimeout()); - lockInfo.setExclusiveLockToken(lockToken); - } - else - { - lockInfo.addSharedLockToken(lockToken); - } + if (createExclusive) + { + // Lock the node + lockInfo.setTimeoutSeconds(getLockTimeout()); + lockInfo.setExclusiveLockToken(lockToken); + } + else + { + lockInfo.addSharedLockToken(lockToken); + } - // Store lock depth - lockInfo.setDepth(WebDAV.getDepthName(m_depth)); - // Store lock scope (shared/exclusive) - String scope = createExclusive ? WebDAV.XML_EXCLUSIVE : WebDAV.XML_SHARED; - lockInfo.setScope(scope); - // Store the owner of this lock - lockInfo.setOwner(userName); - // Lock the node - getLockStore().put(lockNode.getNodeRef(), lockInfo); - - if (logger.isDebugEnabled()) + // Store lock depth + lockInfo.setDepth(WebDAV.getDepthName(m_depth)); + // Store lock scope (shared/exclusive) + String scope = createExclusive ? WebDAV.XML_EXCLUSIVE : WebDAV.XML_SHARED; + lockInfo.setScope(scope); + // Store the owner of this lock + lockInfo.setOwner(userName); + // Lock the node + getLockStore().put(lockNode.getNodeRef(), lockInfo); + + if (logger.isDebugEnabled()) + { + logger.debug("Locked node " + lockNode + ": " + lockInfo); + } + } + finally { - logger.debug("Locked node " + lockNode + ": " + lockInfo); + lockInfo.getRWLock().writeLock().unlock(); } } @@ -429,11 +451,16 @@ public class LockMethod extends WebDAVMethod { if (this.createExclusive) { - // Update the expiry for the lock - if (lockInfo.getExpires() != null) + lockInfo.getRWLock().writeLock().lock(); + try { + // Update the expiry for the lock lockInfo.setTimeoutSeconds(getLockTimeout()); } + finally + { + lockInfo.getRWLock().writeLock().unlock(); + } } } @@ -444,21 +471,33 @@ public class LockMethod extends WebDAVMethod { String scope; String lt; - if (lockToken != null) + String owner; + Date expiry; + + lockInfo.getRWLock().readLock().lock(); + try { - // In case of lock creation take the scope from request header - scope = this.createExclusive ? WebDAV.XML_EXCLUSIVE : WebDAV.XML_SHARED; - // Output created lock - lt = lockToken; + if (lockToken != null) + { + // In case of lock creation take the scope from request header + scope = this.createExclusive ? WebDAV.XML_EXCLUSIVE : WebDAV.XML_SHARED; + // Output created lock + lt = lockToken; + } + else + { + // In case of lock refreshing take the scope from previously stored lock + scope = this.lockInfo.getScope(); + // Output refreshed lock + lt = this.lockInfo.getExclusiveLockToken(); + } + owner = lockInfo.getOwner(); + expiry = lockInfo.getExpires(); } - else + finally { - // In case of lock refreshing take the scope from previously stored lock - scope = this.lockInfo.getScope(); - // Output refreshed lock - lt = this.lockInfo.getExclusiveLockToken(); + lockInfo.getRWLock().readLock().unlock(); } - String owner = lockInfo.getOwner(); XMLWriter xml = createXMLWriter(); @@ -468,7 +507,6 @@ public class LockMethod extends WebDAVMethod xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROP + nsdec, WebDAV.XML_NS_PROP + nsdec, getDAVHelper().getNullAttributes()); // Output the lock details - Date expiry = lockInfo.getExpires(); generateLockDiscoveryXML(xml, lockNodeInfo, false, scope, WebDAV.getDepthName(m_depth), lt, owner, expiry); // Close off the XML diff --git a/source/java/org/alfresco/repo/webdav/LockStore.java b/source/java/org/alfresco/repo/webdav/LockStore.java index 0437b61988..2565c50ad1 100644 --- a/source/java/org/alfresco/repo/webdav/LockStore.java +++ b/source/java/org/alfresco/repo/webdav/LockStore.java @@ -54,5 +54,11 @@ public interface LockStore LockInfo get(NodeRef nodeRef); + /** + * Remove LockInfo for the specified NodeRef. The LockInfo cannot be considered locked + * once removed from the LockStore. + * + * @param nodeRef + */ void remove(NodeRef nodeRef); } diff --git a/source/java/org/alfresco/repo/webdav/PropFindMethod.java b/source/java/org/alfresco/repo/webdav/PropFindMethod.java index 7e49e519a0..7f9dffdf47 100644 --- a/source/java/org/alfresco/repo/webdav/PropFindMethod.java +++ b/source/java/org/alfresco/repo/webdav/PropFindMethod.java @@ -924,9 +924,17 @@ public class PropFindMethod extends WebDAVMethod // Output the lock status response LockInfo lockInfo = getNodeLockInfo(nodeInfo); - if (lockInfo.isLocked()) + lockInfo.getRWLock().readLock().lock(); + try { - generateLockDiscoveryXML(xml, nodeInfo, lockInfo); + if (lockInfo.isLocked()) + { + generateLockDiscoveryXML(xml, nodeInfo, lockInfo); + } + } + finally + { + lockInfo.getRWLock().readLock().unlock(); } } diff --git a/source/java/org/alfresco/repo/webdav/PutMethod.java b/source/java/org/alfresco/repo/webdav/PutMethod.java index a5cc1612a3..e70c0187bb 100644 --- a/source/java/org/alfresco/repo/webdav/PutMethod.java +++ b/source/java/org/alfresco/repo/webdav/PutMethod.java @@ -190,18 +190,29 @@ public class PutMethod extends WebDAVMethod String userName = getDAVHelper().getAuthenticationService().getCurrentUserName(); LockInfo lockInfo = getLockStore().get(contentNodeInfo.getNodeRef()); - if (lockInfo != null && lockInfo.isLocked() && !lockInfo.getOwner().equals(userName)) + if (lockInfo != null) { - if (logger.isDebugEnabled()) + lockInfo.getRWLock().readLock().lock(); + try { - String path = getPath(); - String owner = lockInfo.getOwner(); - logger.debug("Node locked: path=["+path+"], owner=["+owner+"], current user=["+userName+"]"); + if (lockInfo.isLocked() && !lockInfo.getOwner().equals(userName)) + { + if (logger.isDebugEnabled()) + { + String path = getPath(); + String owner = lockInfo.getOwner(); + logger.debug("Node locked: path=["+path+"], owner=["+owner+"], current user=["+userName+"]"); + } + // Indicate that the resource is locked + throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED); + } + } + finally + { + lockInfo.getRWLock().readLock().unlock(); } - // Indicate that the resource is locked - throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED); } - + try { // Access the content diff --git a/source/java/org/alfresco/repo/webdav/UnlockMethod.java b/source/java/org/alfresco/repo/webdav/UnlockMethod.java index 3ee277bab1..0b2909c282 100644 --- a/source/java/org/alfresco/repo/webdav/UnlockMethod.java +++ b/source/java/org/alfresco/repo/webdav/UnlockMethod.java @@ -132,74 +132,92 @@ public class UnlockMethod extends WebDAVMethod NodeRef nodeRef = lockNodeInfo.getNodeRef(); LockInfo lockInfo = getLockStore().get(nodeRef); - if (lockInfo == null || !lockInfo.isLocked()) + if (lockInfo == null) { if (logger.isDebugEnabled()) { - logger.debug("Unlock token=" + getLockToken() + " Not locked"); + logger.debug("Unlock token=" + getLockToken() + " Not locked - no info in lock store."); } // Node is not locked throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED); } - else if (lockInfo.isExpired()) + + lockInfo.getRWLock().writeLock().lock(); + try { - if (logger.isDebugEnabled()) - { - logger.debug("Unlock token=" + getLockToken() + " Lock expired"); - } - // Return a success status - m_response.setStatus(HttpServletResponse.SC_NO_CONTENT); - removeNoContentAspect(nodeRef); - } - else if (lockInfo.isExclusive()) - { - String currentUser = getAuthenticationService().getCurrentUserName(); - if (currentUser.equals(lockInfo.getOwner())) - { - getLockStore().remove(nodeRef); - - // Indicate that the unlock was successful - m_response.setStatus(HttpServletResponse.SC_NO_CONTENT); - removeNoContentAspect(nodeRef); - - if (logger.isDebugEnabled()) - { - logger.debug("Unlock token=" + getLockToken() + " Successful"); - } - } - else + if (!lockInfo.isLocked()) { if (logger.isDebugEnabled()) { - logger.debug("Unlock token=" + getLockToken() + " Not lock owner"); + logger.debug("Unlock token=" + getLockToken() + " Not locked"); } // Node is not locked throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED); } - } - else if (lockInfo.isShared()) - { - Set sharedLocks = lockInfo.getSharedLockTokens(); - if (sharedLocks.contains(m_strLockToken)) + else if (lockInfo.isExpired()) { - sharedLocks.remove(m_strLockToken); - - // Indicate that the unlock was successful - m_response.setStatus(HttpServletResponse.SC_NO_CONTENT); - removeNoContentAspect(nodeRef); - - // DEBUG if (logger.isDebugEnabled()) { - logger.debug("Unlock token=" + getLockToken() + " Successful"); + logger.debug("Unlock token=" + getLockToken() + " Lock expired"); + } + // Return a success status + m_response.setStatus(HttpServletResponse.SC_NO_CONTENT); + removeNoContentAspect(nodeRef); + } + else if (lockInfo.isExclusive()) + { + String currentUser = getAuthenticationService().getCurrentUserName(); + if (currentUser.equals(lockInfo.getOwner())) + { + getLockStore().remove(nodeRef); + + // Indicate that the unlock was successful + m_response.setStatus(HttpServletResponse.SC_NO_CONTENT); + removeNoContentAspect(nodeRef); + + if (logger.isDebugEnabled()) + { + logger.debug("Unlock token=" + getLockToken() + " Successful"); + } + } + else + { + if (logger.isDebugEnabled()) + { + logger.debug("Unlock token=" + getLockToken() + " Not lock owner"); + } + // Node is not locked + throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED); } } + else if (lockInfo.isShared()) + { + Set sharedLocks = lockInfo.getSharedLockTokens(); + if (sharedLocks.contains(m_strLockToken)) + { + sharedLocks.remove(m_strLockToken); + + // Indicate that the unlock was successful + m_response.setStatus(HttpServletResponse.SC_NO_CONTENT); + removeNoContentAspect(nodeRef); + + // DEBUG + if (logger.isDebugEnabled()) + { + logger.debug("Unlock token=" + getLockToken() + " Successful"); + } + } + } + else + { + throw new IllegalStateException("Invalid LockInfo state: " + lockInfo); + } } - else + finally { - throw new IllegalStateException("Invalid LockInfo state: " + lockInfo); + lockInfo.getRWLock().writeLock().unlock(); } - } + } // This method removes a new zero byte node that has been locked, where the // PUT has not taken place but the client has issued an UNLOCK. The Timer diff --git a/source/java/org/alfresco/repo/webdav/WebDAVMethod.java b/source/java/org/alfresco/repo/webdav/WebDAVMethod.java index 6d876d79e9..cd56e019ca 100644 --- a/source/java/org/alfresco/repo/webdav/WebDAVMethod.java +++ b/source/java/org/alfresco/repo/webdav/WebDAVMethod.java @@ -751,9 +751,23 @@ public abstract class WebDAVMethod */ protected void generateLockDiscoveryXML(XMLWriter xml, FileInfo lockNodeInfo, LockInfo lockInfo) throws Exception { - String owner = lockInfo.getOwner(); - Date expiry = lockInfo.getExpires(); - generateLockDiscoveryXML(xml, lockNodeInfo, false, lockInfo.getScope(), lockInfo.getDepth(), + String owner, scope, depth; + Date expiry; + + lockInfo.getRWLock().readLock().lock(); + try + { + owner = lockInfo.getOwner(); + expiry = lockInfo.getExpires(); + scope = lockInfo.getScope(); + depth = lockInfo.getDepth(); + } + finally + { + lockInfo.getRWLock().readLock().unlock(); + } + + generateLockDiscoveryXML(xml, lockNodeInfo, false, scope, depth, WebDAV.makeLockToken(lockNodeInfo.getNodeRef(), owner), owner, expiry); } @@ -873,60 +887,69 @@ public abstract class WebDAVMethod protected LockInfo checkNode(FileInfo fileInfo, boolean ignoreShared, boolean lockMethod) throws WebDAVServerException { LockInfo nodeLockInfo = getNodeLockInfo(fileInfo); - String nodeETag = getDAVHelper().makeQuotedETag(fileInfo); - - if (m_conditions == null) + nodeLockInfo.getRWLock().readLock().lock(); + try { - if (!nodeLockInfo.isLocked()) - { - // Not locked - return nodeLockInfo; - } + String nodeETag = getDAVHelper().makeQuotedETag(fileInfo); + - if (nodeLockInfo.isShared()) + if (m_conditions == null) { - if (nodeLockInfo.getSharedLockTokens().isEmpty()) + if (!nodeLockInfo.isLocked()) { - // Although flagged as shared - no shared locks. + // Not locked return nodeLockInfo; } - if (!ignoreShared) + + if (nodeLockInfo.isShared()) { - // Shared locks exist - throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED); - } - } - else - { - // ALF-3681 fix. WebDrive 10 client doesn't send If header when locked resource is updated so check the node by lockOwner. - if (m_userAgent != null && m_userAgent.equals(WebDAV.AGENT_MICROSOFT_DATA_ACCESS_INTERNET_PUBLISHING_PROVIDER_DAV)) - { - String currentUser = getAuthenticationService().getCurrentUserName(); - String lockOwner = nodeLockInfo.getOwner(); - if (lockOwner.equals(currentUser)) + if (nodeLockInfo.getSharedLockTokens().isEmpty()) { - // OK to write - lock is owned by current user. + // Although flagged as shared - no shared locks. return nodeLockInfo; } + if (!ignoreShared) + { + // Shared locks exist + throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED); + } } else { - // Exclusive lock, owned by someone else - throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED); + // ALF-3681 fix. WebDrive 10 client doesn't send If header when locked resource is updated so check the node by lockOwner. + if (m_userAgent != null && m_userAgent.equals(WebDAV.AGENT_MICROSOFT_DATA_ACCESS_INTERNET_PUBLISHING_PROVIDER_DAV)) + { + String currentUser = getAuthenticationService().getCurrentUserName(); + String lockOwner = nodeLockInfo.getOwner(); + if (lockOwner.equals(currentUser)) + { + // OK to write - lock is owned by current user. + return nodeLockInfo; + } + } + else + { + // Exclusive lock, owned by someone else + throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED); + } } } - } - // Checking of the If tag consists of two checks: - // 1. If the node is locked we need to check it's Lock token independently of conditions check result. - // For example "() (Not )" if always true, - // but request must fail with 423 Locked response because node is locked. - // 2. Check if ANY of the conditions in If header true. - checkLockToken(nodeLockInfo, ignoreShared, lockMethod); - checkConditions(nodeLockInfo.getExclusiveLockToken(), nodeETag); - - return nodeLockInfo; + // Checking of the If tag consists of two checks: + // 1. If the node is locked we need to check it's Lock token independently of conditions check result. + // For example "() (Not )" if always true, + // but request must fail with 423 Locked response because node is locked. + // 2. Check if ANY of the conditions in If header true. + checkLockToken(nodeLockInfo, ignoreShared, lockMethod); + checkConditions(nodeLockInfo.getExclusiveLockToken(), nodeETag); + + return nodeLockInfo; + } + finally + { + nodeLockInfo.getRWLock().readLock().unlock(); + } } /** @@ -945,7 +968,6 @@ public abstract class WebDAVMethod /** * Checks if node can be accessed with WebDAV operation * - * @param nodeLockToken - token to check * @param lockInfo - node's lock info * @param ignoreShared - if true - ignores shared lock tokens * @param lockMethod - must be true if used from lock method @@ -953,67 +975,75 @@ public abstract class WebDAVMethod */ private void checkLockToken(LockInfo lockInfo, boolean ignoreShared, boolean lockMethod) throws WebDAVServerException { - String nodeLockToken = lockInfo.getExclusiveLockToken(); - Set sharedLockTokens = lockInfo.getSharedLockTokens(); - - if (m_conditions != null) + lockInfo.getRWLock().readLock().lock(); + try { - // Request has conditions to check - if (lockInfo.isShared()) + String nodeLockToken = lockInfo.getExclusiveLockToken(); + Set sharedLockTokens = lockInfo.getSharedLockTokens(); + + if (m_conditions != null) { - // Node has shared lock. Check if conditions contains lock token of the node. - // If not throw exception - if (!sharedLockTokens.isEmpty()) + // Request has conditions to check + if (lockInfo.isShared()) { - if (!ignoreShared) + // Node has shared lock. Check if conditions contains lock token of the node. + // If not throw exception + if (!sharedLockTokens.isEmpty()) { - for (Condition condition : m_conditions) + if (!ignoreShared) { - for (String sharedLockToken : sharedLockTokens) + for (Condition condition : m_conditions) { - if (condition.getLockTokensMatch().contains(sharedLockToken)) + for (String sharedLockToken : sharedLockTokens) { - return; + if (condition.getLockTokensMatch().contains(sharedLockToken)) + { + return; + } } } + throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED); } - throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED); + return; } - return; + } + else + { + // Node has exclusive lock. Check if conditions contains lock token of the node + // If not throw exception + for (Condition condition : m_conditions) + { + if (nodeLockToken != null) + { + if (condition.getLockTokensMatch().contains(nodeLockToken)) + { + return; + } + } + } + throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED); } } else { - // Node has exclusive lock. Check if conditions contains lock token of the node - // If not throw exception - for (Condition condition : m_conditions) + // Request has no conditions + if (lockInfo.isShared()) { - if (nodeLockToken != null) + // If lock is shared and check was called not from LOCK method return + if (!lockMethod) { - if (condition.getLockTokensMatch().contains(nodeLockToken)) - { - return; - } + return; } + // Throw exception - we can't set lock on node with shared lock + throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED); } - throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED); } } - else + finally { - // Request has no conditions - if (lockInfo.isShared()) - { - // If lock is shared and check was called not from LOCK method return - if (!lockMethod) - { - return; - } - // Throw exception - we can't set lock on node with shared lock - throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED); - } + lockInfo.getRWLock().readLock().unlock(); } - + throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED); } @@ -1136,9 +1166,20 @@ public abstract class WebDAVMethod lockInfo = m_parentLockInfo.get(parent); - if ((lockInfo != null) && (lockInfo.isLocked())) + if (lockInfo != null) { - return lockInfo; + lockInfo.getRWLock().readLock().lock(); + try + { + if (lockInfo.isLocked()) + { + return lockInfo; + } + } + finally + { + lockInfo.getRWLock().readLock().unlock(); + } } if (lockInfo == null) @@ -1177,12 +1218,24 @@ public abstract class WebDAVMethod { LockInfo lock = getLockStore().get(nodeInfo.getNodeRef()); - if (lock != null && lock.isLocked()) + if (lock == null) { - return lock; + return null; } - return null; + lock.getRWLock().readLock().lock(); + try + { + if (lock.isLocked()) + { + return lock; + } + return null; + } + finally + { + lock.getRWLock().readLock().unlock(); + } } /** @@ -1195,17 +1248,26 @@ public abstract class WebDAVMethod { LockInfo parentLock = getLockStore().get(parent); - if (parentLock != null && WebDAV.INFINITY.equals(parentLock.getDepth())) + if (parentLock == null) + { + return null; + } + + parentLock.getRWLock().readLock().lock(); + try { // now check for lock status ... - if (parentLock.isLocked()) + if (parentLock.isLocked() && WebDAV.INFINITY.equals(parentLock.getDepth())) { // In this case node is locked indirectly. return parentLock; } + return null; + } + finally + { + parentLock.getRWLock().readLock().unlock(); } - - return null; } /**