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;
|
||||
try
|
||||
{
|
||||
if (destPath.endsWith(WebDAVHelper.PathSeperator))
|
||||
{
|
||||
destPath = destPath.substring(0, destPath.length() - 1);
|
||||
}
|
||||
destParentInfo = getDAVHelper().getParentNodeForPath(rootNodeRef, destPath, servletPath);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
@@ -103,7 +107,7 @@ public abstract class AbstractMoveOrCopyMethod extends HierarchicalMethod
|
||||
{
|
||||
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
|
||||
@@ -123,6 +127,8 @@ public abstract class AbstractMoveOrCopyMethod extends HierarchicalMethod
|
||||
// delete the destination node if it is not the same as the source node
|
||||
if (!destInfo.getNodeRef().equals(sourceInfo.getNodeRef()))
|
||||
{
|
||||
checkNode(destInfo);
|
||||
|
||||
// attempting to move or copy onto another node
|
||||
fileFolderService.delete(destInfo.getNodeRef());
|
||||
}
|
||||
@@ -138,7 +144,9 @@ public abstract class AbstractMoveOrCopyMethod extends HierarchicalMethod
|
||||
|
||||
NodeRef sourceNodeRef = sourceInfo.getNodeRef();
|
||||
NodeRef destParentNodeRef = destParentInfo.getNodeRef();
|
||||
|
||||
String name = getDAVHelper().splitPath(destPath)[1];
|
||||
|
||||
moveOrCopy(fileFolderService, sourceNodeRef, destParentNodeRef, name);
|
||||
|
||||
// Set the response status
|
||||
|
@@ -99,6 +99,9 @@ public class DeleteMethod extends WebDAVMethod
|
||||
}
|
||||
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
|
||||
checkNode(fileInfo);
|
||||
|
||||
// delete it
|
||||
fileFolderService.delete(fileInfo.getNodeRef());
|
||||
}
|
||||
|
@@ -293,7 +293,7 @@ public class GetMethod extends WebDAVMethod
|
||||
* @param strETagHeader The header to parse
|
||||
* @return A list of ETags
|
||||
*/
|
||||
private ArrayList parseETags(String strETagHeader)
|
||||
private ArrayList<String> parseETags(String strETagHeader)
|
||||
{
|
||||
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 org.alfresco.model.ContentModel;
|
||||
import org.alfresco.model.WebDAVModel;
|
||||
import org.alfresco.repo.model.filefolder.FileFolderServiceImpl;
|
||||
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.model.FileFolderService;
|
||||
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.dom4j.DocumentHelper;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -54,8 +58,13 @@ public class LockMethod extends WebDAVMethod
|
||||
{
|
||||
public static final String EMPTY_NS = "";
|
||||
|
||||
private String m_strLockToken = null;
|
||||
private int m_timeoutDuration = WebDAV.DEPTH_INFINITY;
|
||||
private int m_timeoutDuration = WebDAV.TIMEOUT_INFINITY;
|
||||
|
||||
private LockInfo lockInfo = new LockInfo();
|
||||
|
||||
private String m_scope = null;
|
||||
|
||||
private String lockToken= null;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
protected final boolean hasLockToken()
|
||||
{
|
||||
return m_strLockToken != null ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the lock token of an existing lock
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
protected final String getLockToken()
|
||||
if (m_conditions != null)
|
||||
{
|
||||
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
|
||||
{
|
||||
// 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
|
||||
|
||||
@@ -147,7 +167,7 @@ public class LockMethod extends WebDAVMethod
|
||||
// DEBUG
|
||||
|
||||
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
|
||||
{
|
||||
// NOTE: There is a body for lock requests which contain the
|
||||
// type of lock to apply and the lock owner but we will
|
||||
// ignore these settings so don't bother reading the body
|
||||
if (m_request.getContentLength() == -1)
|
||||
{
|
||||
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
|
||||
*/
|
||||
@@ -225,21 +282,27 @@ public class LockMethod extends WebDAVMethod
|
||||
" path: " + path + "\n" +
|
||||
" 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())
|
||||
{
|
||||
this.lockInfo = checkNode(lockNodeInfo);
|
||||
// Refresh an existing lock
|
||||
refreshLock(lockNodeInfo.getNodeRef(), userName);
|
||||
refreshLock(lockNodeInfo, userName);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.lockInfo = checkNode(lockNodeInfo, true, WebDAV.XML_EXCLUSIVE.equals(m_scope));
|
||||
// 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_CONTENT_TYPE, WebDAV.XML_CONTENT_TYPE);
|
||||
|
||||
@@ -254,25 +317,35 @@ public class LockMethod extends WebDAVMethod
|
||||
* @param userName String
|
||||
* @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();
|
||||
|
||||
// Check the lock status of the node
|
||||
LockStatus lockSts = lockService.getLockStatus(lockNode);
|
||||
// Create Lock token
|
||||
lockToken = WebDAV.makeLockToken(lockNode.getNodeRef(), userName);
|
||||
|
||||
// DEBUG
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Create lock status=" + lockSts);
|
||||
|
||||
if (lockSts == LockStatus.LOCKED || lockSts == LockStatus.LOCK_OWNER)
|
||||
if (WebDAV.XML_EXCLUSIVE.equals(m_scope))
|
||||
{
|
||||
// Indicate that the resource is already locked
|
||||
throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED);
|
||||
// Lock the node
|
||||
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
|
||||
lockService.lock(lockNode, LockType.WRITE_LOCK, getLockTimeout());
|
||||
// Store lock depth
|
||||
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
|
||||
* @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();
|
||||
|
||||
// Check the lock status of the node
|
||||
LockStatus lockSts = lockService.getLockStatus(lockNode);
|
||||
|
||||
// DEBUG
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Refresh lock status=" + lockSts);
|
||||
|
||||
if (lockSts != LockStatus.LOCK_OWNER)
|
||||
if (WebDAV.XML_EXCLUSIVE.equals(m_scope))
|
||||
{
|
||||
// Indicate that the resource is already locked
|
||||
throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED);
|
||||
}
|
||||
|
||||
// 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.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.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);
|
||||
|
||||
// NOTE: We only support one level of lock at the moment
|
||||
|
||||
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.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_HREF, WebDAV.XML_HREF, nullAttr);
|
||||
|
||||
xml.write(WebDAV.makeLockToken(lockNode, owner));
|
||||
|
||||
if (lockToken != null)
|
||||
{
|
||||
// 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_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.FileNotFoundException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
/**
|
||||
* Implements the WebDAV MKCOL method
|
||||
@@ -66,16 +65,14 @@ public class MkcolMethod extends WebDAVMethod
|
||||
{
|
||||
// There should not be a body with the MKCOL request
|
||||
|
||||
Document body = getRequestBodyAsDocument();
|
||||
|
||||
if (body != null)
|
||||
if (m_request.getContentLength() > 0)
|
||||
{
|
||||
throw new WebDAVServerException(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exceute the request
|
||||
* Execute the request
|
||||
*
|
||||
* @exception WebDAVServerException
|
||||
*/
|
||||
@@ -120,7 +117,7 @@ public class MkcolMethod extends WebDAVMethod
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
// parent path is missing
|
||||
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
|
||||
throw new WebDAVServerException(HttpServletResponse.SC_CONFLICT);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@@ -24,7 +24,13 @@
|
||||
*/
|
||||
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.FileInfo;
|
||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
@@ -47,6 +53,27 @@ public class MoveMethod extends AbstractMoveOrCopyMethod
|
||||
NodeRef destParentNodeRef,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@@ -37,8 +37,6 @@ import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.SessionUser;
|
||||
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.FileInfo;
|
||||
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 FIND_PROPS = 2;
|
||||
|
||||
// Find depth and request type
|
||||
private int m_depth = WebDAV.DEPTH_INFINITY;
|
||||
// Find request type
|
||||
protected int m_mode = GET_ALL_PROPS;
|
||||
|
||||
// Requested properties
|
||||
@@ -86,16 +83,6 @@ public class PropFindMethod extends WebDAVMethod
|
||||
m_namespaces = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the property find depth
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public final int getDepth()
|
||||
{
|
||||
return m_depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
parseDepthHeader();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,7 +168,7 @@ public class PropFindMethod extends WebDAVMethod
|
||||
}
|
||||
|
||||
/**
|
||||
* Exceute the main WebDAV request processing
|
||||
* Execute the main WebDAV request processing
|
||||
*
|
||||
* @exception WebDAVServerException
|
||||
*/
|
||||
@@ -355,7 +328,7 @@ public class PropFindMethod extends WebDAVMethod
|
||||
String strName = node.getLocalName();
|
||||
String strNamespaceUri = node.getNamespaceURI();
|
||||
|
||||
if (strNamespaceUri.equals(WebDAV.DEFAULT_NAMESPACE_URI))
|
||||
if (WebDAV.DEFAULT_NAMESPACE_URI.equals(strNamespaceUri))
|
||||
{
|
||||
property = new WebDAVProperty(strName);
|
||||
}
|
||||
@@ -373,6 +346,10 @@ public class PropFindMethod extends WebDAVMethod
|
||||
*/
|
||||
private String getNamespaceName(String strNamespaceUri)
|
||||
{
|
||||
if (strNamespaceUri == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String strNamespaceName = m_namespaces.get(strNamespaceUri);
|
||||
if (strNamespaceName == null)
|
||||
{
|
||||
@@ -465,7 +442,7 @@ public class PropFindMethod extends WebDAVMethod
|
||||
|
||||
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
|
||||
if (propName.equals(WebDAV.XML_LOCK_DISCOVERY)) // && metaData.isLocked())
|
||||
@@ -624,7 +601,28 @@ public class PropFindMethod extends WebDAVMethod
|
||||
|
||||
// TODO: Custom properties lookup
|
||||
// String qualifiedName = propNamespaceUri + WebDAV.NAMESPACE_SEPARATOR + propName;
|
||||
|
||||
String value = (String) getNodeService().getProperty(nodeRef, property.createQName());
|
||||
if (value == null)
|
||||
{
|
||||
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
|
||||
{
|
||||
// Get the lock status for the node
|
||||
// Output the lock status response
|
||||
|
||||
LockService lockService = getLockService();
|
||||
LockStatus lockSts = lockService.getLockStatus(node);
|
||||
|
||||
// Output the lock status reponse
|
||||
|
||||
if (lockSts != LockStatus.NO_LOCK)
|
||||
generateLockDiscoveryXML(xml, node);
|
||||
LockInfo lockInfo = getNodeLockInfo(node);
|
||||
if (lockInfo.isLocked())
|
||||
{
|
||||
generateLockDiscoveryXML(xml, node, lockInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -31,7 +31,6 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.dom4j.DocumentHelper;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.w3c.dom.Document;
|
||||
@@ -69,6 +68,8 @@ public class PropPatchMethod extends PropFindMethod
|
||||
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
|
||||
checkNode(pathNodeInfo);
|
||||
|
||||
// Set the response 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
|
||||
{
|
||||
protected static final int SET = 0;
|
||||
protected static final int REMOVE = 1;
|
||||
|
||||
// Property on which action should be performed
|
||||
private WebDAVProperty property;
|
||||
|
||||
// Action
|
||||
private int action;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param action
|
||||
* @param property
|
||||
*/
|
||||
public PropertyAction(int action, WebDAVProperty property)
|
||||
{
|
||||
this.action = action;
|
||||
|
@@ -76,9 +76,9 @@ public class PutMethod extends WebDAVMethod
|
||||
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);
|
||||
}
|
||||
|
||||
checkNode(contentNodeInfo);
|
||||
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
|
@@ -24,12 +24,16 @@
|
||||
*/
|
||||
package org.alfresco.repo.webdav;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.model.WebDAVModel;
|
||||
import org.alfresco.service.cmr.lock.LockService;
|
||||
import org.alfresco.service.cmr.lock.LockStatus;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
|
||||
/**
|
||||
* Implements the WebDAV UNLOCK method
|
||||
@@ -104,7 +108,7 @@ public class UnlockMethod extends WebDAVMethod
|
||||
}
|
||||
|
||||
/**
|
||||
* Exceute the request
|
||||
* Execute the request
|
||||
*
|
||||
* @exception WebDAVServerException
|
||||
*/
|
||||
@@ -135,6 +139,7 @@ public class UnlockMethod extends WebDAVMethod
|
||||
|
||||
// Get the lock status for the node
|
||||
LockService lockService = getDAVHelper().getLockService();
|
||||
NodeService nodeService = getNodeService();
|
||||
// String nodeId = lockInfo[0];
|
||||
// String userName = lockInfo[1];
|
||||
|
||||
@@ -143,6 +148,9 @@ public class UnlockMethod extends WebDAVMethod
|
||||
{
|
||||
// Unlock the node
|
||||
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
|
||||
m_response.setStatus(HttpServletResponse.SC_NO_CONTENT);
|
||||
@@ -154,6 +162,28 @@ public class UnlockMethod extends WebDAVMethod
|
||||
}
|
||||
}
|
||||
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
|
||||
if (logger.isDebugEnabled())
|
||||
@@ -162,6 +192,9 @@ public class UnlockMethod extends WebDAVMethod
|
||||
// Node is not locked
|
||||
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if (lockSts == LockStatus.LOCKED)
|
||||
{
|
||||
// DEBUG
|
||||
|
@@ -60,7 +60,7 @@ public class WebDAV
|
||||
public static final String DAV_NS = "D";
|
||||
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_1 = 1;
|
||||
@@ -83,6 +83,7 @@ public class WebDAV
|
||||
public static final String SC_NOT_FOUND_DESC = "Not Found";
|
||||
public static final String SC_FORBIDDEN_DESC = "Forbidden";
|
||||
|
||||
|
||||
// HTTP methods
|
||||
|
||||
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";
|
||||
|
||||
// If header keyword
|
||||
|
||||
public static final String HEADER_KEY_NOT = "Not";
|
||||
|
||||
// General string constants
|
||||
|
||||
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_CANNOT_MODIFY_PROTECTED_PROPERTY = DAV_NS_PREFIX + "cannot-modify-protected-property";
|
||||
|
||||
|
||||
public static final String XML_CONTENT_TYPE = "text/xml; charset=UTF-8";
|
||||
|
||||
// Alfresco specific properties
|
||||
@@ -590,6 +596,30 @@ public class WebDAV
|
||||
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
|
||||
*/
|
||||
|
@@ -28,6 +28,8 @@ import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -36,16 +38,23 @@ import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.model.WebDAVModel;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
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.FileInfo;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
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.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -57,6 +66,7 @@ import org.xml.sax.Attributes;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract base class for all the WebDAV method handling classes
|
||||
*
|
||||
@@ -89,6 +99,19 @@ public abstract class WebDAVMethod
|
||||
|
||||
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
|
||||
*/
|
||||
@@ -125,6 +148,16 @@ public abstract class WebDAVMethod
|
||||
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
|
||||
* 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);
|
||||
|
||||
@@ -248,45 +310,78 @@ public abstract class WebDAVMethod
|
||||
|
||||
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(">");
|
||||
if (idx != -1)
|
||||
m_conditions = new LinkedList<Condition>();
|
||||
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
|
||||
{
|
||||
strLockToken = strIf.substring(WebDAV.OPAQUE_LOCK_TOKEN.length() + 2, idx);
|
||||
}
|
||||
catch (IndexOutOfBoundsException e)
|
||||
String s = conditions[j].substring(index + 1, conditions[j].indexOf(">"));
|
||||
if (!s.startsWith(WebDAV.OPAQUE_LOCK_TOKEN))
|
||||
{
|
||||
logger.warn("Failed to parse If header: " + strIf);
|
||||
if(!fNot)
|
||||
{
|
||||
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST);
|
||||
lockToken = s;
|
||||
c.addLockTocken(lockToken, fNot);
|
||||
}
|
||||
|
||||
// Print a warning if there are other tokens detected
|
||||
|
||||
if (strIf.length() > idx + 2)
|
||||
}
|
||||
catch (IndexOutOfBoundsException e)
|
||||
{
|
||||
logger.warn("The If header contained more than one lock token, only one is supported");
|
||||
}
|
||||
}
|
||||
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");
|
||||
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@@ -437,7 +552,7 @@ public abstract class WebDAVMethod
|
||||
* @param xml XMLWriter
|
||||
* @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();
|
||||
|
||||
@@ -463,13 +578,13 @@ public abstract class WebDAVMethod
|
||||
// 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.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);
|
||||
|
||||
// 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.write(WebDAV.ZERO);
|
||||
xml.write(lockInfo.getDepth());
|
||||
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);
|
||||
@@ -531,7 +646,7 @@ public abstract class WebDAVMethod
|
||||
String strNamespaceName = nameSpaces.get(strNamespaceUri);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates QName of the property
|
||||
*
|
||||
@@ -163,6 +164,7 @@ public class WebDAVProperty
|
||||
WebDAV.XML_SUPPORTED_LOCK.equals(m_strName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the property as a string
|
||||
*
|
||||
|
Reference in New Issue
Block a user