diff --git a/source/java/org/alfresco/repo/webdav/ActivityPoster.java b/source/java/org/alfresco/repo/webdav/ActivityPoster.java index 17d359441c..3405d1d07b 100644 --- a/source/java/org/alfresco/repo/webdav/ActivityPoster.java +++ b/source/java/org/alfresco/repo/webdav/ActivityPoster.java @@ -41,5 +41,6 @@ public interface ActivityPoster String siteId, String tenantDomain, String parentPath, + FileInfo parentNodeInfo, FileInfo contentNodeInfo) throws WebDAVServerException; } diff --git a/source/java/org/alfresco/repo/webdav/ActivityPosterImpl.java b/source/java/org/alfresco/repo/webdav/ActivityPosterImpl.java index b9e4ffbeee..acabdd92d7 100644 --- a/source/java/org/alfresco/repo/webdav/ActivityPosterImpl.java +++ b/source/java/org/alfresco/repo/webdav/ActivityPosterImpl.java @@ -20,15 +20,11 @@ package org.alfresco.repo.webdav; import javax.servlet.http.HttpServletResponse; -import org.alfresco.model.ContentModel; -import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.activities.ActivityType; import org.alfresco.repo.tenant.TenantService; import org.alfresco.service.cmr.activities.ActivityService; import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.util.Pair; import org.json.JSONException; import org.json.JSONObject; @@ -40,13 +36,8 @@ import org.json.JSONObject; */ public class ActivityPosterImpl implements ActivityPoster { - private static final String FILE_ADDED = "org.alfresco.documentlibrary.file-added"; - private static final String FILE_UPDATED = "org.alfresco.documentlibrary.file-updated"; - private static final String FILE_DELETED = "org.alfresco.documentlibrary.file-deleted"; private String appTool; private ActivityService activityService; - private NodeService nodeService; - private PersonService personService; /** @@ -64,12 +55,10 @@ public class ActivityPosterImpl implements ActivityPoster * @param nodeService * @param personService */ - public ActivityPosterImpl(String appTool, ActivityService activityService, NodeService nodeService, PersonService personService) + public ActivityPosterImpl(String appTool, ActivityService activityService) { this.appTool = appTool; this.activityService = activityService; - this.nodeService = nodeService; - this.personService = personService; } @@ -82,7 +71,7 @@ public class ActivityPosterImpl implements ActivityPoster String tenantDomain, FileInfo contentNodeInfo) throws WebDAVServerException { - postFileActivity(FILE_ADDED, siteId, tenantDomain, null, contentNodeInfo); + postFileActivity(ActivityType.FILE_ADDED, siteId, tenantDomain, null, null, contentNodeInfo); } /** @@ -94,7 +83,7 @@ public class ActivityPosterImpl implements ActivityPoster String tenantDomain, FileInfo contentNodeInfo) throws WebDAVServerException { - postFileActivity(FILE_UPDATED, siteId, tenantDomain, null, contentNodeInfo); + postFileActivity(ActivityType.FILE_UPDATED, siteId, tenantDomain, null, null, contentNodeInfo); } /** @@ -105,9 +94,10 @@ public class ActivityPosterImpl implements ActivityPoster String siteId, String tenantDomain, String parentPath, + FileInfo parentNodeInfo, FileInfo contentNodeInfo) throws WebDAVServerException { - postFileActivity(FILE_DELETED, siteId, tenantDomain, parentPath, contentNodeInfo); + postFileActivity(ActivityType.FILE_DELETED, siteId, tenantDomain, parentPath, parentNodeInfo.getNodeRef(), contentNodeInfo); } @@ -116,14 +106,13 @@ public class ActivityPosterImpl implements ActivityPoster String siteId, String tenantDomain, String parentPath, + NodeRef parentNodeRef, FileInfo contentNodeInfo) throws WebDAVServerException { - Pair personName = getPersonName(); - final String firstName = personName.getFirst(); - final String lastName = personName.getSecond(); - final String fileName = contentNodeInfo.getName(); - final NodeRef nodeRef = contentNodeInfo.getNodeRef(); - JSONObject json = createActivityJSON(tenantDomain, parentPath, nodeRef, firstName, lastName, fileName); + String fileName = contentNodeInfo.getName(); + NodeRef nodeRef = contentNodeInfo.getNodeRef(); + + JSONObject json = createActivityJSON(tenantDomain, parentPath, parentNodeRef, nodeRef, fileName); activityService.postActivity( activityType, @@ -138,8 +127,6 @@ public class ActivityPosterImpl implements ActivityPoster * * @param tenantDomain * @param nodeRef - * @param firstName - * @param lastName * @param fileName * @throws WebDAVServerException * @return JSONObject @@ -147,19 +134,25 @@ public class ActivityPosterImpl implements ActivityPoster private JSONObject createActivityJSON( String tenantDomain, String parentPath, + NodeRef parentNodeRef, NodeRef nodeRef, - String firstName, - String lastName, String fileName) throws WebDAVServerException { JSONObject json = new JSONObject(); try { json.put("nodeRef", nodeRef); + + if (parentNodeRef != null) + { + // Used for deleted files. + json.put("parentNodeRef", parentNodeRef); + } + if (parentPath != null) { // Used for deleted files. - json.put("page", "documentlibrary?path=" + parentPath); + json.put("page", "documentlibrary?path=" + parentPath); } else { @@ -167,8 +160,7 @@ public class ActivityPosterImpl implements ActivityPoster json.put("page", "document-details?nodeRef=" + nodeRef); } json.put("title", fileName); - json.put("firstName", firstName); - json.put("lastName", lastName); + if (!tenantDomain.equals(TenantService.DEFAULT_DOMAIN)) { // Only used in multi-tenant setups. @@ -183,26 +175,6 @@ public class ActivityPosterImpl implements ActivityPoster return json; } - /** - * Creates the tuple (firstName, lastName) for the current user. - * - * @return Pair<String, String> - */ - private Pair getPersonName() - { - String firstName = ""; - String lastName = ""; - String userName = AuthenticationUtil.getFullyAuthenticatedUser(); - NodeRef person = personService.getPerson(userName); - if (person != null) - { - firstName = (String) nodeService.getProperty(person, ContentModel.PROP_FIRSTNAME); - lastName = (String) nodeService.getProperty(person, ContentModel.PROP_LASTNAME); - } - - return new Pair(firstName, lastName); - } - public void setAppTool(String appTool) { this.appTool = appTool; @@ -212,14 +184,4 @@ public class ActivityPosterImpl implements ActivityPoster { this.activityService = activityService; } - - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - - public void setPersonService(PersonService personService) - { - this.personService = personService; - } } diff --git a/source/java/org/alfresco/repo/webdav/DeleteMethod.java b/source/java/org/alfresco/repo/webdav/DeleteMethod.java index e351d9e5c1..978ec02f83 100644 --- a/source/java/org/alfresco/repo/webdav/DeleteMethod.java +++ b/source/java/org/alfresco/repo/webdav/DeleteMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -146,7 +146,7 @@ public class DeleteMethod extends WebDAVMethod implements ActivityPostProducer String parentPath = "/"; try { - parentPath = getDAVHelper().getPathFromNode(documentLibrary, parent.getNodeRef()); + parentPath = getDAVHelper().getPathFromNode(documentLibrary, parent.getNodeRef()); } catch (FileNotFoundException error) { @@ -156,7 +156,7 @@ public class DeleteMethod extends WebDAVMethod implements ActivityPostProducer } } - activityPoster.postFileDeleted(siteId, tenantDomain, parentPath, deletedFile); + activityPoster.postFileDeleted(siteId, tenantDomain, parentPath, parent, deletedFile); } } diff --git a/source/java/org/alfresco/repo/webdav/WebDAVServlet.java b/source/java/org/alfresco/repo/webdav/WebDAVServlet.java index 60e6dec469..e85b957a9e 100644 --- a/source/java/org/alfresco/repo/webdav/WebDAVServlet.java +++ b/source/java/org/alfresco/repo/webdav/WebDAVServlet.java @@ -1,488 +1,486 @@ -/* - * Copyright (C) 2005-2011 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 . - */ -package org.alfresco.repo.webdav; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Hashtable; -import java.util.List; - -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.cache.SimpleCache; -import org.alfresco.repo.security.authentication.AuthenticationContext; -import org.alfresco.repo.tenant.TenantService; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.activities.ActivityService; -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.cmr.security.PersonService; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.transaction.TransactionService; -import org.alfresco.util.FileFilterMode; -import org.alfresco.util.FileFilterMode.Client; -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 serviceRegistry; - - private TransactionService transactionService; - private static TenantService tenantService; - private static NodeService nodeService; - private static SearchService searchService; - private static NamespaceService namespaceService; - - // WebDAV method handlers - protected Hashtable> m_davMethods; - - // note: cache is tenant-aware (if using EhCacheAdapter shared cache) - - private static SimpleCache singletonCache; // eg. for webdavRootNodeRef - private static final String KEY_WEBDAV_ROOT_NODEREF = "key.webdavRoot.noderef"; - - private static String rootPath; - - private static NodeRef defaultRootNode; // for default domain - - // WebDAV helper class - private WebDAVHelper m_davHelper; - private ActivityPoster activityPoster; - - /** - * @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(); - } - - FileFilterMode.setClient(Client.webdav); - - 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()+"]"); - } - - FileFilterMode.clearClient(); - } - } - - /** - * Create a WebDAV method handler - * - * @param request HttpServletRequest - * @param response HttpServletResponse - * @return WebDAVMethod - */ - protected 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 methodClass = m_davMethods.get(strHttpMethod); - WebDAVMethod method = null; - - if (methodClass != null) - { - try - { - // Create the handler method - method = methodClass.newInstance(); - method.setDetails(request, response, m_davHelper, getRootNodeRef()); - - // A very few WebDAV methods produce activity posts. - if (method instanceof ActivityPostProducer) - { - ActivityPostProducer activityPostProducer = (ActivityPostProducer) method; - activityPostProducer.setActivityPoster(activityPoster); - } - } - catch (Exception ex) - { - // Debug - - if ( logger.isDebugEnabled()) - logger.debug(ex); - } - } - - // Return the WebDAV method handler, or null if not supported - - return method; - } - - private static NodeRef getRootNodeRef() - { - NodeRef rootNodeRef = singletonCache.get(KEY_WEBDAV_ROOT_NODEREF); - - if (rootNodeRef == null) - { - rootNodeRef = tenantService.getRootNode(nodeService, searchService, namespaceService, rootPath, defaultRootNode); - singletonCache.put(KEY_WEBDAV_ROOT_NODEREF, rootNodeRef); - } - - return rootNodeRef; - } - - /** - * Initialize the servlet - * - * @param config ServletConfig - * @exception ServletException - */ - @SuppressWarnings("unchecked") - 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(); - - rootPath = initParams.getRootPath(); - - // Get beans - - serviceRegistry = (ServiceRegistry)context.getBean(ServiceRegistry.SERVICE_REGISTRY); - - transactionService = serviceRegistry.getTransactionService(); - tenantService = (TenantService) context.getBean("tenantService"); - - AuthenticationService authService = (AuthenticationService) context.getBean("authenticationService"); - - nodeService = (NodeService) context.getBean("NodeService"); - searchService = (SearchService) context.getBean("SearchService"); - namespaceService = (NamespaceService) context.getBean("NamespaceService"); - ActivityService activityService = (ActivityService) context.getBean("activityService"); - PersonService personService = serviceRegistry.getPersonService(); - singletonCache = (SimpleCache)context.getBean("immutableSingletonCache"); - - // Collaborator used by WebDAV methods to create activity posts. - activityPoster = new ActivityPosterImpl("WebDAV", activityService, nodeService, personService); - - // Create the WebDAV helper - m_davHelper = (WebDAVHelper) context.getBean("webDAVHelper"); - - // Initialize the root node - initializeRootNode(storeValue, rootPath, context, nodeService, searchService, namespaceService, tenantService, transactionService); - - // Create the WebDAV methods table - - m_davMethods = new Hashtable>(); - - 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); - } - +/* + * Copyright (C) 2005-2012 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 . + */ +package org.alfresco.repo.webdav; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Hashtable; +import java.util.List; + +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.cache.SimpleCache; +import org.alfresco.repo.security.authentication.AuthenticationContext; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.activities.ActivityService; +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.FileFilterMode; +import org.alfresco.util.FileFilterMode.Client; +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 serviceRegistry; + + private TransactionService transactionService; + private static TenantService tenantService; + private static NodeService nodeService; + private static SearchService searchService; + private static NamespaceService namespaceService; + + // WebDAV method handlers + protected Hashtable> m_davMethods; + + // note: cache is tenant-aware (if using EhCacheAdapter shared cache) + + private static SimpleCache singletonCache; // eg. for webdavRootNodeRef + private static final String KEY_WEBDAV_ROOT_NODEREF = "key.webdavRoot.noderef"; + + private static String rootPath; + + private static NodeRef defaultRootNode; // for default domain + + // WebDAV helper class + private WebDAVHelper m_davHelper; + private ActivityPoster activityPoster; + + /** + * @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(); + } + + FileFilterMode.setClient(Client.webdav); + + 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()+"]"); + } + + FileFilterMode.clearClient(); + } + } + + /** + * Create a WebDAV method handler + * + * @param request HttpServletRequest + * @param response HttpServletResponse + * @return WebDAVMethod + */ + protected 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 methodClass = m_davMethods.get(strHttpMethod); + WebDAVMethod method = null; + + if (methodClass != null) + { + try + { + // Create the handler method + method = methodClass.newInstance(); + method.setDetails(request, response, m_davHelper, getRootNodeRef()); + + // A very few WebDAV methods produce activity posts. + if (method instanceof ActivityPostProducer) + { + ActivityPostProducer activityPostProducer = (ActivityPostProducer) method; + activityPostProducer.setActivityPoster(activityPoster); + } + } + catch (Exception ex) + { + // Debug + + if ( logger.isDebugEnabled()) + logger.debug(ex); + } + } + + // Return the WebDAV method handler, or null if not supported + + return method; + } + + private static NodeRef getRootNodeRef() + { + NodeRef rootNodeRef = singletonCache.get(KEY_WEBDAV_ROOT_NODEREF); + + if (rootNodeRef == null) + { + rootNodeRef = tenantService.getRootNode(nodeService, searchService, namespaceService, rootPath, defaultRootNode); + singletonCache.put(KEY_WEBDAV_ROOT_NODEREF, rootNodeRef); + } + + return rootNodeRef; + } + + /** + * Initialize the servlet + * + * @param config ServletConfig + * @exception ServletException + */ + @SuppressWarnings("unchecked") + 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(); + + rootPath = initParams.getRootPath(); + + // Get beans + + serviceRegistry = (ServiceRegistry)context.getBean(ServiceRegistry.SERVICE_REGISTRY); + + transactionService = serviceRegistry.getTransactionService(); + tenantService = (TenantService) context.getBean("tenantService"); + + AuthenticationService authService = (AuthenticationService) context.getBean("authenticationService"); + + nodeService = (NodeService) context.getBean("NodeService"); + searchService = (SearchService) context.getBean("SearchService"); + namespaceService = (NamespaceService) context.getBean("NamespaceService"); + ActivityService activityService = (ActivityService) context.getBean("activityService"); + singletonCache = (SimpleCache)context.getBean("immutableSingletonCache"); + + // Collaborator used by WebDAV methods to create activity posts. + activityPoster = new ActivityPosterImpl("WebDAV", activityService); + + // Create the WebDAV helper + m_davHelper = (WebDAVHelper) context.getBean("webDAVHelper"); + + // Initialize the root node + initializeRootNode(storeValue, rootPath, context, nodeService, searchService, namespaceService, tenantService, transactionService); + + // Create the WebDAV methods table + + m_davMethods = new Hashtable>(); + + 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); + } + protected WebDAVHelper getDAVHelper() { return m_davHelper; } - - /** - * @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(); - - StoreRef storeRef = new StoreRef(storeValue); - - if (nodeService.exists(storeRef) == false) - { - throw new RuntimeException("No store for path: " + storeRef); - } - - NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef); - - List nodeRefs = searchService.selectNodes(storeRootNodeRef, rootPath, null, namespaceService, false); - - if (nodeRefs.size() > 1) - { - throw new RuntimeException("Multiple possible children for : \n" + " path: " + rootPath + "\n" + " results: " + nodeRefs); - } - else if (nodeRefs.size() == 0) - { - throw new RuntimeException("Node is not found for : \n" + " root path: " + rootPath); - } - - defaultRootNode = nodeRefs.get(0); - - // Commit the transaction - if (tx != null) - tx.commit(); - } - catch (Exception ex) - { - logger.error(ex); - } - finally - { - // Clear the current system user - - authComponent.clearCurrentSecurityContext(); - } - } - - /** - * - * @return root node for WebDAV - */ - public static NodeRef getWebdavRootNode() - { - return getRootNodeRef(); - } - - /** - * 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; + + /** + * @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(); + + StoreRef storeRef = new StoreRef(storeValue); + + if (nodeService.exists(storeRef) == false) + { + throw new RuntimeException("No store for path: " + storeRef); + } + + NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef); + + List nodeRefs = searchService.selectNodes(storeRootNodeRef, rootPath, null, namespaceService, false); + + if (nodeRefs.size() > 1) + { + throw new RuntimeException("Multiple possible children for : \n" + " path: " + rootPath + "\n" + " results: " + nodeRefs); + } + else if (nodeRefs.size() == 0) + { + throw new RuntimeException("Node is not found for : \n" + " root path: " + rootPath); + } + + defaultRootNode = nodeRefs.get(0); + + // Commit the transaction + if (tx != null) + tx.commit(); + } + catch (Exception ex) + { + logger.error(ex); + } + finally + { + // Clear the current system user + + authComponent.clearCurrentSecurityContext(); + } + } + + /** + * + * @return root node for WebDAV + */ + public static NodeRef getWebdavRootNode() + { + return getRootNodeRef(); + } + + /** + * 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; private String urlPathPrefix; - 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; - } + 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; + } /** * Get the path prefix that generated URLs should exhibit, e.g. @@ -517,5 +515,5 @@ public class WebDAVServlet extends HttpServlet { this.urlPathPrefix = urlPathPrefix; } - } -} + } +}