mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
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
407 lines
15 KiB
Java
407 lines
15 KiB
Java
/*
|
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
|
*
|
|
* This file is part of Alfresco
|
|
*
|
|
* Alfresco is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Alfresco 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 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.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;
|
|
}
|
|
}
|
|
}
|