diff --git a/config/alfresco/application-context-core.xml b/config/alfresco/application-context-core.xml
index 329f0c2fab..5e9b9851a9 100644
--- a/config/alfresco/application-context-core.xml
+++ b/config/alfresco/application-context-core.xml
@@ -43,5 +43,6 @@
+
diff --git a/config/alfresco/webdav-context.xml b/config/alfresco/webdav-context.xml
new file mode 100644
index 0000000000..25d83083be
--- /dev/null
+++ b/config/alfresco/webdav-context.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+ ${system.webdav.storeName}
+ ${system.webdav.rootPath}
+ ${system.webdav.servlet.enabled}
+
+
+
+
+
+
+
+
+ ${system.webdav.servlet.enabled}
+
+
+
+
\ No newline at end of file
diff --git a/source/java/org/alfresco/filesys/repo/ContentDiskDriver2.java b/source/java/org/alfresco/filesys/repo/ContentDiskDriver2.java
index 5494c84d10..2529adcb21 100644
--- a/source/java/org/alfresco/filesys/repo/ContentDiskDriver2.java
+++ b/source/java/org/alfresco/filesys/repo/ContentDiskDriver2.java
@@ -26,31 +26,18 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.InetAddress;
-import java.nio.channels.Channels;
import java.nio.charset.Charset;
import java.util.Date;
-import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
-import org.alfresco.filesys.alfresco.AlfrescoClientInfo;
import org.alfresco.filesys.alfresco.AlfrescoContext;
import org.alfresco.filesys.alfresco.AlfrescoDiskDriver;
-import org.alfresco.filesys.alfresco.AlfrescoNetworkFile;
-import org.alfresco.filesys.alfresco.DesktopAction;
-import org.alfresco.filesys.alfresco.DesktopActionTable;
-import org.alfresco.filesys.alfresco.DesktopParams;
-import org.alfresco.filesys.alfresco.DesktopResponse;
-import org.alfresco.filesys.alfresco.DesktopTarget;
import org.alfresco.filesys.alfresco.ExtendedDiskInterface;
-import org.alfresco.filesys.alfresco.IOControl;
-import org.alfresco.filesys.alfresco.IOControlHandler;
import org.alfresco.filesys.alfresco.PseudoFileOverlayImpl;
import org.alfresco.filesys.alfresco.RepositoryDiskInterface;
-import org.alfresco.filesys.alfresco.ShuffleCache;
-import org.alfresco.filesys.config.ServerConfigurationBean;
import org.alfresco.jlan.server.SrvSession;
import org.alfresco.jlan.server.core.DeviceContext;
import org.alfresco.jlan.server.core.DeviceContextException;
@@ -73,10 +60,7 @@ import org.alfresco.jlan.server.filesys.SearchContext;
import org.alfresco.jlan.server.filesys.SrvDiskInfo;
import org.alfresco.jlan.server.filesys.TreeConnection;
import org.alfresco.jlan.server.filesys.cache.FileState;
-import org.alfresco.jlan.server.filesys.cache.FileStateLockManager;
-import org.alfresco.jlan.server.filesys.pseudo.MemoryPseudoFile;
import org.alfresco.jlan.server.filesys.pseudo.PseudoFile;
-import org.alfresco.jlan.server.filesys.pseudo.PseudoFileInterface;
import org.alfresco.jlan.server.filesys.pseudo.PseudoFileList;
import org.alfresco.jlan.server.filesys.pseudo.PseudoNetworkFile;
import org.alfresco.jlan.server.filesys.quota.QuotaManager;
@@ -87,29 +71,19 @@ import org.alfresco.jlan.server.locking.OpLockInterface;
import org.alfresco.jlan.server.locking.OpLockManager;
import org.alfresco.jlan.smb.SMBException;
import org.alfresco.jlan.smb.SMBStatus;
-import org.alfresco.jlan.smb.nt.NTIOCtl;
import org.alfresco.jlan.smb.server.SMBServer;
-import org.alfresco.jlan.smb.server.SMBSrvSession;
-import org.alfresco.jlan.smb.server.disk.JavaNetworkFile;
-import org.alfresco.jlan.server.filesys.FileAttribute;
import org.alfresco.jlan.util.DataBuffer;
import org.alfresco.jlan.util.MemorySize;
import org.alfresco.model.ContentModel;
-import org.alfresco.repo.admin.SysAdminParams;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.encoding.ContentCharsetFinder;
import org.alfresco.repo.content.filestore.FileContentReader;
-import org.alfresco.repo.node.archive.NodeArchiveService;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.repo.security.authentication.AuthenticationContext;
-import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
-import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
-import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.lock.LockService;
-import org.alfresco.service.cmr.lock.LockType;
import org.alfresco.service.cmr.lock.NodeLockedException;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.ContentData;
@@ -125,7 +99,6 @@ import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.AuthenticationService;
-import org.alfresco.service.cmr.security.OwnableService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
@@ -133,7 +106,6 @@ import org.alfresco.util.PropertyCheck;
import org.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.james.mime4j.storage.TempFileStorageProvider;
import org.springframework.extensions.config.ConfigElement;
/**
@@ -762,19 +734,20 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD
try
{
String searchFileSpec = searchPath;
-
+
NodeRef searchRootNodeRef = ctx.getRootNode();
String[] paths = FileName.splitPath(searchPath);
+ String dotPath = paths[0];
// lookup parent directory
- NodeRef dirNodeRef = getNodeForPath(tree, paths[0]);
+ NodeRef dirNodeRef = getNodeForPath(tree, dotPath);
if(dirNodeRef != null)
{
searchRootNodeRef = dirNodeRef;
searchFileSpec = paths[1];
}
-
+
// Convert the all files wildcard
if ( searchFileSpec.equals( "*.*"))
{
@@ -815,10 +788,31 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD
}
DotDotContentSearchContext searchCtx = new DotDotContentSearchContext(getCifsHelper(), results, searchFileSpec, pseudoList, paths[0]);
+
+ FileInfo dotInfo = getCifsHelper().getFileInformation(searchRootNodeRef, false, isLockedFilesAsOffline);
- // Need to set dot and dotdot
- //searchCtx.setDotInfo(finfo);
- //searchCtx.setDotDotInfo(finfo);
+ if ( searchPath.equals( FileName.DOS_SEPERATOR_STR)) {
+ // Searching the root folder, re-use the search folder file information for the '..' pseudo entry
+ FileInfo dotDotInfo = new FileInfo();
+ dotDotInfo.copyFrom(dotInfo);
+ searchCtx.setDotInfo(dotInfo);
+ searchCtx.setDotDotInfo( dotDotInfo);
+ }
+ else
+ {
+ String[] parent = FileName.splitPath(dotPath);
+ NodeRef parentNodeRef = getNodeForPath(tree, parent[0]);
+ if(parentNodeRef != null)
+ {
+ FileInfo dotDotInfo = getCifsHelper().getFileInformation(parentNodeRef, false, isLockedFilesAsOffline);
+ searchCtx.setDotDotInfo(dotDotInfo);
+ }
+
+ // Searching a normal, non root, folder
+ // Need to set dot and dotdot
+ searchCtx.setDotInfo(dotInfo);
+
+ }
// Debug
if (logger.isDebugEnabled())
diff --git a/source/java/org/alfresco/repo/rendition/MockedTestServiceRegistry.java b/source/java/org/alfresco/repo/rendition/MockedTestServiceRegistry.java
index 59f6a47a4c..cd3b3862a4 100644
--- a/source/java/org/alfresco/repo/rendition/MockedTestServiceRegistry.java
+++ b/source/java/org/alfresco/repo/rendition/MockedTestServiceRegistry.java
@@ -76,6 +76,7 @@ import org.alfresco.service.cmr.thumbnail.ThumbnailService;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.cmr.view.ExporterService;
import org.alfresco.service.cmr.view.ImporterService;
+import org.alfresco.service.cmr.webdav.WebDavService;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.service.namespace.NamespaceService;
@@ -548,4 +549,12 @@ public class MockedTestServiceRegistry implements ServiceRegistry
// TODO Auto-generated method stub
return null;
}
+
+
+ @Override
+ public WebDavService getWebDavService()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
}
diff --git a/source/java/org/alfresco/repo/service/ServiceDescriptorRegistry.java b/source/java/org/alfresco/repo/service/ServiceDescriptorRegistry.java
index d30dd28440..9fd2c76d31 100644
--- a/source/java/org/alfresco/repo/service/ServiceDescriptorRegistry.java
+++ b/source/java/org/alfresco/repo/service/ServiceDescriptorRegistry.java
@@ -74,6 +74,7 @@ import org.alfresco.service.cmr.thumbnail.ThumbnailService;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.cmr.view.ExporterService;
import org.alfresco.service.cmr.view.ImporterService;
+import org.alfresco.service.cmr.webdav.WebDavService;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.service.namespace.NamespaceService;
@@ -637,4 +638,10 @@ public class ServiceDescriptorRegistry
final String beanName = "sysAdminParams";
return (SysAdminParams) beanFactory.getBean(beanName);
}
+
+ @Override
+ public WebDavService getWebDavService()
+ {
+ return (WebDavService)getService(WEBDAV_SERVICE);
+ }
}
diff --git a/source/java/org/alfresco/repo/template/BaseContentNode.java b/source/java/org/alfresco/repo/template/BaseContentNode.java
index 1d1fa30936..baf660b8f4 100644
--- a/source/java/org/alfresco/repo/template/BaseContentNode.java
+++ b/source/java/org/alfresco/repo/template/BaseContentNode.java
@@ -39,6 +39,7 @@ import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
+import org.alfresco.service.cmr.webdav.WebDavService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.util.ISO9075;
@@ -422,31 +423,8 @@ public abstract class BaseContentNode implements TemplateContent
*/
public String getWebdavUrl()
{
- try
- {
- if (getIsContainer() || getIsDocument())
- {
- List paths = this.services.getFileFolderService().getNamePath(null, getNodeRef());
-
- // build up the webdav url
- StringBuilder path = new StringBuilder(128);
- path.append("/webdav");
-
- // build up the path skipping the first path as it is the root folder
- for (int i=1; i.
+ */
+package org.alfresco.repo.webdav;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.alfresco.repo.security.authentication.AuthenticationContext;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.tenant.TenantService;
+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.namespace.NamespaceService;
+import org.alfresco.util.PropertyCheck;
+
+/**
+ * In-memory cache that stores nodeRefs per tenant.
+ * It is initialized using path to node and allows to retrieve nodeRef for current tenant.
+ *
+ * @author Stas Sokolovsky
+ * @author Mark Rogers
+ */
+public class MTNodesCache2
+{
+ private boolean enabled = false;
+
+ private NodeService nodeService;
+
+ private SearchService searchService;
+
+ private NamespaceService namespaceService;
+
+ private TenantService tenantService;
+
+ private Map nodesCache = new ConcurrentHashMap();
+
+ private NodeRef defaultNode = null;
+
+ private String storeName;
+ private String rootPath;
+
+ public void init()
+ {
+ PropertyCheck.mandatory(this, "nodeService", getNodeService());
+ PropertyCheck.mandatory(this, "searchService", getSearchService());
+ PropertyCheck.mandatory(this, "namespaceService", getNamespaceService());
+ PropertyCheck.mandatory(this, "tenantService", getTenantService());
+
+ if(!enabled)
+ {
+ return;
+ }
+
+ PropertyCheck.mandatory(this, "storeName", storeName);
+ PropertyCheck.mandatory(this, "rootPath", rootPath);
+
+ AuthenticationUtil.setRunAsUserSystem();
+ try
+ {
+ StoreRef storeRef = new StoreRef(storeName);
+
+ if (nodeService.exists(storeRef) == false)
+ {
+ throw new RuntimeException("No store for path: " + storeName);
+ }
+
+ NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
+
+ List nodeRefs = getSearchService().selectNodes(storeRootNodeRef, rootPath, null, getNamespaceService(), 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);
+ }
+
+ defaultNode = nodeRefs.get(0);
+ }
+ finally
+ {
+ AuthenticationUtil.clearCurrentSecurityContext();
+ }
+ }
+
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+ public NodeService getNodeService()
+ {
+ return nodeService;
+ }
+
+ /**
+ * Returns nodeRef for current user tenant
+ *
+ * @return nodeRef Node Reference
+ */
+ public NodeRef getNodeForCurrentTenant()
+ {
+ NodeRef result = null;
+
+ if (!getTenantService().isEnabled())
+ {
+ result = defaultNode;
+ }
+ else
+ {
+ String domain = getTenantService().getCurrentUserDomain();
+ if (nodesCache.containsKey(domain))
+ {
+ result = nodesCache.get(domain);
+ }
+ else
+ {
+ result = getTenantService().getRootNode(nodeService, getSearchService(), getNamespaceService(), rootPath, defaultNode);
+ nodesCache.put(domain, result);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * @return Returns the name of the store
+ * @throws ServletException if the store name was not set
+ */
+ public String getStoreName()
+ {
+ 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()
+ {
+ return rootPath;
+ }
+ public void setRootPath(String rootPath)
+ {
+ this.rootPath = rootPath;
+ }
+
+ public void setSearchService(SearchService searchService)
+ {
+ this.searchService = searchService;
+ }
+
+ public SearchService getSearchService()
+ {
+ return searchService;
+ }
+
+ public void setNamespaceService(NamespaceService namespaceService)
+ {
+ this.namespaceService = namespaceService;
+ }
+
+ public NamespaceService getNamespaceService()
+ {
+ return namespaceService;
+ }
+
+ public void setTenantService(TenantService tenantService)
+ {
+ this.tenantService = tenantService;
+ }
+
+ public TenantService getTenantService()
+ {
+ return tenantService;
+ }
+ public boolean getEnabled()
+ {
+ return enabled;
+ }
+ public void setEnabled(boolean enabled)
+ {
+ this.enabled = enabled;
+ }
+
+
+
+}
diff --git a/source/java/org/alfresco/repo/webdav/WebDavServiceImpl.java b/source/java/org/alfresco/repo/webdav/WebDavServiceImpl.java
new file mode 100644
index 0000000000..abcd090dfc
--- /dev/null
+++ b/source/java/org/alfresco/repo/webdav/WebDavServiceImpl.java
@@ -0,0 +1,174 @@
+/*
+ * 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 .
+ */
+package org.alfresco.repo.webdav;
+
+import java.util.List;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.model.FileFolderService;
+import org.alfresco.service.cmr.model.FileInfo;
+import org.alfresco.service.cmr.model.FileNotFoundException;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.webdav.WebDavService;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.util.PropertyCheck;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.extensions.surf.util.URLEncoder;
+
+/**
+ * The WebDav client is used by the repository to generate webdav URLs
+ *
+ * This is a bog standard spring bean for the repo side of WebDav.
+ *
+ * @See org.alfresco.repo.webdav.WebDavServlet the server side of webdav.
+ *
+ * @author mrogers
+ */
+public class WebDavServiceImpl implements WebDavService
+{
+ private boolean enabled = false;
+
+
+ private NodeService nodeService;
+ private DictionaryService dictionaryService;
+ private FileFolderService fileFolderService;
+
+
+ private static Log logger = LogFactory.getLog(WebDavServiceImpl.class);
+
+ // Root nodes
+ private MTNodesCache2 rootNode;
+
+ public static final String WEBDAV_PREFIX = "webdav";
+
+ public boolean getEnabled()
+ {
+ return enabled;
+ }
+ public void setEnabled(boolean enabled)
+ {
+ this.enabled = enabled;
+ }
+
+ public void init()
+ {
+ PropertyCheck.mandatory(this, "nodeService", getNodeService());
+ PropertyCheck.mandatory(this, "dictionaryService", getDictionaryService());
+ PropertyCheck.mandatory(this, "fileFolderService", getFileFolderService());
+ PropertyCheck.mandatory(this, "rootNode", getRootNode());
+ }
+
+ /**
+ * Get the WebDavUrl for the specified nodeRef
+ *
+ * @param nodeRef the node that the webdav URL (or null)
+ * @return the URL of the node in webdav or "" if a URL cannot be built.
+ */
+ public String getWebdavUrl(NodeRef nodeRef)
+ {
+ if(!enabled)
+ {
+ return "";
+ }
+
+ try
+ {
+ QName typeName = nodeService.getType(nodeRef);
+
+ if (getIsContainer(typeName) || getIsDocument(typeName))
+ {
+ List paths = fileFolderService.getNamePath(getRootNode().getNodeForCurrentTenant(), nodeRef);
+
+ // build up the webdav url
+ StringBuilder path = new StringBuilder(128);
+ path.append("/" + WEBDAV_PREFIX);
+
+ // build up the path skipping the first path as it is the root folder
+ for (int i=1; i.
+ */
+package org.alfresco.service.cmr.webdav;
+
+import org.alfresco.service.cmr.repository.NodeRef;
+
+public interface WebDavService
+{
+ /**
+ * Get the WebDavUrl for the specified nodeRef
+ * @param nodeRef the node that the webdav URL (or null)
+ * @return the URL of the node in webdav or "" if a URL cannot be built.
+ */
+ public String getWebdavUrl(NodeRef nodeRef);
+
+}