mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-21 18:09:20 +00:00
Merged DEV_TEMPORARY to HEAD
18288: ENH-678: alfresco webdav does not pass litmus webdav test suite git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@18320 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -95,6 +95,10 @@ public abstract class AbstractMoveOrCopyMethod extends HierarchicalMethod
|
|||||||
FileInfo destParentInfo = null;
|
FileInfo destParentInfo = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (destPath.endsWith(WebDAVHelper.PathSeperator))
|
||||||
|
{
|
||||||
|
destPath = destPath.substring(0, destPath.length() - 1);
|
||||||
|
}
|
||||||
destParentInfo = getDAVHelper().getParentNodeForPath(rootNodeRef, destPath, servletPath);
|
destParentInfo = getDAVHelper().getParentNodeForPath(rootNodeRef, destPath, servletPath);
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException e)
|
catch (FileNotFoundException e)
|
||||||
@@ -103,7 +107,7 @@ public abstract class AbstractMoveOrCopyMethod extends HierarchicalMethod
|
|||||||
{
|
{
|
||||||
logger.debug("Destination parent folder doesn't exist: " + destPath);
|
logger.debug("Destination parent folder doesn't exist: " + destPath);
|
||||||
}
|
}
|
||||||
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
|
throw new WebDAVServerException(HttpServletResponse.SC_CONFLICT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for the existence of the destination node
|
// check for the existence of the destination node
|
||||||
@@ -123,6 +127,8 @@ public abstract class AbstractMoveOrCopyMethod extends HierarchicalMethod
|
|||||||
// delete the destination node if it is not the same as the source node
|
// delete the destination node if it is not the same as the source node
|
||||||
if (!destInfo.getNodeRef().equals(sourceInfo.getNodeRef()))
|
if (!destInfo.getNodeRef().equals(sourceInfo.getNodeRef()))
|
||||||
{
|
{
|
||||||
|
checkNode(destInfo);
|
||||||
|
|
||||||
// attempting to move or copy onto another node
|
// attempting to move or copy onto another node
|
||||||
fileFolderService.delete(destInfo.getNodeRef());
|
fileFolderService.delete(destInfo.getNodeRef());
|
||||||
}
|
}
|
||||||
@@ -138,7 +144,9 @@ public abstract class AbstractMoveOrCopyMethod extends HierarchicalMethod
|
|||||||
|
|
||||||
NodeRef sourceNodeRef = sourceInfo.getNodeRef();
|
NodeRef sourceNodeRef = sourceInfo.getNodeRef();
|
||||||
NodeRef destParentNodeRef = destParentInfo.getNodeRef();
|
NodeRef destParentNodeRef = destParentInfo.getNodeRef();
|
||||||
|
|
||||||
String name = getDAVHelper().splitPath(destPath)[1];
|
String name = getDAVHelper().splitPath(destPath)[1];
|
||||||
|
|
||||||
moveOrCopy(fileFolderService, sourceNodeRef, destParentNodeRef, name);
|
moveOrCopy(fileFolderService, sourceNodeRef, destParentNodeRef, name);
|
||||||
|
|
||||||
// Set the response status
|
// Set the response status
|
||||||
|
@@ -99,6 +99,9 @@ public class DeleteMethod extends WebDAVMethod
|
|||||||
}
|
}
|
||||||
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
|
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkNode(fileInfo);
|
||||||
|
|
||||||
// delete it
|
// delete it
|
||||||
fileFolderService.delete(fileInfo.getNodeRef());
|
fileFolderService.delete(fileInfo.getNodeRef());
|
||||||
}
|
}
|
||||||
|
@@ -293,7 +293,7 @@ public class GetMethod extends WebDAVMethod
|
|||||||
* @param strETagHeader The header to parse
|
* @param strETagHeader The header to parse
|
||||||
* @return A list of ETags
|
* @return A list of ETags
|
||||||
*/
|
*/
|
||||||
private ArrayList parseETags(String strETagHeader)
|
private ArrayList<String> parseETags(String strETagHeader)
|
||||||
{
|
{
|
||||||
ArrayList<String> list = new ArrayList<String>();
|
ArrayList<String> list = new ArrayList<String>();
|
||||||
|
|
||||||
|
280
source/java/org/alfresco/repo/webdav/LockInfo.java
Executable file
280
source/java/org/alfresco/repo/webdav/LockInfo.java
Executable file
@@ -0,0 +1,280 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.webdav;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to represent a WebDAV lock info
|
||||||
|
*
|
||||||
|
* @author Ivan Rybnikov
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class LockInfo
|
||||||
|
{
|
||||||
|
// Exclusive lock token
|
||||||
|
private String token = null;
|
||||||
|
|
||||||
|
// Lock scope
|
||||||
|
private String scope = null;
|
||||||
|
|
||||||
|
// Lock depth
|
||||||
|
private String depth = null;
|
||||||
|
|
||||||
|
// If lock is shared
|
||||||
|
private boolean shared = false;
|
||||||
|
|
||||||
|
// Shared lock tokens
|
||||||
|
private LinkedList<String> sharedLockTokens = null;
|
||||||
|
|
||||||
|
// Shared lock token separator
|
||||||
|
private static final String SHARED_LOCK_TOKEN_SEPARATOR = ",";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public LockInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param token Exclusive lock token
|
||||||
|
* @param scope Lock scope (shared/exclusive)
|
||||||
|
* @param depth Lock depth (0/infinity)
|
||||||
|
*/
|
||||||
|
public LockInfo(String token, String scope, String depth)
|
||||||
|
{
|
||||||
|
this.token = token;
|
||||||
|
this.scope = scope;
|
||||||
|
this.depth = depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if node has shared or exclusive locks
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean isLocked()
|
||||||
|
{
|
||||||
|
if (token != null || (sharedLockTokens != null && !sharedLockTokens.isEmpty()))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for exclusive lock token
|
||||||
|
*
|
||||||
|
* @param token Lock token
|
||||||
|
*/
|
||||||
|
public void setToken(String token)
|
||||||
|
{
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for exclusive lock token
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getToken()
|
||||||
|
{
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for lock scope.
|
||||||
|
*
|
||||||
|
* @param scope
|
||||||
|
*/
|
||||||
|
public void setScope(String scope)
|
||||||
|
{
|
||||||
|
this.scope = scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns lock scope
|
||||||
|
*
|
||||||
|
* @return lock scope
|
||||||
|
*/
|
||||||
|
public String getScope()
|
||||||
|
{
|
||||||
|
return scope == null ? WebDAV.XML_EXCLUSIVE : scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for lock depth
|
||||||
|
*
|
||||||
|
* @param depth lock depth
|
||||||
|
*/
|
||||||
|
public void setDepth(String depth)
|
||||||
|
{
|
||||||
|
this.depth = depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns lock depth
|
||||||
|
*
|
||||||
|
* @return lock depth
|
||||||
|
*/
|
||||||
|
public String getDepth()
|
||||||
|
{
|
||||||
|
return depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms shared lock tokens string to list.
|
||||||
|
*
|
||||||
|
* @param sharedLockTokens String contains all node's shared lock tokens
|
||||||
|
* divided with SHARED_LOCK_TOKEN_SEPARATOR value.
|
||||||
|
* @return List of shared lock tokens
|
||||||
|
*/
|
||||||
|
public static LinkedList<String> parseSharedLockTokens(String sharedLockTokens)
|
||||||
|
{
|
||||||
|
if (sharedLockTokens == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinkedList<String> result = new LinkedList<String>();
|
||||||
|
String[] sl = sharedLockTokens.split(SHARED_LOCK_TOKEN_SEPARATOR);
|
||||||
|
for (int i = 0; i < sl.length; i++)
|
||||||
|
{
|
||||||
|
result.add(sl[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for sharedLockTokens list
|
||||||
|
*
|
||||||
|
* @return LinkedList<String>
|
||||||
|
*/
|
||||||
|
public LinkedList<String> getSharedLockTokens()
|
||||||
|
{
|
||||||
|
return sharedLockTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for sharedLockTokens list
|
||||||
|
*
|
||||||
|
* @param sharedLockTokens
|
||||||
|
*/
|
||||||
|
public void setSharedLockTokens(LinkedList<String> sharedLockTokens)
|
||||||
|
{
|
||||||
|
this.sharedLockTokens = sharedLockTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds new shared lock token to sharedLockTokens list
|
||||||
|
*
|
||||||
|
* @param token new token
|
||||||
|
*/
|
||||||
|
public void addSharedLockToken(String token)
|
||||||
|
{
|
||||||
|
if (sharedLockTokens == null)
|
||||||
|
{
|
||||||
|
sharedLockTokens = new LinkedList<String>();
|
||||||
|
}
|
||||||
|
sharedLockTokens.add(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms list of shared locks to string.
|
||||||
|
* Lock tokens separated with SHARED_LOCK_TOKEN_SEPARATOR value.
|
||||||
|
*
|
||||||
|
* @param lockTokens list of shared locks
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public static String makeSharedLockTokensString(LinkedList<String> lockTokens)
|
||||||
|
{
|
||||||
|
StringBuilder str = new StringBuilder();
|
||||||
|
|
||||||
|
boolean first = true;
|
||||||
|
for (String token : lockTokens)
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
{
|
||||||
|
str.append(SHARED_LOCK_TOKEN_SEPARATOR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
str.append(token);
|
||||||
|
}
|
||||||
|
return str.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for shared property
|
||||||
|
*
|
||||||
|
* @param shared
|
||||||
|
*/
|
||||||
|
public void setShared(boolean shared)
|
||||||
|
{
|
||||||
|
this.shared = shared;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true is lock is shared
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean isShared()
|
||||||
|
{
|
||||||
|
return shared;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the lock info as a string
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder str = new StringBuilder();
|
||||||
|
|
||||||
|
str.append("[");
|
||||||
|
|
||||||
|
str.append("token=");
|
||||||
|
str.append(getToken());
|
||||||
|
str.append(",scope=");
|
||||||
|
str.append(getScope());
|
||||||
|
str.append(",depth=");
|
||||||
|
str.append(getDepth());
|
||||||
|
str.append(",shared locks=");
|
||||||
|
str.append(getSharedLockTokens());
|
||||||
|
|
||||||
|
str.append("]");
|
||||||
|
|
||||||
|
return str.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -32,9 +32,9 @@ import java.util.List;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.model.WebDAVModel;
|
||||||
import org.alfresco.repo.model.filefolder.FileFolderServiceImpl;
|
import org.alfresco.repo.model.filefolder.FileFolderServiceImpl;
|
||||||
import org.alfresco.service.cmr.lock.LockService;
|
import org.alfresco.service.cmr.lock.LockService;
|
||||||
import org.alfresco.service.cmr.lock.LockStatus;
|
|
||||||
import org.alfresco.service.cmr.lock.LockType;
|
import org.alfresco.service.cmr.lock.LockType;
|
||||||
import org.alfresco.service.cmr.model.FileFolderService;
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
import org.alfresco.service.cmr.model.FileInfo;
|
import org.alfresco.service.cmr.model.FileInfo;
|
||||||
@@ -43,6 +43,10 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
|||||||
import org.alfresco.service.cmr.repository.NodeService;
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
import org.dom4j.DocumentHelper;
|
import org.dom4j.DocumentHelper;
|
||||||
import org.dom4j.io.XMLWriter;
|
import org.dom4j.io.XMLWriter;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
import org.xml.sax.Attributes;
|
import org.xml.sax.Attributes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,8 +58,13 @@ public class LockMethod extends WebDAVMethod
|
|||||||
{
|
{
|
||||||
public static final String EMPTY_NS = "";
|
public static final String EMPTY_NS = "";
|
||||||
|
|
||||||
private String m_strLockToken = null;
|
private int m_timeoutDuration = WebDAV.TIMEOUT_INFINITY;
|
||||||
private int m_timeoutDuration = WebDAV.DEPTH_INFINITY;
|
|
||||||
|
private LockInfo lockInfo = new LockInfo();
|
||||||
|
|
||||||
|
private String m_scope = null;
|
||||||
|
|
||||||
|
private String lockToken= null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor
|
* Default constructor
|
||||||
@@ -65,23 +74,23 @@ public class LockMethod extends WebDAVMethod
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the lock token is valid
|
* Returns true if request has lock token in the If header
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
protected final boolean hasLockToken()
|
protected final boolean hasLockToken()
|
||||||
{
|
{
|
||||||
return m_strLockToken != null ? true : false;
|
if (m_conditions != null)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the lock token of an existing lock
|
|
||||||
*
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
protected final String getLockToken()
|
|
||||||
{
|
{
|
||||||
return m_strLockToken;
|
for (Condition condition : m_conditions)
|
||||||
|
{
|
||||||
|
if (!condition.getLockTokensMatch().isEmpty())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,9 +110,20 @@ public class LockMethod extends WebDAVMethod
|
|||||||
*/
|
*/
|
||||||
protected void parseRequestHeaders() throws WebDAVServerException
|
protected void parseRequestHeaders() throws WebDAVServerException
|
||||||
{
|
{
|
||||||
// Get the lock token, if any
|
// Get the depth
|
||||||
|
|
||||||
m_strLockToken = parseIfHeader();
|
parseDepthHeader();
|
||||||
|
|
||||||
|
// According to the specification: "Values other than 0 or infinity MUST NOT be used with the Depth header on a LOCK method.".
|
||||||
|
// The specification does not specify the error code for this case - so we use HttpServletResponse.SC_INTERNAL_SERVER_ERROR.
|
||||||
|
if (m_depth != WebDAV.DEPTH_0 && m_depth != WebDAV.DEPTH_INFINITY)
|
||||||
|
{
|
||||||
|
throw new WebDAVServerException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse Lock tokens and ETags, if any
|
||||||
|
|
||||||
|
parseIfHeader();
|
||||||
|
|
||||||
// Get the lock timeout value
|
// Get the lock timeout value
|
||||||
|
|
||||||
@@ -147,7 +167,7 @@ public class LockMethod extends WebDAVMethod
|
|||||||
// DEBUG
|
// DEBUG
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
logger.debug("Lock lockToken=" + getLockToken() + ", timeout=" + getLockTimeout());
|
logger.debug("Timeout=" + getLockTimeout() + ", depth=" + getDepth());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -157,13 +177,50 @@ public class LockMethod extends WebDAVMethod
|
|||||||
*/
|
*/
|
||||||
protected void parseRequestBody() throws WebDAVServerException
|
protected void parseRequestBody() throws WebDAVServerException
|
||||||
{
|
{
|
||||||
// NOTE: There is a body for lock requests which contain the
|
if (m_request.getContentLength() == -1)
|
||||||
// type of lock to apply and the lock owner but we will
|
{
|
||||||
// ignore these settings so don't bother reading the body
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Document body = getRequestBodyAsDocument();
|
||||||
|
if (body != null)
|
||||||
|
{
|
||||||
|
Element rootElement = body.getDocumentElement();
|
||||||
|
NodeList childList = rootElement.getChildNodes();
|
||||||
|
|
||||||
|
for (int i = 0; i < childList.getLength(); i++)
|
||||||
|
{
|
||||||
|
Node currentNode = childList.item(i);
|
||||||
|
switch (currentNode.getNodeType())
|
||||||
|
{
|
||||||
|
case Node.TEXT_NODE:
|
||||||
|
break;
|
||||||
|
case Node.ELEMENT_NODE:
|
||||||
|
if (currentNode.getNodeName().endsWith(WebDAV.XML_LOCK_SCOPE))
|
||||||
|
{
|
||||||
|
NodeList propertiesList = currentNode.getChildNodes();
|
||||||
|
|
||||||
|
for (int j = 0; j < propertiesList.getLength(); j++)
|
||||||
|
{
|
||||||
|
Node propertiesNode = propertiesList.item(j);
|
||||||
|
switch (propertiesNode.getNodeType())
|
||||||
|
{
|
||||||
|
case Node.TEXT_NODE:
|
||||||
|
break;
|
||||||
|
case Node.ELEMENT_NODE:
|
||||||
|
m_scope = propertiesNode.getNodeName();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exceute the request
|
* Execute the request
|
||||||
*
|
*
|
||||||
* @exception WebDAVServerException
|
* @exception WebDAVServerException
|
||||||
*/
|
*/
|
||||||
@@ -225,21 +282,27 @@ public class LockMethod extends WebDAVMethod
|
|||||||
" path: " + path + "\n" +
|
" path: " + path + "\n" +
|
||||||
" node: " + lockNodeInfo);
|
" node: " + lockNodeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_response.setStatus(HttpServletResponse.SC_CREATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check if this is a new lock or a refresh
|
|
||||||
|
// Check if this is a new lock or a lock refresh
|
||||||
if (hasLockToken())
|
if (hasLockToken())
|
||||||
{
|
{
|
||||||
|
this.lockInfo = checkNode(lockNodeInfo);
|
||||||
// Refresh an existing lock
|
// Refresh an existing lock
|
||||||
refreshLock(lockNodeInfo.getNodeRef(), userName);
|
refreshLock(lockNodeInfo, userName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
this.lockInfo = checkNode(lockNodeInfo, true, WebDAV.XML_EXCLUSIVE.equals(m_scope));
|
||||||
// Create a new lock
|
// Create a new lock
|
||||||
createLock(lockNodeInfo.getNodeRef(), userName);
|
createLock(lockNodeInfo, userName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
m_response.setHeader(WebDAV.HEADER_LOCK_TOKEN, "<" + WebDAV.makeLockToken(lockNodeInfo.getNodeRef(), userName) + ">");
|
m_response.setHeader(WebDAV.HEADER_LOCK_TOKEN, "<" + WebDAV.makeLockToken(lockNodeInfo.getNodeRef(), userName) + ">");
|
||||||
m_response.setHeader(WebDAV.HEADER_CONTENT_TYPE, WebDAV.XML_CONTENT_TYPE);
|
m_response.setHeader(WebDAV.HEADER_CONTENT_TYPE, WebDAV.XML_CONTENT_TYPE);
|
||||||
|
|
||||||
@@ -254,25 +317,35 @@ public class LockMethod extends WebDAVMethod
|
|||||||
* @param userName String
|
* @param userName String
|
||||||
* @exception WebDAVServerException
|
* @exception WebDAVServerException
|
||||||
*/
|
*/
|
||||||
private final void createLock(NodeRef lockNode, String userName) throws WebDAVServerException
|
private final void createLock(FileInfo lockNode, String userName) throws WebDAVServerException
|
||||||
{
|
{
|
||||||
LockService lockService = getLockService();
|
LockService lockService = getLockService();
|
||||||
|
|
||||||
// Check the lock status of the node
|
// Create Lock token
|
||||||
LockStatus lockSts = lockService.getLockStatus(lockNode);
|
lockToken = WebDAV.makeLockToken(lockNode.getNodeRef(), userName);
|
||||||
|
|
||||||
// DEBUG
|
if (WebDAV.XML_EXCLUSIVE.equals(m_scope))
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Create lock status=" + lockSts);
|
|
||||||
|
|
||||||
if (lockSts == LockStatus.LOCKED || lockSts == LockStatus.LOCK_OWNER)
|
|
||||||
{
|
{
|
||||||
// Indicate that the resource is already locked
|
// Lock the node
|
||||||
throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED);
|
lockService.lock(lockNode.getNodeRef(), LockType.WRITE_LOCK, getLockTimeout());
|
||||||
|
|
||||||
|
//this.lockInfo.setToken(lockToken);
|
||||||
|
getNodeService().setProperty(lockNode.getNodeRef(), WebDAVModel.PROP_OPAQUE_LOCK_TOKEN, lockToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.lockInfo.addSharedLockToken(lockToken);
|
||||||
|
String sharedLockTokens = LockInfo.makeSharedLockTokensString(this.lockInfo.getSharedLockTokens());
|
||||||
|
getNodeService().setProperty(lockNode.getNodeRef(), WebDAVModel.PROP_SHARED_LOCK_TOKENS, sharedLockTokens);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock the node
|
// Store lock depth
|
||||||
lockService.lock(lockNode, LockType.WRITE_LOCK, getLockTimeout());
|
getNodeService().setProperty(lockNode.getNodeRef(), WebDAVModel.PROP_LOCK_DEPTH, WebDAV.getDepthName(m_depth));
|
||||||
|
|
||||||
|
// Store lock scope (shared/exclusive)
|
||||||
|
getNodeService().setProperty(lockNode.getNodeRef(), WebDAVModel.PROP_LOCK_SCOPE, m_scope);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -282,25 +355,15 @@ public class LockMethod extends WebDAVMethod
|
|||||||
* @param userName String
|
* @param userName String
|
||||||
* @exception WebDAVServerException
|
* @exception WebDAVServerException
|
||||||
*/
|
*/
|
||||||
private final void refreshLock(NodeRef lockNode, String userName) throws WebDAVServerException
|
private final void refreshLock(FileInfo lockNode, String userName) throws WebDAVServerException
|
||||||
{
|
{
|
||||||
LockService lockService = getLockService();
|
LockService lockService = getLockService();
|
||||||
|
|
||||||
// Check the lock status of the node
|
if (WebDAV.XML_EXCLUSIVE.equals(m_scope))
|
||||||
LockStatus lockSts = lockService.getLockStatus(lockNode);
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Refresh lock status=" + lockSts);
|
|
||||||
|
|
||||||
if (lockSts != LockStatus.LOCK_OWNER)
|
|
||||||
{
|
{
|
||||||
// Indicate that the resource is already locked
|
|
||||||
throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the expiry for the lock
|
// Update the expiry for the lock
|
||||||
lockService.lock(lockNode, LockType.WRITE_LOCK, getLockTimeout());
|
lockService.lock(lockNode.getNodeRef(), LockType.WRITE_LOCK, getLockTimeout());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -356,16 +419,21 @@ public class LockMethod extends WebDAVMethod
|
|||||||
xml.write(DocumentHelper.createElement(WebDAV.XML_WRITE));
|
xml.write(DocumentHelper.createElement(WebDAV.XML_WRITE));
|
||||||
xml.endElement(EMPTY_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_LOCK_TYPE);
|
xml.endElement(EMPTY_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_LOCK_TYPE);
|
||||||
|
|
||||||
// NOTE: We only do exclusive lock tokens at the moment
|
|
||||||
|
|
||||||
xml.startElement(EMPTY_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_LOCK_SCOPE, nullAttr);
|
xml.startElement(EMPTY_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_LOCK_SCOPE, nullAttr);
|
||||||
xml.write(DocumentHelper.createElement(WebDAV.XML_EXCLUSIVE));
|
if (lockToken != null)
|
||||||
|
{
|
||||||
|
// In case of lock creation take the scope from request header
|
||||||
|
xml.write(DocumentHelper.createElement(m_scope));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// In case of lock refreshing take the scope from previously stored lock
|
||||||
|
xml.write(DocumentHelper.createElement(this.lockInfo.getScope()));
|
||||||
|
}
|
||||||
xml.endElement(EMPTY_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_LOCK_SCOPE);
|
xml.endElement(EMPTY_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_LOCK_SCOPE);
|
||||||
|
|
||||||
// NOTE: We only support one level of lock at the moment
|
|
||||||
|
|
||||||
xml.startElement(EMPTY_NS, WebDAV.XML_DEPTH, WebDAV.XML_DEPTH, nullAttr);
|
xml.startElement(EMPTY_NS, WebDAV.XML_DEPTH, WebDAV.XML_DEPTH, nullAttr);
|
||||||
xml.write(WebDAV.ZERO);
|
xml.write(WebDAV.getDepthName(m_depth));
|
||||||
xml.endElement(EMPTY_NS, WebDAV.XML_DEPTH, WebDAV.XML_DEPTH);
|
xml.endElement(EMPTY_NS, WebDAV.XML_DEPTH, WebDAV.XML_DEPTH);
|
||||||
|
|
||||||
xml.startElement(EMPTY_NS, WebDAV.XML_OWNER, WebDAV.XML_OWNER, nullAttr);
|
xml.startElement(EMPTY_NS, WebDAV.XML_OWNER, WebDAV.XML_OWNER, nullAttr);
|
||||||
@@ -389,9 +457,16 @@ public class LockMethod extends WebDAVMethod
|
|||||||
|
|
||||||
xml.startElement(EMPTY_NS, WebDAV.XML_LOCK_TOKEN, WebDAV.XML_LOCK_TOKEN, nullAttr);
|
xml.startElement(EMPTY_NS, WebDAV.XML_LOCK_TOKEN, WebDAV.XML_LOCK_TOKEN, nullAttr);
|
||||||
xml.startElement(EMPTY_NS, WebDAV.XML_HREF, WebDAV.XML_HREF, nullAttr);
|
xml.startElement(EMPTY_NS, WebDAV.XML_HREF, WebDAV.XML_HREF, nullAttr);
|
||||||
|
if (lockToken != null)
|
||||||
xml.write(WebDAV.makeLockToken(lockNode, owner));
|
{
|
||||||
|
// Output created lock
|
||||||
|
xml.write(lockToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Output refreshed lock
|
||||||
|
xml.write(this.lockInfo.getToken());
|
||||||
|
}
|
||||||
xml.endElement(EMPTY_NS, WebDAV.XML_HREF, WebDAV.XML_HREF);
|
xml.endElement(EMPTY_NS, WebDAV.XML_HREF, WebDAV.XML_HREF);
|
||||||
xml.endElement(EMPTY_NS, WebDAV.XML_LOCK_TOKEN, WebDAV.XML_LOCK_TOKEN);
|
xml.endElement(EMPTY_NS, WebDAV.XML_LOCK_TOKEN, WebDAV.XML_LOCK_TOKEN);
|
||||||
|
|
||||||
@@ -433,5 +508,4 @@ public class LockMethod extends WebDAVMethod
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -31,7 +31,6 @@ import org.alfresco.service.cmr.model.FileFolderService;
|
|||||||
import org.alfresco.service.cmr.model.FileInfo;
|
import org.alfresco.service.cmr.model.FileInfo;
|
||||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.w3c.dom.Document;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the WebDAV MKCOL method
|
* Implements the WebDAV MKCOL method
|
||||||
@@ -66,16 +65,14 @@ public class MkcolMethod extends WebDAVMethod
|
|||||||
{
|
{
|
||||||
// There should not be a body with the MKCOL request
|
// There should not be a body with the MKCOL request
|
||||||
|
|
||||||
Document body = getRequestBodyAsDocument();
|
if (m_request.getContentLength() > 0)
|
||||||
|
|
||||||
if (body != null)
|
|
||||||
{
|
{
|
||||||
throw new WebDAVServerException(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
|
throw new WebDAVServerException(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exceute the request
|
* Execute the request
|
||||||
*
|
*
|
||||||
* @exception WebDAVServerException
|
* @exception WebDAVServerException
|
||||||
*/
|
*/
|
||||||
@@ -120,7 +117,7 @@ public class MkcolMethod extends WebDAVMethod
|
|||||||
catch (FileNotFoundException e)
|
catch (FileNotFoundException e)
|
||||||
{
|
{
|
||||||
// parent path is missing
|
// parent path is missing
|
||||||
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
|
throw new WebDAVServerException(HttpServletResponse.SC_CONFLICT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -24,7 +24,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.webdav;
|
package org.alfresco.repo.webdav;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.alfresco.service.cmr.model.FileFolderService;
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
|
import org.alfresco.service.cmr.model.FileInfo;
|
||||||
|
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,6 +53,27 @@ public class MoveMethod extends AbstractMoveOrCopyMethod
|
|||||||
NodeRef destParentNodeRef,
|
NodeRef destParentNodeRef,
|
||||||
String name) throws Exception
|
String name) throws Exception
|
||||||
{
|
{
|
||||||
|
NodeRef rootNodeRef = getRootNodeRef();
|
||||||
|
|
||||||
|
String path = getPath();
|
||||||
|
List<String> pathElements = getDAVHelper().splitAllPaths(path);
|
||||||
|
FileInfo fileInfo = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// get the node to move
|
||||||
|
fileInfo = fileFolderService.resolveNamePath(rootNodeRef, pathElements);
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException e)
|
||||||
|
{
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Node not found: " + getPath());
|
||||||
|
}
|
||||||
|
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkNode(fileInfo);
|
||||||
|
|
||||||
fileFolderService.move(sourceNodeRef, destParentNodeRef, name);
|
fileFolderService.move(sourceNodeRef, destParentNodeRef, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -37,8 +37,6 @@ import org.alfresco.error.AlfrescoRuntimeException;
|
|||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.SessionUser;
|
import org.alfresco.repo.SessionUser;
|
||||||
import org.alfresco.repo.webdav.auth.AuthenticationFilter;
|
import org.alfresco.repo.webdav.auth.AuthenticationFilter;
|
||||||
import org.alfresco.service.cmr.lock.LockService;
|
|
||||||
import org.alfresco.service.cmr.lock.LockStatus;
|
|
||||||
import org.alfresco.service.cmr.model.FileFolderService;
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
import org.alfresco.service.cmr.model.FileInfo;
|
import org.alfresco.service.cmr.model.FileInfo;
|
||||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||||
@@ -68,8 +66,7 @@ public class PropFindMethod extends WebDAVMethod
|
|||||||
protected static final int GET_NAMED_PROPS = 1;
|
protected static final int GET_NAMED_PROPS = 1;
|
||||||
protected static final int FIND_PROPS = 2;
|
protected static final int FIND_PROPS = 2;
|
||||||
|
|
||||||
// Find depth and request type
|
// Find request type
|
||||||
private int m_depth = WebDAV.DEPTH_INFINITY;
|
|
||||||
protected int m_mode = GET_ALL_PROPS;
|
protected int m_mode = GET_ALL_PROPS;
|
||||||
|
|
||||||
// Requested properties
|
// Requested properties
|
||||||
@@ -86,16 +83,6 @@ public class PropFindMethod extends WebDAVMethod
|
|||||||
m_namespaces = new HashMap<String, String>();
|
m_namespaces = new HashMap<String, String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the property find depth
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public final int getDepth()
|
|
||||||
{
|
|
||||||
return m_depth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the find mode
|
* Return the find mode
|
||||||
*
|
*
|
||||||
@@ -115,22 +102,8 @@ public class PropFindMethod extends WebDAVMethod
|
|||||||
{
|
{
|
||||||
// Store the Depth header as this is used by several WebDAV methods
|
// Store the Depth header as this is used by several WebDAV methods
|
||||||
|
|
||||||
String strDepth = m_request.getHeader(WebDAV.HEADER_DEPTH);
|
parseDepthHeader();
|
||||||
if (strDepth != null && strDepth.length() > 0)
|
|
||||||
{
|
|
||||||
if (strDepth.equals(WebDAV.ZERO))
|
|
||||||
{
|
|
||||||
m_depth = WebDAV.DEPTH_0;
|
|
||||||
}
|
|
||||||
else if (strDepth.equals(WebDAV.ONE))
|
|
||||||
{
|
|
||||||
m_depth = WebDAV.DEPTH_1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_depth = WebDAV.DEPTH_INFINITY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -195,7 +168,7 @@ public class PropFindMethod extends WebDAVMethod
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exceute the main WebDAV request processing
|
* Execute the main WebDAV request processing
|
||||||
*
|
*
|
||||||
* @exception WebDAVServerException
|
* @exception WebDAVServerException
|
||||||
*/
|
*/
|
||||||
@@ -355,7 +328,7 @@ public class PropFindMethod extends WebDAVMethod
|
|||||||
String strName = node.getLocalName();
|
String strName = node.getLocalName();
|
||||||
String strNamespaceUri = node.getNamespaceURI();
|
String strNamespaceUri = node.getNamespaceURI();
|
||||||
|
|
||||||
if (strNamespaceUri.equals(WebDAV.DEFAULT_NAMESPACE_URI))
|
if (WebDAV.DEFAULT_NAMESPACE_URI.equals(strNamespaceUri))
|
||||||
{
|
{
|
||||||
property = new WebDAVProperty(strName);
|
property = new WebDAVProperty(strName);
|
||||||
}
|
}
|
||||||
@@ -373,6 +346,10 @@ public class PropFindMethod extends WebDAVMethod
|
|||||||
*/
|
*/
|
||||||
private String getNamespaceName(String strNamespaceUri)
|
private String getNamespaceName(String strNamespaceUri)
|
||||||
{
|
{
|
||||||
|
if (strNamespaceUri == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
String strNamespaceName = m_namespaces.get(strNamespaceUri);
|
String strNamespaceName = m_namespaces.get(strNamespaceUri);
|
||||||
if (strNamespaceName == null)
|
if (strNamespaceName == null)
|
||||||
{
|
{
|
||||||
@@ -465,7 +442,7 @@ public class PropFindMethod extends WebDAVMethod
|
|||||||
|
|
||||||
Object davValue = null;
|
Object davValue = null;
|
||||||
|
|
||||||
if (propNamespaceUri.equals(WebDAV.DEFAULT_NAMESPACE_URI))
|
if (WebDAV.DEFAULT_NAMESPACE_URI.equals(propNamespaceUri))
|
||||||
{
|
{
|
||||||
// Check if the client is requesting lock information
|
// Check if the client is requesting lock information
|
||||||
if (propName.equals(WebDAV.XML_LOCK_DISCOVERY)) // && metaData.isLocked())
|
if (propName.equals(WebDAV.XML_LOCK_DISCOVERY)) // && metaData.isLocked())
|
||||||
@@ -624,7 +601,28 @@ public class PropFindMethod extends WebDAVMethod
|
|||||||
|
|
||||||
// TODO: Custom properties lookup
|
// TODO: Custom properties lookup
|
||||||
// String qualifiedName = propNamespaceUri + WebDAV.NAMESPACE_SEPARATOR + propName;
|
// String qualifiedName = propNamespaceUri + WebDAV.NAMESPACE_SEPARATOR + propName;
|
||||||
|
|
||||||
|
String value = (String) getNodeService().getProperty(nodeRef, property.createQName());
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
propertiesNotFound.add(property);
|
propertiesNotFound.add(property);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (property.hasNamespaceName())
|
||||||
|
{
|
||||||
|
xml.startElement(property.getNamespaceName(), property.getName(), property.getNamespaceName() + WebDAV.NAMESPACE_SEPARATOR + property.getName(), nullAttr);
|
||||||
|
xml.write(value);
|
||||||
|
xml.endElement(property.getNamespaceName(), property.getName(), property.getNamespaceName() + WebDAV.NAMESPACE_SEPARATOR + property.getName());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xml.startElement("", property.getName(), property.getName(), nullAttr);
|
||||||
|
xml.write(value);
|
||||||
|
xml.endElement("", property.getName(), property.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -894,15 +892,13 @@ public class PropFindMethod extends WebDAVMethod
|
|||||||
*/
|
*/
|
||||||
protected void generateLockDiscoveryResponse(XMLWriter xml, NodeRef node, boolean isDir) throws Exception
|
protected void generateLockDiscoveryResponse(XMLWriter xml, NodeRef node, boolean isDir) throws Exception
|
||||||
{
|
{
|
||||||
// Get the lock status for the node
|
// Output the lock status response
|
||||||
|
|
||||||
LockService lockService = getLockService();
|
LockInfo lockInfo = getNodeLockInfo(node);
|
||||||
LockStatus lockSts = lockService.getLockStatus(node);
|
if (lockInfo.isLocked())
|
||||||
|
{
|
||||||
// Output the lock status reponse
|
generateLockDiscoveryXML(xml, node, lockInfo);
|
||||||
|
}
|
||||||
if (lockSts != LockStatus.NO_LOCK)
|
|
||||||
generateLockDiscoveryXML(xml, node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -31,7 +31,6 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.service.cmr.model.FileInfo;
|
import org.alfresco.service.cmr.model.FileInfo;
|
||||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
|
||||||
import org.dom4j.DocumentHelper;
|
import org.dom4j.DocumentHelper;
|
||||||
import org.dom4j.io.XMLWriter;
|
import org.dom4j.io.XMLWriter;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
@@ -69,6 +68,8 @@ public class PropPatchMethod extends PropFindMethod
|
|||||||
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
|
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkNode(pathNodeInfo);
|
||||||
|
|
||||||
// Set the response content type
|
// Set the response content type
|
||||||
m_response.setContentType(WebDAV.XML_CONTENT_TYPE);
|
m_response.setContentType(WebDAV.XML_CONTENT_TYPE);
|
||||||
|
|
||||||
@@ -353,14 +354,29 @@ public class PropPatchMethod extends PropFindMethod
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores information about PROPPATCH action(set or remove) an according property.
|
||||||
|
*
|
||||||
|
* @author Ivan Rybnikov
|
||||||
|
*/
|
||||||
private class PropertyAction
|
private class PropertyAction
|
||||||
{
|
{
|
||||||
protected static final int SET = 0;
|
protected static final int SET = 0;
|
||||||
protected static final int REMOVE = 1;
|
protected static final int REMOVE = 1;
|
||||||
|
|
||||||
|
// Property on which action should be performed
|
||||||
private WebDAVProperty property;
|
private WebDAVProperty property;
|
||||||
|
|
||||||
|
// Action
|
||||||
private int action;
|
private int action;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* @param property
|
||||||
|
*/
|
||||||
public PropertyAction(int action, WebDAVProperty property)
|
public PropertyAction(int action, WebDAVProperty property)
|
||||||
{
|
{
|
||||||
this.action = action;
|
this.action = action;
|
||||||
|
@@ -76,9 +76,9 @@ public class PutMethod extends WebDAVMethod
|
|||||||
m_expectHeaderPresent = true;
|
m_expectHeaderPresent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the lock token, if any
|
// Parse Lock tokens and ETags, if any
|
||||||
|
|
||||||
m_strLockToken = parseIfHeader();
|
parseIfHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,6 +112,9 @@ public class PutMethod extends WebDAVMethod
|
|||||||
{
|
{
|
||||||
throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST);
|
throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkNode(contentNodeInfo);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException e)
|
catch (FileNotFoundException e)
|
||||||
{
|
{
|
||||||
|
@@ -24,12 +24,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.webdav;
|
package org.alfresco.repo.webdav;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.alfresco.model.WebDAVModel;
|
||||||
import org.alfresco.service.cmr.lock.LockService;
|
import org.alfresco.service.cmr.lock.LockService;
|
||||||
import org.alfresco.service.cmr.lock.LockStatus;
|
import org.alfresco.service.cmr.lock.LockStatus;
|
||||||
import org.alfresco.service.cmr.model.FileInfo;
|
import org.alfresco.service.cmr.model.FileInfo;
|
||||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the WebDAV UNLOCK method
|
* Implements the WebDAV UNLOCK method
|
||||||
@@ -104,7 +108,7 @@ public class UnlockMethod extends WebDAVMethod
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exceute the request
|
* Execute the request
|
||||||
*
|
*
|
||||||
* @exception WebDAVServerException
|
* @exception WebDAVServerException
|
||||||
*/
|
*/
|
||||||
@@ -135,6 +139,7 @@ public class UnlockMethod extends WebDAVMethod
|
|||||||
|
|
||||||
// Get the lock status for the node
|
// Get the lock status for the node
|
||||||
LockService lockService = getDAVHelper().getLockService();
|
LockService lockService = getDAVHelper().getLockService();
|
||||||
|
NodeService nodeService = getNodeService();
|
||||||
// String nodeId = lockInfo[0];
|
// String nodeId = lockInfo[0];
|
||||||
// String userName = lockInfo[1];
|
// String userName = lockInfo[1];
|
||||||
|
|
||||||
@@ -143,6 +148,9 @@ public class UnlockMethod extends WebDAVMethod
|
|||||||
{
|
{
|
||||||
// Unlock the node
|
// Unlock the node
|
||||||
lockService.unlock(lockNodeInfo.getNodeRef());
|
lockService.unlock(lockNodeInfo.getNodeRef());
|
||||||
|
nodeService.removeProperty(lockNodeInfo.getNodeRef(), WebDAVModel.PROP_OPAQUE_LOCK_TOKEN);
|
||||||
|
nodeService.removeProperty(lockNodeInfo.getNodeRef(), WebDAVModel.PROP_LOCK_DEPTH);
|
||||||
|
nodeService.removeProperty(lockNodeInfo.getNodeRef(), WebDAVModel.PROP_LOCK_SCOPE);
|
||||||
|
|
||||||
// Indicate that the unlock was successful
|
// Indicate that the unlock was successful
|
||||||
m_response.setStatus(HttpServletResponse.SC_NO_CONTENT);
|
m_response.setStatus(HttpServletResponse.SC_NO_CONTENT);
|
||||||
@@ -154,6 +162,28 @@ public class UnlockMethod extends WebDAVMethod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (lockSts == LockStatus.NO_LOCK)
|
else if (lockSts == LockStatus.NO_LOCK)
|
||||||
|
{
|
||||||
|
String sharedLocks = (String) nodeService.getProperty(lockNodeInfo.getNodeRef(), WebDAVModel.PROP_SHARED_LOCK_TOKENS);
|
||||||
|
if (sharedLocks != null)
|
||||||
|
{
|
||||||
|
LinkedList<String> locks = LockInfo.parseSharedLockTokens(sharedLocks);
|
||||||
|
|
||||||
|
if (locks != null && locks.contains(m_strLockToken))
|
||||||
|
{
|
||||||
|
locks.remove(m_strLockToken);
|
||||||
|
nodeService.setProperty(lockNodeInfo.getNodeRef(), WebDAVModel.PROP_SHARED_LOCK_TOKENS, LockInfo.makeSharedLockTokensString(locks));
|
||||||
|
|
||||||
|
// Indicate that the unlock was successful
|
||||||
|
m_response.setStatus(HttpServletResponse.SC_NO_CONTENT);
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Unlock token=" + getLockToken() + " Successful");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// DEBUG
|
// DEBUG
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
@@ -162,6 +192,9 @@ public class UnlockMethod extends WebDAVMethod
|
|||||||
// Node is not locked
|
// Node is not locked
|
||||||
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
|
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
else if (lockSts == LockStatus.LOCKED)
|
else if (lockSts == LockStatus.LOCKED)
|
||||||
{
|
{
|
||||||
// DEBUG
|
// DEBUG
|
||||||
|
@@ -60,7 +60,7 @@ public class WebDAV
|
|||||||
public static final String DAV_NS = "D";
|
public static final String DAV_NS = "D";
|
||||||
public static final String DAV_NS_PREFIX = DAV_NS + ":";
|
public static final String DAV_NS_PREFIX = DAV_NS + ":";
|
||||||
|
|
||||||
// PROPFIND depth
|
// PROPFIND, LOCK depth
|
||||||
|
|
||||||
public static final int DEPTH_0 = 0;
|
public static final int DEPTH_0 = 0;
|
||||||
public static final int DEPTH_1 = 1;
|
public static final int DEPTH_1 = 1;
|
||||||
@@ -83,6 +83,7 @@ public class WebDAV
|
|||||||
public static final String SC_NOT_FOUND_DESC = "Not Found";
|
public static final String SC_NOT_FOUND_DESC = "Not Found";
|
||||||
public static final String SC_FORBIDDEN_DESC = "Forbidden";
|
public static final String SC_FORBIDDEN_DESC = "Forbidden";
|
||||||
|
|
||||||
|
|
||||||
// HTTP methods
|
// HTTP methods
|
||||||
|
|
||||||
public static final String METHOD_PUT = "PUT";
|
public static final String METHOD_PUT = "PUT";
|
||||||
@@ -124,6 +125,10 @@ public class WebDAV
|
|||||||
|
|
||||||
public static final String HEADER_IF_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";
|
public static final String HEADER_IF_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";
|
||||||
|
|
||||||
|
// If header keyword
|
||||||
|
|
||||||
|
public static final String HEADER_KEY_NOT = "Not";
|
||||||
|
|
||||||
// General string constants
|
// General string constants
|
||||||
|
|
||||||
public static final String ASTERISK = "*";
|
public static final String ASTERISK = "*";
|
||||||
@@ -214,6 +219,7 @@ public class WebDAV
|
|||||||
public static final String XML_NS_ERROR = DAV_NS_PREFIX + "error";
|
public static final String XML_NS_ERROR = DAV_NS_PREFIX + "error";
|
||||||
public static final String XML_NS_CANNOT_MODIFY_PROTECTED_PROPERTY = DAV_NS_PREFIX + "cannot-modify-protected-property";
|
public static final String XML_NS_CANNOT_MODIFY_PROTECTED_PROPERTY = DAV_NS_PREFIX + "cannot-modify-protected-property";
|
||||||
|
|
||||||
|
|
||||||
public static final String XML_CONTENT_TYPE = "text/xml; charset=UTF-8";
|
public static final String XML_CONTENT_TYPE = "text/xml; charset=UTF-8";
|
||||||
|
|
||||||
// Alfresco specific properties
|
// Alfresco specific properties
|
||||||
@@ -590,6 +596,30 @@ public class WebDAV
|
|||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns string representation of the depth
|
||||||
|
*
|
||||||
|
* @param depth
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public static final String getDepthName(int depth)
|
||||||
|
{
|
||||||
|
switch (depth)
|
||||||
|
{
|
||||||
|
case DEPTH_0:
|
||||||
|
return ZERO;
|
||||||
|
|
||||||
|
case DEPTH_1:
|
||||||
|
return ONE;
|
||||||
|
|
||||||
|
case DEPTH_INFINITY:
|
||||||
|
return INFINITY;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unknown depth:" + depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static initializer
|
* Static initializer
|
||||||
*/
|
*/
|
||||||
|
@@ -28,6 +28,8 @@ import java.io.IOException;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
@@ -36,16 +38,23 @@ import javax.xml.parsers.DocumentBuilderFactory;
|
|||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.model.WebDAVModel;
|
||||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
import org.alfresco.service.ServiceRegistry;
|
import org.alfresco.service.ServiceRegistry;
|
||||||
import org.alfresco.service.cmr.lock.LockService;
|
import org.alfresco.service.cmr.lock.LockService;
|
||||||
|
import org.alfresco.service.cmr.lock.LockStatus;
|
||||||
import org.alfresco.service.cmr.model.FileFolderService;
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
|
import org.alfresco.service.cmr.model.FileInfo;
|
||||||
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.search.SearchService;
|
||||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
@@ -57,6 +66,7 @@ import org.xml.sax.Attributes;
|
|||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for all the WebDAV method handling classes
|
* Abstract base class for all the WebDAV method handling classes
|
||||||
*
|
*
|
||||||
@@ -89,6 +99,19 @@ public abstract class WebDAVMethod
|
|||||||
|
|
||||||
protected String m_strPath = null;
|
protected String m_strPath = null;
|
||||||
|
|
||||||
|
|
||||||
|
// If header conditions
|
||||||
|
|
||||||
|
protected LinkedList<Condition> m_conditions = null;
|
||||||
|
|
||||||
|
// If header resource-tag
|
||||||
|
|
||||||
|
protected String m_resourceTag = null;
|
||||||
|
|
||||||
|
// Depth header
|
||||||
|
|
||||||
|
protected int m_depth = WebDAV.DEPTH_INFINITY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor
|
* Default constructor
|
||||||
*/
|
*/
|
||||||
@@ -125,6 +148,16 @@ public abstract class WebDAVMethod
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the property find depth
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public final int getDepth()
|
||||||
|
{
|
||||||
|
return m_depth;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the method, wrapping the call to {@link #executeImpl()} in an appropriate transaction
|
* Executes the method, wrapping the call to {@link #executeImpl()} in an appropriate transaction
|
||||||
* and handling the error conditions.
|
* and handling the error conditions.
|
||||||
@@ -233,13 +266,42 @@ public abstract class WebDAVMethod
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the lock token present in the If header
|
* Parses "Depth" request header
|
||||||
*
|
*
|
||||||
* @return The lock token present in the If header
|
* @throws WebDAVServerException
|
||||||
*/
|
*/
|
||||||
protected String parseIfHeader() throws WebDAVServerException
|
protected void parseDepthHeader() throws WebDAVServerException
|
||||||
{
|
{
|
||||||
String strLockToken = null;
|
// Store the Depth header as this is used by several WebDAV methods
|
||||||
|
|
||||||
|
String strDepth = m_request.getHeader(WebDAV.HEADER_DEPTH);
|
||||||
|
if (strDepth != null && strDepth.length() > 0)
|
||||||
|
{
|
||||||
|
if (strDepth.equals(WebDAV.ZERO))
|
||||||
|
{
|
||||||
|
m_depth = WebDAV.DEPTH_0;
|
||||||
|
}
|
||||||
|
else if (strDepth.equals(WebDAV.ONE))
|
||||||
|
{
|
||||||
|
m_depth = WebDAV.DEPTH_1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_depth = WebDAV.DEPTH_INFINITY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses "If" header of the request.
|
||||||
|
* Stores conditions that should be checked.
|
||||||
|
* Parses both No-tag-list and Tagged-list formats
|
||||||
|
* See "10.4.2 Syntax" paragraph of the WebDAV specification for "If" header format.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected void parseIfHeader() throws WebDAVServerException
|
||||||
|
{
|
||||||
|
//String strLockToken = null;
|
||||||
|
|
||||||
String strIf = m_request.getHeader(WebDAV.HEADER_IF);
|
String strIf = m_request.getHeader(WebDAV.HEADER_IF);
|
||||||
|
|
||||||
@@ -248,45 +310,78 @@ public abstract class WebDAVMethod
|
|||||||
|
|
||||||
if (strIf != null && strIf.length() > 0)
|
if (strIf != null && strIf.length() > 0)
|
||||||
{
|
{
|
||||||
if (strIf.startsWith("(<"))
|
if (strIf.startsWith("<"))
|
||||||
{
|
{
|
||||||
// Parse the tokens (only get the first one though)
|
m_resourceTag = strIf.substring(1, strIf.indexOf(">"));
|
||||||
|
strIf = strIf.substring(m_resourceTag.length() + 3);
|
||||||
|
}
|
||||||
|
|
||||||
int idx = strIf.indexOf(">");
|
m_conditions = new LinkedList<Condition>();
|
||||||
if (idx != -1)
|
String[] parts = strIf.split("\\) \\(");
|
||||||
|
for (int i = 0; i < parts.length; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
String partString = parts[i].replaceAll("\\(", "").replaceAll("\\)", "");
|
||||||
|
|
||||||
|
Condition c = new Condition();
|
||||||
|
String[] conditions = partString.split(" ");
|
||||||
|
|
||||||
|
for (int j = 0; j < conditions.length; j++)
|
||||||
|
{
|
||||||
|
boolean fNot = false;
|
||||||
|
String eTag = null;
|
||||||
|
String lockToken = null;
|
||||||
|
|
||||||
|
if (WebDAV.HEADER_KEY_NOT.equals(conditions[j]))
|
||||||
|
{
|
||||||
|
// Check if Not keyword followed by State-token or entity-tag
|
||||||
|
if (j == (conditions.length - 1))
|
||||||
|
{
|
||||||
|
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
|
||||||
|
}
|
||||||
|
fNot = true;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read State-token
|
||||||
|
int index = conditions[j].indexOf('<');
|
||||||
|
if (index != -1)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
strLockToken = strIf.substring(WebDAV.OPAQUE_LOCK_TOKEN.length() + 2, idx);
|
String s = conditions[j].substring(index + 1, conditions[j].indexOf(">"));
|
||||||
}
|
if (!s.startsWith(WebDAV.OPAQUE_LOCK_TOKEN))
|
||||||
catch (IndexOutOfBoundsException e)
|
|
||||||
{
|
{
|
||||||
logger.warn("Failed to parse If header: " + strIf);
|
if(!fNot)
|
||||||
|
{
|
||||||
|
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST);
|
lockToken = s;
|
||||||
|
c.addLockTocken(lockToken, fNot);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Print a warning if there are other tokens detected
|
catch (IndexOutOfBoundsException e)
|
||||||
|
|
||||||
if (strIf.length() > idx + 2)
|
|
||||||
{
|
{
|
||||||
logger.warn("The If header contained more than one lock token, only one is supported");
|
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strIf.startsWith("<"))
|
|
||||||
{
|
|
||||||
logger.warn("Tagged lists in the If header are not supported");
|
|
||||||
}
|
|
||||||
else if (strIf.startsWith("(["))
|
|
||||||
{
|
|
||||||
logger.warn("ETags in the If header are not supported");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return strLockToken;
|
// read entity-tag
|
||||||
|
index = conditions[j].indexOf("[\"");
|
||||||
|
if (index != -1)
|
||||||
|
{
|
||||||
|
// TODO: implement parsing of weak ETags: W/"123..".
|
||||||
|
eTag = conditions[j].substring(index + 1, conditions[j].indexOf("]"));
|
||||||
|
c.addETag(eTag, fNot);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
m_conditions.add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -329,6 +424,26 @@ public abstract class WebDAVMethod
|
|||||||
return m_davHelper.getNodeService();
|
return m_davHelper.getNodeService();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method to return the search service
|
||||||
|
*
|
||||||
|
* @return SearchService
|
||||||
|
*/
|
||||||
|
protected final SearchService getSearchService()
|
||||||
|
{
|
||||||
|
return m_davHelper.getSearchService();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method to return the namespace service
|
||||||
|
*
|
||||||
|
* @return NamespaceService
|
||||||
|
*/
|
||||||
|
protected final NamespaceService getNamespaceService()
|
||||||
|
{
|
||||||
|
return m_davHelper.getNamespaceService();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Returns the general file/folder manipulation service
|
* @return Returns the general file/folder manipulation service
|
||||||
*/
|
*/
|
||||||
@@ -437,7 +552,7 @@ public abstract class WebDAVMethod
|
|||||||
* @param xml XMLWriter
|
* @param xml XMLWriter
|
||||||
* @param lockNode NodeRef
|
* @param lockNode NodeRef
|
||||||
*/
|
*/
|
||||||
protected void generateLockDiscoveryXML(XMLWriter xml, NodeRef lockNode) throws Exception
|
protected void generateLockDiscoveryXML(XMLWriter xml, NodeRef lockNode, LockInfo lockInfo) throws Exception
|
||||||
{
|
{
|
||||||
Attributes nullAttr= getDAVHelper().getNullAttributes();
|
Attributes nullAttr= getDAVHelper().getNullAttributes();
|
||||||
|
|
||||||
@@ -463,13 +578,13 @@ public abstract class WebDAVMethod
|
|||||||
// NOTE: We only do exclusive lock tokens at the moment
|
// NOTE: We only do exclusive lock tokens at the moment
|
||||||
|
|
||||||
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE, nullAttr);
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE, nullAttr);
|
||||||
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_EXCLUSIVE));
|
xml.write(DocumentHelper.createElement(lockInfo.getScope()));
|
||||||
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE);
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE);
|
||||||
|
|
||||||
// NOTE: We only support one level of lock at the moment
|
// NOTE: We only support one level of lock at the moment
|
||||||
|
|
||||||
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_DEPTH, WebDAV.XML_NS_DEPTH, nullAttr);
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_DEPTH, WebDAV.XML_NS_DEPTH, nullAttr);
|
||||||
xml.write(WebDAV.ZERO);
|
xml.write(lockInfo.getDepth());
|
||||||
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_DEPTH, WebDAV.XML_NS_DEPTH);
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_DEPTH, WebDAV.XML_NS_DEPTH);
|
||||||
|
|
||||||
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_OWNER, WebDAV.XML_NS_OWNER, nullAttr);
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_OWNER, WebDAV.XML_NS_OWNER, nullAttr);
|
||||||
@@ -531,7 +646,7 @@ public abstract class WebDAVMethod
|
|||||||
String strNamespaceName = nameSpaces.get(strNamespaceUri);
|
String strNamespaceName = nameSpaces.get(strNamespaceUri);
|
||||||
|
|
||||||
ns.append(" ").append(WebDAV.XML_NS).append(":").append(strNamespaceName).append("=\"");
|
ns.append(" ").append(WebDAV.XML_NS).append(":").append(strNamespaceName).append("=\"");
|
||||||
ns.append(strNamespaceUri).append("\" ");
|
ns.append(strNamespaceUri == null ? "" : strNamespaceUri).append("\" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -539,4 +654,451 @@ public abstract class WebDAVMethod
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if write operation can be performed on node.
|
||||||
|
*
|
||||||
|
* @param fileInfo - node's file info
|
||||||
|
* @param ignoreShared - if true ignores shared locks
|
||||||
|
* @param lockMethod - must be true if used from lock method
|
||||||
|
* @return node's lock info
|
||||||
|
* @throws WebDAVServerException if node has shared or exclusive lock
|
||||||
|
* or If header preconditions failed
|
||||||
|
*/
|
||||||
|
protected LockInfo checkNode(FileInfo fileInfo, boolean ignoreShared, boolean lockMethod) throws WebDAVServerException
|
||||||
|
{
|
||||||
|
LockInfo nodeLockInfo = getNodeLockInfo(fileInfo.getNodeRef());
|
||||||
|
String nodeETag = getDAVHelper().makeQuotedETag(fileInfo.getNodeRef());
|
||||||
|
|
||||||
|
|
||||||
|
if (m_conditions == null)
|
||||||
|
{
|
||||||
|
if (nodeLockInfo.getToken() == null)
|
||||||
|
{
|
||||||
|
if (nodeLockInfo.getSharedLockTokens() == null)
|
||||||
|
{
|
||||||
|
return nodeLockInfo;
|
||||||
|
}
|
||||||
|
if (!ignoreShared)
|
||||||
|
{
|
||||||
|
throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 "(<wrong token>) (Not <DAV:no-lock>)" 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.getToken(), nodeETag);
|
||||||
|
|
||||||
|
return nodeLockInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if write operation can be performed on node.
|
||||||
|
*
|
||||||
|
* @param fileInfo
|
||||||
|
* @return
|
||||||
|
* @throws WebDAVServerException if node has shared or exclusive lock
|
||||||
|
* or If header preconditions failed
|
||||||
|
*/
|
||||||
|
protected LockInfo checkNode(FileInfo fileInfo) throws WebDAVServerException
|
||||||
|
{
|
||||||
|
return checkNode(fileInfo, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @throws WebDAVServerException if node has no appropriate lock token
|
||||||
|
*/
|
||||||
|
private void checkLockToken(LockInfo lockInfo, boolean ignoreShared, boolean lockMethod) throws WebDAVServerException
|
||||||
|
{
|
||||||
|
String nodeLockToken = lockInfo.getToken();
|
||||||
|
LinkedList<String> sharedLockTokens = lockInfo.getSharedLockTokens();
|
||||||
|
|
||||||
|
if (m_conditions != null)
|
||||||
|
{
|
||||||
|
// Request has conditions to check
|
||||||
|
if (lockInfo.isShared())
|
||||||
|
{
|
||||||
|
// Node has shared lock. Check if conditions contains lock token of the node.
|
||||||
|
// If not throw exception
|
||||||
|
if (sharedLockTokens != null)
|
||||||
|
{
|
||||||
|
if (!ignoreShared)
|
||||||
|
{
|
||||||
|
for (Condition condition : m_conditions)
|
||||||
|
{
|
||||||
|
for (String sharedLockToken : sharedLockTokens)
|
||||||
|
{
|
||||||
|
if (condition.getLockTokensMatch().contains(sharedLockToken))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED);
|
||||||
|
}
|
||||||
|
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
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks If header conditions. Throws WebDAVServerException with 412(Precondition failed)
|
||||||
|
* if none of the conditions success.
|
||||||
|
*
|
||||||
|
* @param nodeLockToken - node's lock token
|
||||||
|
* @param nodeETag - node's ETag
|
||||||
|
* @throws WebDAVServerException if conditions fail
|
||||||
|
*/
|
||||||
|
private void checkConditions(String nodeLockToken, String nodeETag) throws WebDAVServerException
|
||||||
|
{
|
||||||
|
// Checks If header conditions.
|
||||||
|
// Each condition can contain check of ETag and check of Lock token.
|
||||||
|
|
||||||
|
if (m_conditions == null)
|
||||||
|
{
|
||||||
|
// No conditions were provided with "If" request header, so check successful
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the list of "If" header's conditions.
|
||||||
|
// If any condition conforms then check is successful
|
||||||
|
for (Condition condition : m_conditions)
|
||||||
|
{
|
||||||
|
// Flag for ETag conditions
|
||||||
|
boolean fMatchETag = true;
|
||||||
|
// Flag for Lock token conditions
|
||||||
|
boolean fMatchLockToken = true;
|
||||||
|
|
||||||
|
// Check ETags that should match
|
||||||
|
if (condition.getETagsMatch() != null)
|
||||||
|
{
|
||||||
|
fMatchETag = condition.getETagsMatch().contains(nodeETag) ? true : false;
|
||||||
|
}
|
||||||
|
// Check ETags that shouldn't match
|
||||||
|
if (condition.getETagsNotMatch() != null)
|
||||||
|
{
|
||||||
|
fMatchETag = condition.getETagsNotMatch().contains(nodeETag) ? false : true;
|
||||||
|
}
|
||||||
|
// Check lock tokens that should match
|
||||||
|
if (condition.getLockTokensMatch() != null)
|
||||||
|
{
|
||||||
|
fMatchLockToken = condition.getLockTokensMatch().contains(nodeLockToken) ? true : false;
|
||||||
|
}
|
||||||
|
// Check lock tokens that shouldn't match
|
||||||
|
if (condition.getLockTokensNotMatch() != null)
|
||||||
|
{
|
||||||
|
fMatchLockToken = condition.getLockTokensNotMatch().contains(nodeLockToken) ? false : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fMatchETag && fMatchLockToken)
|
||||||
|
{
|
||||||
|
// Condition conforms
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// None of the conditions successful
|
||||||
|
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns node Lock token in consideration of WebDav lock depth.
|
||||||
|
*
|
||||||
|
* @param fileInfo node
|
||||||
|
* @return String Lock token
|
||||||
|
*/
|
||||||
|
protected LockInfo getNodeLockInfo(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
LockInfo lockInfo = new LockInfo();
|
||||||
|
NodeService nodeService = getNodeService();
|
||||||
|
LockService lockService = getLockService();
|
||||||
|
|
||||||
|
// Check if node is locked directly.
|
||||||
|
LockStatus lockSts = lockService.getLockStatus(nodeRef);
|
||||||
|
if (lockSts == LockStatus.LOCKED || lockSts == LockStatus.LOCK_OWNER)
|
||||||
|
{
|
||||||
|
String propOpaqueLockToken = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_OPAQUE_LOCK_TOKEN);
|
||||||
|
if (propOpaqueLockToken != null)
|
||||||
|
{
|
||||||
|
// Get lock depth
|
||||||
|
String depth = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_LOCK_DEPTH);
|
||||||
|
//Get lock scope
|
||||||
|
String scope = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_LOCK_SCOPE);
|
||||||
|
// Get shared lock tokens
|
||||||
|
String sharedLocks = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_SHARED_LOCK_TOKENS);
|
||||||
|
|
||||||
|
// Node has it's own Lock token.
|
||||||
|
// Store lock information to the lockInfo object
|
||||||
|
lockInfo.setToken(propOpaqueLockToken);
|
||||||
|
lockInfo.setDepth(depth);
|
||||||
|
lockInfo.setScope(scope);
|
||||||
|
lockInfo.setSharedLockTokens(LockInfo.parseSharedLockTokens(sharedLocks));
|
||||||
|
|
||||||
|
return lockInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No has no exclusive lock but can be locked with shared lock
|
||||||
|
String sharedLocks = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_SHARED_LOCK_TOKENS);
|
||||||
|
if (sharedLocks != null)
|
||||||
|
{
|
||||||
|
// Get lock depth
|
||||||
|
String depth = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_LOCK_DEPTH);
|
||||||
|
//Get lock scope
|
||||||
|
String scope = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_LOCK_SCOPE);
|
||||||
|
|
||||||
|
// Node has it's own Lock token.
|
||||||
|
// Store lock information to the lockInfo object
|
||||||
|
lockInfo.setDepth(depth);
|
||||||
|
lockInfo.setScope(scope);
|
||||||
|
lockInfo.setSharedLockTokens(LockInfo.parseSharedLockTokens(sharedLocks));
|
||||||
|
lockInfo.setShared(true);
|
||||||
|
|
||||||
|
return lockInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Node isn't locked directly and has no it's own Lock token.
|
||||||
|
// Try to search indirect lock.
|
||||||
|
NodeRef node = nodeRef;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
List<ChildAssociationRef> assocs = nodeService.getParentAssocs(node, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
|
||||||
|
if (assocs.isEmpty())
|
||||||
|
{
|
||||||
|
// Node has no lock and Lock token
|
||||||
|
return new LockInfo();
|
||||||
|
}
|
||||||
|
NodeRef parent = assocs.get(0).getParentRef();
|
||||||
|
|
||||||
|
lockSts = lockService.getLockStatus(parent);
|
||||||
|
if (lockSts == LockStatus.LOCKED || lockSts == LockStatus.LOCK_OWNER)
|
||||||
|
{
|
||||||
|
// Check node lock depth.
|
||||||
|
// If depth is WebDAV.INFINITY then return this node's Lock token.
|
||||||
|
String depth = (String) nodeService.getProperty(parent, WebDAVModel.PROP_LOCK_DEPTH);
|
||||||
|
if (WebDAV.INFINITY.equals(depth))
|
||||||
|
{
|
||||||
|
// In this case node is locked indirectly.
|
||||||
|
|
||||||
|
//Get lock scope
|
||||||
|
String scope = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_LOCK_SCOPE);
|
||||||
|
// Get shared lock tokens
|
||||||
|
String sharedLocks = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_SHARED_LOCK_TOKENS);
|
||||||
|
|
||||||
|
// Store lock information to the lockInfo object
|
||||||
|
|
||||||
|
// Get lock token of the locked node - this is indirect lock token.
|
||||||
|
String propOpaqueLockToken = (String) nodeService.getProperty(parent, WebDAVModel.PROP_OPAQUE_LOCK_TOKEN);
|
||||||
|
lockInfo.setToken(propOpaqueLockToken);
|
||||||
|
lockInfo.setDepth(depth);
|
||||||
|
lockInfo.setScope(scope);
|
||||||
|
lockInfo.setSharedLockTokens(LockInfo.parseSharedLockTokens(sharedLocks));
|
||||||
|
|
||||||
|
return lockInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No has no exclusive lock but can be locked with shared lock
|
||||||
|
String sharedLocks = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_SHARED_LOCK_TOKENS);
|
||||||
|
if (sharedLocks != null)
|
||||||
|
{
|
||||||
|
// Check node lock depth.
|
||||||
|
// If depth is WebDAV.INFINITY then return this node's Lock token.
|
||||||
|
String depth = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_LOCK_DEPTH);
|
||||||
|
if (WebDAV.INFINITY.equals(depth))
|
||||||
|
{
|
||||||
|
// In this case node is locked indirectly.
|
||||||
|
|
||||||
|
//Get lock scope
|
||||||
|
String scope = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_LOCK_SCOPE);
|
||||||
|
|
||||||
|
// Node has it's own Lock token.
|
||||||
|
lockInfo.setDepth(depth);
|
||||||
|
lockInfo.setScope(scope);
|
||||||
|
lockInfo.setSharedLockTokens(LockInfo.parseSharedLockTokens(sharedLocks));
|
||||||
|
|
||||||
|
lockInfo.setShared(true);
|
||||||
|
|
||||||
|
return lockInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used for storing conditions which comes with "If" header of the request
|
||||||
|
*
|
||||||
|
* @author ivanry
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected class Condition
|
||||||
|
{
|
||||||
|
// These tokens will be checked on equivalence against node's lock token
|
||||||
|
private LinkedList<String> lockTokensMatch = new LinkedList<String>();
|
||||||
|
|
||||||
|
// These tokens will be checked on non-equivalence against node's lock token
|
||||||
|
private LinkedList<String> lockTokensNotMatch = new LinkedList<String>();
|
||||||
|
|
||||||
|
// These ETags will be checked on equivalence against node's ETags
|
||||||
|
private LinkedList<String> eTagsMatch;
|
||||||
|
|
||||||
|
// These ETags will be checked on non-equivalence against node's ETags
|
||||||
|
private LinkedList<String> eTagsNotMatch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public Condition()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of lock tokens that should be checked against node's lock token on equivalence.
|
||||||
|
*
|
||||||
|
* @return lock tokens
|
||||||
|
*/
|
||||||
|
public LinkedList<String> getLockTokensMatch()
|
||||||
|
{
|
||||||
|
return this.lockTokensMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of lock tokens that should be checked against node's lock token on non-equivalence.
|
||||||
|
*
|
||||||
|
* @return lock tokens
|
||||||
|
*/
|
||||||
|
public LinkedList<String> getLockTokensNotMatch()
|
||||||
|
{
|
||||||
|
return this.lockTokensNotMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of ETags that should be checked against node's ETag on equivalence.
|
||||||
|
*
|
||||||
|
* @return ETags list
|
||||||
|
*/
|
||||||
|
public LinkedList<String> getETagsMatch()
|
||||||
|
{
|
||||||
|
return this.eTagsMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of ETags that should be checked against node's ETag on non-equivalence.
|
||||||
|
*
|
||||||
|
* @return ETags list
|
||||||
|
*/
|
||||||
|
public LinkedList<String> getETagsNotMatch()
|
||||||
|
{
|
||||||
|
return this.eTagsNotMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds lock token to check
|
||||||
|
*
|
||||||
|
* @param lockToken String
|
||||||
|
* @param notMatch true is lock token should be added to the list matched tokens.
|
||||||
|
* false if should be added to the list of non-matches.
|
||||||
|
*/
|
||||||
|
public void addLockTocken(String lockToken, boolean notMatch)
|
||||||
|
{
|
||||||
|
if (notMatch)
|
||||||
|
{
|
||||||
|
this.lockTokensNotMatch.add(lockToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.lockTokensMatch.add(lockToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add ETag to check
|
||||||
|
*
|
||||||
|
* @param eTag String
|
||||||
|
* @param notMatch true is ETag should be added to the list matched ETags.
|
||||||
|
* false if should be added to the list of non-matches.
|
||||||
|
*/
|
||||||
|
public void addETag(String eTag, boolean notMatch)
|
||||||
|
{
|
||||||
|
if (notMatch)
|
||||||
|
{
|
||||||
|
if (eTagsNotMatch == null)
|
||||||
|
{
|
||||||
|
eTagsNotMatch = new LinkedList<String>();
|
||||||
|
}
|
||||||
|
this.eTagsNotMatch.add(eTag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (eTagsMatch == null)
|
||||||
|
{
|
||||||
|
eTagsMatch = new LinkedList<String>();
|
||||||
|
}
|
||||||
|
this.eTagsMatch.add(eTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -138,6 +138,7 @@ public class WebDAVProperty
|
|||||||
m_strValue = strValue;
|
m_strValue = strValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates QName of the property
|
* Creates QName of the property
|
||||||
*
|
*
|
||||||
@@ -163,6 +164,7 @@ public class WebDAVProperty
|
|||||||
WebDAV.XML_SUPPORTED_LOCK.equals(m_strName);
|
WebDAV.XML_SUPPORTED_LOCK.equals(m_strName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the property as a string
|
* Return the property as a string
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user