diff --git a/source/java/org/alfresco/filesys/ServerConfigurationBean.java b/source/java/org/alfresco/filesys/ServerConfigurationBean.java index b2b6919cfc..5a453ca5a5 100644 --- a/source/java/org/alfresco/filesys/ServerConfigurationBean.java +++ b/source/java/org/alfresco/filesys/ServerConfigurationBean.java @@ -88,6 +88,7 @@ import org.alfresco.filesys.alfresco.AlfrescoClientInfoFactory; import org.alfresco.filesys.alfresco.DesktopAction; import org.alfresco.filesys.alfresco.DesktopActionException; import org.alfresco.filesys.alfresco.DesktopActionTable; +import org.alfresco.filesys.alfresco.HomeShareMapper; import org.alfresco.filesys.avm.AVMContext; import org.alfresco.filesys.avm.AVMDiskDriver; import org.alfresco.filesys.repo.ContentContext; @@ -2422,6 +2423,29 @@ public class ServerConfigurationBean extends ServerConfiguration implements Appl } } } + + // Check for the home folder filesystem + + ConfigElement homeElem = config.getConfigElement("homeFolder"); + + if ( homeElem != null) + { + try + { + // Initialize the home folder share mapper + + secConfig.setShareMapper( "org.alfresco.filesys.alfresco.HomeShareMapper", homeElem); + + // Debug + + if ( logger.isDebugEnabled()) + logger.debug("Using home folder share mapper"); + } + catch (InvalidConfigurationException ex) + { + throw new AlfrescoRuntimeException("Failed to initialize home folder share mapper", ex); + } + } } /** @@ -2473,13 +2497,15 @@ public class ServerConfigurationBean extends ServerConfiguration implements Appl if ( mapperElem != null) { - // Check if the shre mapper type has been specified + // Check if the share mapper type has been specified String mapperType = mapperElem.getAttribute( "type"); String mapperClass = null; if ( mapperType.equalsIgnoreCase( "multi-tenant")) mapperClass = "org.alfresco.filesys.alfresco.MultiTenantShareMapper"; + else if ( mapperType.equalsIgnoreCase( "home-folder")) + mapperClass = "org.alfresco.filesys.alfresco.HomeShareMapper"; else { // Get the share mapper class diff --git a/source/java/org/alfresco/filesys/alfresco/HomeShareMapper.java b/source/java/org/alfresco/filesys/alfresco/HomeShareMapper.java new file mode 100644 index 0000000000..2078eaabf1 --- /dev/null +++ b/source/java/org/alfresco/filesys/alfresco/HomeShareMapper.java @@ -0,0 +1,346 @@ +/* + * Copyright (C) 2006-2009 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ + +package org.alfresco.filesys.alfresco; + +import java.util.Enumeration; + +import org.alfresco.config.ConfigElement; +import org.alfresco.filesys.AlfrescoConfigSection; +import org.alfresco.filesys.repo.ContentContext; +import org.alfresco.filesys.repo.ContentDiskDriver; +import org.alfresco.jlan.server.SrvSession; +import org.alfresco.jlan.server.auth.InvalidUserException; +import org.alfresco.jlan.server.config.InvalidConfigurationException; +import org.alfresco.jlan.server.config.ServerConfiguration; +import org.alfresco.jlan.server.core.ShareMapper; +import org.alfresco.jlan.server.core.ShareType; +import org.alfresco.jlan.server.core.SharedDevice; +import org.alfresco.jlan.server.core.SharedDeviceList; +import org.alfresco.jlan.server.filesys.DiskSharedDevice; +import org.alfresco.jlan.server.filesys.FilesystemsConfigSection; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Home Share Mapper Class + * + *
Maps disk share lookup requests to the list of shares defined in the server
+ * configuration and provides a dynamic home share mapped to the users home node.
+ *
+ * @author GKSpencer
+ */
+public class HomeShareMapper implements ShareMapper
+{
+ // Logging
+
+ private static final Log logger = LogFactory.getLog("org.alfresco.smb.protocol");
+
+ // Home folder share name
+
+ public static final String HOME_FOLDER_SHARE = "HOME";
+
+ // Server configuration
+
+ private ServerConfiguration m_config;
+
+ private AlfrescoConfigSection m_alfConfig;
+ private FilesystemsConfigSection m_fsysConfig;
+
+ // Home folder share name
+
+ private String m_homeShareName = HOME_FOLDER_SHARE;
+
+ // Debug enable flag
+
+ private boolean m_debug;
+
+ /**
+ * Default constructor
+ */
+ public HomeShareMapper()
+ {
+ }
+
+ /**
+ * Initialize the share mapper
+ *
+ * @param config ServerConfiguration
+ * @param params ConfigElement
+ * @exception InvalidConfigurationException
+ */
+ public void initializeMapper(ServerConfiguration config, ConfigElement params) throws InvalidConfigurationException
+ {
+ // Save the server configuration
+
+ m_config = config;
+
+ m_alfConfig = (AlfrescoConfigSection) m_config.getConfigSection( AlfrescoConfigSection.SectionName);
+ m_fsysConfig = (FilesystemsConfigSection) m_config.getConfigSection( FilesystemsConfigSection.SectionName);
+
+ // Check if the home share name has been specified
+
+ String homeName = params.getAttribute("name");
+ if ( homeName != null && homeName.length() > 0)
+ m_homeShareName = homeName;
+
+ // Check if debug is enabled
+
+ if (params != null && params.getChild("debug") != null)
+ m_debug = true;
+ }
+
+ /**
+ * Check if debug output is enabled
+ *
+ * @return boolean
+ */
+ public final boolean hasDebug()
+ {
+ return m_debug;
+ }
+
+ /**
+ * Return the home folder share name
+ *
+ * @return String
+ */
+ public final String getHomeFolderName()
+ {
+ return m_homeShareName;
+ }
+
+ /**
+ * Return the list of available shares.
+ *
+ * @param host String
+ * @param sess SrvSession
+ * @param allShares boolean
+ * @return SharedDeviceList
+ */
+ public SharedDeviceList getShareList(String host, SrvSession sess, boolean allShares)
+ {
+ // Check if the user has a home folder, and the session does not currently have any
+ // dynamic shares defined
+
+ if ( sess != null && sess.hasClientInformation() && sess.hasDynamicShares() == false &&
+ sess.getClientInformation() instanceof AlfrescoClientInfo)
+ {
+ AlfrescoClientInfo client = (AlfrescoClientInfo) sess.getClientInformation();
+ if ( client.hasHomeFolder())
+ {
+ // Create the home folder share
+
+ DiskSharedDevice homeShare = createHomeDiskShare(client);
+ sess.addDynamicShare(homeShare);
+
+ // Debug
+
+ if ( logger.isDebugEnabled())
+ logger.debug("Added " + getHomeFolderName() + " share to list of shares for " + client.getUserName());
+ }
+ }
+
+ // Make a copy of the global share list and add the per session dynamic shares
+
+ SharedDeviceList shrList = new SharedDeviceList(m_fsysConfig.getShares());
+
+ if ( sess != null && sess.hasDynamicShares()) {
+
+ // Add the per session dynamic shares
+
+ shrList.addShares(sess.getDynamicShareList());
+ }
+
+ // Remove unavailable shares from the list and return the list
+
+ if ( allShares == false)
+ shrList.removeUnavailableShares();
+ return shrList;
+ }
+
+ /**
+ * Find a share using the name and type for the specified client.
+ *
+ * @param host String
+ * @param name String
+ * @param typ int
+ * @param sess SrvSession
+ * @param create boolean
+ * @return SharedDevice
+ * @exception InvalidUserException
+ */
+ public SharedDevice findShare(String tohost, String name, int typ, SrvSession sess, boolean create)
+ throws Exception
+ {
+
+ // Check for the special HOME disk share
+
+ SharedDevice share = null;
+
+ if (( typ == ShareType.DISK || typ == ShareType.UNKNOWN) && name.equalsIgnoreCase(getHomeFolderName()) &&
+ sess.getClientInformation() != null && sess.getClientInformation() instanceof AlfrescoClientInfo) {
+
+ // Get the client details
+
+ AlfrescoClientInfo client = (AlfrescoClientInfo) sess.getClientInformation();
+
+ // DEBUG
+
+ if ( logger.isDebugEnabled())
+ logger.debug("Map share " + name + ", type=" + ShareType.TypeAsString(typ) + ", client=" + client);
+
+ // Check if the user has a home folder node
+
+ if ( client != null && client.hasHomeFolder()) {
+
+ // Check if the share has already been created for the session
+
+ if ( sess.hasDynamicShares()) {
+
+ // Check if the required share exists in the sessions dynamic share list
+
+ share = sess.getDynamicShareList().findShare(name, typ, false);
+
+ // DEBUG
+
+ if ( logger.isDebugEnabled())
+ logger.debug(" Reusing existing dynamic share for " + name);
+ }
+
+ // Check if we found a share, if not then create a new dynamic share for the home directory
+
+ if ( share == null && create == true) {
+
+ // Create the home share mapped to the users home folder
+
+ DiskSharedDevice diskShare = createHomeDiskShare(client);
+
+ // Add the new share to the sessions dynamic share list
+
+ sess.addDynamicShare(diskShare);
+ share = diskShare;
+
+ // DEBUG
+
+ if (logger.isDebugEnabled())
+ logger.debug(" Mapped share " + name + " to " + client.getHomeFolder());
+ }
+ }
+ else
+ throw new InvalidUserException("No home directory");
+ }
+ else {
+
+ // Find the required share by name/type. Use a case sensitive search first, if that fails use a case
+ // insensitive search.
+
+ share = m_fsysConfig.getShares().findShare(name, typ, false);
+
+ if ( share == null) {
+
+ // Try a case insensitive search for the required share
+
+ share = m_fsysConfig.getShares().findShare(name, typ, true);
+ }
+ }
+
+ // Check if the share is available
+
+ if ( share != null && share.getContext() != null && share.getContext().isAvailable() == false)
+ share = null;
+
+ // Return the shared device, or null if no matching device was found
+
+ return share;
+ }
+
+ /**
+ * Delete temporary shares for the specified session
+ *
+ * @param sess SrvSession
+ */
+ public void deleteShares(SrvSession sess)
+ {
+
+ // Check if the session has any dynamic shares
+
+ if ( sess.hasDynamicShares() == false)
+ return;
+
+ // Delete the dynamic shares
+
+ SharedDeviceList shares = sess.getDynamicShareList();
+ Enumeration