ALF-12866: WebDAV in-memory locking - threading issues.

* LockInfo instances provide a ReentrantReadWriteLock for clients to use
* LockInfo client code synchronises uses provided RRWLs.



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@34212 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Matt Ward
2012-02-24 11:28:09 +00:00
parent e579b15f15
commit 894056132b
7 changed files with 368 additions and 197 deletions

View File

@@ -22,9 +22,13 @@ import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; 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 * @author Ivan Rybnikov
* *
@@ -33,6 +37,8 @@ public final class LockInfo implements Serializable
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
// Exclusive lock token // Exclusive lock token
private String exclusiveLockToken = null; private String exclusiveLockToken = null;
@@ -73,6 +79,20 @@ public final class LockInfo implements Serializable
this.depth = depth; 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.
* <p>
* Not to be confused with WebDAV locks.
*
* @return
*/
public ReentrantReadWriteLock getRWLock()
{
return rwLock;
}
/** /**
* Returns true if node has shared or exclusive locks * 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 * @param lockTimeout
*/ */
public void setTimeoutSeconds(int lockTimeout) public void setTimeoutSeconds(int lockTimeout)
{ {
int timeoutMillis = (lockTimeout * 60 * 1000); if (lockTimeout == WebDAV.TIMEOUT_INFINITY)
Date now = new Date(); {
Date nextExpiry = new Date(now.getTime() + timeoutMillis); setExpires(null);
setExpires(nextExpiry); }
else
{
int timeoutMillis = (lockTimeout * 60 * 1000);
Date now = new Date();
Date nextExpiry = new Date(now.getTime() + timeoutMillis);
setExpires(nextExpiry);
}
} }
} }

View File

@@ -336,25 +336,39 @@ public class LockMethod extends WebDAVMethod
m_response.setStatus(HttpServletResponse.SC_CREATED); m_response.setStatus(HttpServletResponse.SC_CREATED);
} }
// Check if this is a new lock or a lock refresh // Check if this is a new lock or a lock refresh
if (hasLockToken()) if (hasLockToken())
{ {
this.lockInfo = checkNode(lockNodeInfo); lockInfo = checkNode(lockNodeInfo);
// If a request body is not defined and "If" header is sent we have createExclusive as false, lockInfo.getRWLock().writeLock().lock();
// but we need to check a previous LOCK was an exclusive. I.e. get the property for node. It try
// 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. // If a request body is not defined and "If" header is sent we have createExclusive as false,
this.createExclusive = WebDAV.XML_EXCLUSIVE.equals(this.lockInfo.getScope()); // but we need to check a previous LOCK was an exclusive. I.e. get the property for node. It
// Refresh an existing lock // is already has got in a checkNode method, so we need just get a scope from lockInfo.
refreshLock(lockNodeInfo, userName); // 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 else
{ {
this.lockInfo = checkNode(lockNodeInfo, true, this.createExclusive); lockInfo = checkNode(lockNodeInfo, true, createExclusive);
// Create a new lock lockInfo.getRWLock().writeLock().lock();
createLock(lockNodeInfo, userName); 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 // Create Lock token
lockToken = WebDAV.makeLockToken(lockNode.getNodeRef(), userName); lockToken = WebDAV.makeLockToken(lockNode.getNodeRef(), userName);
if (createExclusive) lockInfo.getRWLock().writeLock().lock();
try
{ {
// Lock the node if (createExclusive)
lockInfo.setTimeoutSeconds(getLockTimeout()); {
lockInfo.setExclusiveLockToken(lockToken); // Lock the node
} lockInfo.setTimeoutSeconds(getLockTimeout());
else lockInfo.setExclusiveLockToken(lockToken);
{ }
lockInfo.addSharedLockToken(lockToken); else
} {
lockInfo.addSharedLockToken(lockToken);
}
// Store lock depth // Store lock depth
lockInfo.setDepth(WebDAV.getDepthName(m_depth)); lockInfo.setDepth(WebDAV.getDepthName(m_depth));
// Store lock scope (shared/exclusive) // Store lock scope (shared/exclusive)
String scope = createExclusive ? WebDAV.XML_EXCLUSIVE : WebDAV.XML_SHARED; String scope = createExclusive ? WebDAV.XML_EXCLUSIVE : WebDAV.XML_SHARED;
lockInfo.setScope(scope); lockInfo.setScope(scope);
// Store the owner of this lock // Store the owner of this lock
lockInfo.setOwner(userName); lockInfo.setOwner(userName);
// Lock the node // Lock the node
getLockStore().put(lockNode.getNodeRef(), lockInfo); getLockStore().put(lockNode.getNodeRef(), lockInfo);
if (logger.isDebugEnabled()) 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) if (this.createExclusive)
{ {
// Update the expiry for the lock lockInfo.getRWLock().writeLock().lock();
if (lockInfo.getExpires() != null) try
{ {
// Update the expiry for the lock
lockInfo.setTimeoutSeconds(getLockTimeout()); lockInfo.setTimeoutSeconds(getLockTimeout());
} }
finally
{
lockInfo.getRWLock().writeLock().unlock();
}
} }
} }
@@ -444,21 +471,33 @@ public class LockMethod extends WebDAVMethod
{ {
String scope; String scope;
String lt; 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 if (lockToken != null)
scope = this.createExclusive ? WebDAV.XML_EXCLUSIVE : WebDAV.XML_SHARED; {
// Output created lock // In case of lock creation take the scope from request header
lt = lockToken; 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 lockInfo.getRWLock().readLock().unlock();
scope = this.lockInfo.getScope();
// Output refreshed lock
lt = this.lockInfo.getExclusiveLockToken();
} }
String owner = lockInfo.getOwner();
XMLWriter xml = createXMLWriter(); 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()); xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROP + nsdec, WebDAV.XML_NS_PROP + nsdec, getDAVHelper().getNullAttributes());
// Output the lock details // Output the lock details
Date expiry = lockInfo.getExpires();
generateLockDiscoveryXML(xml, lockNodeInfo, false, scope, WebDAV.getDepthName(m_depth), lt, owner, expiry); generateLockDiscoveryXML(xml, lockNodeInfo, false, scope, WebDAV.getDepthName(m_depth), lt, owner, expiry);
// Close off the XML // Close off the XML

View File

@@ -54,5 +54,11 @@ public interface LockStore
LockInfo get(NodeRef nodeRef); 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); void remove(NodeRef nodeRef);
} }

View File

@@ -924,9 +924,17 @@ public class PropFindMethod extends WebDAVMethod
// Output the lock status response // Output the lock status response
LockInfo lockInfo = getNodeLockInfo(nodeInfo); 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();
} }
} }

View File

@@ -190,18 +190,29 @@ public class PutMethod extends WebDAVMethod
String userName = getDAVHelper().getAuthenticationService().getCurrentUserName(); String userName = getDAVHelper().getAuthenticationService().getCurrentUserName();
LockInfo lockInfo = getLockStore().get(contentNodeInfo.getNodeRef()); 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(); if (lockInfo.isLocked() && !lockInfo.getOwner().equals(userName))
String owner = lockInfo.getOwner(); {
logger.debug("Node locked: path=["+path+"], owner=["+owner+"], current user=["+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 try
{ {
// Access the content // Access the content

View File

@@ -132,74 +132,92 @@ public class UnlockMethod extends WebDAVMethod
NodeRef nodeRef = lockNodeInfo.getNodeRef(); NodeRef nodeRef = lockNodeInfo.getNodeRef();
LockInfo lockInfo = getLockStore().get(nodeRef); LockInfo lockInfo = getLockStore().get(nodeRef);
if (lockInfo == null || !lockInfo.isLocked()) if (lockInfo == null)
{ {
if (logger.isDebugEnabled()) 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 // Node is not locked
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED); throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
} }
else if (lockInfo.isExpired())
lockInfo.getRWLock().writeLock().lock();
try
{ {
if (logger.isDebugEnabled()) if (!lockInfo.isLocked())
{
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()) if (logger.isDebugEnabled())
{ {
logger.debug("Unlock token=" + getLockToken() + " Not lock owner"); logger.debug("Unlock token=" + getLockToken() + " Not locked");
} }
// Node is not locked // Node is not locked
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED); throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
} }
} else if (lockInfo.isExpired())
else if (lockInfo.isShared())
{
Set<String> 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()) 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<String> 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 // 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 // PUT has not taken place but the client has issued an UNLOCK. The Timer

View File

@@ -751,9 +751,23 @@ public abstract class WebDAVMethod
*/ */
protected void generateLockDiscoveryXML(XMLWriter xml, FileInfo lockNodeInfo, LockInfo lockInfo) throws Exception protected void generateLockDiscoveryXML(XMLWriter xml, FileInfo lockNodeInfo, LockInfo lockInfo) throws Exception
{ {
String owner = lockInfo.getOwner(); String owner, scope, depth;
Date expiry = lockInfo.getExpires(); Date expiry;
generateLockDiscoveryXML(xml, lockNodeInfo, false, lockInfo.getScope(), lockInfo.getDepth(),
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); 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 protected LockInfo checkNode(FileInfo fileInfo, boolean ignoreShared, boolean lockMethod) throws WebDAVServerException
{ {
LockInfo nodeLockInfo = getNodeLockInfo(fileInfo); LockInfo nodeLockInfo = getNodeLockInfo(fileInfo);
String nodeETag = getDAVHelper().makeQuotedETag(fileInfo);
if (m_conditions == null) nodeLockInfo.getRWLock().readLock().lock();
try
{ {
if (!nodeLockInfo.isLocked()) String nodeETag = getDAVHelper().makeQuotedETag(fileInfo);
{
// Not locked
return nodeLockInfo;
}
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; return nodeLockInfo;
} }
if (!ignoreShared)
if (nodeLockInfo.isShared())
{ {
// Shared locks exist if (nodeLockInfo.getSharedLockTokens().isEmpty())
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))
{ {
// OK to write - lock is owned by current user. // Although flagged as shared - no shared locks.
return nodeLockInfo; return nodeLockInfo;
} }
if (!ignoreShared)
{
// Shared locks exist
throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED);
}
} }
else else
{ {
// Exclusive lock, owned by someone else // ALF-3681 fix. WebDrive 10 client doesn't send If header when locked resource is updated so check the node by lockOwner.
throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED); 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: // 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. // 1. If the node is locked we need to check it's Lock token independently of conditions check result.
// For example "(<wrong token>) (Not <DAV:no-lock>)" if always true, // For example "(<wrong token>) (Not <DAV:no-lock>)" if always true,
// but request must fail with 423 Locked response because node is locked. // but request must fail with 423 Locked response because node is locked.
// 2. Check if ANY of the conditions in If header true. // 2. Check if ANY of the conditions in If header true.
checkLockToken(nodeLockInfo, ignoreShared, lockMethod); checkLockToken(nodeLockInfo, ignoreShared, lockMethod);
checkConditions(nodeLockInfo.getExclusiveLockToken(), nodeETag); checkConditions(nodeLockInfo.getExclusiveLockToken(), nodeETag);
return nodeLockInfo; return nodeLockInfo;
}
finally
{
nodeLockInfo.getRWLock().readLock().unlock();
}
} }
/** /**
@@ -945,7 +968,6 @@ public abstract class WebDAVMethod
/** /**
* Checks if node can be accessed with WebDAV operation * Checks if node can be accessed with WebDAV operation
* *
* @param nodeLockToken - token to check
* @param lockInfo - node's lock info * @param lockInfo - node's lock info
* @param ignoreShared - if true - ignores shared lock tokens * @param ignoreShared - if true - ignores shared lock tokens
* @param lockMethod - must be true if used from lock method * @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 private void checkLockToken(LockInfo lockInfo, boolean ignoreShared, boolean lockMethod) throws WebDAVServerException
{ {
String nodeLockToken = lockInfo.getExclusiveLockToken(); lockInfo.getRWLock().readLock().lock();
Set<String> sharedLockTokens = lockInfo.getSharedLockTokens(); try
if (m_conditions != null)
{ {
// Request has conditions to check String nodeLockToken = lockInfo.getExclusiveLockToken();
if (lockInfo.isShared()) Set<String> sharedLockTokens = lockInfo.getSharedLockTokens();
if (m_conditions != null)
{ {
// Node has shared lock. Check if conditions contains lock token of the node. // Request has conditions to check
// If not throw exception if (lockInfo.isShared())
if (!sharedLockTokens.isEmpty())
{ {
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 else
{ {
// Node has exclusive lock. Check if conditions contains lock token of the node // Request has no conditions
// If not throw exception if (lockInfo.isShared())
for (Condition condition : m_conditions)
{ {
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 lockInfo.getRWLock().readLock().unlock();
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);
}
} }
throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED); throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED);
} }
@@ -1136,9 +1166,20 @@ public abstract class WebDAVMethod
lockInfo = m_parentLockInfo.get(parent); 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) if (lockInfo == null)
@@ -1177,12 +1218,24 @@ public abstract class WebDAVMethod
{ {
LockInfo lock = getLockStore().get(nodeInfo.getNodeRef()); 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); 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 ... // now check for lock status ...
if (parentLock.isLocked()) if (parentLock.isLocked() && WebDAV.INFINITY.equals(parentLock.getDepth()))
{ {
// In this case node is locked indirectly. // In this case node is locked indirectly.
return parentLock; return parentLock;
} }
return null;
}
finally
{
parentLock.getRWLock().readLock().unlock();
} }
return null;
} }
/** /**