Merged DEV/SWIFT to HEAD

25960: RepoBM: improve configurability
          - add option to configure base folder path
          - enable params (base urls, threads, base folder path, ...) to be configured via ant build.properties
   25961: Merged BRANCHES/DEV/BM to BRANCHES/DEV/SWIFT:
      24568: WebDAV - use fileInfo props (instead of nodeRef + getProp(s)) - resolve conflict
      24727: SPP/WebDAV - compile fix (follow-on to r24568)
      24855: BM - WebDAV - fix litmus -> locks -> 7. discover FAIL (fallout from r24568)
             + ran litmus 0.12.1
   25963: Merged BRANCHES/DEV/BM to BRANCHES/DEV/SWIFT:
      24784: Log stack trace when reporting exception
   25966: Merged BRANCHES/DEV/BM to BRANCHES/DEV/SWIFT:
      24725: BM - tweak validate (to use read-only txn)
   25968: Merged BRANCHES/DEV/BM to BRANCHES/DEV/SWIFT:
      24736: BM - getChildByName optimisation (add reverse-lookup for parentAssocs)
   25992: RepoBM: add TPS
          - extend default ant-jmeter report to show approx/rounded test Time & TPS (note: not done for detailed report)
          - comment out detailed report
          - also expose "duration" param in ant build.xml / build.properties
   26035: RepoBM: ALF-6796 - fix perf of report generation (switch from xalan to saxon)
          - also do not fail on error
   26042: RepoBM: update readme (for ALF-6796) + add zip target
   26045: (RECORD ONLY) Merged DEV/BM to DEV/SWIFT (RECORD ONLY) - already resolved for V3.4 & SWIFT
        Merged BRANCHES/V3.4 to BRANCHES/DEV/BM:
           23613: Merged BRANCHES/DEV/BELARUS/HEAD_2010_10_21 to BRANCHES/V3.4:
              23601: ALF-5447: It's impossible to save the MS Office 2010 document via webdav.
        Merged BRANCHES/V3.4 to BRANCHES/DEV/BM:
           23618: Merged BRANCHES/DEV/V3.3-BUG-FIX to BRANCHES/V3.4:
              23617: Merged BRANCHES/DEV/BELARUS/V3.3-2010_11_10 to BRANCHES/DEV/V3.3-BUG-FIX:
                 23602: ALF-5517: Webdav "supportedlock" propfind request fails if locking enabled
        Merged BRANCHES/V3.4 to BRANCHES/DEV/BM:
           23997: Fix ALF-5731: Saving a doc from Office 2003 via WebDAV fails
   26049: RepoBM: add "folder create" unit test
          - ALF-7309 (WebDAV)
          - ALF-7310 (CMIS)
   26147: RepoBM: update WebDAV test
          - add patched sardine (thanks Florian) 
          - adds "getResources(String url, int depth, boolean allProps)"
   26219: RepoBM: test additions & improvements
          - add "itemRename" (document or folder) - for CMIS (ALF-7362) and WebDAV (ALF-7630)
          - update mixed scenario (add "folderCreate" & "itemRename") - for CMIS (ALF-7546) and WebDAV (ALF-7545)
          - cleanup of common code
   26269: RepoBM: fix mixed scenarios (# of threads & weighted distribution)
          - use single thread group and interleave controllers
          - for CMIS (ALF-7546) and WebDAV (ALF-7545)
   26271: (RECORD ONLY) Merged BRANCHES/DEV/BM to BRANCHES/DEV/SWIFT (RECORD-ONLY)
          - NOTE: verified w/ florian
          - NOTE: OpenCMIS and cmis-client-api are already on SWIFT
          - NOTE: cmis-bm has been superceded by repository-bm
   26273: (RECORD ONLY) Merged BRANCHES/DEV/BM to BRANCHES/DEV/SWIFT (RECORD-ONLY)
      24326: OpenCMIS update
   26395: ALF-7755: add "system-build-test" project (and related RepoBM updates)
          - add ability to run "remote" tests (ie. selected *SystemTest)  against embedded Jetty
          - initially run sanity builds test for RepoBM (RepositoryBenchmarkWebDAVSystemTest + RepositoryBenchmarkCMISSystemTest) & also SiteActivitySystemTest
          - RepoBM enhanced to import test data if not present (also added additional testItemDelete unit test)
          - using local copy of Spring 3.0.5 (requires at least 3.0.2) - can be rationalised once rest of Alfresco (ie. 3rd-party libs) moves up to a higher Spring version
   26420: ALF-7755: tweak "system-build-test" for build box
          - also includes minor fixes to RepoBM (+ readme)
   26448: ALF-7755: tweak "system-build-test"
          - for ant scripts (eg. running on build box)
   26457: ALF-7898 - Alfresco Web Services: fix-up broken/regressed tests (WebServiceSuiteSystemTest)
          - revert default url context ... from "contentspaces" -> "alfresco" (broken during merge from ADB LC branch)
          - fix AuthoringServiceSystemTest.testVersionMethods() - when deleting version history
          - fix RepositoryServiceSystemTest.testPropertySetGet() - when creating dynamic model
   26462: ALF-7898 / ALF-7755: add additional 'system' tests
          - effectively runs Alf Web Service build sanity tests (~= WebServiceSuiteSystemTest)
   26478: ALF-7898 / ALF-7755: additional classpath fiddling (to get around limitation on Windows)
          - see also r26093
   26487: Build fix: cut-and-paste formatting issue
   26502: RepoBM: add "itemUpdate" (update props for doc or folder)
          - for CMIS (ALF-7633) - use Alfresco OpenCMIS Extension to update aspect props
          - for WebDAV (ALF-7631) - patch Sardine to allow custom namespaces
   26526: ALF-7755: use temp classpaths
   26528: ALF-7755: comment out for now
          - seems to work locally and on build boxes when run separately, but fails during full build
          - pending further investigation and testing (eg. when bamboo agents become free)
   26567: ALF-7755: remove test-repository-bm since not used
          - was breaking the test classpath (for following tests)
   26571: ALF-7755: re-enable RepoBenchmarkSystemTestSuite
   26600: ALF-7755: test-system-build-test
          - add user.home (for build box env)
          - re-enable MiscSystemTestSuite (includes Alf WS* tests)
   26609: ALF-7755: fix build/test (RepositoryServiceSystemTest.testPropertySetGet)
          - due to earlier MT test

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@28217 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2011-06-06 18:31:52 +00:00
parent 2300403bb4
commit 23207fbf7f
6 changed files with 448 additions and 446 deletions

View File

@@ -29,7 +29,6 @@ import java.util.StringTokenizer;
import javax.servlet.http.HttpServletResponse;
import org.springframework.extensions.surf.util.I18NUtil;
import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
@@ -40,6 +39,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.repository.datatype.TypeConverter;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* Implements the WebDAV GET method
@@ -50,8 +50,8 @@ public class GetMethod extends WebDAVMethod
{
// Request parameters
private ArrayList ifMatchTags = null;
private ArrayList ifNoneMatchTags = null;
private ArrayList<String> ifMatchTags = null;
private ArrayList<String> ifNoneMatchTags = null;
private Date m_ifModifiedSince = null;
private Date m_ifUnModifiedSince = null;
@@ -188,13 +188,12 @@ public class GetMethod extends WebDAVMethod
}
else
{
NodeRef pathNodeRef = realNodeInfo.getNodeRef();
// Return the node details, and content if requested, check that the node passes the pre-conditions
checkPreConditions(realNodeInfo);
// Build the response header
m_response.setHeader(WebDAV.HEADER_ETAG, getDAVHelper().makeQuotedETag(pathNodeRef));
m_response.setHeader(WebDAV.HEADER_ETAG, getDAVHelper().makeQuotedETag(nodeInfo));
Date modifiedDate = realNodeInfo.getModifiedDate();
if (modifiedDate != null)
@@ -231,7 +230,7 @@ public class GetMethod extends WebDAVMethod
{
// Make an etag for the node
String strETag = getDAVHelper().makeQuotedETag(nodeInfo.getNodeRef());
String strETag = getDAVHelper().makeQuotedETag(nodeInfo);
TypeConverter typeConv = DefaultTypeConverter.INSTANCE;
// Check the If-Match header, don't send any content back if none of the tags in

View File

@@ -291,7 +291,7 @@ public class LockMethod extends WebDAVMethod
m_response.setHeader(WebDAV.HEADER_CONTENT_TYPE, WebDAV.XML_CONTENT_TYPE);
// We either created a new lock or refreshed an existing lock, send back the lock details
generateResponse(lockNodeInfo.getNodeRef(), userName);
generateResponse(lockNodeInfo, userName);
}
/**
@@ -326,6 +326,9 @@ public class LockMethod extends WebDAVMethod
{
// Lock the node
lockService.lock(lockNode.getNodeRef(), LockType.WRITE_LOCK, getLockTimeout());
// update local cache (will be read back when generating the response)
lockNode.getProperties().put(ContentModel.PROP_LOCK_OWNER, userName);
//this.lockInfo.setToken(lockToken);
getNodeService().setProperty(lockNode.getNodeRef(), WebDAVModel.PROP_OPAQUE_LOCK_TOKEN, lockToken);
@@ -366,7 +369,7 @@ public class LockMethod extends WebDAVMethod
/**
* Generates the XML lock discovery response body
*/
protected void generateResponse(NodeRef lockNode, String userName) throws Exception
protected void generateResponse(FileInfo lockNodeInfo, String userName) throws Exception
{
String scope;
String lt;
@@ -384,7 +387,7 @@ public class LockMethod extends WebDAVMethod
// Output refreshed lock
lt = this.lockInfo.getToken();
}
String owner = (String) getNodeService().getProperty(lockNode, ContentModel.PROP_LOCK_OWNER);
String owner = (String) lockNodeInfo.getProperties().get(ContentModel.PROP_LOCK_OWNER);
XMLWriter xml = createXMLWriter();
@@ -394,7 +397,7 @@ public class LockMethod extends WebDAVMethod
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROP + nsdec, WebDAV.XML_NS_PROP + nsdec, getDAVHelper().getNullAttributes());
// Output the lock details
generateLockDiscoveryXML(xml, lockNode, false, scope, WebDAV.getDepthName(m_depth), lt, owner);
generateLockDiscoveryXML(xml, lockNodeInfo, false, scope, WebDAV.getDepthName(m_depth), lt, owner);
// Close off the XML
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP);

View File

@@ -36,7 +36,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.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.repository.datatype.TypeConverter;
@@ -370,7 +369,6 @@ public class PropFindMethod extends WebDAVMethod
*/
protected void generateResponseForNode(XMLWriter xml, FileInfo nodeInfo, String path) throws Exception
{
NodeRef nodeRef = nodeInfo.getNodeRef();
boolean isFolder = nodeInfo.isFolder();
// Output the response block for the current node
@@ -411,10 +409,10 @@ public class PropFindMethod extends WebDAVMethod
generateNamedPropertiesResponse(xml, nodeInfo, isFolder);
break;
case GET_ALL_PROPS:
generateAllPropertiesResponse(xml, nodeRef, isFolder);
generateAllPropertiesResponse(xml, nodeInfo, isFolder);
break;
case FIND_PROPS:
generateFindPropertiesResponse(xml, nodeRef, isFolder);
generateFindPropertiesResponse(xml, nodeInfo, isFolder);
break;
}
@@ -432,10 +430,8 @@ public class PropFindMethod extends WebDAVMethod
*/
private void generateNamedPropertiesResponse(XMLWriter xml, FileInfo nodeInfo, boolean isDir) throws Exception
{
NodeRef nodeRef = nodeInfo.getNodeRef();
// Get the properties for the node
Map<QName, Serializable> props = getNodeService().getProperties(nodeRef);
Map<QName, Serializable> props = nodeInfo.getProperties();
// Output the start of the properties element
Attributes nullAttr = getDAVHelper().getNullAttributes();
@@ -454,7 +450,6 @@ public class PropFindMethod extends WebDAVMethod
String propName = property.getName();
String propNamespaceUri = property.getNamespaceUri();
// String propNamespaceName = property.getNamespaceName();
// Check if the property is a standard WebDAV property
@@ -465,7 +460,7 @@ public class PropFindMethod extends WebDAVMethod
// Check if the client is requesting lock information
if (propName.equals(WebDAV.XML_LOCK_DISCOVERY)) // && metaData.isLocked())
{
generateLockDiscoveryResponse(xml, nodeRef, isDir);
generateLockDiscoveryResponse(xml, nodeInfo, isDir);
}
else if (propName.equals(WebDAV.XML_SUPPORTED_LOCK))
{
@@ -489,7 +484,7 @@ public class PropFindMethod extends WebDAVMethod
else if (propName.equals(WebDAV.XML_DISPLAYNAME))
{
// Get the node name
if (getRootNodeRef().equals(nodeRef))
if (getRootNodeRef().equals(nodeInfo.getNodeRef()))
{
// Output an empty name for the root node
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_SOURCE));
@@ -506,7 +501,7 @@ public class PropFindMethod extends WebDAVMethod
String name = typeConv.convert(String.class, davValue);
if (name == null || name.length() == 0)
{
logger.error("WebDAV name is null, value=" + davValue.getClass().getName() + ", node=" + nodeRef);
logger.error("WebDAV name is null, value=" + davValue.getClass().getName() + ", node=" + nodeInfo.getNodeRef());
}
xml.write(name);
}
@@ -563,7 +558,7 @@ public class PropFindMethod extends WebDAVMethod
// Output the etag
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_ETAG, WebDAV.XML_NS_GET_ETAG, nullAttr);
xml.write(getDAVHelper().makeETag(nodeRef));
xml.write(getDAVHelper().makeETag(nodeInfo));
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_ETAG, WebDAV.XML_NS_GET_ETAG);
}
else if (propName.equals(WebDAV.XML_GET_CONTENT_LENGTH))
@@ -616,11 +611,11 @@ public class PropFindMethod extends WebDAVMethod
else
{
// Look in the custom properties
// TODO: Custom properties lookup
// String qualifiedName = propNamespaceUri + WebDAV.NAMESPACE_SEPARATOR + propName;
String value = (String) getNodeService().getProperty(nodeRef, property.createQName());
// String qualifiedName = propNamespaceUri + WebDAV.NAMESPACE_SEPARATOR + propName;
String value = (String) nodeInfo.getProperties().get(property.createQName());
if (value == null)
{
propertiesNotFound.add(property);
@@ -699,11 +694,11 @@ public class PropFindMethod extends WebDAVMethod
* @param node NodeRef
* @param isDir boolean
*/
protected void generateAllPropertiesResponse(XMLWriter xml, NodeRef node, boolean isDir) throws Exception
protected void generateAllPropertiesResponse(XMLWriter xml, FileInfo nodeInfo, boolean isDir) throws Exception
{
// Get the properties for the node
Map<QName, Serializable> props = getNodeService().getProperties(node);
Map<QName, Serializable> props = nodeInfo.getProperties();
// Output the start of the properties element
@@ -714,7 +709,7 @@ public class PropFindMethod extends WebDAVMethod
// Generate a lock status report, if locked
generateLockDiscoveryResponse(xml, node, isDir);
generateLockDiscoveryResponse(xml, nodeInfo, isDir);
// Output the supported lock types
@@ -741,7 +736,7 @@ public class PropFindMethod extends WebDAVMethod
String name = typeConv.convert(String.class, davValue);
if (name == null || name.length() == 0)
{
logger.error("WebDAV name is null, value=" + davValue.getClass().getName() + ", node=" + node);
logger.error("WebDAV name is null, value=" + davValue.getClass().getName() + ", node=" + nodeInfo.getNodeRef());
}
xml.write(name);
}
@@ -801,7 +796,7 @@ public class PropFindMethod extends WebDAVMethod
// Output the etag
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_ETAG, WebDAV.XML_NS_GET_ETAG, nullAttr);
xml.write(getDAVHelper().makeETag(node));
xml.write(getDAVHelper().makeETag(nodeInfo));
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_ETAG, WebDAV.XML_NS_GET_ETAG);
}
@@ -850,7 +845,7 @@ public class PropFindMethod extends WebDAVMethod
* @param node NodeRef
* @param isDir boolean
*/
protected void generateFindPropertiesResponse(XMLWriter xml, NodeRef node, boolean isDir)
protected void generateFindPropertiesResponse(XMLWriter xml, FileInfo nodeInfo, boolean isDir)
{
try
{
@@ -908,14 +903,14 @@ public class PropFindMethod extends WebDAVMethod
* @param node NodeRef
* @param isDir boolean
*/
protected void generateLockDiscoveryResponse(XMLWriter xml, NodeRef node, boolean isDir) throws Exception
protected void generateLockDiscoveryResponse(XMLWriter xml, FileInfo nodeInfo, boolean isDir) throws Exception
{
// Output the lock status response
LockInfo lockInfo = getNodeLockInfo(node);
LockInfo lockInfo = getNodeLockInfo(nodeInfo);
if (lockInfo.isLocked())
{
generateLockDiscoveryXML(xml, node, lockInfo);
generateLockDiscoveryXML(xml, nodeInfo, lockInfo);
}
}

View File

@@ -353,24 +353,24 @@ public class WebDAVHelper
/**
* Make an ETag value for a node using the GUID and modify date/time
*/
public final String makeETag(NodeRef node)
public final String makeETag(FileInfo nodeInfo)
{
// Get the modify date/time property for the node
StringBuilder etag = new StringBuilder();
makeETagString(node, etag);
makeETagString(nodeInfo, etag);
return etag.toString();
}
/**
* Make an ETag value for a node using the GUID and modify date/time
*/
public final String makeQuotedETag(NodeRef node)
public final String makeQuotedETag(FileInfo nodeInfo)
{
StringBuilder etag = new StringBuilder();
etag.append("\"");
makeETagString(node, etag);
makeETagString(nodeInfo, etag);
etag.append("\"");
return etag.toString();
}
@@ -378,13 +378,13 @@ public class WebDAVHelper
/**
* Make an ETag value for a node using the GUID and modify date/time
*/
protected final void makeETagString(NodeRef node, StringBuilder etag)
protected final void makeETagString(FileInfo nodeInfo, StringBuilder etag)
{
// Get the modify date/time property for the node
Object modVal = getNodeService().getProperty(node, ContentModel.PROP_MODIFIED);
Object modVal = nodeInfo.getProperties().get(ContentModel.PROP_MODIFIED);
etag.append(node.getId());
etag.append(nodeInfo.getNodeRef().getId());
if ( modVal != null)
{

View File

@@ -737,10 +737,10 @@ public abstract class WebDAVMethod
* @param xml XMLWriter
* @param lockNode NodeRef
*/
protected void generateLockDiscoveryXML(XMLWriter xml, NodeRef lockNode, LockInfo lockInfo) throws Exception
protected void generateLockDiscoveryXML(XMLWriter xml, FileInfo lockNodeInfo, LockInfo lockInfo) throws Exception
{
String owner = (String) getNodeService().getProperty(lockNode, ContentModel.PROP_LOCK_OWNER);
generateLockDiscoveryXML(xml, lockNode, false, lockInfo.getScope(), lockInfo.getDepth(), WebDAV.makeLockToken(lockNode, owner), owner);
String owner = (String) lockNodeInfo.getProperties().get(ContentModel.PROP_LOCK_OWNER);
generateLockDiscoveryXML(xml, lockNodeInfo, false, lockInfo.getScope(), lockInfo.getDepth(), WebDAV.makeLockToken(lockNodeInfo.getNodeRef(), owner), owner);
}
/**
@@ -755,18 +755,14 @@ public abstract class WebDAVMethod
* @param owner String lock owner
*
*/
protected void generateLockDiscoveryXML(XMLWriter xml, NodeRef lockNode, boolean emptyNamespace, String scope, String depth, String lToken, String owner) throws Exception
protected void generateLockDiscoveryXML(XMLWriter xml, FileInfo lockNodeInfo, boolean emptyNamespace, String scope, String depth, String lToken, String owner) throws Exception
{
Attributes nullAttr= getDAVHelper().getNullAttributes();
String ns = emptyNamespace ? "" : WebDAV.DAV_NS;
if (lockNode != null)
if (lockNodeInfo != null)
{
// Get the lock details
NodeService nodeService = getNodeService();
Date expiryDate = (Date) nodeService.getProperty(lockNode, ContentModel.PROP_EXPIRY_DATE);
Date expiryDate = (Date) lockNodeInfo.getProperties().get(ContentModel.PROP_EXPIRY_DATE);
// Output the XML response
@@ -864,8 +860,8 @@ public abstract class WebDAVMethod
*/
protected LockInfo checkNode(FileInfo fileInfo, boolean ignoreShared, boolean lockMethod) throws WebDAVServerException
{
LockInfo nodeLockInfo = getNodeLockInfo(fileInfo.getNodeRef());
String nodeETag = getDAVHelper().makeQuotedETag(fileInfo.getNodeRef());
LockInfo nodeLockInfo = getNodeLockInfo(fileInfo);
String nodeETag = getDAVHelper().makeQuotedETag(fileInfo);
if (m_conditions == null)
@@ -1055,25 +1051,25 @@ public abstract class WebDAVMethod
* @param fileInfo node
* @return String Lock token
*/
protected LockInfo getNodeLockInfo(NodeRef nodeRef)
protected LockInfo getNodeLockInfo(FileInfo nodeInfo)
{
LockInfo lockInfo = new LockInfo();
NodeService nodeService = getNodeService();
LockService lockService = getLockService();
// Check if node is locked directly.
LockStatus lockSts = lockService.getLockStatus(nodeRef);
LockStatus lockSts = lockService.getLockStatus(nodeInfo.getNodeRef());
if (lockSts == LockStatus.LOCKED || lockSts == LockStatus.LOCK_OWNER)
{
String propOpaqueLockToken = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_OPAQUE_LOCK_TOKEN);
String propOpaqueLockToken = (String) nodeInfo.getProperties().get(WebDAVModel.PROP_OPAQUE_LOCK_TOKEN);
if (propOpaqueLockToken != null)
{
// Get lock depth
String depth = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_LOCK_DEPTH);
String depth = (String) nodeInfo.getProperties().get(WebDAVModel.PROP_LOCK_DEPTH);
//Get lock scope
String scope = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_LOCK_SCOPE);
String scope = (String) nodeInfo.getProperties().get(WebDAVModel.PROP_LOCK_SCOPE);
// Get shared lock tokens
String sharedLocks = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_SHARED_LOCK_TOKENS);
String sharedLocks = (String) nodeInfo.getProperties().get(WebDAVModel.PROP_SHARED_LOCK_TOKENS);
// Node has it's own Lock token.
// Store lock information to the lockInfo object
@@ -1088,13 +1084,13 @@ public abstract class WebDAVMethod
else
{
// No has no exclusive lock but can be locked with shared lock
String sharedLocks = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_SHARED_LOCK_TOKENS);
String sharedLocks = (String) nodeInfo.getProperties().get(WebDAVModel.PROP_SHARED_LOCK_TOKENS);
if (sharedLocks != null)
{
// Get lock depth
String depth = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_LOCK_DEPTH);
String depth = (String) nodeInfo.getProperties().get(WebDAVModel.PROP_LOCK_DEPTH);
//Get lock scope
String scope = (String) nodeService.getProperty(nodeRef, WebDAVModel.PROP_LOCK_SCOPE);
String scope = (String) nodeInfo.getProperties().get(WebDAVModel.PROP_LOCK_SCOPE);
// Node has it's own Lock token.
// Store lock information to the lockInfo object
@@ -1110,6 +1106,7 @@ public abstract class WebDAVMethod
// Node isn't locked directly and has no it's own Lock token.
// Try to search indirect lock.
NodeRef nodeRef = nodeInfo.getNodeRef();
NodeRef node = nodeRef;
while (true)
{

View File

@@ -1,4 +1,4 @@
/*
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
@@ -14,385 +14,393 @@
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.webdav;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Properties;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.UserTransaction;
import org.alfresco.repo.security.authentication.AuthenticationContext;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* Servlet that accepts WebDAV requests for the hub. The request is served by the hub's content
* repository framework and the response sent back using the WebDAV protocol.
*
* @author gavinc
*/
public class WebDAVServlet extends HttpServlet
{
private static final long serialVersionUID = 6900069445027527165L;
// Logging
private static Log logger = LogFactory.getLog("org.alfresco.webdav.protocol");
// Constants
public static final String WEBDAV_PREFIX = "webdav";
private static final String INTERNAL_SERVER_ERROR = "Internal Server Error: ";
// Init parameter names
private static final String BEAN_INIT_PARAMS = "webdav.initParams";
// Service registry, used by methods to find services to process requests
private ServiceRegistry m_serviceRegistry;
// Transaction service, each request is wrapped in a transaction
private TransactionService m_transactionService;
// WebDAV method handlers
protected Hashtable<String,Class<? extends WebDAVMethod>> m_davMethods;
// Root node
private MTNodesCache m_rootNodes;
// WebDAV helper class
private WebDAVHelper m_davHelper;
/**
* @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException
{
long startTime = 0;
if (logger.isInfoEnabled())
{
startTime = System.currentTimeMillis();
}
try
{
// Create the appropriate WebDAV method for the request and execute it
final WebDAVMethod method = createMethod(request, response);
if (method == null)
{
if ( logger.isErrorEnabled())
logger.error("WebDAV method not implemented - " + request.getMethod());
// Return an error status
response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
return;
}
else if (method.getRootNodeRef() == null)
{
if ( logger.isErrorEnabled())
logger.error("No root node for request");
// Return an error status
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
// Execute the WebDAV request, which must take care of its own transaction
method.execute();
}
catch (Throwable e)
{
if (!(e instanceof WebDAVServerException) && e.getCause() != null)
{
if (e.getCause() instanceof WebDAVServerException)
{
e = e.getCause();
}
}
// Work out how to handle the error
if (e instanceof WebDAVServerException)
{
WebDAVServerException error = (WebDAVServerException) e;
if (error.getCause() != null)
{
logger.error(INTERNAL_SERVER_ERROR, error.getCause());
}
if (logger.isDebugEnabled())
{
// Show what status code the method sent back
logger.debug(request.getMethod() + " is returning status code: " + error.getHttpStatusCode());
}
if (response.isCommitted())
{
logger.warn("Could not return the status code to the client as the response has already been committed!");
}
else
{
response.sendError(error.getHttpStatusCode());
}
}
else
{
logger.error(INTERNAL_SERVER_ERROR, e);
if (response.isCommitted())
{
logger.warn("Could not return the internal server error code to the client as the response has already been committed!");
}
else
{
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
}
finally
{
if (logger.isInfoEnabled())
{
logger.info(request.getMethod() + " took " + (System.currentTimeMillis()-startTime) + "ms to execute ["+request.getRequestURI()+"]");
}
}
}
/**
* Create a WebDAV method handler
*
* @param request HttpServletRequest
* @param response HttpServletResponse
* @return WebDAVMethod
*/
private WebDAVMethod createMethod(HttpServletRequest request, HttpServletResponse response)
{
// Get the type of the current request
String strHttpMethod = request.getMethod();
if (logger.isDebugEnabled())
logger.debug("WebDAV request " + strHttpMethod + " on path "
+ request.getRequestURI());
Class<? extends WebDAVMethod> methodClass = m_davMethods.get(strHttpMethod);
WebDAVMethod method = null;
if ( methodClass != null)
{
try
{
// Create the handler method
method = methodClass.newInstance();
NodeRef rootNodeRef = m_rootNodes.getNodeForCurrentTenant();
method.setDetails(request, response, m_davHelper, rootNodeRef);
}
catch (Exception ex)
{
// Debug
if ( logger.isDebugEnabled())
logger.debug(ex);
}
}
// Return the WebDAV method handler, or null if not supported
return method;
}
/**
* Initialize the servlet
*
* @param config ServletConfig
* @exception ServletException
*/
public void init(ServletConfig config) throws ServletException
{
super.init(config);
// Get service registry
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
// If no context has been initialised, exit silently so config changes can be made
if (context == null)
{
return;
}
// Get global configuration properties
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
WebDAVInitParameters initParams = (WebDAVInitParameters) wc.getBean(BEAN_INIT_PARAMS);
// Render this servlet permanently unavailable if its enablement property is not set
if (!initParams.getEnabled())
{
throw new UnavailableException("WebDAV not enabled.");
}
// Get root paths
String storeValue = initParams.getStoreName();
String rootPath = initParams.getRootPath();
// Get beans
m_serviceRegistry = (ServiceRegistry)context.getBean(ServiceRegistry.SERVICE_REGISTRY);
m_transactionService = m_serviceRegistry.getTransactionService();
TenantService tenantService = (TenantService) context.getBean("tenantService");
AuthenticationService authService = (AuthenticationService) context.getBean("authenticationService");
NodeService nodeService = (NodeService) context.getBean("NodeService");
SearchService searchService = (SearchService) context.getBean("SearchService");
NamespaceService namespaceService = (NamespaceService) context.getBean("NamespaceService");
// Create the WebDAV helper
m_davHelper = new WebDAVHelper(m_serviceRegistry, authService);
// Initialize the root node
initializeRootNode(storeValue, rootPath, context, nodeService, searchService, namespaceService, tenantService, m_transactionService);
// Create the WebDAV methods table
m_davMethods = new Hashtable<String, Class<? extends WebDAVMethod>>();
m_davMethods.put(WebDAV.METHOD_PROPFIND, PropFindMethod.class);
m_davMethods.put(WebDAV.METHOD_PROPPATCH, PropPatchMethod.class);
m_davMethods.put(WebDAV.METHOD_COPY, CopyMethod.class);
m_davMethods.put(WebDAV.METHOD_DELETE, DeleteMethod.class);
m_davMethods.put(WebDAV.METHOD_GET, GetMethod.class);
m_davMethods.put(WebDAV.METHOD_HEAD, HeadMethod.class);
m_davMethods.put(WebDAV.METHOD_LOCK, LockMethod.class);
m_davMethods.put(WebDAV.METHOD_MKCOL, MkcolMethod.class);
m_davMethods.put(WebDAV.METHOD_MOVE, MoveMethod.class);
m_davMethods.put(WebDAV.METHOD_OPTIONS, OptionsMethod.class);
m_davMethods.put(WebDAV.METHOD_POST, PostMethod.class);
m_davMethods.put(WebDAV.METHOD_PUT, PutMethod.class);
m_davMethods.put(WebDAV.METHOD_UNLOCK, UnlockMethod.class);
}
/**
* @param storeValue
* @param rootPath
* @param context
* @param nodeService
* @param searchService
* @param namespaceService
* @param tenantService
* @param m_transactionService
*/
private void initializeRootNode(String storeValue, String rootPath, WebApplicationContext context, NodeService nodeService, SearchService searchService,
NamespaceService namespaceService, TenantService tenantService, TransactionService m_transactionService)
{
// Use the system user as the authenticated context for the filesystem initialization
AuthenticationContext authComponent = (AuthenticationContext) context.getBean("authenticationContext");
authComponent.setSystemUserAsCurrentUser();
// Wrap the initialization in a transaction
UserTransaction tx = m_transactionService.getUserTransaction(true);
try
{
// Start the transaction
if (tx != null)
tx.begin();
m_rootNodes = new MTNodesCache(new StoreRef(storeValue), rootPath, nodeService, searchService, namespaceService, tenantService);
// Commit the transaction
tx.commit();
}
catch (Exception ex)
{
logger.error(ex);
}
finally
{
// Clear the current system user
authComponent.clearCurrentSecurityContext();
}
}
/**
* Bean to hold injected initialization parameters.
*
* @author Derek Hulley
* @since V3.5 Team
*/
public static class WebDAVInitParameters
{
private boolean enabled = false;
private String storeName;
private String rootPath;
public boolean getEnabled()
{
return enabled;
}
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
}
/**
* @return Returns the name of the store
* @throws ServletException if the store name was not set
*/
public String getStoreName() throws ServletException
{
if (!PropertyCheck.isValidPropertyString(storeName))
{
throw new ServletException("WebDAV missing 'storeName' value.");
}
return storeName;
}
public void setStoreName(String storeName)
{
this.storeName = storeName;
}
/**
* @return Returns the WebDAV root path within the store
* @throws ServletException if the root path was not set
*/
public String getRootPath() throws ServletException
{
if (!PropertyCheck.isValidPropertyString(rootPath))
{
throw new ServletException("WebDAV missing 'rootPath' value.");
}
return rootPath;
}
public void setRootPath(String rootPath)
{
this.rootPath = rootPath;
}
}
}
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.webdav;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Hashtable;
import java.util.Properties;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.UserTransaction;
import org.alfresco.repo.security.authentication.AuthenticationContext;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* Servlet that accepts WebDAV requests for the hub. The request is served by the hub's content
* repository framework and the response sent back using the WebDAV protocol.
*
* @author gavinc
*/
public class WebDAVServlet extends HttpServlet
{
private static final long serialVersionUID = 6900069445027527165L;
// Logging
private static Log logger = LogFactory.getLog("org.alfresco.webdav.protocol");
// Constants
public static final String WEBDAV_PREFIX = "webdav";
private static final String INTERNAL_SERVER_ERROR = "Internal Server Error: ";
// Init parameter names
private static final String BEAN_INIT_PARAMS = "webdav.initParams";
// Service registry, used by methods to find services to process requests
private ServiceRegistry m_serviceRegistry;
// Transaction service, each request is wrapped in a transaction
private TransactionService m_transactionService;
// WebDAV method handlers
protected Hashtable<String,Class<? extends WebDAVMethod>> m_davMethods;
// Root node
private MTNodesCache m_rootNodes;
// WebDAV helper class
private WebDAVHelper m_davHelper;
/**
* @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException
{
long startTime = 0;
if (logger.isInfoEnabled())
{
startTime = System.currentTimeMillis();
}
try
{
// Create the appropriate WebDAV method for the request and execute it
final WebDAVMethod method = createMethod(request, response);
if (method == null)
{
if ( logger.isErrorEnabled())
logger.error("WebDAV method not implemented - " + request.getMethod());
// Return an error status
response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
return;
}
else if (method.getRootNodeRef() == null)
{
if ( logger.isErrorEnabled())
logger.error("No root node for request");
// Return an error status
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
// Execute the WebDAV request, which must take care of its own transaction
method.execute();
}
catch (Throwable e)
{
if (!(e instanceof WebDAVServerException) && e.getCause() != null)
{
if (e.getCause() instanceof WebDAVServerException)
{
e = e.getCause();
}
}
// Work out how to handle the error
if (e instanceof WebDAVServerException)
{
WebDAVServerException error = (WebDAVServerException) e;
if (error.getCause() != null)
{
StringWriter writer = new StringWriter();
PrintWriter print = new PrintWriter(writer);
error.printStackTrace(print);
logger.error(print.toString(), e);
}
if (logger.isDebugEnabled())
{
// Show what status code the method sent back
logger.debug(request.getMethod() + " is returning status code: " + error.getHttpStatusCode());
}
if (response.isCommitted())
{
logger.warn("Could not return the status code to the client as the response has already been committed!");
}
else
{
response.sendError(error.getHttpStatusCode());
}
}
else
{
StringWriter writer = new StringWriter();
PrintWriter print = new PrintWriter(writer);
e.printStackTrace(print);
logger.error(print.toString(), e);
if (response.isCommitted())
{
logger.warn("Could not return the internal server error code to the client as the response has already been committed!");
}
else
{
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
}
finally
{
if (logger.isInfoEnabled())
{
logger.info(request.getMethod() + " took " + (System.currentTimeMillis()-startTime) + "ms to execute ["+request.getRequestURI()+"]");
}
}
}
/**
* Create a WebDAV method handler
*
* @param request HttpServletRequest
* @param response HttpServletResponse
* @return WebDAVMethod
*/
private WebDAVMethod createMethod(HttpServletRequest request, HttpServletResponse response)
{
// Get the type of the current request
String strHttpMethod = request.getMethod();
if (logger.isDebugEnabled())
logger.debug("WebDAV request " + strHttpMethod + " on path "
+ request.getRequestURI());
Class<? extends WebDAVMethod> methodClass = m_davMethods.get(strHttpMethod);
WebDAVMethod method = null;
if ( methodClass != null)
{
try
{
// Create the handler method
method = methodClass.newInstance();
NodeRef rootNodeRef = m_rootNodes.getNodeForCurrentTenant();
method.setDetails(request, response, m_davHelper, rootNodeRef);
}
catch (Exception ex)
{
// Debug
if ( logger.isDebugEnabled())
logger.debug(ex);
}
}
// Return the WebDAV method handler, or null if not supported
return method;
}
/**
* Initialize the servlet
*
* @param config ServletConfig
* @exception ServletException
*/
public void init(ServletConfig config) throws ServletException
{
super.init(config);
// Get service registry
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
// If no context has been initialised, exit silently so config changes can be made
if (context == null)
{
return;
}
// Get global configuration properties
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
WebDAVInitParameters initParams = (WebDAVInitParameters) wc.getBean(BEAN_INIT_PARAMS);
// Render this servlet permanently unavailable if its enablement property is not set
if (!initParams.getEnabled())
{
throw new UnavailableException("WebDAV not enabled.");
}
// Get root paths
String storeValue = initParams.getStoreName();
String rootPath = initParams.getRootPath();
// Get beans
m_serviceRegistry = (ServiceRegistry)context.getBean(ServiceRegistry.SERVICE_REGISTRY);
m_transactionService = m_serviceRegistry.getTransactionService();
TenantService tenantService = (TenantService) context.getBean("tenantService");
AuthenticationService authService = (AuthenticationService) context.getBean("authenticationService");
NodeService nodeService = (NodeService) context.getBean("NodeService");
SearchService searchService = (SearchService) context.getBean("SearchService");
NamespaceService namespaceService = (NamespaceService) context.getBean("NamespaceService");
// Create the WebDAV helper
m_davHelper = new WebDAVHelper(m_serviceRegistry, authService);
// Initialize the root node
initializeRootNode(storeValue, rootPath, context, nodeService, searchService, namespaceService, tenantService, m_transactionService);
// Create the WebDAV methods table
m_davMethods = new Hashtable<String, Class<? extends WebDAVMethod>>();
m_davMethods.put(WebDAV.METHOD_PROPFIND, PropFindMethod.class);
m_davMethods.put(WebDAV.METHOD_PROPPATCH, PropPatchMethod.class);
m_davMethods.put(WebDAV.METHOD_COPY, CopyMethod.class);
m_davMethods.put(WebDAV.METHOD_DELETE, DeleteMethod.class);
m_davMethods.put(WebDAV.METHOD_GET, GetMethod.class);
m_davMethods.put(WebDAV.METHOD_HEAD, HeadMethod.class);
m_davMethods.put(WebDAV.METHOD_LOCK, LockMethod.class);
m_davMethods.put(WebDAV.METHOD_MKCOL, MkcolMethod.class);
m_davMethods.put(WebDAV.METHOD_MOVE, MoveMethod.class);
m_davMethods.put(WebDAV.METHOD_OPTIONS, OptionsMethod.class);
m_davMethods.put(WebDAV.METHOD_POST, PostMethod.class);
m_davMethods.put(WebDAV.METHOD_PUT, PutMethod.class);
m_davMethods.put(WebDAV.METHOD_UNLOCK, UnlockMethod.class);
}
/**
* @param storeValue
* @param rootPath
* @param context
* @param nodeService
* @param searchService
* @param namespaceService
* @param tenantService
* @param m_transactionService
*/
private void initializeRootNode(String storeValue, String rootPath, WebApplicationContext context, NodeService nodeService, SearchService searchService,
NamespaceService namespaceService, TenantService tenantService, TransactionService m_transactionService)
{
// Use the system user as the authenticated context for the filesystem initialization
AuthenticationContext authComponent = (AuthenticationContext) context.getBean("authenticationContext");
authComponent.setSystemUserAsCurrentUser();
// Wrap the initialization in a transaction
UserTransaction tx = m_transactionService.getUserTransaction(true);
try
{
// Start the transaction
if (tx != null)
tx.begin();
m_rootNodes = new MTNodesCache(new StoreRef(storeValue), rootPath, nodeService, searchService, namespaceService, tenantService);
// Commit the transaction
tx.commit();
}
catch (Exception ex)
{
logger.error(ex);
}
finally
{
// Clear the current system user
authComponent.clearCurrentSecurityContext();
}
}
/**
* Bean to hold injected initialization parameters.
*
* @author Derek Hulley
* @since V3.5 Team
*/
public static class WebDAVInitParameters
{
private boolean enabled = false;
private String storeName;
private String rootPath;
public boolean getEnabled()
{
return enabled;
}
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
}
/**
* @return Returns the name of the store
* @throws ServletException if the store name was not set
*/
public String getStoreName() throws ServletException
{
if (!PropertyCheck.isValidPropertyString(storeName))
{
throw new ServletException("WebDAV missing 'storeName' value.");
}
return storeName;
}
public void setStoreName(String storeName)
{
this.storeName = storeName;
}
/**
* @return Returns the WebDAV root path within the store
* @throws ServletException if the root path was not set
*/
public String getRootPath() throws ServletException
{
if (!PropertyCheck.isValidPropertyString(rootPath))
{
throw new ServletException("WebDAV missing 'rootPath' value.");
}
return rootPath;
}
public void setRootPath(String rootPath)
{
this.rootPath = rootPath;
}
}
}