diff --git a/source/java/org/alfresco/cmis/mapping/CMISServicesImpl.java b/source/java/org/alfresco/cmis/mapping/CMISServicesImpl.java
index be1839840a..baba3ac0a8 100644
--- a/source/java/org/alfresco/cmis/mapping/CMISServicesImpl.java
+++ b/source/java/org/alfresco/cmis/mapping/CMISServicesImpl.java
@@ -695,7 +695,13 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware,
}
if (direction == CMISRelationshipDirectionEnum.TARGET || direction == CMISRelationshipDirectionEnum.EITHER)
{
- assocs.addAll(nodeService.getSourceAssocs(node, RegexQNamePattern.MATCH_ALL));
+ try
+ {
+ assocs.addAll(nodeService.getSourceAssocs(node, RegexQNamePattern.MATCH_ALL));
+ }
+ catch (UnsupportedOperationException uoe) {
+ // NodeServiceImpl#getSourceAssocs - This operation is not supported for a version store
+ }
}
// filter association by type
diff --git a/source/java/org/alfresco/filesys/config/ServerConfigurationBean.java b/source/java/org/alfresco/filesys/config/ServerConfigurationBean.java
index 9a1e375b08..29f1034f18 100644
--- a/source/java/org/alfresco/filesys/config/ServerConfigurationBean.java
+++ b/source/java/org/alfresco/filesys/config/ServerConfigurationBean.java
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
@@ -14,2232 +14,2240 @@
* 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.filesys.config;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.NetworkInterface;
-import java.net.Socket;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-import java.nio.charset.Charset;
-import java.nio.charset.IllegalCharsetNameException;
-import java.nio.charset.UnsupportedCharsetException;
-import java.util.EnumSet;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.StringTokenizer;
-
-import org.springframework.extensions.config.element.GenericConfigElement;
-import org.alfresco.error.AlfrescoRuntimeException;
-import org.alfresco.filesys.AbstractServerConfigurationBean;
-import org.alfresco.filesys.alfresco.AlfrescoContext;
-import org.alfresco.filesys.alfresco.ExtendedDiskInterface;
-import org.alfresco.filesys.avm.AVMContext;
-import org.alfresco.filesys.avm.AVMDiskDriver;
-import org.alfresco.filesys.config.acl.AccessControlListBean;
-import org.alfresco.filesys.repo.ContentContext;
-import org.alfresco.jlan.ftp.FTPAuthenticator;
-import org.alfresco.jlan.ftp.FTPConfigSection;
-import org.alfresco.jlan.ftp.FTPPath;
-import org.alfresco.jlan.ftp.InvalidPathException;
-import org.alfresco.jlan.netbios.NetBIOSSession;
-import org.alfresco.jlan.netbios.RFCNetBIOSProtocol;
-import org.alfresco.jlan.netbios.win32.Win32NetBIOS;
-import org.alfresco.jlan.oncrpc.RpcAuthenticator;
-import org.alfresco.jlan.oncrpc.nfs.NFSConfigSection;
-import org.alfresco.jlan.server.auth.ICifsAuthenticator;
-import org.alfresco.jlan.server.auth.acl.AccessControlList;
-import org.alfresco.jlan.server.auth.passthru.DomainMapping;
-import org.alfresco.jlan.server.auth.passthru.RangeDomainMapping;
-import org.alfresco.jlan.server.auth.passthru.SubnetDomainMapping;
-import org.alfresco.jlan.server.config.CoreServerConfigSection;
-import org.alfresco.jlan.server.config.InvalidConfigurationException;
-import org.alfresco.jlan.server.config.SecurityConfigSection;
-import org.alfresco.jlan.server.core.DeviceContext;
-import org.alfresco.jlan.server.core.DeviceContextException;
-import org.alfresco.jlan.server.core.ShareMapper;
-import org.alfresco.jlan.server.core.ShareType;
-import org.alfresco.jlan.server.filesys.DiskDeviceContext;
-import org.alfresco.jlan.server.filesys.DiskSharedDevice;
-import org.alfresco.jlan.server.filesys.FilesystemsConfigSection;
-import org.alfresco.jlan.server.filesys.cache.FileStateLockManager;
-import org.alfresco.jlan.server.filesys.cache.StandaloneFileStateCache;
-import org.alfresco.jlan.server.filesys.cache.hazelcast.ClusterConfigSection;
-import org.alfresco.jlan.server.filesys.cache.hazelcast.HazelCastClusterFileStateCache;
-import org.alfresco.jlan.server.thread.ThreadRequestPool;
-import org.alfresco.jlan.smb.server.CIFSConfigSection;
-import org.alfresco.jlan.util.IPAddress;
-import org.alfresco.jlan.util.MemorySize;
-import org.alfresco.jlan.util.Platform;
-import org.alfresco.jlan.util.StringList;
-import org.alfresco.jlan.util.X64;
-import org.alfresco.repo.management.subsystems.ActivateableBean;
-
-import com.hazelcast.core.HazelcastInstance;
-
-/**
- * Alfresco File Server Configuration Bean Class
- *
- * Acts as an adaptor between JLAN's configuration requirements and the spring configuration of
- * the Alfresco filesystem subsystem.
- *
- * Also contains an amount of initialisation logic.
- *
- * @author gkspencer
- * @author dward
- * @author mrogers
- */
-public class ServerConfigurationBean extends AbstractServerConfigurationBean
-{
- private CIFSConfigBean cifsConfigBean;
- private FTPConfigBean ftpConfigBean;
- private NFSConfigBean nfsConfigBean;
- private List filesystemContexts;
- private boolean avmAllStores;
- private SecurityConfigBean securityConfigBean;
- private CoreServerConfigBean coreServerConfigBean;
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.filesys.config;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.NetworkInterface;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.EnumSet;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.springframework.extensions.config.element.GenericConfigElement;
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.filesys.AbstractServerConfigurationBean;
+import org.alfresco.filesys.alfresco.AlfrescoContext;
+import org.alfresco.filesys.alfresco.ExtendedDiskInterface;
+import org.alfresco.filesys.avm.AVMContext;
+import org.alfresco.filesys.avm.AVMDiskDriver;
+import org.alfresco.filesys.config.acl.AccessControlListBean;
+import org.alfresco.filesys.repo.ContentContext;
+import org.alfresco.jlan.ftp.FTPAuthenticator;
+import org.alfresco.jlan.ftp.FTPConfigSection;
+import org.alfresco.jlan.ftp.FTPPath;
+import org.alfresco.jlan.ftp.InvalidPathException;
+import org.alfresco.jlan.netbios.NetBIOSSession;
+import org.alfresco.jlan.netbios.RFCNetBIOSProtocol;
+import org.alfresco.jlan.netbios.win32.Win32NetBIOS;
+import org.alfresco.jlan.oncrpc.RpcAuthenticator;
+import org.alfresco.jlan.oncrpc.nfs.NFSConfigSection;
+import org.alfresco.jlan.server.auth.ICifsAuthenticator;
+import org.alfresco.jlan.server.auth.acl.AccessControlList;
+import org.alfresco.jlan.server.auth.passthru.DomainMapping;
+import org.alfresco.jlan.server.auth.passthru.RangeDomainMapping;
+import org.alfresco.jlan.server.auth.passthru.SubnetDomainMapping;
+import org.alfresco.jlan.server.config.CoreServerConfigSection;
+import org.alfresco.jlan.server.config.InvalidConfigurationException;
+import org.alfresco.jlan.server.config.SecurityConfigSection;
+import org.alfresco.jlan.server.core.DeviceContext;
+import org.alfresco.jlan.server.core.DeviceContextException;
+import org.alfresco.jlan.server.core.ShareMapper;
+import org.alfresco.jlan.server.core.ShareType;
+import org.alfresco.jlan.server.filesys.DiskDeviceContext;
+import org.alfresco.jlan.server.filesys.DiskSharedDevice;
+import org.alfresco.jlan.server.filesys.FilesystemsConfigSection;
+import org.alfresco.jlan.server.filesys.cache.FileStateLockManager;
+import org.alfresco.jlan.server.filesys.cache.StandaloneFileStateCache;
+import org.alfresco.jlan.server.filesys.cache.hazelcast.ClusterConfigSection;
+import org.alfresco.jlan.server.filesys.cache.hazelcast.HazelCastClusterFileStateCache;
+import org.alfresco.jlan.server.thread.ThreadRequestPool;
+import org.alfresco.jlan.smb.server.CIFSConfigSection;
+import org.alfresco.jlan.util.IPAddress;
+import org.alfresco.jlan.util.MemorySize;
+import org.alfresco.jlan.util.Platform;
+import org.alfresco.jlan.util.StringList;
+import org.alfresco.jlan.util.X64;
+import org.alfresco.repo.management.subsystems.ActivateableBean;
+import org.springframework.beans.factory.DisposableBean;
+
+import com.hazelcast.core.HazelcastInstance;
+
+/**
+ * Alfresco File Server Configuration Bean Class
+ *
+ * Acts as an adaptor between JLAN's configuration requirements and the spring configuration of
+ * the Alfresco filesystem subsystem.
+ *
+ * Also contains an amount of initialisation logic.
+ *
+ * @author gkspencer
+ * @author dward
+ * @author mrogers
+ */
+public class ServerConfigurationBean extends AbstractServerConfigurationBean implements DisposableBean
+{
+ private CIFSConfigBean cifsConfigBean;
+ private FTPConfigBean ftpConfigBean;
+ private NFSConfigBean nfsConfigBean;
+ private List filesystemContexts;
+ private boolean avmAllStores;
+ private SecurityConfigBean securityConfigBean;
+ private CoreServerConfigBean coreServerConfigBean;
+
+ private ThreadRequestPool threadPool;
private ClusterConfigBean clusterConfigBean;
-
- /**
- * Default constructor
- */
- public ServerConfigurationBean()
- {
- super("");
- }
-
- /**
- * Class constructor
- *
- * @param srvName
- * String
- */
- public ServerConfigurationBean(String srvName)
- {
- super(srvName);
- }
-
- public void setCifsConfigBean(CIFSConfigBean cifsConfigBean)
- {
- this.cifsConfigBean = cifsConfigBean;
- }
-
- public void setFtpConfigBean(FTPConfigBean ftpConfigBean)
- {
- this.ftpConfigBean = ftpConfigBean;
- }
-
- public void setNfsConfigBean(NFSConfigBean nfsConfigBean)
- {
- this.nfsConfigBean = nfsConfigBean;
- }
-
- public void setFilesystemContexts(List filesystemContexts)
- {
- this.filesystemContexts = filesystemContexts;
- }
-
- public void setAvmAllStores(boolean avmAllStores)
- {
- this.avmAllStores = avmAllStores;
- }
-
- public void setSecurityConfigBean(SecurityConfigBean securityConfigBean)
- {
- this.securityConfigBean = securityConfigBean;
- }
-
- public void setCoreServerConfigBean(CoreServerConfigBean coreServerConfigBean)
- {
- this.coreServerConfigBean = coreServerConfigBean;
- }
-
- public void setClusterConfigBean(ClusterConfigBean clusterConfigBean)
- {
- this.clusterConfigBean = clusterConfigBean;
- }
-
- /**
- * Process the CIFS server configuration
- */
- protected void processCIFSServerConfig()
- {
- // If the configuration section is not valid then CIFS is disabled
-
- if (cifsConfigBean == null)
- {
- removeConfigSection(CIFSConfigSection.SectionName);
- return;
- }
-
- // Check if the server has been disabled
- if (!cifsConfigBean.getServerEnabled())
- {
- removeConfigSection(CIFSConfigSection.SectionName);
- return;
- }
-
- // Before we go any further, let's make sure there's a compatible authenticator in the authentication chain.
- ICifsAuthenticator authenticator = cifsConfigBean.getAuthenticator();
- if (authenticator == null || authenticator instanceof ActivateableBean && !((ActivateableBean)authenticator).isActive())
- {
- logger.warn("No enabled CIFS authenticator found in authentication chain. CIFS Server disabled");
- removeConfigSection(CIFSConfigSection.SectionName);
- return;
- }
-
- // Create the CIFS server configuration section
-
- CIFSConfigSection cifsConfig = new CIFSConfigSection(this);
-
- try
- {
- // Check if native code calls should be disabled on Windows
- if (cifsConfigBean.getDisableNativeCode())
- {
- // Disable native code calls so that the JNI DLL is not required
-
- cifsConfig.setNativeCodeDisabled(true);
- m_disableNativeCode = true;
-
- // Warning
-
- logger.warn("CIFS server native calls disabled, JNI code will not be used");
- }
-
- // Get the network broadcast address
- //
- // Note: We need to set this first as the call to getLocalDomainName() may use a NetBIOS
- // name lookup, so the broadcast mask must be set before then.
-
- String broadcastAddess = cifsConfigBean.getBroadcastAddress();
- if (broadcastAddess != null && broadcastAddess.length() > 0)
- {
-
- // Check if the broadcast mask is a valid numeric IP address
-
- if (IPAddress.isNumericAddress(broadcastAddess) == false)
- throw new AlfrescoRuntimeException("Invalid broadcast mask, must be n.n.n.n format");
-
- // Set the network broadcast mask
-
- cifsConfig.setBroadcastMask(broadcastAddess);
- }
-
- // Get the host configuration
-
- String hostName = cifsConfigBean.getServerName();
- if (hostName == null || hostName.length() == 0)
- throw new AlfrescoRuntimeException("Host name not specified or invalid");
-
- // Check if the host name contains the local name token
-
- int pos = hostName.indexOf(TokenLocalName);
- if (pos != -1)
- {
-
- // Get the local server name
-
- String srvName = getLocalServerName(true);
-
- // Rebuild the host name substituting the token with the local server name
-
- StringBuilder hostStr = new StringBuilder();
-
- hostStr.append(hostName.substring(0, pos));
- hostStr.append(srvName);
-
- pos += TokenLocalName.length();
- if (pos < hostName.length())
- hostStr.append(hostName.substring(pos));
-
- hostName = hostStr.toString();
-
- // Make sure the CIFS server name does not match the local server name
-
- if (hostName.equals(srvName) && getPlatformType() == Platform.Type.WINDOWS)
- throw new AlfrescoRuntimeException("CIFS server name must be unique");
- }
-
- // Check if the host name is longer than 15 characters. NetBIOS only allows a maximum of 16 characters in
- // the
- // server name with the last character reserved for the service type.
-
- if (hostName.length() > 15)
- {
- // Truncate the CIFS server name
-
- hostName = hostName.substring(0, 15);
-
- // Output a warning
-
- logger.warn("CIFS server name is longer than 15 characters, truncated to " + hostName);
- }
-
- // Set the CIFS server name
-
- cifsConfig.setServerName(hostName.toUpperCase());
- setServerName(hostName.toUpperCase());
-
- // Get the domain/workgroup name
-
- String domain = cifsConfigBean.getDomainName();
- if (domain != null && domain.length() > 0)
- {
- // Set the domain/workgroup name
-
- cifsConfig.setDomainName(domain.toUpperCase());
- }
- else
- {
- // Get the local domain/workgroup name
-
- String localDomain = getLocalDomainName();
-
- if (localDomain == null && (getPlatformType() != Platform.Type.WINDOWS || isNativeCodeDisabled()))
- {
- // Use a default domain/workgroup name
-
- localDomain = "WORKGROUP";
-
- // Output a warning
-
- logger.error("Failed to get local domain/workgroup name, using default of " + localDomain);
- logger.error("(This may be due to firewall settings or incorrect setting)");
- }
-
- // Set the local domain/workgroup that the CIFS server belongs to
-
- cifsConfig.setDomainName(localDomain);
- }
-
- // Check for a server comment
- String comment = cifsConfigBean.getServerComment();
- if (comment != null && comment.length() > 0)
- {
- cifsConfig.setComment(comment);
- }
-
- // Check for a bind address
-
- // Check if the network adapter name has been specified
- String bindToAdapter = cifsConfigBean.getBindToAdapter();
- String bindTo;
-
- if (bindToAdapter != null && bindToAdapter.length() > 0)
- {
-
- // Get the IP address for the adapter
-
- InetAddress bindAddr = parseAdapterName(bindToAdapter);
-
- // Set the bind address for the server
-
- cifsConfig.setSMBBindAddress(bindAddr);
- }
- else if ((bindTo = cifsConfigBean.getBindToAddress()) != null && bindTo.length() > 0
- && !bindTo.equals(BIND_TO_IGNORE))
- {
-
- // Validate the bind address
- try
- {
- // Check the bind address
-
- InetAddress bindAddr = InetAddress.getByName(bindTo);
-
- // Set the bind address for the server
-
- cifsConfig.setSMBBindAddress(bindAddr);
- }
- catch (UnknownHostException ex)
- {
- throw new AlfrescoRuntimeException("Invalid CIFS server bind address");
- }
- }
-
- // Get the authenticator
-
- if (authenticator != null)
- {
- cifsConfig.setAuthenticator(authenticator);
- }
- else
- throw new AlfrescoRuntimeException("CIFS authenticator not specified");
-
- // Check if the host announcer has been disabled
-
- if (!cifsConfigBean.getHostAccouncerEnabled())
- {
- // Switch off the host announcer
-
- cifsConfig.setHostAnnouncer( false);
-
- // Log that host announcements are not enabled
-
- logger.info("Host announcements not enabled");
- }
- else
- {
- // Check for an announcement interval
-
- Integer interval = cifsConfigBean.getHostAccounceInterval();
- if (interval != null)
- {
- cifsConfig.setHostAnnounceInterval(interval);
- }
-
- // Check if the domain name has been set, this is required if the
- // host announcer is enabled
-
- if (cifsConfig.getDomainName() == null)
- throw new AlfrescoRuntimeException("Domain name must be specified if host announcement is enabled");
-
- // Enable host announcement
-
- cifsConfig.setHostAnnouncer(true);
- }
-
- // Check if NetBIOS SMB is enabled
- NetBIOSSMBConfigBean netBIOSSMBConfigBean = cifsConfigBean.getNetBIOSSMB();
- if (netBIOSSMBConfigBean != null)
- {
- // Check if NetBIOS over TCP/IP is enabled for the current platform
-
- String platformsStr = netBIOSSMBConfigBean.getPlatforms();
- boolean platformOK = false;
-
- if (platformsStr != null && platformsStr.length() > 0)
- {
- // Parse the list of platforms that NetBIOS over TCP/IP is to be enabled for and
- // check if the current platform is included
-
- EnumSet enabledPlatforms = parsePlatformString(platformsStr);
- if (enabledPlatforms.contains(getPlatformType()))
- platformOK = true;
- }
- else
- {
- // No restriction on platforms
-
- platformOK = true;
- }
-
- // Enable the NetBIOS SMB support, if enabled for this platform
-
- cifsConfig.setNetBIOSSMB(platformOK);
-
- // Parse/check NetBIOS settings, if enabled
-
- if (cifsConfig.hasNetBIOSSMB())
- {
- // Check if the broadcast mask has been specified
-
- if (cifsConfig.getBroadcastMask() == null)
- throw new AlfrescoRuntimeException("Network broadcast mask not specified");
-
- // Check for a bind address
-
- String bindto = netBIOSSMBConfigBean.getBindTo();
- if (bindto != null && bindto.length() > 0 && !bindto.equals(BIND_TO_IGNORE))
- {
-
- // Validate the bind address
-
- try
- {
-
- // Check the bind address
-
- InetAddress bindAddr = InetAddress.getByName(bindto);
-
- // Set the bind address for the NetBIOS name server
-
- cifsConfig.setNetBIOSBindAddress(bindAddr);
- }
- catch (UnknownHostException ex)
- {
- throw new AlfrescoRuntimeException("Invalid NetBIOS bind address");
- }
- }
- else if (cifsConfig.hasSMBBindAddress())
- {
-
- // Use the SMB bind address for the NetBIOS name server
-
- cifsConfig.setNetBIOSBindAddress(cifsConfig.getSMBBindAddress());
- }
- else
- {
- // Get a list of all the local addresses
-
- InetAddress[] addrs = null;
-
- try
- {
- // Get the local server IP address list
-
- addrs = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName());
- }
- catch (UnknownHostException ex)
- {
- logger.error("Failed to get local address list", ex);
- }
-
- // Check the address list for one or more valid local addresses filtering out the loopback
- // address
-
- int addrCnt = 0;
-
- if (addrs != null)
- {
- for (int i = 0; i < addrs.length; i++)
- {
-
- // Check for a valid address, filter out '127.0.0.1' and '0.0.0.0' addresses
-
- if (addrs[i].getHostAddress().equals("127.0.0.1") == false
- && addrs[i].getHostAddress().equals("0.0.0.0") == false)
- addrCnt++;
- }
- }
-
- // Check if any addresses were found
-
- if (addrCnt == 0)
- {
- // Enumerate the network adapter list
-
- Enumeration niEnum = null;
-
- try
- {
- niEnum = NetworkInterface.getNetworkInterfaces();
- }
- catch (SocketException ex)
- {
- }
-
- if (niEnum != null)
- {
- while (niEnum.hasMoreElements())
- {
- // Get the current network interface
-
- NetworkInterface ni = niEnum.nextElement();
-
- // Enumerate the addresses for the network adapter
-
- Enumeration niAddrs = ni.getInetAddresses();
- if (niAddrs != null)
- {
- // Check for any valid addresses
-
- while (niAddrs.hasMoreElements())
- {
- InetAddress curAddr = niAddrs.nextElement();
-
- if (curAddr.getHostAddress().equals("127.0.0.1") == false
- && curAddr.getHostAddress().equals("0.0.0.0") == false)
- addrCnt++;
- }
- }
- }
-
- // DEBUG
-
- if (addrCnt > 0 && logger.isDebugEnabled())
- logger.debug("Found valid IP address from interface list");
- }
-
- // Check if we found any valid network addresses
-
- if (addrCnt == 0)
- {
- // Log the available IP addresses
-
- if (logger.isDebugEnabled())
- {
- logger.debug("Local address list dump :-");
- if (addrs != null)
- {
- for (int i = 0; i < addrs.length; i++)
- logger.debug(" Address: " + addrs[i]);
- }
- else
- logger.debug(" No addresses");
- }
-
- // Throw an exception to stop the CIFS/NetBIOS name server from starting
-
- throw new AlfrescoRuntimeException(
- "Failed to get IP address(es) for the local server, check hosts file and/or DNS setup");
- }
- }
- }
-
- // Check if the session port has been specified
-
- Integer portNum = netBIOSSMBConfigBean.getSessionPort();
- if (portNum != null)
- {
- cifsConfig.setSessionPort(portNum);
- if (cifsConfig.getSessionPort() <= 0 || cifsConfig.getSessionPort() >= 65535)
- throw new AlfrescoRuntimeException("NetBIOS session port out of valid range");
- }
-
- // Check if the name port has been specified
-
- portNum = netBIOSSMBConfigBean.getNamePort();
- if (portNum != null)
- {
- cifsConfig.setNameServerPort(portNum);
- if (cifsConfig.getNameServerPort() <= 0 || cifsConfig.getNameServerPort() >= 65535)
- throw new AlfrescoRuntimeException("NetBIOS name port out of valid range");
- }
-
- // Check if the datagram port has been specified
-
- portNum = netBIOSSMBConfigBean.getDatagramPort();
- if (portNum != null)
- {
- cifsConfig.setDatagramPort(portNum);
- if (cifsConfig.getDatagramPort() <= 0 || cifsConfig.getDatagramPort() >= 65535)
- throw new AlfrescoRuntimeException("NetBIOS datagram port out of valid range");
- }
-
- // Check for a bind address
-
- String attr = netBIOSSMBConfigBean.getBindTo();
- if (attr != null && attr.length() > 0 && !attr.equals(BIND_TO_IGNORE))
- {
-
- // Validate the bind address
-
- try
- {
-
- // Check the bind address
-
- InetAddress bindAddr = InetAddress.getByName(attr);
-
- // Set the bind address for the NetBIOS name server
-
- cifsConfig.setNetBIOSBindAddress(bindAddr);
- }
- catch (UnknownHostException ex)
- {
- throw new InvalidConfigurationException(ex.toString());
- }
- }
-
- // Check for a bind address using the adapter name
-
- else if ((attr = netBIOSSMBConfigBean.getAdapter()) != null && attr.length() > 0)
- {
-
- // Get the bind address via the network adapter name
-
- InetAddress bindAddr = parseAdapterName(attr);
- cifsConfig.setNetBIOSBindAddress(bindAddr);
- }
- else if (cifsConfig.hasSMBBindAddress())
- {
-
- // Use the SMB bind address for the NetBIOS name server
-
- cifsConfig.setNetBIOSBindAddress(cifsConfig.getSMBBindAddress());
- }
-
- }
- }
- else
- {
-
- // Disable NetBIOS SMB support
-
- cifsConfig.setNetBIOSSMB(false);
- }
-
- // Check if TCP/IP SMB is enabled
-
- TcpipSMBConfigBean tcpipSMBConfigBean = cifsConfigBean.getTcpipSMB();
- if (tcpipSMBConfigBean != null)
- {
-
- // Check if native SMB is enabled for the current platform
-
- String platformsStr = tcpipSMBConfigBean.getPlatforms();
- boolean platformOK = false;
-
- if (platformsStr != null)
- {
- // Parse the list of platforms that native SMB is to be enabled for and
- // check if the current platform is included
-
- EnumSet enabledPlatforms = parsePlatformString(platformsStr);
- if (enabledPlatforms.contains(getPlatformType()))
- platformOK = true;
- }
- else
- {
- // No restriction on platforms
-
- platformOK = true;
- }
-
- // Enable the TCP/IP SMB support, if enabled for this platform
-
- cifsConfig.setTcpipSMB(platformOK);
-
- // Check if the port has been specified
-
- Integer portNum = tcpipSMBConfigBean.getPort();
- if (portNum != null)
- {
- cifsConfig.setTcpipSMBPort(portNum);
- if (cifsConfig.getTcpipSMBPort() <= 0 || cifsConfig.getTcpipSMBPort() >= 65535)
- throw new AlfrescoRuntimeException("TCP/IP SMB port out of valid range");
- }
-
- // Check if IPv6 support should be enabled
-
- if ( tcpipSMBConfigBean.getIpv6Enabled())
- {
- try
- {
- // Use the IPv6 bind all address
-
- cifsConfig.setSMBBindAddress( InetAddress.getByName( "::"));
-
- // DEBUG
-
- if ( logger.isInfoEnabled())
- logger.info("Enabled CIFS IPv6 bind address for native SMB");
- }
- catch ( UnknownHostException ex)
- {
- throw new AlfrescoRuntimeException("Failed to enable IPv6 bind address, " + ex.getMessage());
- }
- }
-
- }
- else
- {
-
- // Disable TCP/IP SMB support
-
- cifsConfig.setTcpipSMB(false);
- }
-
- // Check if Win32 NetBIOS is enabled
-
- Win32NetBIOSConfigBean win32NetBIOSConfigBean = cifsConfigBean.getWin32NetBIOS();
- if (win32NetBIOSConfigBean != null)
- {
-
- // Check if the Win32 NetBIOS server name has been specified
-
- String win32Name = win32NetBIOSConfigBean.getName();
- if (win32Name != null && win32Name.length() > 0)
- {
-
- // Validate the name
-
- if (win32Name.length() > 16)
- throw new AlfrescoRuntimeException("Invalid Win32 NetBIOS name, " + win32Name);
-
- // Set the Win32 NetBIOS file server name
-
- cifsConfig.setWin32NetBIOSName(win32Name);
- }
-
- // Check if the Win32 NetBIOS LANA has been specified
-
- String lanaStr = win32NetBIOSConfigBean.getLana();
- if (lanaStr != null && lanaStr.length() > 0)
- {
- // Check if the LANA has been specified as an IP address or adapter name
-
- int lana = -1;
-
- if (IPAddress.isNumericAddress(lanaStr))
- {
-
- // Convert the IP address to a LANA id
-
- lana = Win32NetBIOS.getLANAForIPAddress(lanaStr);
- if (lana == -1)
- throw new AlfrescoRuntimeException("Failed to convert IP address " + lanaStr + " to a LANA");
- }
- else if (lanaStr.length() > 1 && Character.isLetter(lanaStr.charAt(0)))
- {
-
- // Convert the network adapter to a LANA id
-
- lana = Win32NetBIOS.getLANAForAdapterName(lanaStr);
- if (lana == -1)
- throw new AlfrescoRuntimeException("Failed to convert network adapter " + lanaStr
- + " to a LANA");
- }
- else
- {
-
- try
- {
- lana = Integer.parseInt(lanaStr);
- }
- catch (NumberFormatException ex)
- {
- throw new AlfrescoRuntimeException("Invalid win32 NetBIOS LANA specified");
- }
- }
-
- // LANA should be in the range 0-255
-
- if (lana < 0 || lana > 255)
- throw new AlfrescoRuntimeException("Invalid Win32 NetBIOS LANA number, " + lana);
-
- // Set the LANA number
-
- cifsConfig.setWin32LANA(lana);
- }
-
- // Check if the native NetBIOS interface has been specified, either 'winsock' or 'netbios'
-
- String nativeAPI = win32NetBIOSConfigBean.getApi();
- if (nativeAPI != null && nativeAPI.length() > 0)
- {
- // Validate the API type
-
- boolean useWinsock = true;
-
- if (nativeAPI.equalsIgnoreCase("netbios"))
- useWinsock = false;
- else if (nativeAPI.equalsIgnoreCase("winsock") == false)
- throw new AlfrescoRuntimeException("Invalid NetBIOS API type, spefify 'winsock' or 'netbios'");
-
- // Set the NetBIOS API to use
-
- cifsConfig.setWin32WinsockNetBIOS(useWinsock);
- }
-
- // Force the older NetBIOS API code to be used on 64Bit Windows
-
- if (cifsConfig.useWinsockNetBIOS() == true && X64.isWindows64())
- {
- // Debug
-
- if (logger.isDebugEnabled())
- logger.debug("Using older Netbios() API code");
-
- // Use the older NetBIOS API code
-
- cifsConfig.setWin32WinsockNetBIOS(false);
- }
-
- // Check if the current operating system is supported by the Win32
- // NetBIOS handler
-
- String osName = System.getProperty("os.name");
- if (osName.startsWith("Windows")
- && (osName.endsWith("95") == false && osName.endsWith("98") == false && osName.endsWith("ME") == false)
- && isNativeCodeDisabled() == false)
- {
-
- // Call the Win32NetBIOS native code to make sure it is initialized
-
- if (Win32NetBIOS.LanaEnumerate() != null)
- {
- // Enable Win32 NetBIOS
-
- cifsConfig.setWin32NetBIOS(true);
- }
- else
- {
- logger.warn("No NetBIOS LANAs available");
- }
- }
- else
- {
-
- // Win32 NetBIOS not supported on the current operating system
-
- cifsConfig.setWin32NetBIOS(false);
- }
- }
- else
- {
-
- // Disable Win32 NetBIOS
-
- cifsConfig.setWin32NetBIOS(false);
- }
-
- // Check if the Win32 host announcer has been disabled
-
- if ( !cifsConfigBean.getWin32HostAnnouncerEnabled())
- {
- // Switch off the Win32 host announcer
-
- cifsConfig.setWin32HostAnnouncer( false);
-
- // Log that host announcements are not enabled
-
- logger.info("Win32 host announcements not enabled");
- }
- else
- {
- // Check for an announcement interval
- Integer interval = cifsConfigBean.getWin32HostAnnounceInterval();
- if (interval != null)
- {
- cifsConfig.setWin32HostAnnounceInterval(interval);
- }
-
- // Check if the domain name has been set, this is required if the
- // host announcer is enabled
-
- if (cifsConfig.getDomainName() == null)
- throw new AlfrescoRuntimeException("Domain name must be specified if host announcement is enabled");
-
- // Enable Win32 NetBIOS host announcement
-
- cifsConfig.setWin32HostAnnouncer(true);
- }
-
- // Check if NetBIOS and/or TCP/IP SMB have been enabled
-
- if (cifsConfig.hasNetBIOSSMB() == false && cifsConfig.hasTcpipSMB() == false
- && cifsConfig.hasWin32NetBIOS() == false)
- throw new AlfrescoRuntimeException("NetBIOS SMB, TCP/IP SMB or Win32 NetBIOS must be enabled");
-
- // Check if WINS servers are configured
-
- WINSConfigBean winsConfigBean = cifsConfigBean.getWINSConfig();
-
- if (winsConfigBean != null && !winsConfigBean.isAutoDetectEnabled())
- {
-
- // Get the primary WINS server
-
- String priWins = winsConfigBean.getPrimary();
-
- if (priWins == null || priWins.length() == 0)
- throw new AlfrescoRuntimeException("No primary WINS server configured");
-
- // Validate the WINS server address
-
- InetAddress primaryWINS = null;
-
- try
- {
- primaryWINS = InetAddress.getByName(priWins);
- }
- catch (UnknownHostException ex)
- {
- throw new AlfrescoRuntimeException("Invalid primary WINS server address, " + priWins);
- }
-
- // Check if a secondary WINS server has been specified
-
- String secWins = winsConfigBean.getSecondary();
- InetAddress secondaryWINS = null;
-
- if (secWins != null && secWins.length() > 0)
- {
-
- // Validate the secondary WINS server address
-
- try
- {
- secondaryWINS = InetAddress.getByName(secWins);
- }
- catch (UnknownHostException ex)
- {
- throw new AlfrescoRuntimeException("Invalid secondary WINS server address, " + secWins);
- }
- }
-
- // Set the WINS server address(es)
-
- cifsConfig.setPrimaryWINSServer(primaryWINS);
- if (secondaryWINS != null)
- cifsConfig.setSecondaryWINSServer(secondaryWINS);
-
- // Pass the setting to the NetBIOS session class
-
- NetBIOSSession.setDefaultWINSServer(primaryWINS);
- }
-
- // Check if WINS is configured, if we are running on Windows and socket based NetBIOS is enabled
-
- else if (cifsConfig.hasNetBIOSSMB() && getPlatformType() == Platform.Type.WINDOWS && !isNativeCodeDisabled())
- {
- // Get the WINS server list
-
- String winsServers = Win32NetBIOS.getWINSServerList();
-
- if (winsServers != null)
- {
- // Use the first WINS server address for now
-
- StringTokenizer tokens = new StringTokenizer(winsServers, ",");
- String addr = tokens.nextToken();
-
- try
- {
- // Convert to a network address and check if the WINS server is accessible
-
- InetAddress winsAddr = InetAddress.getByName(addr);
-
- Socket winsSocket = new Socket();
- InetSocketAddress sockAddr = new InetSocketAddress(winsAddr, RFCNetBIOSProtocol.NAME_PORT);
-
- winsSocket.connect(sockAddr, 3000);
- winsSocket.close();
-
- // Set the primary WINS server address
-
- cifsConfig.setPrimaryWINSServer(winsAddr);
-
- // Debug
-
- if (logger.isDebugEnabled())
- logger.debug("Configuring to use WINS server " + addr);
- }
- catch (UnknownHostException ex)
- {
- throw new AlfrescoRuntimeException("Invalid auto WINS server address, " + addr);
- }
- catch (IOException ex)
- {
- if (logger.isDebugEnabled())
- logger.debug("Failed to connect to auto WINS server " + addr);
- }
- }
- }
-
- // Check for session debug flags
-
- String flags = cifsConfigBean.getSessionDebugFlags();
-
- int sessDbg = 0;
-
- if (flags != null && flags.length() > 0)
- {
-
- // Parse the flags
-
- flags = flags.toUpperCase();
- StringTokenizer token = new StringTokenizer(flags, ",");
-
- while (token.hasMoreTokens())
- {
- // Get the current debug flag token
-
- String dbg = token.nextToken().trim();
-
- // Find the debug flag name
-
- int idx = 0;
-
- while (idx < m_sessDbgStr.length && m_sessDbgStr[idx].equalsIgnoreCase(dbg) == false)
- idx++;
-
- if (idx > m_sessDbgStr.length)
- throw new AlfrescoRuntimeException("Invalid session debug flag, " + dbg);
-
- // Set the debug flag
-
- sessDbg += 1 << idx;
- }
- }
-
- // Set the session debug flags
-
- cifsConfig.setSessionDebugFlags(sessDbg);
-
- // Check if NIO based socket code should be disabled
-
- if (cifsConfigBean.getDisableNIO())
- {
-
- // Disable NIO based code
-
- cifsConfig.setDisableNIOCode(true);
-
- // DEBUG
-
- if (logger.isDebugEnabled())
- logger.debug("NIO based code disabled for CIFS server");
- }
-
-
- // Check if a session timeout is configured
-
- Integer tmo = cifsConfigBean.getSessionTimeout();
- if (tmo != null)
- {
-
- // Validate the session timeout value
-
- if (tmo < 0 || tmo > MaxSessionTimeout)
- throw new AlfrescoRuntimeException("Session timeout out of range (0 - " + MaxSessionTimeout + ")");
-
- // Convert the session timeout to milliseconds
-
- cifsConfig.setSocketTimeout(tmo * 1000);
- }
- }
- catch (InvalidConfigurationException ex)
- {
- throw new AlfrescoRuntimeException(ex.getMessage());
- }
- }
-
- /**
- * Process the FTP server configuration
- */
- protected void processFTPServerConfig()
- {
- // If the configuration section is not valid then FTP is disabled
-
- if (ftpConfigBean == null)
- {
- removeConfigSection(FTPConfigSection.SectionName);
- return;
- }
-
- // Check if the server has been disabled
-
- if (!ftpConfigBean.getServerEnabled())
- {
- removeConfigSection(FTPConfigSection.SectionName);
- return;
- }
-
- // Create the FTP configuration section
-
- FTPConfigSection ftpConfig = new FTPConfigSection(this);
-
- try
- {
- // Check for a bind address
-
- String bindText = ftpConfigBean.getBindTo();
- if (bindText != null && bindText.length() > 0 && !bindText.equals(BIND_TO_IGNORE))
- {
-
- // Validate the bind address
-
- try
- {
-
- // Check the bind address
-
- InetAddress bindAddr = InetAddress.getByName(bindText);
-
- // Set the bind address for the FTP server
-
- ftpConfig.setFTPBindAddress(bindAddr);
- }
- catch (UnknownHostException ex)
- {
- throw new AlfrescoRuntimeException("Invalid FTP bindto address, " + bindText);
- }
- }
-
- // Check for an FTP server port
-
- Integer port = ftpConfigBean.getPort();
- if (port != null)
- {
- ftpConfig.setFTPPort(port);
- if (ftpConfig.getFTPPort() <= 0 || ftpConfig.getFTPPort() >= 65535)
- throw new AlfrescoRuntimeException("FTP server port out of valid range");
- }
- else
- {
-
- // Use the default FTP port
-
- ftpConfig.setFTPPort(DefaultFTPServerPort);
- }
-
- // Check if anonymous login is allowed
-
- if (ftpConfigBean.getAllowAnonymous())
- {
-
- // Enable anonymous login to the FTP server
-
- ftpConfig.setAllowAnonymousFTP(true);
-
- // Check if an anonymous account has been specified
-
- String anonAcc = ftpConfigBean.getAnonymousAccount();
- if (anonAcc != null && anonAcc.length() > 0)
- {
-
- // Set the anonymous account name
-
- ftpConfig.setAnonymousFTPAccount(anonAcc);
-
- // Check if the anonymous account name is valid
-
- if (ftpConfig.getAnonymousFTPAccount() == null || ftpConfig.getAnonymousFTPAccount().length() == 0)
- throw new AlfrescoRuntimeException("Anonymous FTP account invalid");
- }
- else
- {
-
- // Use the default anonymous account name
-
- ftpConfig.setAnonymousFTPAccount(DefaultFTPAnonymousAccount);
- }
- }
- else
- {
-
- // Disable anonymous logins
-
- ftpConfig.setAllowAnonymousFTP(false);
- }
-
- // Check if a root path has been specified
-
- String rootPath = ftpConfigBean.getRootDirectory();
- if (rootPath != null && rootPath.length() > 0)
- {
- try
- {
-
- // Parse the path
-
- new FTPPath(rootPath);
-
- // Set the root path
-
- ftpConfig.setFTPRootPath(rootPath);
- }
- catch (InvalidPathException ex)
- {
- throw new AlfrescoRuntimeException("Invalid FTP root directory, " + rootPath);
- }
- }
-
- // Check for FTP debug flags
-
- String flags = ftpConfigBean.getDebugFlags();
- int ftpDbg = 0;
-
- if (flags != null)
- {
-
- // Parse the flags
-
- flags = flags.toUpperCase();
- StringTokenizer token = new StringTokenizer(flags, ",");
-
- while (token.hasMoreTokens())
- {
-
- // Get the current debug flag token
-
- String dbg = token.nextToken().trim();
-
- // Find the debug flag name
-
- int idx = 0;
-
- while (idx < m_ftpDebugStr.length && m_ftpDebugStr[idx].equalsIgnoreCase(dbg) == false)
- idx++;
-
- if (idx >= m_ftpDebugStr.length)
- throw new AlfrescoRuntimeException("Invalid FTP debug flag, " + dbg);
-
- // Set the debug flag
-
- ftpDbg += 1 << idx;
- }
-
- // Set the FTP debug flags
-
- ftpConfig.setFTPDebug(ftpDbg);
- }
-
- // Check if a character set has been specified
-
- String charSet = ftpConfigBean.getCharSet();
- if (charSet != null && charSet.length() > 0)
- {
-
- try
- {
-
- // Validate the character set name
-
- Charset.forName(charSet);
-
- // Set the FTP character set
-
- ftpConfig.setFTPCharacterSet(charSet);
- }
- catch (IllegalCharsetNameException ex)
- {
- throw new AlfrescoRuntimeException("Illegal character set name, " + charSet);
- }
- catch (UnsupportedCharsetException ex)
- {
- throw new AlfrescoRuntimeException("Unsupported character set name, " + charSet);
- }
- }
-
- // Check if an authenticator has been specified
-
- FTPAuthenticator auth = ftpConfigBean.getAuthenticator();
- if (auth != null)
- {
-
- // Initialize and set the authenticator class
-
- ftpConfig.setAuthenticator(auth);
- }
- else
- throw new AlfrescoRuntimeException("FTP authenticator not specified");
-
- // Check if a data port range has been specified
-
- if ( ftpConfigBean.getDataPortFrom() != 0 && ftpConfigBean.getDataPortTo() != 0) {
-
- // Range check the data port values
-
- int rangeFrom = ftpConfigBean.getDataPortFrom();
- int rangeTo = ftpConfigBean.getDataPortTo();
-
- if ( rangeFrom != 0 && rangeTo != 0) {
-
- // Validate the FTP data port range
-
- if ( rangeFrom < 1024 || rangeFrom > 65535)
- throw new InvalidConfigurationException("Invalid FTP data port range from value, " + rangeFrom);
-
- if ( rangeTo < 1024 || rangeTo > 65535)
- throw new InvalidConfigurationException("Invalid FTP data port range to value, " + rangeTo);
-
- if ( rangeFrom >= rangeTo)
- throw new InvalidConfigurationException("Invalid FTP data port range, " + rangeFrom + "-" + rangeTo);
-
- // Set the FTP data port range
-
- ftpConfig.setFTPDataPortLow(rangeFrom);
- ftpConfig.setFTPDataPortHigh(rangeTo);
-
- // Log the data port range
-
- logger.info("FTP server data ports restricted to range " + rangeFrom + ":" + rangeTo);
- }
- }
-
- // FTPS parameter parsing
- //
- // Check if a key store path has been specified
-
- if ( ftpConfigBean.getKeyStorePath() != null && ftpConfigBean.getKeyStorePath().length() > 0) {
-
- // Get the path to the key store, check that the file exists
-
- String keyStorePath = ftpConfigBean.getKeyStorePath();
- File keyStoreFile = new File( keyStorePath);
-
- if ( keyStoreFile.exists() == false)
- throw new InvalidConfigurationException("FTPS key store file does not exist, " + keyStorePath);
- else if ( keyStoreFile.isDirectory())
- throw new InvalidConfigurationException("FTPS key store path is a directory, " + keyStorePath);
-
- // Set the key store path
-
- ftpConfig.setKeyStorePath( keyStorePath);
- }
-
- // Check if the trust store path has been specified
-
- if ( ftpConfigBean.getTrustStorePath() != null && ftpConfigBean.getTrustStorePath().length() > 0) {
-
- // Get the path to the trust store, check that the file exists
-
- String trustStorePath = ftpConfigBean.getTrustStorePath();
- File trustStoreFile = new File( trustStorePath);
-
- if ( trustStoreFile.exists() == false)
- throw new InvalidConfigurationException("FTPS trust store file does not exist, " + trustStorePath);
- else if ( trustStoreFile.isDirectory())
- throw new InvalidConfigurationException("FTPS trust store path is a directory, " + trustStorePath);
-
- // Set the trust store path
-
- ftpConfig.setTrustStorePath( trustStorePath);
- }
-
- // Check if the store passphrase has been specified
-
- if ( ftpConfigBean.getPassphrase() != null && ftpConfigBean.getPassphrase().length() > 0) {
-
- // Set the store passphrase
-
- ftpConfig.setPassphrase( ftpConfigBean.getPassphrase());
- }
-
- // Check if only secure sessions should be allowed to logon
-
- if ( ftpConfigBean.hasRequireSecureSession()) {
-
- // Only allow secure sessions to logon to the FTP server
-
- ftpConfig.setRequireSecureSession( true);
- }
-
- // Check that all the required FTPS parameters have been set
-
- if ( ftpConfig.getKeyStorePath() != null || ftpConfig.getTrustStorePath() != null || ftpConfig.getPassphrase() != null) {
-
- // Make sure all parameters are set
-
- if ( ftpConfig.getKeyStorePath() == null || ftpConfig.getTrustStorePath() == null || ftpConfig.getPassphrase() == null)
- throw new InvalidConfigurationException("FTPS configuration requires keyStore, trustStore and storePassphrase to be set");
- }
-
- // Check if SSLEngine debug output should be enabled
-
- if ( ftpConfigBean.hasSslEngineDebug()) {
-
- // Enable SSLEngine debug output
-
- System.setProperty("javax.net.debug", "ssl,handshake");
- }
- }
- catch (InvalidConfigurationException ex)
- {
- throw new AlfrescoRuntimeException(ex.getMessage());
- }
- }
-
- /**
- * Process the NFS server configuration
- */
- protected void processNFSServerConfig()
- {
- // If the configuration section is not valid then NFS is disabled
-
- if (nfsConfigBean == null)
- {
- removeConfigSection(NFSConfigSection.SectionName);
- return;
- }
-
- // Check if the server has been disabled
-
- if (!nfsConfigBean.getServerEnabled())
- {
- removeConfigSection(NFSConfigSection.SectionName);
- return;
- }
-
- // Create the NFS configuration section
-
- NFSConfigSection nfsConfig = new NFSConfigSection(this);
-
- try
- {
- // Check if the port mapper is enabled
-
- if (nfsConfigBean.getPortMapperEnabled())
- nfsConfig.setNFSPortMapper(true);
-
- // Check for the thread pool size
-
- Integer poolSize = nfsConfigBean.getThreadPool();
-
- if (poolSize != null)
- {
-
- // Range check the pool size value
-
- if (poolSize < 4)
- throw new AlfrescoRuntimeException("NFS thread pool size is below minimum of 4");
-
- // Set the thread pool size
-
- nfsConfig.setNFSThreadPoolSize(poolSize);
- }
-
- // NFS packet pool size
-
- Integer pktPoolSize = nfsConfigBean.getPacketPool();
-
- if (pktPoolSize != null)
- {
- // Range check the pool size value
-
- if (pktPoolSize < 10)
- throw new AlfrescoRuntimeException("NFS packet pool size is below minimum of 10");
-
- if (pktPoolSize < nfsConfig.getNFSThreadPoolSize() + 1)
- throw new AlfrescoRuntimeException("NFS packet pool must be at least thread pool size plus one");
-
- // Set the packet pool size
-
- nfsConfig.setNFSPacketPoolSize(pktPoolSize);
- }
-
- // Check for a port mapper server port
-
- Integer portMapperPort = nfsConfigBean.getPortMapperPort();
- if (portMapperPort != null)
- {
- nfsConfig.setPortMapperPort(portMapperPort);
- if ( nfsConfig.getPortMapperPort() == -1) {
- logger.info("NFS portmapper registration disabled");
- }
- else {
- if (nfsConfig.getPortMapperPort() <= 0 || nfsConfig.getPortMapperPort() >= 65535)
- throw new AlfrescoRuntimeException("Port mapper server port out of valid range");
- }
- }
-
- // Check for a mount server port
-
- Integer mountServerPort = nfsConfigBean.getMountServerPort();
- if (mountServerPort != null)
- {
- nfsConfig.setMountServerPort(mountServerPort);
- if (nfsConfig.getMountServerPort() < 0 || nfsConfig.getMountServerPort() >= 65535)
- throw new AlfrescoRuntimeException("Mount server port out of valid range");
- }
-
- // Check for an NFS server port
-
- Integer nfsServerPort = nfsConfigBean.getNfsServerPort();
- if (nfsServerPort != null)
- {
- nfsConfig.setNFSServerPort(nfsServerPort);
- if (nfsConfig.getNFSServerPort() < 0 || nfsConfig.getNFSServerPort() >= 65535)
- throw new AlfrescoRuntimeException("NFS server port out of valid range");
- }
-
- // Check for an RPC registration port
-
- Integer rpcRegisterPort = nfsConfigBean.getRpcRegisterPort();
- if ( rpcRegisterPort != null)
- {
- nfsConfig.setRPCRegistrationPort( rpcRegisterPort);
- if ( nfsConfig.getRPCRegistrationPort() < 0 || nfsConfig.getRPCRegistrationPort() >= 65535)
- throw new AlfrescoRuntimeException("RPC registrtion port out of valid range");
- }
-
- // Check for NFS debug flags
-
- String flags = nfsConfigBean.getDebugFlags();
- int nfsDbg = 0;
-
- if (flags != null && flags.length() > 0)
- {
-
- // Parse the flags
-
- flags = flags.toUpperCase();
- StringTokenizer token = new StringTokenizer(flags, ",");
-
- while (token.hasMoreTokens())
- {
-
- // Get the current debug flag token
-
- String dbg = token.nextToken().trim();
-
- // Find the debug flag name
-
- int idx = 0;
-
- while (idx < m_nfsDebugStr.length && m_nfsDebugStr[idx].equalsIgnoreCase(dbg) == false)
- idx++;
-
- if (idx >= m_nfsDebugStr.length)
- throw new AlfrescoRuntimeException("Invalid NFS debug flag, " + dbg);
-
- // Set the debug flag
-
- nfsDbg += 1 << idx;
- }
-
- // Set the NFS debug flags
-
- nfsConfig.setNFSDebug(nfsDbg);
- }
-
- // Check if mount server debug output is enabled
-
- if (nfsConfigBean.getMountServerDebug())
- nfsConfig.setMountServerDebug(true);
-
- // Check if portmapper debug output is enabled
-
- if (nfsConfigBean.getPortMapperDebug())
- nfsConfig.setPortMapperDebug(true);
-
- // Create the RPC authenticator
- RpcAuthenticator rpcAuthenticator = nfsConfigBean.getRpcAuthenticator();
- if (rpcAuthenticator != null)
- {
- nfsConfig.setRpcAuthenticator(rpcAuthenticator);
- }
- else
- throw new AlfrescoRuntimeException("RPC authenticator configuration missing, require user mappings");
- }
- catch (InvalidConfigurationException ex)
- {
- throw new AlfrescoRuntimeException(ex.getMessage());
- }
- }
-
- /**
- * Process the filesystems configuration
- */
- protected void processFilesystemsConfig()
- {
- // Create the filesystems configuration section
-
- FilesystemsConfigSection fsysConfig = new FilesystemsConfigSection(this);
-
- // Access the security configuration section
-
- SecurityConfigSection secConfig = (SecurityConfigSection) getConfigSection(SecurityConfigSection.SectionName);
-
- // Process the filesystems list
-
- if (this.filesystemContexts != null)
- {
-
- // Add the filesystems
-
- for (DeviceContext filesystem : this.filesystemContexts)
- {
-
- // Get the current filesystem configuration
-
- try
- {
- // Check the filesystem type and use the appropriate driver
-
- DiskSharedDevice filesys = null;
-
- if (filesystem instanceof AVMContext)
- {
- // Create a new filesystem driver instance and register a context for
- // the new filesystem
-
- ExtendedDiskInterface filesysDriver = getAvmDiskInterface();
- DiskDeviceContext diskCtx = (DiskDeviceContext) filesystem;
-
- if(clusterConfigBean != null && clusterConfigBean.getClusterEnabled())
- {
- if(logger.isDebugEnabled())
- {
- logger.debug("start hazelcast cache : " + clusterConfigBean.getClusterName() + ", shareName: "+ diskCtx.getShareName());
- }
- GenericConfigElement hazelConfig = createClusterConfig(diskCtx.getShareName());
- HazelCastClusterFileStateCache hazel = new HazelCastClusterFileStateCache();
- hazel.initializeCache(hazelConfig, this);
- diskCtx.setStateCache(hazel);
- }
- else
- {
- // Check if the filesystem uses the file state cache, if so then add to the file state reaper
- StandaloneFileStateCache standaloneCache = new StandaloneFileStateCache();
- standaloneCache.initializeCache( new GenericConfigElement( ""), this);
- diskCtx.setStateCache(standaloneCache);
- }
- if ( diskCtx.hasStateCache()) {
-
- // Register the state cache with the reaper thread
-
- fsysConfig.addFileStateCache( filesystem.getDeviceName(), diskCtx.getStateCache());
- }
-
- filesysDriver.registerContext(filesystem);
-
- // Create the shared filesystem
-
- filesys = new DiskSharedDevice(filesystem.getDeviceName(), filesysDriver, (AVMContext)filesystem);
- filesys.setConfiguration( this);
- // Start the filesystem
-
- ((AVMContext)filesystem).startFilesystem(filesys);
- }
- else
- {
- // Create a new filesystem driver instance and register a context for
- // the new filesystem
-
- ExtendedDiskInterface filesysDriver = getRepoDiskInterface();
- ContentContext filesysContext = (ContentContext) filesystem;
-
- if(clusterConfigBean != null && clusterConfigBean.getClusterEnabled())
- {
- if(logger.isDebugEnabled())
- {
- logger.debug("start hazelcast cache : " + clusterConfigBean.getClusterName() + ", shareName: "+ filesysContext.getShareName());
- }
- GenericConfigElement hazelConfig = createClusterConfig(filesysContext.getShareName());
- HazelCastClusterFileStateCache hazel = new HazelCastClusterFileStateCache();
- hazel.initializeCache(hazelConfig, this);
- filesysContext.setStateCache(hazel);
- }
- else
- {
- // Create state cache here and inject
- StandaloneFileStateCache standaloneCache = new StandaloneFileStateCache();
- standaloneCache.initializeCache( new GenericConfigElement( ""), this);
- filesysContext.setStateCache(standaloneCache);
- }
-
- if ( filesysContext.hasStateCache()) {
-
- // Register the state cache with the reaper thread
-
- fsysConfig.addFileStateCache( filesystem.getDeviceName(), filesysContext.getStateCache());
-
- // Create the lock manager for the context.
- FileStateLockManager lockMgr = new FileStateLockManager(filesysContext.getStateCache());
- filesysContext.setLockManager(lockMgr);
- filesysContext.setOpLockManager(lockMgr);
- }
-
- filesysDriver.registerContext(filesystem);
-
- // Check if an access control list has been specified
-
- AccessControlList acls = null;
- AccessControlListBean accessControls = filesysContext.getAccessControlList();
- if (accessControls != null)
- {
- // Parse the access control list
- acls = accessControls.toAccessControlList(secConfig);
- }
- else if (secConfig.hasGlobalAccessControls())
- {
-
- // Use the global access control list for this disk share
- acls = secConfig.getGlobalAccessControls();
- }
-
- // Create the shared filesystem
-
- filesys = new DiskSharedDevice(filesystem.getDeviceName(), filesysDriver, filesysContext);
- filesys.setConfiguration( this);
-
- // Add any access controls to the share
-
- filesys.setAccessControlList(acls);
-
-
-
- // Check if change notifications should be enabled
-
- if ( filesysContext.getDisableChangeNotifications() == false)
- filesysContext.enableChangeHandler( true);
-
- // Start the filesystem
-
- filesysContext.startFilesystem(filesys);
- }
-
- // Add the new filesystem
-
- fsysConfig.addShare(filesys);
- }
- catch (DeviceContextException ex)
- {
- throw new AlfrescoRuntimeException("Error creating filesystem " + filesystem.getDeviceName(), ex);
- }
- catch (InvalidConfigurationException ex)
- {
- throw new AlfrescoRuntimeException(ex.getMessage(), ex);
- }
- }
- }
- else
- {
- // No filesystems defined
-
- logger.warn("No filesystems defined");
- }
-
- // Check if shares should be added for all AVM stores
- if (this.avmAllStores && getAvmDiskInterface() != null)
- {
- // Get the list of store names
-
- AVMDiskDriver avmDriver = (AVMDiskDriver) getAvmDiskInterface();
- StringList storeNames = avmDriver.getAVMStoreNames();
-
- // Add shares for each of the store names, if the share name does not already exist
-
- if (storeNames != null && storeNames.numberOfStrings() > 0)
- {
- // Add a share for each store
-
- for (int i = 0; i < storeNames.numberOfStrings(); i++)
- {
- String storeName = storeNames.getStringAt(i);
-
- // Check if a share of the same name already exists
-
- if (fsysConfig.getShares().findShare(storeName, ShareType.DISK, true) == null)
- {
- // Create the new share for the store
-
- AVMContext avmContext = new AVMContext(storeName, storeName + ":/", AVMContext.VERSION_HEAD);
-// avmContext.enableStateCache(this, true);
-
- // Create the shared filesystem
-
- DiskSharedDevice filesys = new DiskSharedDevice(storeName, avmDriver, avmContext);
- filesys.setConfiguration( this);
-
- fsysConfig.addShare( filesys);
-
- // DEBUG
-
- if (logger.isDebugEnabled())
- logger.debug("Added AVM share " + storeName);
- }
- }
- }
- }
-
-
- // home folder share mapper could be declared in security config
- }
-
- /**
- * Process the security configuration
- */
- protected void processSecurityConfig()
- {
- // Create the security configuration section
-
- SecurityConfigSection secConfig = new SecurityConfigSection(this);
-
- try
- {
- // Check if global access controls have been specified
-
- AccessControlListBean accessControls = securityConfigBean.getGlobalAccessControl();
-
- if (accessControls != null)
- {
- // Parse the access control list
- AccessControlList acls = accessControls.toAccessControlList(secConfig);
- if (acls != null)
- secConfig.setGlobalAccessControls(acls);
- }
-
-
- // Check if a JCE provider class has been specified
-
- String jceProvider = securityConfigBean.getJCEProvider();
- if (jceProvider != null && jceProvider.length() > 0)
- {
-
- // Set the JCE provider
-
- secConfig.setJCEProvider(jceProvider);
- }
- else
- {
- // Use the default Bouncy Castle JCE provider
-
- secConfig.setJCEProvider("org.bouncycastle.jce.provider.BouncyCastleProvider");
- }
-
- // Check if a share mapper has been specified
-
- ShareMapper shareMapper = securityConfigBean.getShareMapper();
- if (shareMapper != null)
- {
- // Associate the share mapper
- secConfig.setShareMapper(shareMapper);
- }
- else
- {
- // Check if the tenant service is enabled
- if (m_tenantService != null && m_tenantService.isEnabled())
- {
- // Initialize the multi-tenancy share mapper
-
- secConfig.setShareMapper("org.alfresco.filesys.alfresco.MultiTenantShareMapper",
- new GenericConfigElement("shareMapper"));
-
- }
- }
-
- // Check if any domain mappings have been specified
-
- List mappings = securityConfigBean.getDomainMappings();
- if (mappings != null)
- {
- DomainMapping mapping = null;
-
- for (DomainMappingConfigBean domainMap : mappings)
- {
- // Get the domain name
-
- String name = domainMap.getName();
-
- // Check if the domain is specified by subnet or range
-
- String subnetStr = domainMap.getSubnet();
- String rangeFromStr;
- if (subnetStr != null && subnetStr.length() > 0)
- {
- String maskStr = domainMap.getMask();
-
- // Parse the subnet and mask, to validate and convert to int values
-
- int subnet = IPAddress.parseNumericAddress(subnetStr);
- int mask = IPAddress.parseNumericAddress(maskStr);
-
- if (subnet == 0 || mask == 0)
- throw new AlfrescoRuntimeException("Invalid subnet/mask for domain mapping " + name);
-
- // Create the subnet domain mapping
-
- mapping = new SubnetDomainMapping(name, subnet, mask);
- }
- else if ((rangeFromStr = domainMap.getRangeFrom()) != null && rangeFromStr.length() > 0)
- {
- String rangeToStr = domainMap.getRangeTo();
-
- // Parse the range from/to values and convert to int values
-
- int rangeFrom = IPAddress.parseNumericAddress(rangeFromStr);
- int rangeTo = IPAddress.parseNumericAddress(rangeToStr);
-
- if (rangeFrom == 0 || rangeTo == 0)
- throw new AlfrescoRuntimeException("Invalid address range domain mapping " + name);
-
- // Create the subnet domain mapping
-
- mapping = new RangeDomainMapping(name, rangeFrom, rangeTo);
- }
- else
- throw new AlfrescoRuntimeException("Invalid domain mapping specified");
-
- // Add the domain mapping
-
- secConfig.addDomainMapping(mapping);
- }
- }
- }
- catch (InvalidConfigurationException ex)
- {
- throw new AlfrescoRuntimeException(ex.getMessage());
- }
- }
-
- /**
- * Process the core server configuration
- *
- * @exception InvalidConfigurationException
- */
- protected void processCoreServerConfig() throws InvalidConfigurationException
- {
- // Create the core server configuration section
-
- CoreServerConfigSection coreConfig = new CoreServerConfigSection(this);
-
- // Check if the CIFS server is not enabled, do not create the thread/memory pools
-
- if ( cifsConfigBean == null || cifsConfigBean.getServerEnabled() == false)
- return;
-
- // Check if the server core element has been specified
-
- if (coreServerConfigBean == null)
- {
-
- // Configure a default memory pool
-
- coreConfig.setMemoryPool(DefaultMemoryPoolBufSizes, DefaultMemoryPoolInitAlloc, DefaultMemoryPoolMaxAlloc);
-
- // Configure a default thread pool size
-
- coreConfig.setThreadPool(DefaultThreadPoolInit, DefaultThreadPoolMax);
- return;
- }
-
- // Check if the thread pool size has been specified
-
- Integer initSize = coreServerConfigBean.getThreadPoolInit();
- if (initSize == null)
- {
- initSize = DefaultThreadPoolInit;
- }
- Integer maxSize = coreServerConfigBean.getThreadPoolMax();
- if (maxSize == null)
- {
- maxSize = DefaultThreadPoolMax;
- }
-
- // Range check the thread pool size
-
- if (initSize < ThreadRequestPool.MinimumWorkerThreads)
- throw new InvalidConfigurationException("Thread pool size below minimum allowed size");
-
- if (initSize > ThreadRequestPool.MaximumWorkerThreads)
- throw new InvalidConfigurationException("Thread pool size above maximum allowed size");
-
- // Range check the maximum thread pool size
-
- if (maxSize < ThreadRequestPool.MinimumWorkerThreads)
- throw new InvalidConfigurationException("Thread pool maximum size below minimum allowed size");
-
- if (maxSize > ThreadRequestPool.MaximumWorkerThreads)
- throw new InvalidConfigurationException("Thread pool maximum size above maximum allowed size");
-
- if (maxSize < initSize)
- throw new InvalidConfigurationException("Initial size is larger than maxmimum size");
-
- // Configure the thread pool
-
- coreConfig.setThreadPool(initSize, maxSize);
-
- // Check if thread pool debug output is enabled
-
- if (coreServerConfigBean.getThreadPoolDebug())
- coreConfig.getThreadPool().setDebug(true);
-
- // Check if the packet sizes/allocations have been specified
-
- List packetSizes = coreServerConfigBean.getMemoryPacketSizes();
- if (packetSizes != null)
- {
-
- // Calculate the array size for the packet size/allocation arrays
-
- int elemCnt = packetSizes.size();
-
- // Create the packet size, initial allocation and maximum allocation arrays
-
- int[] pktSizes = new int[elemCnt];
- int[] initSizes = new int[elemCnt];
- int[] maxSizes = new int[elemCnt];
-
- int elemIdx = 0;
-
- // Process the packet size elements
- for (MemoryPacketConfigBean curChild : packetSizes)
- {
-
- // Get the packet size
-
- int pktSize = -1;
-
- Long pktSizeLong = curChild.getSize();
- if (pktSizeLong == null)
- throw new InvalidConfigurationException("Memory pool packet size not specified");
-
- // Parse the packet size
-
- try
- {
- pktSize = MemorySize.getByteValueInt(pktSizeLong.toString());
- }
- catch (NumberFormatException ex)
- {
- throw new InvalidConfigurationException("Memory pool packet size, invalid size value, "
- + pktSizeLong);
- }
-
- // Make sure the packet sizes have been specified in ascending order
-
- if (elemIdx > 0 && pktSizes[elemIdx - 1] >= pktSize)
- throw new InvalidConfigurationException(
- "Invalid packet size specified, less than/equal to previous packet size");
-
- // Get the initial allocation for the current packet size
- Integer initAlloc = curChild.getInit();
- if (initAlloc == null)
- throw new InvalidConfigurationException("Memory pool initial allocation not specified");
-
- // Range check the initial allocation
-
- if (initAlloc < MemoryPoolMinimumAllocation)
- throw new InvalidConfigurationException("Initial memory pool allocation below minimum of "
- + MemoryPoolMinimumAllocation);
-
- if (initAlloc > MemoryPoolMaximumAllocation)
- throw new InvalidConfigurationException("Initial memory pool allocation above maximum of "
- + MemoryPoolMaximumAllocation);
-
- // Get the maximum allocation for the current packet size
-
- Integer maxAlloc = curChild.getMax();
- if (maxAlloc == null)
- throw new InvalidConfigurationException("Memory pool maximum allocation not specified");
-
- // Range check the maximum allocation
-
- if (maxAlloc < MemoryPoolMinimumAllocation)
- throw new InvalidConfigurationException("Maximum memory pool allocation below minimum of "
- + MemoryPoolMinimumAllocation);
-
- if (initAlloc > MemoryPoolMaximumAllocation)
- throw new InvalidConfigurationException("Maximum memory pool allocation above maximum of "
- + MemoryPoolMaximumAllocation);
-
- // Set the current packet size elements
-
- pktSizes[elemIdx] = pktSize;
- initSizes[elemIdx] = initAlloc;
- maxSizes[elemIdx] = maxAlloc;
-
- elemIdx++;
- }
-
- // Check if all elements were used in the packet size/allocation arrays
-
- if (elemIdx < pktSizes.length)
- {
-
- // Re-allocate the packet size/allocation arrays
-
- int[] newPktSizes = new int[elemIdx];
- int[] newInitSizes = new int[elemIdx];
- int[] newMaxSizes = new int[elemIdx];
-
- // Copy the values to the shorter arrays
-
- System.arraycopy(pktSizes, 0, newPktSizes, 0, elemIdx);
- System.arraycopy(initSizes, 0, newInitSizes, 0, elemIdx);
- System.arraycopy(maxSizes, 0, newMaxSizes, 0, elemIdx);
-
- // Move the new arrays into place
-
- pktSizes = newPktSizes;
- initSizes = newInitSizes;
- maxSizes = newMaxSizes;
- }
-
- // Configure the memory pool
-
- coreConfig.setMemoryPool(pktSizes, initSizes, maxSizes);
- }
- else
- {
-
- // Configure a default memory pool
-
- coreConfig.setMemoryPool(DefaultMemoryPoolBufSizes, DefaultMemoryPoolInitAlloc, DefaultMemoryPoolMaxAlloc);
- }
- }
-
- /**
- * Initialise a runtime context - not configured through spring e.g MT.
- *
- * TODO - what about desktop actions etc?
- *
- * @param diskCtx
- */
- public void initialiseRuntimeContext(AlfrescoContext diskCtx)
- {
- if (diskCtx.getStateCache() == null) {
-
- // Set the state cache, use a hard coded standalone cache for now
- FilesystemsConfigSection filesysConfig = (FilesystemsConfigSection) this.getConfigSection( FilesystemsConfigSection.SectionName);
-
- if ( filesysConfig != null)
- {
-
- try
- {
- if(clusterConfigBean != null && clusterConfigBean.getClusterEnabled())
- {
- if(logger.isDebugEnabled())
- {
- logger.debug("start hazelcast cache : " + clusterConfigBean.getClusterName() + ", shareName: "+ diskCtx.getShareName());
- }
- GenericConfigElement hazelConfig = createClusterConfig(diskCtx.getShareName());
- HazelCastClusterFileStateCache hazel = new HazelCastClusterFileStateCache();
- hazel.initializeCache(hazelConfig, this);
- diskCtx.setStateCache(hazel);
- }
- else
- {
- // Create a standalone state cache
- StandaloneFileStateCache standaloneCache = new StandaloneFileStateCache();
- standaloneCache.initializeCache( new GenericConfigElement( ""), this);
- filesysConfig.addFileStateCache( diskCtx.getDeviceName(), standaloneCache);
- diskCtx.setStateCache( standaloneCache);
- }
-
- FileStateLockManager lockMgr = new FileStateLockManager(diskCtx.getStateCache());
- diskCtx.setLockManager(lockMgr);
- diskCtx.setOpLockManager(lockMgr);
- }
- catch ( InvalidConfigurationException ex)
- {
- throw new AlfrescoRuntimeException( "Failed to initialize standalone state cache for " + diskCtx.getDeviceName());
- }
- }
- }
- }
-
-
- @Override
- protected void processClusterConfig() throws InvalidConfigurationException
- {
-
-// Done by org.alfresco.jlan.server.config.ServerConfiguration.closeConfiguration
-// /**
-// * Close the old hazelcast configuration
-// */
-// ClusterConfigSection secConfig = (ClusterConfigSection) getConfigSection(ClusterConfigSection.SectionName);
-// {
-// if(secConfig != null)
-// {
-// secConfig.closeConfig();
-// }
-// }
-
- if (clusterConfigBean == null || !clusterConfigBean.getClusterEnabled())
- {
- removeConfigSection(ClusterConfigSection.SectionName);
- logger.info("Filesystem cluster cache not enabled");
- return;
- }
-
- String clusterName = clusterConfigBean.getClusterName();
- if (clusterName == null || clusterName.length() == 0)
- {
- throw new InvalidConfigurationException("Cluster name not specified or invalid");
- }
-
- String clusterFile = clusterConfigBean.getConfigFile();
- if (clusterFile == null || clusterFile.length() == 0)
- {
- throw new InvalidConfigurationException("Cluster config file not specified or invalid");
- }
-
- // New Hazelcast instance created here within the ClusterConfigSection
+
+ /**
+ * Default constructor
+ */
+ public ServerConfigurationBean()
+ {
+ super("");
+ }
+
+ /**
+ * Class constructor
+ *
+ * @param srvName
+ * String
+ */
+ public ServerConfigurationBean(String srvName)
+ {
+ super(srvName);
+ }
+
+ public void setCifsConfigBean(CIFSConfigBean cifsConfigBean)
+ {
+ this.cifsConfigBean = cifsConfigBean;
+ }
+
+ public void setFtpConfigBean(FTPConfigBean ftpConfigBean)
+ {
+ this.ftpConfigBean = ftpConfigBean;
+ }
+
+ public void setNfsConfigBean(NFSConfigBean nfsConfigBean)
+ {
+ this.nfsConfigBean = nfsConfigBean;
+ }
+
+ public void setFilesystemContexts(List filesystemContexts)
+ {
+ this.filesystemContexts = filesystemContexts;
+ }
+
+ public void setAvmAllStores(boolean avmAllStores)
+ {
+ this.avmAllStores = avmAllStores;
+ }
+
+ public void setSecurityConfigBean(SecurityConfigBean securityConfigBean)
+ {
+ this.securityConfigBean = securityConfigBean;
+ }
+
+ public void setCoreServerConfigBean(CoreServerConfigBean coreServerConfigBean)
+ {
+ this.coreServerConfigBean = coreServerConfigBean;
+ }
+
+ public void setClusterConfigBean(ClusterConfigBean clusterConfigBean)
+ {
+ this.clusterConfigBean = clusterConfigBean;
+ }
+
+ /**
+ * Process the CIFS server configuration
+ */
+ protected void processCIFSServerConfig()
+ {
+ // If the configuration section is not valid then CIFS is disabled
+
+ if (cifsConfigBean == null)
+ {
+ removeConfigSection(CIFSConfigSection.SectionName);
+ return;
+ }
+
+ // Check if the server has been disabled
+ if (!cifsConfigBean.getServerEnabled())
+ {
+ removeConfigSection(CIFSConfigSection.SectionName);
+ return;
+ }
+
+ // Before we go any further, let's make sure there's a compatible authenticator in the authentication chain.
+ ICifsAuthenticator authenticator = cifsConfigBean.getAuthenticator();
+ if (authenticator == null || authenticator instanceof ActivateableBean && !((ActivateableBean)authenticator).isActive())
+ {
+ logger.warn("No enabled CIFS authenticator found in authentication chain. CIFS Server disabled");
+ removeConfigSection(CIFSConfigSection.SectionName);
+ return;
+ }
+
+ // Create the CIFS server configuration section
+
+ CIFSConfigSection cifsConfig = new CIFSConfigSection(this);
+
+ try
+ {
+ // Check if native code calls should be disabled on Windows
+ if (cifsConfigBean.getDisableNativeCode())
+ {
+ // Disable native code calls so that the JNI DLL is not required
+
+ cifsConfig.setNativeCodeDisabled(true);
+ m_disableNativeCode = true;
+
+ // Warning
+
+ logger.warn("CIFS server native calls disabled, JNI code will not be used");
+ }
+
+ // Get the network broadcast address
+ //
+ // Note: We need to set this first as the call to getLocalDomainName() may use a NetBIOS
+ // name lookup, so the broadcast mask must be set before then.
+
+ String broadcastAddess = cifsConfigBean.getBroadcastAddress();
+ if (broadcastAddess != null && broadcastAddess.length() > 0)
+ {
+
+ // Check if the broadcast mask is a valid numeric IP address
+
+ if (IPAddress.isNumericAddress(broadcastAddess) == false)
+ throw new AlfrescoRuntimeException("Invalid broadcast mask, must be n.n.n.n format");
+
+ // Set the network broadcast mask
+
+ cifsConfig.setBroadcastMask(broadcastAddess);
+ }
+
+ // Get the host configuration
+
+ String hostName = cifsConfigBean.getServerName();
+ if (hostName == null || hostName.length() == 0)
+ throw new AlfrescoRuntimeException("Host name not specified or invalid");
+
+ // Check if the host name contains the local name token
+
+ int pos = hostName.indexOf(TokenLocalName);
+ if (pos != -1)
+ {
+
+ // Get the local server name
+
+ String srvName = getLocalServerName(true);
+
+ // Rebuild the host name substituting the token with the local server name
+
+ StringBuilder hostStr = new StringBuilder();
+
+ hostStr.append(hostName.substring(0, pos));
+ hostStr.append(srvName);
+
+ pos += TokenLocalName.length();
+ if (pos < hostName.length())
+ hostStr.append(hostName.substring(pos));
+
+ hostName = hostStr.toString();
+
+ // Make sure the CIFS server name does not match the local server name
+
+ if (hostName.equals(srvName) && getPlatformType() == Platform.Type.WINDOWS)
+ throw new AlfrescoRuntimeException("CIFS server name must be unique");
+ }
+
+ // Check if the host name is longer than 15 characters. NetBIOS only allows a maximum of 16 characters in
+ // the
+ // server name with the last character reserved for the service type.
+
+ if (hostName.length() > 15)
+ {
+ // Truncate the CIFS server name
+
+ hostName = hostName.substring(0, 15);
+
+ // Output a warning
+
+ logger.warn("CIFS server name is longer than 15 characters, truncated to " + hostName);
+ }
+
+ // Set the CIFS server name
+
+ cifsConfig.setServerName(hostName.toUpperCase());
+ setServerName(hostName.toUpperCase());
+
+ // Get the domain/workgroup name
+
+ String domain = cifsConfigBean.getDomainName();
+ if (domain != null && domain.length() > 0)
+ {
+ // Set the domain/workgroup name
+
+ cifsConfig.setDomainName(domain.toUpperCase());
+ }
+ else
+ {
+ // Get the local domain/workgroup name
+
+ String localDomain = getLocalDomainName();
+
+ if (localDomain == null && (getPlatformType() != Platform.Type.WINDOWS || isNativeCodeDisabled()))
+ {
+ // Use a default domain/workgroup name
+
+ localDomain = "WORKGROUP";
+
+ // Output a warning
+
+ logger.error("Failed to get local domain/workgroup name, using default of " + localDomain);
+ logger.error("(This may be due to firewall settings or incorrect setting)");
+ }
+
+ // Set the local domain/workgroup that the CIFS server belongs to
+
+ cifsConfig.setDomainName(localDomain);
+ }
+
+ // Check for a server comment
+ String comment = cifsConfigBean.getServerComment();
+ if (comment != null && comment.length() > 0)
+ {
+ cifsConfig.setComment(comment);
+ }
+
+ // Check for a bind address
+
+ // Check if the network adapter name has been specified
+ String bindToAdapter = cifsConfigBean.getBindToAdapter();
+ String bindTo;
+
+ if (bindToAdapter != null && bindToAdapter.length() > 0)
+ {
+
+ // Get the IP address for the adapter
+
+ InetAddress bindAddr = parseAdapterName(bindToAdapter);
+
+ // Set the bind address for the server
+
+ cifsConfig.setSMBBindAddress(bindAddr);
+ }
+ else if ((bindTo = cifsConfigBean.getBindToAddress()) != null && bindTo.length() > 0
+ && !bindTo.equals(BIND_TO_IGNORE))
+ {
+
+ // Validate the bind address
+ try
+ {
+ // Check the bind address
+
+ InetAddress bindAddr = InetAddress.getByName(bindTo);
+
+ // Set the bind address for the server
+
+ cifsConfig.setSMBBindAddress(bindAddr);
+ }
+ catch (UnknownHostException ex)
+ {
+ throw new AlfrescoRuntimeException("Invalid CIFS server bind address");
+ }
+ }
+
+ // Get the authenticator
+
+ if (authenticator != null)
+ {
+ cifsConfig.setAuthenticator(authenticator);
+ }
+ else
+ throw new AlfrescoRuntimeException("CIFS authenticator not specified");
+
+ // Check if the host announcer has been disabled
+
+ if (!cifsConfigBean.getHostAccouncerEnabled())
+ {
+ // Switch off the host announcer
+
+ cifsConfig.setHostAnnouncer( false);
+
+ // Log that host announcements are not enabled
+
+ logger.info("Host announcements not enabled");
+ }
+ else
+ {
+ // Check for an announcement interval
+
+ Integer interval = cifsConfigBean.getHostAccounceInterval();
+ if (interval != null)
+ {
+ cifsConfig.setHostAnnounceInterval(interval);
+ }
+
+ // Check if the domain name has been set, this is required if the
+ // host announcer is enabled
+
+ if (cifsConfig.getDomainName() == null)
+ throw new AlfrescoRuntimeException("Domain name must be specified if host announcement is enabled");
+
+ // Enable host announcement
+
+ cifsConfig.setHostAnnouncer(true);
+ }
+
+ // Check if NetBIOS SMB is enabled
+ NetBIOSSMBConfigBean netBIOSSMBConfigBean = cifsConfigBean.getNetBIOSSMB();
+ if (netBIOSSMBConfigBean != null)
+ {
+ // Check if NetBIOS over TCP/IP is enabled for the current platform
+
+ String platformsStr = netBIOSSMBConfigBean.getPlatforms();
+ boolean platformOK = false;
+
+ if (platformsStr != null && platformsStr.length() > 0)
+ {
+ // Parse the list of platforms that NetBIOS over TCP/IP is to be enabled for and
+ // check if the current platform is included
+
+ EnumSet enabledPlatforms = parsePlatformString(platformsStr);
+ if (enabledPlatforms.contains(getPlatformType()))
+ platformOK = true;
+ }
+ else
+ {
+ // No restriction on platforms
+
+ platformOK = true;
+ }
+
+ // Enable the NetBIOS SMB support, if enabled for this platform
+
+ cifsConfig.setNetBIOSSMB(platformOK);
+
+ // Parse/check NetBIOS settings, if enabled
+
+ if (cifsConfig.hasNetBIOSSMB())
+ {
+ // Check if the broadcast mask has been specified
+
+ if (cifsConfig.getBroadcastMask() == null)
+ throw new AlfrescoRuntimeException("Network broadcast mask not specified");
+
+ // Check for a bind address
+
+ String bindto = netBIOSSMBConfigBean.getBindTo();
+ if (bindto != null && bindto.length() > 0 && !bindto.equals(BIND_TO_IGNORE))
+ {
+
+ // Validate the bind address
+
+ try
+ {
+
+ // Check the bind address
+
+ InetAddress bindAddr = InetAddress.getByName(bindto);
+
+ // Set the bind address for the NetBIOS name server
+
+ cifsConfig.setNetBIOSBindAddress(bindAddr);
+ }
+ catch (UnknownHostException ex)
+ {
+ throw new AlfrescoRuntimeException("Invalid NetBIOS bind address");
+ }
+ }
+ else if (cifsConfig.hasSMBBindAddress())
+ {
+
+ // Use the SMB bind address for the NetBIOS name server
+
+ cifsConfig.setNetBIOSBindAddress(cifsConfig.getSMBBindAddress());
+ }
+ else
+ {
+ // Get a list of all the local addresses
+
+ InetAddress[] addrs = null;
+
+ try
+ {
+ // Get the local server IP address list
+
+ addrs = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName());
+ }
+ catch (UnknownHostException ex)
+ {
+ logger.error("Failed to get local address list", ex);
+ }
+
+ // Check the address list for one or more valid local addresses filtering out the loopback
+ // address
+
+ int addrCnt = 0;
+
+ if (addrs != null)
+ {
+ for (int i = 0; i < addrs.length; i++)
+ {
+
+ // Check for a valid address, filter out '127.0.0.1' and '0.0.0.0' addresses
+
+ if (addrs[i].getHostAddress().equals("127.0.0.1") == false
+ && addrs[i].getHostAddress().equals("0.0.0.0") == false)
+ addrCnt++;
+ }
+ }
+
+ // Check if any addresses were found
+
+ if (addrCnt == 0)
+ {
+ // Enumerate the network adapter list
+
+ Enumeration niEnum = null;
+
+ try
+ {
+ niEnum = NetworkInterface.getNetworkInterfaces();
+ }
+ catch (SocketException ex)
+ {
+ }
+
+ if (niEnum != null)
+ {
+ while (niEnum.hasMoreElements())
+ {
+ // Get the current network interface
+
+ NetworkInterface ni = niEnum.nextElement();
+
+ // Enumerate the addresses for the network adapter
+
+ Enumeration niAddrs = ni.getInetAddresses();
+ if (niAddrs != null)
+ {
+ // Check for any valid addresses
+
+ while (niAddrs.hasMoreElements())
+ {
+ InetAddress curAddr = niAddrs.nextElement();
+
+ if (curAddr.getHostAddress().equals("127.0.0.1") == false
+ && curAddr.getHostAddress().equals("0.0.0.0") == false)
+ addrCnt++;
+ }
+ }
+ }
+
+ // DEBUG
+
+ if (addrCnt > 0 && logger.isDebugEnabled())
+ logger.debug("Found valid IP address from interface list");
+ }
+
+ // Check if we found any valid network addresses
+
+ if (addrCnt == 0)
+ {
+ // Log the available IP addresses
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Local address list dump :-");
+ if (addrs != null)
+ {
+ for (int i = 0; i < addrs.length; i++)
+ logger.debug(" Address: " + addrs[i]);
+ }
+ else
+ logger.debug(" No addresses");
+ }
+
+ // Throw an exception to stop the CIFS/NetBIOS name server from starting
+
+ throw new AlfrescoRuntimeException(
+ "Failed to get IP address(es) for the local server, check hosts file and/or DNS setup");
+ }
+ }
+ }
+
+ // Check if the session port has been specified
+
+ Integer portNum = netBIOSSMBConfigBean.getSessionPort();
+ if (portNum != null)
+ {
+ cifsConfig.setSessionPort(portNum);
+ if (cifsConfig.getSessionPort() <= 0 || cifsConfig.getSessionPort() >= 65535)
+ throw new AlfrescoRuntimeException("NetBIOS session port out of valid range");
+ }
+
+ // Check if the name port has been specified
+
+ portNum = netBIOSSMBConfigBean.getNamePort();
+ if (portNum != null)
+ {
+ cifsConfig.setNameServerPort(portNum);
+ if (cifsConfig.getNameServerPort() <= 0 || cifsConfig.getNameServerPort() >= 65535)
+ throw new AlfrescoRuntimeException("NetBIOS name port out of valid range");
+ }
+
+ // Check if the datagram port has been specified
+
+ portNum = netBIOSSMBConfigBean.getDatagramPort();
+ if (portNum != null)
+ {
+ cifsConfig.setDatagramPort(portNum);
+ if (cifsConfig.getDatagramPort() <= 0 || cifsConfig.getDatagramPort() >= 65535)
+ throw new AlfrescoRuntimeException("NetBIOS datagram port out of valid range");
+ }
+
+ // Check for a bind address
+
+ String attr = netBIOSSMBConfigBean.getBindTo();
+ if (attr != null && attr.length() > 0 && !attr.equals(BIND_TO_IGNORE))
+ {
+
+ // Validate the bind address
+
+ try
+ {
+
+ // Check the bind address
+
+ InetAddress bindAddr = InetAddress.getByName(attr);
+
+ // Set the bind address for the NetBIOS name server
+
+ cifsConfig.setNetBIOSBindAddress(bindAddr);
+ }
+ catch (UnknownHostException ex)
+ {
+ throw new InvalidConfigurationException(ex.toString());
+ }
+ }
+
+ // Check for a bind address using the adapter name
+
+ else if ((attr = netBIOSSMBConfigBean.getAdapter()) != null && attr.length() > 0)
+ {
+
+ // Get the bind address via the network adapter name
+
+ InetAddress bindAddr = parseAdapterName(attr);
+ cifsConfig.setNetBIOSBindAddress(bindAddr);
+ }
+ else if (cifsConfig.hasSMBBindAddress())
+ {
+
+ // Use the SMB bind address for the NetBIOS name server
+
+ cifsConfig.setNetBIOSBindAddress(cifsConfig.getSMBBindAddress());
+ }
+
+ }
+ }
+ else
+ {
+
+ // Disable NetBIOS SMB support
+
+ cifsConfig.setNetBIOSSMB(false);
+ }
+
+ // Check if TCP/IP SMB is enabled
+
+ TcpipSMBConfigBean tcpipSMBConfigBean = cifsConfigBean.getTcpipSMB();
+ if (tcpipSMBConfigBean != null)
+ {
+
+ // Check if native SMB is enabled for the current platform
+
+ String platformsStr = tcpipSMBConfigBean.getPlatforms();
+ boolean platformOK = false;
+
+ if (platformsStr != null)
+ {
+ // Parse the list of platforms that native SMB is to be enabled for and
+ // check if the current platform is included
+
+ EnumSet enabledPlatforms = parsePlatformString(platformsStr);
+ if (enabledPlatforms.contains(getPlatformType()))
+ platformOK = true;
+ }
+ else
+ {
+ // No restriction on platforms
+
+ platformOK = true;
+ }
+
+ // Enable the TCP/IP SMB support, if enabled for this platform
+
+ cifsConfig.setTcpipSMB(platformOK);
+
+ // Check if the port has been specified
+
+ Integer portNum = tcpipSMBConfigBean.getPort();
+ if (portNum != null)
+ {
+ cifsConfig.setTcpipSMBPort(portNum);
+ if (cifsConfig.getTcpipSMBPort() <= 0 || cifsConfig.getTcpipSMBPort() >= 65535)
+ throw new AlfrescoRuntimeException("TCP/IP SMB port out of valid range");
+ }
+
+ // Check if IPv6 support should be enabled
+
+ if ( tcpipSMBConfigBean.getIpv6Enabled())
+ {
+ try
+ {
+ // Use the IPv6 bind all address
+
+ cifsConfig.setSMBBindAddress( InetAddress.getByName( "::"));
+
+ // DEBUG
+
+ if ( logger.isInfoEnabled())
+ logger.info("Enabled CIFS IPv6 bind address for native SMB");
+ }
+ catch ( UnknownHostException ex)
+ {
+ throw new AlfrescoRuntimeException("Failed to enable IPv6 bind address, " + ex.getMessage());
+ }
+ }
+
+ }
+ else
+ {
+
+ // Disable TCP/IP SMB support
+
+ cifsConfig.setTcpipSMB(false);
+ }
+
+ // Check if Win32 NetBIOS is enabled
+
+ Win32NetBIOSConfigBean win32NetBIOSConfigBean = cifsConfigBean.getWin32NetBIOS();
+ if (win32NetBIOSConfigBean != null)
+ {
+
+ // Check if the Win32 NetBIOS server name has been specified
+
+ String win32Name = win32NetBIOSConfigBean.getName();
+ if (win32Name != null && win32Name.length() > 0)
+ {
+
+ // Validate the name
+
+ if (win32Name.length() > 16)
+ throw new AlfrescoRuntimeException("Invalid Win32 NetBIOS name, " + win32Name);
+
+ // Set the Win32 NetBIOS file server name
+
+ cifsConfig.setWin32NetBIOSName(win32Name);
+ }
+
+ // Check if the Win32 NetBIOS LANA has been specified
+
+ String lanaStr = win32NetBIOSConfigBean.getLana();
+ if (lanaStr != null && lanaStr.length() > 0)
+ {
+ // Check if the LANA has been specified as an IP address or adapter name
+
+ int lana = -1;
+
+ if (IPAddress.isNumericAddress(lanaStr))
+ {
+
+ // Convert the IP address to a LANA id
+
+ lana = Win32NetBIOS.getLANAForIPAddress(lanaStr);
+ if (lana == -1)
+ throw new AlfrescoRuntimeException("Failed to convert IP address " + lanaStr + " to a LANA");
+ }
+ else if (lanaStr.length() > 1 && Character.isLetter(lanaStr.charAt(0)))
+ {
+
+ // Convert the network adapter to a LANA id
+
+ lana = Win32NetBIOS.getLANAForAdapterName(lanaStr);
+ if (lana == -1)
+ throw new AlfrescoRuntimeException("Failed to convert network adapter " + lanaStr
+ + " to a LANA");
+ }
+ else
+ {
+
+ try
+ {
+ lana = Integer.parseInt(lanaStr);
+ }
+ catch (NumberFormatException ex)
+ {
+ throw new AlfrescoRuntimeException("Invalid win32 NetBIOS LANA specified");
+ }
+ }
+
+ // LANA should be in the range 0-255
+
+ if (lana < 0 || lana > 255)
+ throw new AlfrescoRuntimeException("Invalid Win32 NetBIOS LANA number, " + lana);
+
+ // Set the LANA number
+
+ cifsConfig.setWin32LANA(lana);
+ }
+
+ // Check if the native NetBIOS interface has been specified, either 'winsock' or 'netbios'
+
+ String nativeAPI = win32NetBIOSConfigBean.getApi();
+ if (nativeAPI != null && nativeAPI.length() > 0)
+ {
+ // Validate the API type
+
+ boolean useWinsock = true;
+
+ if (nativeAPI.equalsIgnoreCase("netbios"))
+ useWinsock = false;
+ else if (nativeAPI.equalsIgnoreCase("winsock") == false)
+ throw new AlfrescoRuntimeException("Invalid NetBIOS API type, spefify 'winsock' or 'netbios'");
+
+ // Set the NetBIOS API to use
+
+ cifsConfig.setWin32WinsockNetBIOS(useWinsock);
+ }
+
+ // Force the older NetBIOS API code to be used on 64Bit Windows
+
+ if (cifsConfig.useWinsockNetBIOS() == true && X64.isWindows64())
+ {
+ // Debug
+
+ if (logger.isDebugEnabled())
+ logger.debug("Using older Netbios() API code");
+
+ // Use the older NetBIOS API code
+
+ cifsConfig.setWin32WinsockNetBIOS(false);
+ }
+
+ // Check if the current operating system is supported by the Win32
+ // NetBIOS handler
+
+ String osName = System.getProperty("os.name");
+ if (osName.startsWith("Windows")
+ && (osName.endsWith("95") == false && osName.endsWith("98") == false && osName.endsWith("ME") == false)
+ && isNativeCodeDisabled() == false)
+ {
+
+ // Call the Win32NetBIOS native code to make sure it is initialized
+
+ if (Win32NetBIOS.LanaEnumerate() != null)
+ {
+ // Enable Win32 NetBIOS
+
+ cifsConfig.setWin32NetBIOS(true);
+ }
+ else
+ {
+ logger.warn("No NetBIOS LANAs available");
+ }
+ }
+ else
+ {
+
+ // Win32 NetBIOS not supported on the current operating system
+
+ cifsConfig.setWin32NetBIOS(false);
+ }
+ }
+ else
+ {
+
+ // Disable Win32 NetBIOS
+
+ cifsConfig.setWin32NetBIOS(false);
+ }
+
+ // Check if the Win32 host announcer has been disabled
+
+ if ( !cifsConfigBean.getWin32HostAnnouncerEnabled())
+ {
+ // Switch off the Win32 host announcer
+
+ cifsConfig.setWin32HostAnnouncer( false);
+
+ // Log that host announcements are not enabled
+
+ logger.info("Win32 host announcements not enabled");
+ }
+ else
+ {
+ // Check for an announcement interval
+ Integer interval = cifsConfigBean.getWin32HostAnnounceInterval();
+ if (interval != null)
+ {
+ cifsConfig.setWin32HostAnnounceInterval(interval);
+ }
+
+ // Check if the domain name has been set, this is required if the
+ // host announcer is enabled
+
+ if (cifsConfig.getDomainName() == null)
+ throw new AlfrescoRuntimeException("Domain name must be specified if host announcement is enabled");
+
+ // Enable Win32 NetBIOS host announcement
+
+ cifsConfig.setWin32HostAnnouncer(true);
+ }
+
+ // Check if NetBIOS and/or TCP/IP SMB have been enabled
+
+ if (cifsConfig.hasNetBIOSSMB() == false && cifsConfig.hasTcpipSMB() == false
+ && cifsConfig.hasWin32NetBIOS() == false)
+ throw new AlfrescoRuntimeException("NetBIOS SMB, TCP/IP SMB or Win32 NetBIOS must be enabled");
+
+ // Check if WINS servers are configured
+
+ WINSConfigBean winsConfigBean = cifsConfigBean.getWINSConfig();
+
+ if (winsConfigBean != null && !winsConfigBean.isAutoDetectEnabled())
+ {
+
+ // Get the primary WINS server
+
+ String priWins = winsConfigBean.getPrimary();
+
+ if (priWins == null || priWins.length() == 0)
+ throw new AlfrescoRuntimeException("No primary WINS server configured");
+
+ // Validate the WINS server address
+
+ InetAddress primaryWINS = null;
+
+ try
+ {
+ primaryWINS = InetAddress.getByName(priWins);
+ }
+ catch (UnknownHostException ex)
+ {
+ throw new AlfrescoRuntimeException("Invalid primary WINS server address, " + priWins);
+ }
+
+ // Check if a secondary WINS server has been specified
+
+ String secWins = winsConfigBean.getSecondary();
+ InetAddress secondaryWINS = null;
+
+ if (secWins != null && secWins.length() > 0)
+ {
+
+ // Validate the secondary WINS server address
+
+ try
+ {
+ secondaryWINS = InetAddress.getByName(secWins);
+ }
+ catch (UnknownHostException ex)
+ {
+ throw new AlfrescoRuntimeException("Invalid secondary WINS server address, " + secWins);
+ }
+ }
+
+ // Set the WINS server address(es)
+
+ cifsConfig.setPrimaryWINSServer(primaryWINS);
+ if (secondaryWINS != null)
+ cifsConfig.setSecondaryWINSServer(secondaryWINS);
+
+ // Pass the setting to the NetBIOS session class
+
+ NetBIOSSession.setDefaultWINSServer(primaryWINS);
+ }
+
+ // Check if WINS is configured, if we are running on Windows and socket based NetBIOS is enabled
+
+ else if (cifsConfig.hasNetBIOSSMB() && getPlatformType() == Platform.Type.WINDOWS && !isNativeCodeDisabled())
+ {
+ // Get the WINS server list
+
+ String winsServers = Win32NetBIOS.getWINSServerList();
+
+ if (winsServers != null)
+ {
+ // Use the first WINS server address for now
+
+ StringTokenizer tokens = new StringTokenizer(winsServers, ",");
+ String addr = tokens.nextToken();
+
+ try
+ {
+ // Convert to a network address and check if the WINS server is accessible
+
+ InetAddress winsAddr = InetAddress.getByName(addr);
+
+ Socket winsSocket = new Socket();
+ InetSocketAddress sockAddr = new InetSocketAddress(winsAddr, RFCNetBIOSProtocol.NAME_PORT);
+
+ winsSocket.connect(sockAddr, 3000);
+ winsSocket.close();
+
+ // Set the primary WINS server address
+
+ cifsConfig.setPrimaryWINSServer(winsAddr);
+
+ // Debug
+
+ if (logger.isDebugEnabled())
+ logger.debug("Configuring to use WINS server " + addr);
+ }
+ catch (UnknownHostException ex)
+ {
+ throw new AlfrescoRuntimeException("Invalid auto WINS server address, " + addr);
+ }
+ catch (IOException ex)
+ {
+ if (logger.isDebugEnabled())
+ logger.debug("Failed to connect to auto WINS server " + addr);
+ }
+ }
+ }
+
+ // Check for session debug flags
+
+ String flags = cifsConfigBean.getSessionDebugFlags();
+
+ int sessDbg = 0;
+
+ if (flags != null && flags.length() > 0)
+ {
+
+ // Parse the flags
+
+ flags = flags.toUpperCase();
+ StringTokenizer token = new StringTokenizer(flags, ",");
+
+ while (token.hasMoreTokens())
+ {
+ // Get the current debug flag token
+
+ String dbg = token.nextToken().trim();
+
+ // Find the debug flag name
+
+ int idx = 0;
+
+ while (idx < m_sessDbgStr.length && m_sessDbgStr[idx].equalsIgnoreCase(dbg) == false)
+ idx++;
+
+ if (idx > m_sessDbgStr.length)
+ throw new AlfrescoRuntimeException("Invalid session debug flag, " + dbg);
+
+ // Set the debug flag
+
+ sessDbg += 1 << idx;
+ }
+ }
+
+ // Set the session debug flags
+
+ cifsConfig.setSessionDebugFlags(sessDbg);
+
+ // Check if NIO based socket code should be disabled
+
+ if (cifsConfigBean.getDisableNIO())
+ {
+
+ // Disable NIO based code
+
+ cifsConfig.setDisableNIOCode(true);
+
+ // DEBUG
+
+ if (logger.isDebugEnabled())
+ logger.debug("NIO based code disabled for CIFS server");
+ }
+
+
+ // Check if a session timeout is configured
+
+ Integer tmo = cifsConfigBean.getSessionTimeout();
+ if (tmo != null)
+ {
+
+ // Validate the session timeout value
+
+ if (tmo < 0 || tmo > MaxSessionTimeout)
+ throw new AlfrescoRuntimeException("Session timeout out of range (0 - " + MaxSessionTimeout + ")");
+
+ // Convert the session timeout to milliseconds
+
+ cifsConfig.setSocketTimeout(tmo * 1000);
+ }
+ }
+ catch (InvalidConfigurationException ex)
+ {
+ throw new AlfrescoRuntimeException(ex.getMessage());
+ }
+ }
+
+ /**
+ * Process the FTP server configuration
+ */
+ protected void processFTPServerConfig()
+ {
+ // If the configuration section is not valid then FTP is disabled
+
+ if (ftpConfigBean == null)
+ {
+ removeConfigSection(FTPConfigSection.SectionName);
+ return;
+ }
+
+ // Check if the server has been disabled
+
+ if (!ftpConfigBean.getServerEnabled())
+ {
+ removeConfigSection(FTPConfigSection.SectionName);
+ return;
+ }
+
+ // Create the FTP configuration section
+
+ FTPConfigSection ftpConfig = new FTPConfigSection(this);
+
+ try
+ {
+ // Check for a bind address
+
+ String bindText = ftpConfigBean.getBindTo();
+ if (bindText != null && bindText.length() > 0 && !bindText.equals(BIND_TO_IGNORE))
+ {
+
+ // Validate the bind address
+
+ try
+ {
+
+ // Check the bind address
+
+ InetAddress bindAddr = InetAddress.getByName(bindText);
+
+ // Set the bind address for the FTP server
+
+ ftpConfig.setFTPBindAddress(bindAddr);
+ }
+ catch (UnknownHostException ex)
+ {
+ throw new AlfrescoRuntimeException("Invalid FTP bindto address, " + bindText);
+ }
+ }
+
+ // Check for an FTP server port
+
+ Integer port = ftpConfigBean.getPort();
+ if (port != null)
+ {
+ ftpConfig.setFTPPort(port);
+ if (ftpConfig.getFTPPort() <= 0 || ftpConfig.getFTPPort() >= 65535)
+ throw new AlfrescoRuntimeException("FTP server port out of valid range");
+ }
+ else
+ {
+
+ // Use the default FTP port
+
+ ftpConfig.setFTPPort(DefaultFTPServerPort);
+ }
+
+ // Check if anonymous login is allowed
+
+ if (ftpConfigBean.getAllowAnonymous())
+ {
+
+ // Enable anonymous login to the FTP server
+
+ ftpConfig.setAllowAnonymousFTP(true);
+
+ // Check if an anonymous account has been specified
+
+ String anonAcc = ftpConfigBean.getAnonymousAccount();
+ if (anonAcc != null && anonAcc.length() > 0)
+ {
+
+ // Set the anonymous account name
+
+ ftpConfig.setAnonymousFTPAccount(anonAcc);
+
+ // Check if the anonymous account name is valid
+
+ if (ftpConfig.getAnonymousFTPAccount() == null || ftpConfig.getAnonymousFTPAccount().length() == 0)
+ throw new AlfrescoRuntimeException("Anonymous FTP account invalid");
+ }
+ else
+ {
+
+ // Use the default anonymous account name
+
+ ftpConfig.setAnonymousFTPAccount(DefaultFTPAnonymousAccount);
+ }
+ }
+ else
+ {
+
+ // Disable anonymous logins
+
+ ftpConfig.setAllowAnonymousFTP(false);
+ }
+
+ // Check if a root path has been specified
+
+ String rootPath = ftpConfigBean.getRootDirectory();
+ if (rootPath != null && rootPath.length() > 0)
+ {
+ try
+ {
+
+ // Parse the path
+
+ new FTPPath(rootPath);
+
+ // Set the root path
+
+ ftpConfig.setFTPRootPath(rootPath);
+ }
+ catch (InvalidPathException ex)
+ {
+ throw new AlfrescoRuntimeException("Invalid FTP root directory, " + rootPath);
+ }
+ }
+
+ // Check for FTP debug flags
+
+ String flags = ftpConfigBean.getDebugFlags();
+ int ftpDbg = 0;
+
+ if (flags != null)
+ {
+
+ // Parse the flags
+
+ flags = flags.toUpperCase();
+ StringTokenizer token = new StringTokenizer(flags, ",");
+
+ while (token.hasMoreTokens())
+ {
+
+ // Get the current debug flag token
+
+ String dbg = token.nextToken().trim();
+
+ // Find the debug flag name
+
+ int idx = 0;
+
+ while (idx < m_ftpDebugStr.length && m_ftpDebugStr[idx].equalsIgnoreCase(dbg) == false)
+ idx++;
+
+ if (idx >= m_ftpDebugStr.length)
+ throw new AlfrescoRuntimeException("Invalid FTP debug flag, " + dbg);
+
+ // Set the debug flag
+
+ ftpDbg += 1 << idx;
+ }
+
+ // Set the FTP debug flags
+
+ ftpConfig.setFTPDebug(ftpDbg);
+ }
+
+ // Check if a character set has been specified
+
+ String charSet = ftpConfigBean.getCharSet();
+ if (charSet != null && charSet.length() > 0)
+ {
+
+ try
+ {
+
+ // Validate the character set name
+
+ Charset.forName(charSet);
+
+ // Set the FTP character set
+
+ ftpConfig.setFTPCharacterSet(charSet);
+ }
+ catch (IllegalCharsetNameException ex)
+ {
+ throw new AlfrescoRuntimeException("Illegal character set name, " + charSet);
+ }
+ catch (UnsupportedCharsetException ex)
+ {
+ throw new AlfrescoRuntimeException("Unsupported character set name, " + charSet);
+ }
+ }
+
+ // Check if an authenticator has been specified
+
+ FTPAuthenticator auth = ftpConfigBean.getAuthenticator();
+ if (auth != null)
+ {
+
+ // Initialize and set the authenticator class
+
+ ftpConfig.setAuthenticator(auth);
+ }
+ else
+ throw new AlfrescoRuntimeException("FTP authenticator not specified");
+
+ // Check if a data port range has been specified
+
+ if ( ftpConfigBean.getDataPortFrom() != 0 && ftpConfigBean.getDataPortTo() != 0) {
+
+ // Range check the data port values
+
+ int rangeFrom = ftpConfigBean.getDataPortFrom();
+ int rangeTo = ftpConfigBean.getDataPortTo();
+
+ if ( rangeFrom != 0 && rangeTo != 0) {
+
+ // Validate the FTP data port range
+
+ if ( rangeFrom < 1024 || rangeFrom > 65535)
+ throw new InvalidConfigurationException("Invalid FTP data port range from value, " + rangeFrom);
+
+ if ( rangeTo < 1024 || rangeTo > 65535)
+ throw new InvalidConfigurationException("Invalid FTP data port range to value, " + rangeTo);
+
+ if ( rangeFrom >= rangeTo)
+ throw new InvalidConfigurationException("Invalid FTP data port range, " + rangeFrom + "-" + rangeTo);
+
+ // Set the FTP data port range
+
+ ftpConfig.setFTPDataPortLow(rangeFrom);
+ ftpConfig.setFTPDataPortHigh(rangeTo);
+
+ // Log the data port range
+
+ logger.info("FTP server data ports restricted to range " + rangeFrom + ":" + rangeTo);
+ }
+ }
+
+ // FTPS parameter parsing
+ //
+ // Check if a key store path has been specified
+
+ if ( ftpConfigBean.getKeyStorePath() != null && ftpConfigBean.getKeyStorePath().length() > 0) {
+
+ // Get the path to the key store, check that the file exists
+
+ String keyStorePath = ftpConfigBean.getKeyStorePath();
+ File keyStoreFile = new File( keyStorePath);
+
+ if ( keyStoreFile.exists() == false)
+ throw new InvalidConfigurationException("FTPS key store file does not exist, " + keyStorePath);
+ else if ( keyStoreFile.isDirectory())
+ throw new InvalidConfigurationException("FTPS key store path is a directory, " + keyStorePath);
+
+ // Set the key store path
+
+ ftpConfig.setKeyStorePath( keyStorePath);
+ }
+
+ // Check if the trust store path has been specified
+
+ if ( ftpConfigBean.getTrustStorePath() != null && ftpConfigBean.getTrustStorePath().length() > 0) {
+
+ // Get the path to the trust store, check that the file exists
+
+ String trustStorePath = ftpConfigBean.getTrustStorePath();
+ File trustStoreFile = new File( trustStorePath);
+
+ if ( trustStoreFile.exists() == false)
+ throw new InvalidConfigurationException("FTPS trust store file does not exist, " + trustStorePath);
+ else if ( trustStoreFile.isDirectory())
+ throw new InvalidConfigurationException("FTPS trust store path is a directory, " + trustStorePath);
+
+ // Set the trust store path
+
+ ftpConfig.setTrustStorePath( trustStorePath);
+ }
+
+ // Check if the store passphrase has been specified
+
+ if ( ftpConfigBean.getPassphrase() != null && ftpConfigBean.getPassphrase().length() > 0) {
+
+ // Set the store passphrase
+
+ ftpConfig.setPassphrase( ftpConfigBean.getPassphrase());
+ }
+
+ // Check if only secure sessions should be allowed to logon
+
+ if ( ftpConfigBean.hasRequireSecureSession()) {
+
+ // Only allow secure sessions to logon to the FTP server
+
+ ftpConfig.setRequireSecureSession( true);
+ }
+
+ // Check that all the required FTPS parameters have been set
+
+ if ( ftpConfig.getKeyStorePath() != null || ftpConfig.getTrustStorePath() != null || ftpConfig.getPassphrase() != null) {
+
+ // Make sure all parameters are set
+
+ if ( ftpConfig.getKeyStorePath() == null || ftpConfig.getTrustStorePath() == null || ftpConfig.getPassphrase() == null)
+ throw new InvalidConfigurationException("FTPS configuration requires keyStore, trustStore and storePassphrase to be set");
+ }
+
+ // Check if SSLEngine debug output should be enabled
+
+ if ( ftpConfigBean.hasSslEngineDebug()) {
+
+ // Enable SSLEngine debug output
+
+ System.setProperty("javax.net.debug", "ssl,handshake");
+ }
+ }
+ catch (InvalidConfigurationException ex)
+ {
+ throw new AlfrescoRuntimeException(ex.getMessage());
+ }
+ }
+
+ /**
+ * Process the NFS server configuration
+ */
+ protected void processNFSServerConfig()
+ {
+ // If the configuration section is not valid then NFS is disabled
+
+ if (nfsConfigBean == null)
+ {
+ removeConfigSection(NFSConfigSection.SectionName);
+ return;
+ }
+
+ // Check if the server has been disabled
+
+ if (!nfsConfigBean.getServerEnabled())
+ {
+ removeConfigSection(NFSConfigSection.SectionName);
+ return;
+ }
+
+ // Create the NFS configuration section
+
+ NFSConfigSection nfsConfig = new NFSConfigSection(this);
+
+ try
+ {
+ // Check if the port mapper is enabled
+
+ if (nfsConfigBean.getPortMapperEnabled())
+ nfsConfig.setNFSPortMapper(true);
+
+ // Check for the thread pool size
+
+ Integer poolSize = nfsConfigBean.getThreadPool();
+
+ if (poolSize != null)
+ {
+
+ // Range check the pool size value
+
+ if (poolSize < 4)
+ throw new AlfrescoRuntimeException("NFS thread pool size is below minimum of 4");
+
+ // Set the thread pool size
+
+ nfsConfig.setNFSThreadPoolSize(poolSize);
+ }
+
+ // NFS packet pool size
+
+ Integer pktPoolSize = nfsConfigBean.getPacketPool();
+
+ if (pktPoolSize != null)
+ {
+ // Range check the pool size value
+
+ if (pktPoolSize < 10)
+ throw new AlfrescoRuntimeException("NFS packet pool size is below minimum of 10");
+
+ if (pktPoolSize < nfsConfig.getNFSThreadPoolSize() + 1)
+ throw new AlfrescoRuntimeException("NFS packet pool must be at least thread pool size plus one");
+
+ // Set the packet pool size
+
+ nfsConfig.setNFSPacketPoolSize(pktPoolSize);
+ }
+
+ // Check for a port mapper server port
+
+ Integer portMapperPort = nfsConfigBean.getPortMapperPort();
+ if (portMapperPort != null)
+ {
+ nfsConfig.setPortMapperPort(portMapperPort);
+ if ( nfsConfig.getPortMapperPort() == -1) {
+ logger.info("NFS portmapper registration disabled");
+ }
+ else {
+ if (nfsConfig.getPortMapperPort() <= 0 || nfsConfig.getPortMapperPort() >= 65535)
+ throw new AlfrescoRuntimeException("Port mapper server port out of valid range");
+ }
+ }
+
+ // Check for a mount server port
+
+ Integer mountServerPort = nfsConfigBean.getMountServerPort();
+ if (mountServerPort != null)
+ {
+ nfsConfig.setMountServerPort(mountServerPort);
+ if (nfsConfig.getMountServerPort() < 0 || nfsConfig.getMountServerPort() >= 65535)
+ throw new AlfrescoRuntimeException("Mount server port out of valid range");
+ }
+
+ // Check for an NFS server port
+
+ Integer nfsServerPort = nfsConfigBean.getNfsServerPort();
+ if (nfsServerPort != null)
+ {
+ nfsConfig.setNFSServerPort(nfsServerPort);
+ if (nfsConfig.getNFSServerPort() < 0 || nfsConfig.getNFSServerPort() >= 65535)
+ throw new AlfrescoRuntimeException("NFS server port out of valid range");
+ }
+
+ // Check for an RPC registration port
+
+ Integer rpcRegisterPort = nfsConfigBean.getRpcRegisterPort();
+ if ( rpcRegisterPort != null)
+ {
+ nfsConfig.setRPCRegistrationPort( rpcRegisterPort);
+ if ( nfsConfig.getRPCRegistrationPort() < 0 || nfsConfig.getRPCRegistrationPort() >= 65535)
+ throw new AlfrescoRuntimeException("RPC registrtion port out of valid range");
+ }
+
+ // Check for NFS debug flags
+
+ String flags = nfsConfigBean.getDebugFlags();
+ int nfsDbg = 0;
+
+ if (flags != null && flags.length() > 0)
+ {
+
+ // Parse the flags
+
+ flags = flags.toUpperCase();
+ StringTokenizer token = new StringTokenizer(flags, ",");
+
+ while (token.hasMoreTokens())
+ {
+
+ // Get the current debug flag token
+
+ String dbg = token.nextToken().trim();
+
+ // Find the debug flag name
+
+ int idx = 0;
+
+ while (idx < m_nfsDebugStr.length && m_nfsDebugStr[idx].equalsIgnoreCase(dbg) == false)
+ idx++;
+
+ if (idx >= m_nfsDebugStr.length)
+ throw new AlfrescoRuntimeException("Invalid NFS debug flag, " + dbg);
+
+ // Set the debug flag
+
+ nfsDbg += 1 << idx;
+ }
+
+ // Set the NFS debug flags
+
+ nfsConfig.setNFSDebug(nfsDbg);
+ }
+
+ // Check if mount server debug output is enabled
+
+ if (nfsConfigBean.getMountServerDebug())
+ nfsConfig.setMountServerDebug(true);
+
+ // Check if portmapper debug output is enabled
+
+ if (nfsConfigBean.getPortMapperDebug())
+ nfsConfig.setPortMapperDebug(true);
+
+ // Create the RPC authenticator
+ RpcAuthenticator rpcAuthenticator = nfsConfigBean.getRpcAuthenticator();
+ if (rpcAuthenticator != null)
+ {
+ nfsConfig.setRpcAuthenticator(rpcAuthenticator);
+ }
+ else
+ throw new AlfrescoRuntimeException("RPC authenticator configuration missing, require user mappings");
+ }
+ catch (InvalidConfigurationException ex)
+ {
+ throw new AlfrescoRuntimeException(ex.getMessage());
+ }
+ }
+
+ /**
+ * Process the filesystems configuration
+ */
+ protected void processFilesystemsConfig()
+ {
+ // Create the filesystems configuration section
+
+ FilesystemsConfigSection fsysConfig = new FilesystemsConfigSection(this);
+
+ // Access the security configuration section
+
+ SecurityConfigSection secConfig = (SecurityConfigSection) getConfigSection(SecurityConfigSection.SectionName);
+
+ // Process the filesystems list
+
+ if (this.filesystemContexts != null)
+ {
+
+ // Add the filesystems
+
+ for (DeviceContext filesystem : this.filesystemContexts)
+ {
+
+ // Get the current filesystem configuration
+
+ try
+ {
+ // Check the filesystem type and use the appropriate driver
+
+ DiskSharedDevice filesys = null;
+
+ if (filesystem instanceof AVMContext)
+ {
+ // Create a new filesystem driver instance and register a context for
+ // the new filesystem
+
+ ExtendedDiskInterface filesysDriver = getAvmDiskInterface();
+ DiskDeviceContext diskCtx = (DiskDeviceContext) filesystem;
+
+ if(clusterConfigBean != null && clusterConfigBean.getClusterEnabled())
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("start hazelcast cache : " + clusterConfigBean.getClusterName() + ", shareName: "+ diskCtx.getShareName());
+ }
+ GenericConfigElement hazelConfig = createClusterConfig(diskCtx.getShareName());
+ HazelCastClusterFileStateCache hazel = new HazelCastClusterFileStateCache();
+ hazel.initializeCache(hazelConfig, this);
+ diskCtx.setStateCache(hazel);
+ }
+ else
+ {
+ // Check if the filesystem uses the file state cache, if so then add to the file state reaper
+ StandaloneFileStateCache standaloneCache = new StandaloneFileStateCache();
+ standaloneCache.initializeCache( new GenericConfigElement( ""), this);
+ diskCtx.setStateCache(standaloneCache);
+ }
+ if ( diskCtx.hasStateCache()) {
+
+ // Register the state cache with the reaper thread
+
+ fsysConfig.addFileStateCache( filesystem.getDeviceName(), diskCtx.getStateCache());
+ }
+
+ filesysDriver.registerContext(filesystem);
+
+ // Create the shared filesystem
+
+ filesys = new DiskSharedDevice(filesystem.getDeviceName(), filesysDriver, (AVMContext)filesystem);
+ filesys.setConfiguration( this);
+ // Start the filesystem
+
+ ((AVMContext)filesystem).startFilesystem(filesys);
+ }
+ else
+ {
+ // Create a new filesystem driver instance and register a context for
+ // the new filesystem
+
+ ExtendedDiskInterface filesysDriver = getRepoDiskInterface();
+ ContentContext filesysContext = (ContentContext) filesystem;
+
+ if(clusterConfigBean != null && clusterConfigBean.getClusterEnabled())
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("start hazelcast cache : " + clusterConfigBean.getClusterName() + ", shareName: "+ filesysContext.getShareName());
+ }
+ GenericConfigElement hazelConfig = createClusterConfig(filesysContext.getShareName());
+ HazelCastClusterFileStateCache hazel = new HazelCastClusterFileStateCache();
+ hazel.initializeCache(hazelConfig, this);
+ filesysContext.setStateCache(hazel);
+ }
+ else
+ {
+ // Create state cache here and inject
+ StandaloneFileStateCache standaloneCache = new StandaloneFileStateCache();
+ standaloneCache.initializeCache( new GenericConfigElement( ""), this);
+ filesysContext.setStateCache(standaloneCache);
+ }
+
+ if ( filesysContext.hasStateCache()) {
+
+ // Register the state cache with the reaper thread
+
+ fsysConfig.addFileStateCache( filesystem.getDeviceName(), filesysContext.getStateCache());
+
+ // Create the lock manager for the context.
+ FileStateLockManager lockMgr = new FileStateLockManager(filesysContext.getStateCache());
+ filesysContext.setLockManager(lockMgr);
+ filesysContext.setOpLockManager(lockMgr);
+ }
+
+ filesysDriver.registerContext(filesystem);
+
+ // Check if an access control list has been specified
+
+ AccessControlList acls = null;
+ AccessControlListBean accessControls = filesysContext.getAccessControlList();
+ if (accessControls != null)
+ {
+ // Parse the access control list
+ acls = accessControls.toAccessControlList(secConfig);
+ }
+ else if (secConfig.hasGlobalAccessControls())
+ {
+
+ // Use the global access control list for this disk share
+ acls = secConfig.getGlobalAccessControls();
+ }
+
+ // Create the shared filesystem
+
+ filesys = new DiskSharedDevice(filesystem.getDeviceName(), filesysDriver, filesysContext);
+ filesys.setConfiguration( this);
+
+ // Add any access controls to the share
+
+ filesys.setAccessControlList(acls);
+
+
+
+ // Check if change notifications should be enabled
+
+ if ( filesysContext.getDisableChangeNotifications() == false)
+ filesysContext.enableChangeHandler( true);
+
+ // Start the filesystem
+
+ filesysContext.startFilesystem(filesys);
+ }
+
+ // Add the new filesystem
+
+ fsysConfig.addShare(filesys);
+ }
+ catch (DeviceContextException ex)
+ {
+ throw new AlfrescoRuntimeException("Error creating filesystem " + filesystem.getDeviceName(), ex);
+ }
+ catch (InvalidConfigurationException ex)
+ {
+ throw new AlfrescoRuntimeException(ex.getMessage(), ex);
+ }
+ }
+ }
+ else
+ {
+ // No filesystems defined
+
+ logger.warn("No filesystems defined");
+ }
+
+ // Check if shares should be added for all AVM stores
+ if (this.avmAllStores && getAvmDiskInterface() != null)
+ {
+ // Get the list of store names
+
+ AVMDiskDriver avmDriver = (AVMDiskDriver) getAvmDiskInterface();
+ StringList storeNames = avmDriver.getAVMStoreNames();
+
+ // Add shares for each of the store names, if the share name does not already exist
+
+ if (storeNames != null && storeNames.numberOfStrings() > 0)
+ {
+ // Add a share for each store
+
+ for (int i = 0; i < storeNames.numberOfStrings(); i++)
+ {
+ String storeName = storeNames.getStringAt(i);
+
+ // Check if a share of the same name already exists
+
+ if (fsysConfig.getShares().findShare(storeName, ShareType.DISK, true) == null)
+ {
+ // Create the new share for the store
+
+ AVMContext avmContext = new AVMContext(storeName, storeName + ":/", AVMContext.VERSION_HEAD);
+// avmContext.enableStateCache(this, true);
+
+ // Create the shared filesystem
+
+ DiskSharedDevice filesys = new DiskSharedDevice(storeName, avmDriver, avmContext);
+ filesys.setConfiguration( this);
+
+ fsysConfig.addShare( filesys);
+
+ // DEBUG
+
+ if (logger.isDebugEnabled())
+ logger.debug("Added AVM share " + storeName);
+ }
+ }
+ }
+ }
+
+
+ // home folder share mapper could be declared in security config
+ }
+
+ /**
+ * Process the security configuration
+ */
+ protected void processSecurityConfig()
+ {
+ // Create the security configuration section
+
+ SecurityConfigSection secConfig = new SecurityConfigSection(this);
+
+ try
+ {
+ // Check if global access controls have been specified
+
+ AccessControlListBean accessControls = securityConfigBean.getGlobalAccessControl();
+
+ if (accessControls != null)
+ {
+ // Parse the access control list
+ AccessControlList acls = accessControls.toAccessControlList(secConfig);
+ if (acls != null)
+ secConfig.setGlobalAccessControls(acls);
+ }
+
+
+ // Check if a JCE provider class has been specified
+
+ String jceProvider = securityConfigBean.getJCEProvider();
+ if (jceProvider != null && jceProvider.length() > 0)
+ {
+
+ // Set the JCE provider
+
+ secConfig.setJCEProvider(jceProvider);
+ }
+ else
+ {
+ // Use the default Bouncy Castle JCE provider
+
+ secConfig.setJCEProvider("org.bouncycastle.jce.provider.BouncyCastleProvider");
+ }
+
+ // Check if a share mapper has been specified
+
+ ShareMapper shareMapper = securityConfigBean.getShareMapper();
+ if (shareMapper != null)
+ {
+ // Associate the share mapper
+ secConfig.setShareMapper(shareMapper);
+ }
+ else
+ {
+ // Check if the tenant service is enabled
+ if (m_tenantService != null && m_tenantService.isEnabled())
+ {
+ // Initialize the multi-tenancy share mapper
+
+ secConfig.setShareMapper("org.alfresco.filesys.alfresco.MultiTenantShareMapper",
+ new GenericConfigElement("shareMapper"));
+
+ }
+ }
+
+ // Check if any domain mappings have been specified
+
+ List mappings = securityConfigBean.getDomainMappings();
+ if (mappings != null)
+ {
+ DomainMapping mapping = null;
+
+ for (DomainMappingConfigBean domainMap : mappings)
+ {
+ // Get the domain name
+
+ String name = domainMap.getName();
+
+ // Check if the domain is specified by subnet or range
+
+ String subnetStr = domainMap.getSubnet();
+ String rangeFromStr;
+ if (subnetStr != null && subnetStr.length() > 0)
+ {
+ String maskStr = domainMap.getMask();
+
+ // Parse the subnet and mask, to validate and convert to int values
+
+ int subnet = IPAddress.parseNumericAddress(subnetStr);
+ int mask = IPAddress.parseNumericAddress(maskStr);
+
+ if (subnet == 0 || mask == 0)
+ throw new AlfrescoRuntimeException("Invalid subnet/mask for domain mapping " + name);
+
+ // Create the subnet domain mapping
+
+ mapping = new SubnetDomainMapping(name, subnet, mask);
+ }
+ else if ((rangeFromStr = domainMap.getRangeFrom()) != null && rangeFromStr.length() > 0)
+ {
+ String rangeToStr = domainMap.getRangeTo();
+
+ // Parse the range from/to values and convert to int values
+
+ int rangeFrom = IPAddress.parseNumericAddress(rangeFromStr);
+ int rangeTo = IPAddress.parseNumericAddress(rangeToStr);
+
+ if (rangeFrom == 0 || rangeTo == 0)
+ throw new AlfrescoRuntimeException("Invalid address range domain mapping " + name);
+
+ // Create the subnet domain mapping
+
+ mapping = new RangeDomainMapping(name, rangeFrom, rangeTo);
+ }
+ else
+ throw new AlfrescoRuntimeException("Invalid domain mapping specified");
+
+ // Add the domain mapping
+
+ secConfig.addDomainMapping(mapping);
+ }
+ }
+ }
+ catch (InvalidConfigurationException ex)
+ {
+ throw new AlfrescoRuntimeException(ex.getMessage());
+ }
+ }
+
+ /**
+ * Process the core server configuration
+ *
+ * @exception InvalidConfigurationException
+ */
+ protected void processCoreServerConfig() throws InvalidConfigurationException
+ {
+ // Create the core server configuration section
+
+ CoreServerConfigSection coreConfig = new CoreServerConfigSection(this);
+
+ // Check if the CIFS server is not enabled, do not create the thread/memory pools
+
+ if ( cifsConfigBean == null || cifsConfigBean.getServerEnabled() == false)
+ return;
+
+ // Check if the server core element has been specified
+
+ if (coreServerConfigBean == null)
+ {
+
+ // Configure a default memory pool
+
+ coreConfig.setMemoryPool(DefaultMemoryPoolBufSizes, DefaultMemoryPoolInitAlloc, DefaultMemoryPoolMaxAlloc);
+
+ // Configure a default thread pool size
+
+ coreConfig.setThreadPool(DefaultThreadPoolInit, DefaultThreadPoolMax);
+
+ threadPool = coreConfig.getThreadPool();
+
+ return;
+ }
+
+ // Check if the thread pool size has been specified
+
+ Integer initSize = coreServerConfigBean.getThreadPoolInit();
+ if (initSize == null)
+ {
+ initSize = DefaultThreadPoolInit;
+ }
+ Integer maxSize = coreServerConfigBean.getThreadPoolMax();
+ if (maxSize == null)
+ {
+ maxSize = DefaultThreadPoolMax;
+ }
+
+ // Range check the thread pool size
+
+ if (initSize < ThreadRequestPool.MinimumWorkerThreads)
+ throw new InvalidConfigurationException("Thread pool size below minimum allowed size");
+
+ if (initSize > ThreadRequestPool.MaximumWorkerThreads)
+ throw new InvalidConfigurationException("Thread pool size above maximum allowed size");
+
+ // Range check the maximum thread pool size
+
+ if (maxSize < ThreadRequestPool.MinimumWorkerThreads)
+ throw new InvalidConfigurationException("Thread pool maximum size below minimum allowed size");
+
+ if (maxSize > ThreadRequestPool.MaximumWorkerThreads)
+ throw new InvalidConfigurationException("Thread pool maximum size above maximum allowed size");
+
+ if (maxSize < initSize)
+ throw new InvalidConfigurationException("Initial size is larger than maxmimum size");
+
+ // Configure the thread pool
+
+ coreConfig.setThreadPool(initSize, maxSize);
+
+ threadPool = coreConfig.getThreadPool();
+
+ // Check if thread pool debug output is enabled
+
+ if (coreServerConfigBean.getThreadPoolDebug())
+ coreConfig.getThreadPool().setDebug(true);
+
+ // Check if the packet sizes/allocations have been specified
+
+ List packetSizes = coreServerConfigBean.getMemoryPacketSizes();
+ if (packetSizes != null)
+ {
+
+ // Calculate the array size for the packet size/allocation arrays
+
+ int elemCnt = packetSizes.size();
+
+ // Create the packet size, initial allocation and maximum allocation arrays
+
+ int[] pktSizes = new int[elemCnt];
+ int[] initSizes = new int[elemCnt];
+ int[] maxSizes = new int[elemCnt];
+
+ int elemIdx = 0;
+
+ // Process the packet size elements
+ for (MemoryPacketConfigBean curChild : packetSizes)
+ {
+
+ // Get the packet size
+
+ int pktSize = -1;
+
+ Long pktSizeLong = curChild.getSize();
+ if (pktSizeLong == null)
+ throw new InvalidConfigurationException("Memory pool packet size not specified");
+
+ // Parse the packet size
+
+ try
+ {
+ pktSize = MemorySize.getByteValueInt(pktSizeLong.toString());
+ }
+ catch (NumberFormatException ex)
+ {
+ throw new InvalidConfigurationException("Memory pool packet size, invalid size value, "
+ + pktSizeLong);
+ }
+
+ // Make sure the packet sizes have been specified in ascending order
+
+ if (elemIdx > 0 && pktSizes[elemIdx - 1] >= pktSize)
+ throw new InvalidConfigurationException(
+ "Invalid packet size specified, less than/equal to previous packet size");
+
+ // Get the initial allocation for the current packet size
+ Integer initAlloc = curChild.getInit();
+ if (initAlloc == null)
+ throw new InvalidConfigurationException("Memory pool initial allocation not specified");
+
+ // Range check the initial allocation
+
+ if (initAlloc < MemoryPoolMinimumAllocation)
+ throw new InvalidConfigurationException("Initial memory pool allocation below minimum of "
+ + MemoryPoolMinimumAllocation);
+
+ if (initAlloc > MemoryPoolMaximumAllocation)
+ throw new InvalidConfigurationException("Initial memory pool allocation above maximum of "
+ + MemoryPoolMaximumAllocation);
+
+ // Get the maximum allocation for the current packet size
+
+ Integer maxAlloc = curChild.getMax();
+ if (maxAlloc == null)
+ throw new InvalidConfigurationException("Memory pool maximum allocation not specified");
+
+ // Range check the maximum allocation
+
+ if (maxAlloc < MemoryPoolMinimumAllocation)
+ throw new InvalidConfigurationException("Maximum memory pool allocation below minimum of "
+ + MemoryPoolMinimumAllocation);
+
+ if (initAlloc > MemoryPoolMaximumAllocation)
+ throw new InvalidConfigurationException("Maximum memory pool allocation above maximum of "
+ + MemoryPoolMaximumAllocation);
+
+ // Set the current packet size elements
+
+ pktSizes[elemIdx] = pktSize;
+ initSizes[elemIdx] = initAlloc;
+ maxSizes[elemIdx] = maxAlloc;
+
+ elemIdx++;
+ }
+
+ // Check if all elements were used in the packet size/allocation arrays
+
+ if (elemIdx < pktSizes.length)
+ {
+
+ // Re-allocate the packet size/allocation arrays
+
+ int[] newPktSizes = new int[elemIdx];
+ int[] newInitSizes = new int[elemIdx];
+ int[] newMaxSizes = new int[elemIdx];
+
+ // Copy the values to the shorter arrays
+
+ System.arraycopy(pktSizes, 0, newPktSizes, 0, elemIdx);
+ System.arraycopy(initSizes, 0, newInitSizes, 0, elemIdx);
+ System.arraycopy(maxSizes, 0, newMaxSizes, 0, elemIdx);
+
+ // Move the new arrays into place
+
+ pktSizes = newPktSizes;
+ initSizes = newInitSizes;
+ maxSizes = newMaxSizes;
+ }
+
+ // Configure the memory pool
+
+ coreConfig.setMemoryPool(pktSizes, initSizes, maxSizes);
+ }
+ else
+ {
+
+ // Configure a default memory pool
+
+ coreConfig.setMemoryPool(DefaultMemoryPoolBufSizes, DefaultMemoryPoolInitAlloc, DefaultMemoryPoolMaxAlloc);
+ }
+ }
+
+ /**
+ * Initialise a runtime context - not configured through spring e.g MT.
+ *
+ * TODO - what about desktop actions etc?
+ *
+ * @param diskCtx
+ */
+ public void initialiseRuntimeContext(AlfrescoContext diskCtx)
+ {
+ if (diskCtx.getStateCache() == null) {
+
+ // Set the state cache, use a hard coded standalone cache for now
+ FilesystemsConfigSection filesysConfig = (FilesystemsConfigSection) this.getConfigSection( FilesystemsConfigSection.SectionName);
+
+ if ( filesysConfig != null)
+ {
+
+ try
+ {
+ if(clusterConfigBean != null && clusterConfigBean.getClusterEnabled())
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("start hazelcast cache : " + clusterConfigBean.getClusterName() + ", shareName: "+ diskCtx.getShareName());
+ }
+ GenericConfigElement hazelConfig = createClusterConfig(diskCtx.getShareName());
+ HazelCastClusterFileStateCache hazel = new HazelCastClusterFileStateCache();
+ hazel.initializeCache(hazelConfig, this);
+ diskCtx.setStateCache(hazel);
+ }
+ else
+ {
+ // Create a standalone state cache
+ StandaloneFileStateCache standaloneCache = new StandaloneFileStateCache();
+ standaloneCache.initializeCache( new GenericConfigElement( ""), this);
+ filesysConfig.addFileStateCache( diskCtx.getDeviceName(), standaloneCache);
+ diskCtx.setStateCache( standaloneCache);
+ }
+
+ FileStateLockManager lockMgr = new FileStateLockManager(diskCtx.getStateCache());
+ diskCtx.setLockManager(lockMgr);
+ diskCtx.setOpLockManager(lockMgr);
+ }
+ catch ( InvalidConfigurationException ex)
+ {
+ throw new AlfrescoRuntimeException( "Failed to initialize standalone state cache for " + diskCtx.getDeviceName());
+ }
+ }
+ }
+ }
+
+
+ @Override
+ protected void processClusterConfig() throws InvalidConfigurationException
+ {
+
+// Done by org.alfresco.jlan.server.config.ServerConfiguration.closeConfiguration
+// /**
+// * Close the old hazelcast configuration
+// */
+// ClusterConfigSection secConfig = (ClusterConfigSection) getConfigSection(ClusterConfigSection.SectionName);
+// {
+// if(secConfig != null)
+// {
+// secConfig.closeConfig();
+// }
+// }
+
+ if (clusterConfigBean == null || !clusterConfigBean.getClusterEnabled())
+ {
+ removeConfigSection(ClusterConfigSection.SectionName);
+ logger.info("Filesystem cluster cache not enabled");
+ return;
+ }
+
+ String clusterName = clusterConfigBean.getClusterName();
+ if (clusterName == null || clusterName.length() == 0)
+ {
+ throw new InvalidConfigurationException("Cluster name not specified or invalid");
+ }
+
+ String clusterFile = clusterConfigBean.getConfigFile();
+ if (clusterFile == null || clusterFile.length() == 0)
+ {
+ throw new InvalidConfigurationException("Cluster config file not specified or invalid");
+ }
+
+ // New Hazelcast instance created here within the ClusterConfigSection
ClusterConfigSection jlanClusterConfig = new ClusterConfigSection(this);
try
@@ -2253,8 +2261,8 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean
throw new InvalidConfigurationException("Unable to start filsystem cluster", e);
}
}
-
-
+
+
private GenericConfigElement createClusterConfig(String topicName) throws InvalidConfigurationException
{
GenericConfigElement config = new GenericConfigElement("hazelcastStateCache");
@@ -2285,6 +2293,13 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean
config.addChild(nearCacheCfg);
}
return config;
- }
-
-}
+ }
+
+ @Override
+ public void destroy() throws Exception
+ {
+ threadPool.shutdownThreadPool();
+ threadPool = null;
+ }
+
+}
diff --git a/source/java/org/alfresco/filesys/repo/ContentContext.java b/source/java/org/alfresco/filesys/repo/ContentContext.java
index 43984a7b41..66b4f28b0c 100644
--- a/source/java/org/alfresco/filesys/repo/ContentContext.java
+++ b/source/java/org/alfresco/filesys/repo/ContentContext.java
@@ -32,6 +32,7 @@ import org.alfresco.jlan.server.filesys.DiskInterface;
import org.alfresco.jlan.server.filesys.DiskSharedDevice;
import org.alfresco.jlan.server.filesys.FileName;
import org.alfresco.jlan.server.filesys.FileSystem;
+import org.alfresco.jlan.server.filesys.cache.FileStateLockManager;
import org.alfresco.jlan.server.filesys.quota.QuotaManagerException;
import org.alfresco.jlan.server.thread.ThreadRequestPool;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -66,6 +67,10 @@ public class ContentContext extends AlfrescoContext
private AccessControlListBean m_accessControlList;
+ // File state based lock/oplock manager
+
+ private FileStateLockManager m_lockManager;
+
// Enable/disable oplocks
private boolean m_oplocksDisabled;
@@ -206,7 +211,15 @@ public class ContentContext extends AlfrescoContext
if (m_rootPath == null || m_rootPath.length() == 0)
{
throw new AlfrescoRuntimeException("Device missing rootPath");
- }
+ }
+
+ // Enable file state caching
+
+ getStateCache().setCaseSensitive( false);
+
+ // Create the file state based lock manager
+
+ m_lockManager = new FileStateLockManager( getStateCache());
}
/**
@@ -279,6 +292,15 @@ public class ContentContext extends AlfrescoContext
return m_oplocksDisabled;
}
+ /**
+ * Return the lock manager
+ *
+ * @return FileStateLockManager
+ */
+ public FileStateLockManager getLockManager() {
+ return m_lockManager;
+ }
+
/**
* Determine if change notifications are disabled
*
@@ -385,6 +407,15 @@ public class ContentContext extends AlfrescoContext
if ( coreConfig != null)
m_threadPool = coreConfig.getThreadPool();
+ // Start the lock manager, use the thread pool if available
+
+ if ( getLockManager() != null) {
+
+ // Start the lock manager
+
+ m_lockManager.startLockManager( "OplockExpire_" + share.getName(), m_threadPool);
+ }
+
// Start the node monitor, if enabled
if ( m_nodeMonitor != null)
diff --git a/source/java/org/alfresco/filesys/repo/ContentDiskDriver.java b/source/java/org/alfresco/filesys/repo/ContentDiskDriver.java
index 35e3980837..ccacc7e63d 100644
--- a/source/java/org/alfresco/filesys/repo/ContentDiskDriver.java
+++ b/source/java/org/alfresco/filesys/repo/ContentDiskDriver.java
@@ -200,8 +200,8 @@ public class ContentDiskDriver extends AlfrescoTxDiskDriver implements DiskInter
private BehaviourFilter policyBehaviourFilter;
private NodeMonitorFactory m_nodeMonitorFactory;
- private static FileStateLockManager _lockManager;
-
+
+
/**
* Class constructor
*
@@ -774,11 +774,11 @@ public class ContentDiskDriver extends AlfrescoTxDiskDriver implements DiskInter
logger.info("Locked files will be marked as offline");
}
+
+ // Enable file state caching
-// // Enable file state caching
-//
// context.enableStateCache(serverConfig, true);
-
+
// Install the node service monitor
if ( !context.getDisableNodeMonitor() && m_nodeMonitorFactory != null) {
@@ -789,10 +789,6 @@ public class ContentDiskDriver extends AlfrescoTxDiskDriver implements DiskInter
context.setNodeMonitor( nodeMonitor);
}
- // Create the lock manager
-
- _lockManager = new FileStateLockManager( context.getStateCache());
-
// Check if oplocks are enabled
if ( context.getDisableOplocks() == true)
@@ -1719,7 +1715,8 @@ public class ContentDiskDriver extends AlfrescoTxDiskDriver implements DiskInter
// Check if the current file open allows the required shared access
boolean nosharing = false;
-
+ String noshrReason = null;
+
// TEST
if ( params.getAccessMode() == AccessMode.NTFileGenericExecute && params.getPath().toLowerCase().endsWith( ".exe") == false) {
@@ -1736,45 +1733,53 @@ public class ContentDiskDriver extends AlfrescoTxDiskDriver implements DiskInter
if ( fstate.getOpenCount() > 0) {
- // Check for impersonation security level from the original process that opened the file
-
- if ( params.getSecurityLevel() == WinNT.SecurityImpersonation && params.getProcessId() == fstate.getProcessId())
- nosharing = false;
-
- // Check if the caller wants read access, check the sharing mode
-
- else if ( params.isReadOnlyAccess() && (fstate.getSharedAccess() & SharingMode.READ) != 0)
- nosharing = false;
-
- // Check if the caller wants write access, check the sharing mode
-
- else if (( params.isReadWriteAccess() || params.isWriteOnlyAccess()) && (fstate.getSharedAccess() & SharingMode.WRITE) == 0)
- {
- // DEBUG
-
+ // Check for impersonation security level from the original process that opened the file
+
+ if ( params.getSecurityLevel() == WinNT.SecurityImpersonation && params.getProcessId() == fstate.getProcessId())
+ nosharing = false;
+
+ // Check if the caller wants read access, check the sharing mode
+ // Check if the caller wants write access, check if the sharing mode allows write
+
+ else if ( params.isReadOnlyAccess() && (fstate.getSharedAccess() & SharingMode.READ) != 0)
+ nosharing = false;
+
+ // Check if the caller wants write access, check the sharing mode
+
+ else if (( params.isReadWriteAccess() || params.isWriteOnlyAccess()) && (fstate.getSharedAccess() & SharingMode.WRITE) == 0)
+ {
+ nosharing = true;
+ noshrReason = "Sharing mode disallows write";
+
+ // DEBUG
+
if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
- logger.debug("Sharing mode disallows write access path=" + params.getPath());
-
- // Access not allowed
-
- throw new AccessDeniedException( "Sharing mode (write)");
- }
-
- // Check if the file has been opened for exclusive access
-
- else if ( fstate.getSharedAccess() == SharingMode.NOSHARING)
- nosharing = true;
-
- // Check if the required sharing mode is allowed by the current file open
-
- else if ( ( fstate.getSharedAccess() & params.getSharedAccess()) != params.getSharedAccess())
- nosharing = true;
-
- // Check if the caller wants exclusive access to the file
-
- else if ( params.getSharedAccess() == SharingMode.NOSHARING)
- nosharing = true;
-
+ logger.debug("Sharing mode disallows write access path=" + params.getPath());
+ }
+
+ // Check if the file has been opened for exclusive access
+
+ else if ( fstate.getSharedAccess() == SharingMode.NOSHARING) {
+ nosharing = true;
+ noshrReason = "Sharing mode exclusive";
+ }
+
+ // Check if the required sharing mode is allowed by the current file open
+
+ else if ((fstate.getSharedAccess() & params.getSharedAccess()) != params.getSharedAccess()) {
+ nosharing = true;
+ noshrReason = "Sharing mode mismatch";
+
+ if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
+ logger.debug("Local share mode=0x" + Integer.toHexString(fstate.getSharedAccess()) + ", params share mode=0x" + Integer.toHexString(params.getSharedAccess()));
+ }
+
+ // Check if the caller wants exclusive access to the file
+
+ else if ( params.getSharedAccess() == SharingMode.NOSHARING) {
+ nosharing = true;
+ noshrReason = "Requestor wants exclusive mode";
+ }
}
// Check if the file allows shared access
@@ -1786,7 +1791,7 @@ public class ContentDiskDriver extends AlfrescoTxDiskDriver implements DiskInter
// DEBUG
if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
- logger.debug("Sharing violation path=" + params.getPath() + ", sharing=0x" + Integer.toHexString(fstate.getSharedAccess()));
+ logger.debug("Sharing violation path=" + params.getPath() + ", sharing=0x" + Integer.toHexString(fstate.getSharedAccess()) + ",reason=" + noshrReason);
// File is locked by another user
@@ -4024,7 +4029,8 @@ public class ContentDiskDriver extends AlfrescoTxDiskDriver implements DiskInter
* @return LockManager
*/
public LockManager getLockManager(SrvSession sess, TreeConnection tree) {
- return _lockManager;
+ ContentContext ctx = (ContentContext) tree.getContext();
+ return ctx.getLockManager();
}
/**
@@ -4035,7 +4041,8 @@ public class ContentDiskDriver extends AlfrescoTxDiskDriver implements DiskInter
* @return OpLockManager
*/
public OpLockManager getOpLockManager(SrvSession sess, TreeConnection tree) {
- return _lockManager;
+ ContentContext ctx = (ContentContext) tree.getContext();
+ return ctx.getLockManager();
}
/**
diff --git a/source/java/org/alfresco/filesys/repo/ContentQuotaManager.java b/source/java/org/alfresco/filesys/repo/ContentQuotaManager.java
index 012bc3ca10..5dcb67bc67 100644
--- a/source/java/org/alfresco/filesys/repo/ContentQuotaManager.java
+++ b/source/java/org/alfresco/filesys/repo/ContentQuotaManager.java
@@ -21,6 +21,7 @@ package org.alfresco.filesys.repo;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
import org.alfresco.jlan.server.SrvSession;
import org.alfresco.jlan.server.filesys.DiskDeviceContext;
@@ -72,8 +73,8 @@ public class ContentQuotaManager implements QuotaManager, Runnable {
// Track live usage of users that are writing files
- private HashMap m_liveUsage;
- private Object m_addDetailsLock = new Object();
+ private Map m_liveUsage;
+ private Object m_liveUsageLock = new Object();
// User details inactivity checker thread
@@ -141,10 +142,12 @@ public class ContentQuotaManager implements QuotaManager, Runnable {
// Check if there is a live usage record for the user
UserQuotaDetails userQuota = getQuotaDetails(sess, true);
- if ( userQuota != null)
- {
- return userQuota.getAvailableSpace();
- }
+ if ( userQuota != null) {
+ synchronized (userQuota) {
+ return userQuota.getAvailableSpace();
+ }
+ }
+
// No quota details available
return 0L;
@@ -177,10 +180,10 @@ public class ContentQuotaManager implements QuotaManager, Runnable {
// Check if the user has a usage quota
- if ( userQuota.hasUserQuota()) {
+ synchronized ( userQuota) {
- synchronized ( userQuota) {
-
+ if ( userQuota.hasUserQuota()) {
+
// Check if the user has enough free space allocation
if ( alloc > 0 && userQuota.getAvailableSpace() >= alloc) {
@@ -188,12 +191,9 @@ public class ContentQuotaManager implements QuotaManager, Runnable {
allowedAlloc = alloc;
}
}
- }
- else {
+ else {
- // Update the live usage
-
- synchronized ( userQuota) {
+ // Update the live usage
userQuota.addToCurrentUsage( alloc);
allowedAlloc = alloc;
}
@@ -308,12 +308,14 @@ public class ContentQuotaManager implements QuotaManager, Runnable {
}
// Clear out the live usage details
-
- m_liveUsage.clear();
+ synchronized (m_liveUsageLock)
+ {
+ m_liveUsage.clear();
+ m_shutdown = true;
+ }
// Shutdown the checker thread
- m_shutdown = true;
m_thread.interrupt();
}
@@ -326,37 +328,40 @@ public class ContentQuotaManager implements QuotaManager, Runnable {
*/
private UserQuotaDetails getQuotaDetails(SrvSession sess, boolean loadDetails) {
- UserQuotaDetails userQuota = null;
+ synchronized (m_liveUsageLock) {
+
+ UserQuotaDetails userQuota = null;
String userName = AuthenticationUtil.getFullyAuthenticatedUser();
-
+
if ( sess != null && userName != null)
{
- // Get the live usage values
-
+ // Get the live usage values
userQuota = m_liveUsage.get(userName);
if ( userQuota == null && loadDetails == true)
{
- // User is not in the live tracking table, load details for the user
+ // User is not in the live tracking table, load details for the user
+
try
{
logger.debug("user is not in cache - load details");
userQuota = loadUsageDetails(userName);
- }
+ }
catch ( QuotaManagerException ex)
{
- if ( logger.isDebugEnabled())
+ if ( logger.isDebugEnabled())
{
logger.debug("Unable to load usage details", ex);
}
- }
- }
- }
-
- // Return the user quota details
-
- return userQuota;
+ }
+ }
+ }
+
+ // Return the user quota details
+
+ return userQuota;
+ }
}
/**
@@ -396,8 +401,6 @@ public class ContentQuotaManager implements QuotaManager, Runnable {
// Add the details to the live tracking table
- synchronized ( m_addDetailsLock) {
-
// Check if another thread has added the details
UserQuotaDetails details = m_liveUsage.get( userName);
@@ -409,7 +412,6 @@ public class ContentQuotaManager implements QuotaManager, Runnable {
{
m_liveUsage.put( userName, quotaDetails);
}
- }
// DEBUG
@@ -479,61 +481,66 @@ public class ContentQuotaManager implements QuotaManager, Runnable {
}
// Check if there are any user quota details to check
-
- if ( m_liveUsage != null && m_liveUsage.size() > 0)
+ synchronized (m_liveUsageLock)
{
- try
+ if ( m_liveUsage != null && m_liveUsage.size() > 0)
{
- // Timestamp to check if the quota details is inactive
+ try
+ {
+ // Timestamp to check if the quota details is inactive
- long checkTime = System.currentTimeMillis() - UserQuotaExpireInterval;
+ long checkTime = System.currentTimeMillis() - UserQuotaExpireInterval;
- // Loop through the user quota details
+ // Loop through the user quota details
- removeNameList.remoteAllStrings();
- Iterator userNames = m_liveUsage.keySet().iterator();
+ removeNameList.remoteAllStrings();
+ Iterator userNames = m_liveUsage.keySet().iterator();
- while ( userNames.hasNext()) {
+ while ( userNames.hasNext()) {
- // Get the user quota details and check if it has been inactive in the last check interval
+ // Get the user quota details and check if it has been inactive in the last check interval
- String userName = userNames.next();
- UserQuotaDetails quotaDetails = m_liveUsage.get( userName);
+ String userName = userNames.next();
+ UserQuotaDetails quotaDetails = m_liveUsage.get( userName);
- if ( quotaDetails.getLastUpdated() < checkTime) {
-
- // Add the user name to the remove list, inactive
-
- removeNameList.addString( userName);
- }
- }
+ synchronized (quotaDetails) {
+ if ( quotaDetails.getLastUpdated() < checkTime) {
+
+ // Add the user name to the remove list, inactive
+
+ removeNameList.addString( userName);
+ }
+ }
+ }
- // Remove inactive records from the live quota tracking
+ // Remove inactive records from the live quota tracking
while ( removeNameList.numberOfStrings() > 0)
{
- // Get the current user name and remove the record
+ // Get the current user name and remove the record
- String userName = removeNameList.removeStringAt( 0);
- UserQuotaDetails quotaDetails = m_liveUsage.remove( userName);
+ String userName = removeNameList.removeStringAt( 0);
+ UserQuotaDetails quotaDetails = m_liveUsage.remove( userName);
- // DEBUG
+ // DEBUG
- if ( logger.isDebugEnabled())
- logger.debug("Removed inactive usage tracking, " + quotaDetails);
+ if ( logger.isDebugEnabled())
+ logger.debug("Removed inactive usage tracking, " + quotaDetails);
+ }
+ }
+ catch (Exception ex)
+ {
+ // Log errors if not shutting down
+
+ if ( m_shutdown == false)
+ logger.debug(ex);
}
}
- catch (Exception ex)
- {
- // Log errors if not shutting down
-
- if ( m_shutdown == false)
- logger.debug(ex);
- }
}
- }
- }
+ }
+
+ }
public void setContentService(ContentService contentService)
{
diff --git a/source/java/org/alfresco/repo/audit/AuditMethodInterceptor.java b/source/java/org/alfresco/repo/audit/AuditMethodInterceptor.java
index c61923da3a..b0f1ffda89 100644
--- a/source/java/org/alfresco/repo/audit/AuditMethodInterceptor.java
+++ b/source/java/org/alfresco/repo/audit/AuditMethodInterceptor.java
@@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;
+import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.error.StackTraceUtil;
import org.alfresco.repo.audit.model.AuditApplication;
import org.alfresco.repo.domain.schema.SchemaBootstrap;
@@ -216,8 +217,8 @@ public class AuditMethodInterceptor implements MethodInterceptor
}
catch (Throwable e)
{
- // Failure to audit should not break the invocation
- logger.error(
+ // Failure to audit must stop the process: ALF-11139
+ throw new AlfrescoRuntimeException(
"Failed to audit pre-invocation: \n" +
" Invocation: " + mi,
e);
@@ -243,8 +244,8 @@ public class AuditMethodInterceptor implements MethodInterceptor
}
catch (Throwable e)
{
- // Failure to audit should not break the invocation
- logger.error(
+ // Failure to audit must stop the process: ALF-11139
+ throw new AlfrescoRuntimeException(
"Failed to audit post-invocation: \n" +
" Invocation: " + mi,
e);
diff --git a/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImpl.java b/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImpl.java
index 98110b8e25..d5abca02f9 100644
--- a/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImpl.java
+++ b/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImpl.java
@@ -367,7 +367,7 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
throw new CheckOutCheckInServiceException(MSG_ALREADY_CHECKEDOUT);
}
- // Make sure we are no checking out a working copy node
+ // Make sure we are not checking out a working copy node
if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY))
{
throw new CheckOutCheckInServiceException(MSG_ERR_ALREADY_WORKING_COPY);
@@ -400,10 +400,6 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
// Invoke before check out policy
invokeBeforeCheckOut(nodeRef, destinationParentNodeRef, destinationAssocTypeQName, destinationAssocQName);
-
- // Rename the working copy
- String copyName = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
- copyName = createWorkingCopyName(copyName);
// Get the user
final String userName = getUserName();
@@ -411,7 +407,12 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
NodeRef workingCopy = null;
ruleService.disableRuleType(RuleType.UPDATE);
try
- {
+ {
+ // Rename the working copy
+ String copyName = (String)this.nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
+ String workingCopyLabel = getWorkingCopyLabel();
+ copyName = createWorkingCopyName(copyName, workingCopyLabel);
+
// Make the working copy
final QName copyQName = QName.createQName(destinationAssocQName.getNamespaceURI(), QName.createValidLocalName(copyName));
@@ -455,6 +456,7 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
// Apply the working copy aspect to the working copy
Map workingCopyProperties = new HashMap(1);
workingCopyProperties.put(ContentModel.PROP_WORKING_COPY_OWNER, userName);
+ workingCopyProperties.put(ContentModel.PROP_WORKING_COPY_LABEL, workingCopyLabel);
nodeService.addAspect(workingCopy, ContentModel.ASPECT_WORKING_COPY, workingCopyProperties);
nodeService.addAspect(nodeRef, ContentModel.ASPECT_CHECKED_OUT, null);
nodeService.createAssociation(nodeRef, workingCopy, ContentModel.ASSOC_WORKING_COPY_LINK);
@@ -572,36 +574,43 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
{
String origName = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
String name = (String)nodeService.getProperty(workingCopyNodeRef, ContentModel.PROP_NAME);
- if (hasWorkingCopyNameChanged(name, origName))
+ String wcLabel = (String)this.nodeService.getProperty(workingCopyNodeRef, ContentModel.PROP_WORKING_COPY_LABEL);
+ if (wcLabel == null)
+ {
+ wcLabel = getWorkingCopyLabel();
+ }
+
+ if (hasWorkingCopyNameChanged(name, origName, wcLabel))
{
// ensure working copy has working copy label in its name to avoid name clash
- if (!name.contains(" " + getWorkingCopyLabel()))
+ if (!name.contains(" " + wcLabel))
{
try
{
- fileFolderService.rename(workingCopyNodeRef, createWorkingCopyName(name));
+ fileFolderService.rename(workingCopyNodeRef, createWorkingCopyName(name, wcLabel));
}
catch (FileExistsException e)
{
- throw new CheckOutCheckInServiceException(e, MSG_ERR_CANNOT_RENAME, name, createWorkingCopyName(name));
+ throw new CheckOutCheckInServiceException(e, MSG_ERR_CANNOT_RENAME, name, wcLabel);
}
catch (FileNotFoundException e)
{
- throw new CheckOutCheckInServiceException(e, MSG_ERR_CANNOT_RENAME, name, createWorkingCopyName(name));
+ throw new CheckOutCheckInServiceException(e, MSG_ERR_CANNOT_RENAME, name, wcLabel);
}
}
+ String newName = getNameFromWorkingCopyName(name, wcLabel);
try
{
// rename original to changed working name
- fileFolderService.rename(nodeRef, getNameFromWorkingCopyName(name));
+ fileFolderService.rename(nodeRef, newName);
}
catch (FileExistsException e)
{
- throw new CheckOutCheckInServiceException(e, MSG_ERR_CANNOT_RENAME, origName, getNameFromWorkingCopyName(name));
+ throw new CheckOutCheckInServiceException(e, MSG_ERR_CANNOT_RENAME, origName, newName);
}
catch (FileNotFoundException e)
{
- throw new CheckOutCheckInServiceException(e, MSG_ERR_CANNOT_RENAME, name, getNameFromWorkingCopyName(name));
+ throw new CheckOutCheckInServiceException(e, MSG_ERR_CANNOT_RENAME, name, newName);
}
}
}
@@ -745,14 +754,25 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
}
/**
- * Create working copy name
+ * Create a working copy name using the given fileName and workingCopyLabel. The label will be inserted before
+ * the file extension (if present), or else appended to the name (in either case a space is prepended to the
+ * workingCopyLabel).
+ *
+ * Examples, where workingCopyLabel is "wc":
+ *
+ * "Myfile.txt" becomes "Myfile wc.txt", "Myfile" becomes "Myfile wc".
+ *
+ * In the event that fileName is empty or null, the workingCopyLabel is used for the new working copy name
+ *
+ * Example: "" becomes "wc".
*
- * @param name name
- * @return working copy name
+ * @param name
+ * @param workingCopyLabel
+ * @return
*/
- public static String createWorkingCopyName(String name)
+ public static String createWorkingCopyName(String name, final String workingCopyLabel)
{
- if (getWorkingCopyLabel() != null && getWorkingCopyLabel().length() != 0)
+ if (workingCopyLabel != null && workingCopyLabel.length() != 0)
{
if (name != null && name.length() != 0)
{
@@ -760,30 +780,31 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
if (index > 0)
{
// Insert the working copy label before the file extension
- name = name.substring(0, index) + " " + getWorkingCopyLabel() + name.substring(index);
+ name = name.substring(0, index) + " " + workingCopyLabel + name.substring(index);
}
else
{
// Simply append the working copy label onto the end of the existing name
- name = name + " " + getWorkingCopyLabel();
+ name = name + " " + workingCopyLabel;
}
}
else
{
- name = getWorkingCopyLabel();
+ name = workingCopyLabel;
}
}
return name;
}
/**
- * Get original name from working copy name
+ * Get original name from the working copy name and the cm:workingCopyLabel
+ * that was used to create it.
*
+ * @param workingCopyLabel
* @return original name
*/
- private String getNameFromWorkingCopyName(String workingCopyName)
+ private String getNameFromWorkingCopyName(String workingCopyName, String workingCopyLabel)
{
- String workingCopyLabel = getWorkingCopyLabel();
String workingCopyLabelRegEx = workingCopyLabel.replaceAll("\\(", "\\\\(");
workingCopyLabelRegEx = workingCopyLabelRegEx.replaceAll("\\)", "\\\\)");
if (workingCopyName.contains(" " + workingCopyLabel))
@@ -800,13 +821,15 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
/**
* Has the working copy name changed compared to the original name
*
- * @param name working copy name
+ * @param workingCopyName working copy name
* @param origName original name
+ * @param wcLabel that was inserted into origName to create the original working copy name
* @return true => if changed
*/
- private boolean hasWorkingCopyNameChanged(String workingCopyName, String origName)
+ private boolean hasWorkingCopyNameChanged(String workingCopyName, String origName, String wcLabel)
{
- return !workingCopyName.equals(createWorkingCopyName(origName));
+ String origWorkingCopyName = createWorkingCopyName(origName, wcLabel);
+ return !workingCopyName.equals(origWorkingCopyName);
}
/**
diff --git a/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImplTest.java b/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImplTest.java
index b1301fd7de..5823d1fa63 100644
--- a/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImplTest.java
+++ b/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImplTest.java
@@ -22,6 +22,7 @@ import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import org.alfresco.model.ContentModel;
@@ -53,6 +54,7 @@ import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.BaseSpringTest;
import org.alfresco.util.GUID;
import org.alfresco.util.TestWithUserUtils;
+import org.springframework.extensions.surf.util.I18NUtil;
/**
* Version operations service implementation unit tests
@@ -218,12 +220,20 @@ public class CheckOutCheckInServiceImplTest extends BaseSpringTest
// Check that the working copy owner has been set correctly
assertEquals(this.userNodeRef, nodeService.getProperty(workingCopy, ContentModel.PROP_WORKING_COPY_OWNER));
+
// Check that the working copy name has been set correctly
- String name = (String)nodeService.getProperty(this.nodeRef, PROP_NAME_QNAME);
- String workingCopyLabel = CheckOutCheckInServiceImpl.createWorkingCopyName(name);
- String workingCopyName = (String)nodeService.getProperty(workingCopy, PROP_NAME_QNAME);
- assertEquals(workingCopyLabel, workingCopyName);
+ String name = (String)this.nodeService.getProperty(this.nodeRef, PROP_NAME_QNAME);
+ String expectedWorkingCopyLabel = I18NUtil.getMessage("coci_service.working_copy_label");
+ String expectedWorkingCopyName =
+ ((CheckOutCheckInServiceImpl)this.cociService).createWorkingCopyName(name, expectedWorkingCopyLabel);
+ String workingCopyName = (String)this.nodeService.getProperty(workingCopy, PROP_NAME_QNAME);
+ assertEquals(expectedWorkingCopyName, workingCopyName);
+ // Check a record has been kept of the working copy label used to create the working copy name
+ assertEquals(
+ "No record of working copy label kept",
+ expectedWorkingCopyLabel,
+ nodeService.getProperty(workingCopy, ContentModel.PROP_WORKING_COPY_LABEL));
// Ensure that the content has been copied correctly
ContentReader contentReader = this.contentService.getReader(this.nodeRef, ContentModel.PROP_CONTENT);
@@ -298,10 +308,63 @@ public class CheckOutCheckInServiceImplTest extends BaseSpringTest
NodeRef workingCopy2 = checkout();
Map versionProperties2 = new HashMap();
versionProperties2.put(Version.PROP_DESCRIPTION, "Another version test");
- cociService.checkin(workingCopy2, versionProperties2, null, true);
- cociService.checkin(workingCopy2, new HashMap(), null, true);
+ this.cociService.checkin(workingCopy2, versionProperties2, null, true);
+ this.cociService.checkin(workingCopy2, new HashMap(), null, true);
}
+ public void testCheckOutCheckInWithDifferentLocales()
+ {
+ // Check-out nodeRef using the locale fr_FR
+ Locale.setDefault(Locale.FRANCE);
+ NodeRef workingCopy = this.cociService.checkout(
+ this.nodeRef,
+ this.rootNodeRef,
+ ContentModel.ASSOC_CHILDREN,
+ QName.createQName("workingCopy"));
+ assertNotNull(workingCopy);
+
+ // Check that the working copy name has been set correctly
+ String workingCopyName = (String) nodeService.getProperty(workingCopy, PROP_NAME_QNAME);
+ assertEquals("Working copy name not correct", "myDocument (Copie de Travail).doc", workingCopyName);
+
+ // Check-in using the locale en_GB
+ Locale.setDefault(Locale.UK);
+ Map versionProperties = new HashMap();
+ versionProperties.put(Version.PROP_DESCRIPTION, "This is a test version");
+ cociService.checkin(workingCopy, versionProperties);
+
+ String name = (String) nodeService.getProperty(nodeRef, PROP_NAME_QNAME);
+ assertEquals("Working copy label was not removed.", "myDocument.doc", name);
+ }
+
+ public void testCheckOutCheckInWithAlteredWorkingCopyName()
+ {
+ // Check-out nodeRef using the locale fr_FR
+ Locale.setDefault(Locale.FRANCE);
+ NodeRef workingCopy = this.cociService.checkout(
+ this.nodeRef,
+ this.rootNodeRef,
+ ContentModel.ASSOC_CHILDREN,
+ QName.createQName("workingCopy"));
+ assertNotNull(workingCopy);
+
+ // Check that the working copy name has been set correctly
+ String workingCopyName = (String) nodeService.getProperty(workingCopy, PROP_NAME_QNAME);
+ assertEquals("Working copy name not correct", "myDocument (Copie de Travail).doc", workingCopyName);
+
+ // Alter the working copy name
+ nodeService.setProperty(workingCopy, PROP_NAME_QNAME, "newName (Copie de Travail).doc");
+
+ // Check-in using the locale en_GB
+ Locale.setDefault(Locale.UK);
+ Map versionProperties = new HashMap();
+ versionProperties.put(Version.PROP_DESCRIPTION, "This is a test version");
+ cociService.checkin(workingCopy, versionProperties);
+
+ String name = (String) nodeService.getProperty(nodeRef, PROP_NAME_QNAME);
+ assertEquals("File not renamed correctly.", "newName.doc", name);
+ }
+
public void testCheckInWithNameChange()
{
// Check out the file
diff --git a/source/java/org/alfresco/repo/imap/ImapMessageTest.java b/source/java/org/alfresco/repo/imap/ImapMessageTest.java
index a2541b2d3c..813cb809b4 100644
--- a/source/java/org/alfresco/repo/imap/ImapMessageTest.java
+++ b/source/java/org/alfresco/repo/imap/ImapMessageTest.java
@@ -205,7 +205,7 @@ public class ImapMessageTest extends TestCase
// Starting IMAP
- imapServiceImpl.startup();
+ imapServiceImpl.startupInTxn();
nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore + "/" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + IMAP_FOLDER_NAME, null,
namespaceService, false);
diff --git a/source/java/org/alfresco/repo/imap/ImapServiceImpl.java b/source/java/org/alfresco/repo/imap/ImapServiceImpl.java
index 2cf79f3e6a..982ebe38f4 100644
--- a/source/java/org/alfresco/repo/imap/ImapServiceImpl.java
+++ b/source/java/org/alfresco/repo/imap/ImapServiceImpl.java
@@ -204,27 +204,24 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
@Override
protected void onBootstrap(ApplicationEvent event)
{
- service.serviceRegistry.getTransactionService().getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
- {
- @Override
- public Void execute() throws Throwable
- {
- if (service.getImapServerEnabled())
- {
- service.startup();
- }
- return null;
- }
- });
+ service.startupInTxn();
}
@Override
protected void onShutdown(ApplicationEvent event)
{
- if (service.getImapServerEnabled())
+ AuthenticationUtil.runAs(new RunAsWork()
{
- service.shutdown();
- }
+ @Override
+ public Void doWork() throws Exception
+ {
+ if (service.getImapServerEnabled())
+ {
+ service.shutdown();
+ }
+ return null;
+ }
+ }, AuthenticationUtil.getSystemUserName());
}
}
@@ -390,6 +387,9 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
}
}
+ /**
+ * This method is run as System within a single transaction on startup.
+ */
public void startup()
{
bindBehaviour();
@@ -398,61 +398,62 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
final SearchService searchService = serviceRegistry.getSearchService();
// Get NodeRefs for folders to ignore
- this.ignoreExtractionFolders = AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork>()
+ this.ignoreExtractionFolders = new HashSet(ignoreExtractionFoldersBeans.length * 2);
+
+ for (RepositoryFolderConfigBean ignoreExtractionFoldersBean : ignoreExtractionFoldersBeans)
{
- public Set doWork() throws Exception
+ NodeRef nodeRef = ignoreExtractionFoldersBean.getFolderPath(namespaceService, nodeService, searchService,
+ fileFolderService);
+
+ if (!ignoreExtractionFolders.add(nodeRef))
{
- Set result = new HashSet(ignoreExtractionFoldersBeans.length * 2);
-
- for (RepositoryFolderConfigBean ignoreExtractionFoldersBean : ignoreExtractionFoldersBeans)
- {
- NodeRef nodeRef = ignoreExtractionFoldersBean.getFolderPath(
- namespaceService, nodeService, searchService, fileFolderService);
-
- if (!result.add(nodeRef))
- {
- // It was already in the set
- throw new AlfrescoRuntimeException(
- "The folder extraction path has been referenced already: \n" +
- " Folder: " + ignoreExtractionFoldersBean);
- }
- }
-
- return result;
+ // It was already in the set
+ throw new AlfrescoRuntimeException("The folder extraction path has been referenced already: \n"
+ + " Folder: " + ignoreExtractionFoldersBean);
}
- }, AuthenticationUtil.getSystemUserName());
+ }
// Locate or create IMAP home
- imapHomeNodeRef = AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
- {
- public NodeRef doWork() throws Exception
- {
- return imapHomeConfigBean.getOrCreateFolderPath(namespaceService, nodeService, searchService, fileFolderService);
- }
- }, AuthenticationUtil.getSystemUserName());
+ imapHomeNodeRef = imapHomeConfigBean.getOrCreateFolderPath(namespaceService, nodeService, searchService, fileFolderService);
// Hit the mount points and warm the caches for early failure
- AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
+ for (String mountPointName : imapConfigMountPoints.keySet())
{
- public Void doWork() throws Exception
+ for (AlfrescoImapFolder mailbox : listMailboxes(new AlfrescoImapUser(null, AuthenticationUtil
+ .getSystemUserName(), null), mountPointName + "*", false))
{
- for (String mountPointName: imapConfigMountPoints.keySet())
- {
- for (AlfrescoImapFolder mailbox : listMailboxes(new AlfrescoImapUser(null, AuthenticationUtil
- .getSystemUserName(), null), mountPointName + "*", false))
- {
- mailbox.getUidNext();
- }
- }
- return null;
+ mailbox.getUidNext();
}
- }, AuthenticationUtil.getSystemUserName());
-
+ }
}
public void shutdown()
{
}
+
+ protected void startupInTxn()
+ {
+ if (getImapServerEnabled())
+ {
+ AuthenticationUtil.runAs(new RunAsWork()
+ {
+ @Override
+ public Void doWork() throws Exception
+ {
+ return serviceRegistry.getTransactionService().getRetryingTransactionHelper().doInTransaction(
+ new RetryingTransactionCallback()
+ {
+ @Override
+ public Void execute() throws Throwable
+ {
+ startup();
+ return null;
+ }
+ });
+ }
+ }, AuthenticationUtil.getSystemUserName());
+ }
+ }
protected void bindBehaviour()
{
diff --git a/source/java/org/alfresco/repo/imap/ImapServiceImplCacheTest.java b/source/java/org/alfresco/repo/imap/ImapServiceImplCacheTest.java
index 5bcf42cbbb..fada432d22 100644
--- a/source/java/org/alfresco/repo/imap/ImapServiceImplCacheTest.java
+++ b/source/java/org/alfresco/repo/imap/ImapServiceImplCacheTest.java
@@ -10,7 +10,6 @@ import junit.framework.TestCase;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
import org.alfresco.repo.model.filefolder.FileFolderServiceImpl;
-import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
@@ -99,15 +98,7 @@ public class ImapServiceImplCacheTest extends TestCase
imapServiceImpl.setImapHome(imapHome);
// Starting IMAP
- transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
- {
- @Override
- public Void execute() throws Throwable
- {
- imapServiceImpl.startup();
- return null;
- }
- });
+ imapServiceImpl.startupInTxn();
nodeRefs = searchService.selectNodes(storeRootNodeRef,
companyHomePathInStore + "/" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + TEST_IMAP_FOLDER_NAME,
diff --git a/source/java/org/alfresco/repo/imap/ImapServiceImplTest.java b/source/java/org/alfresco/repo/imap/ImapServiceImplTest.java
index e0c4369141..1921d511ae 100644
--- a/source/java/org/alfresco/repo/imap/ImapServiceImplTest.java
+++ b/source/java/org/alfresco/repo/imap/ImapServiceImplTest.java
@@ -180,7 +180,7 @@ public class ImapServiceImplTest extends TestCase
imapServiceImpl.setImapHome(imapHome);
// Starting IMAP
- imapServiceImpl.startup();
+ imapServiceImpl.startupInTxn();
nodeRefs = searchService.selectNodes(storeRootNodeRef,
companyHomePathInStore + "/" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + TEST_IMAP_FOLDER_NAME,
diff --git a/source/java/org/alfresco/repo/imap/LoadTester.java b/source/java/org/alfresco/repo/imap/LoadTester.java
index eda81042d5..9aec62b9fd 100644
--- a/source/java/org/alfresco/repo/imap/LoadTester.java
+++ b/source/java/org/alfresco/repo/imap/LoadTester.java
@@ -163,7 +163,7 @@ public class LoadTester extends TestCase
imapServiceImpl.setImapHome(imapHome);
// Starting IMAP
- imapServiceImpl.startup();
+ imapServiceImpl.startupInTxn();
nodeRefs = searchService.selectNodes(storeRootNodeRef,
companyHomePathInStore + "/" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + TEST_IMAP_ROOT_FOLDER_NAME,
diff --git a/source/java/org/alfresco/repo/jscript/ScriptUtils.java b/source/java/org/alfresco/repo/jscript/ScriptUtils.java
index 569beeef34..ad771d9374 100644
--- a/source/java/org/alfresco/repo/jscript/ScriptUtils.java
+++ b/source/java/org/alfresco/repo/jscript/ScriptUtils.java
@@ -282,9 +282,10 @@ public final class ScriptUtils extends BaseScopableProcessorExtension
/**
* Sets current Locale from string
*/
- public void setLocale(String language)
+ public void setLocale(String localeStr)
{
- I18NUtil.setLocale(new Locale(language));
+ Locale newLocale = I18NUtil.parseLocale(localeStr);
+ I18NUtil.setLocale(newLocale);
}
/**
diff --git a/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java b/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java
index 710f2d583b..5fb70ae720 100644
--- a/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java
+++ b/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java
@@ -417,6 +417,7 @@ public class ChildApplicationContextFactory extends AbstractPropertyBackedBean i
PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
configurer.setProperties(properties);
configurer.setIgnoreUnresolvablePlaceholders(true);
+ configurer.setSearchSystemEnvironment(false);
addBeanFactoryPostProcessor(configurer);
// Add all the post processors of the parent, e.g. to make sure system placeholders get expanded properly
diff --git a/source/java/org/alfresco/repo/node/FullNodeServiceTest.java b/source/java/org/alfresco/repo/node/FullNodeServiceTest.java
index 9d63b9e96c..950b9f262a 100644
--- a/source/java/org/alfresco/repo/node/FullNodeServiceTest.java
+++ b/source/java/org/alfresco/repo/node/FullNodeServiceTest.java
@@ -24,6 +24,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -56,6 +57,8 @@ public class FullNodeServiceTest extends BaseNodeServiceTest
protected void onSetUpInTransaction() throws Exception
{
super.onSetUpInTransaction();
+ Locale.setDefault(Locale.ENGLISH);
+ MLPropertyInterceptor.setMLAware(false);
}
public void testMLTextValues() throws Exception
@@ -73,7 +76,7 @@ public class FullNodeServiceTest extends BaseNodeServiceTest
BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE,
mlTextProperty);
- // Check filterered property retrieval
+ // Check filtered property retrieval
Serializable textValueFiltered = nodeService.getProperty(
rootNodeRef,
BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE);
@@ -90,6 +93,139 @@ public class FullNodeServiceTest extends BaseNodeServiceTest
propertiesFiltered.get(BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE));
}
+ /**
+ * ALF-3756 - original fix didn't cope with existing MLText properties having one or more variants
+ * of a particular language. Upgrading to the fix would therefore not solve the problem properly.
+ *
+ * For example, if a property has en_GB text in it, then 'updating' that property
+ * with a locale of en_US will result in the addition of the en_US text rather than a true update (they're both
+ * English, and using two slightly differently configured browsers in this way leads to confusion).
+ */
+ public void testMLTextUpdatedForCorrectLanguage() throws Exception
+ {
+ Locale.setDefault(Locale.UK);
+ MLPropertyInterceptor.setMLAware(true);
+ MLText mlTextProperty = new MLText();
+ mlTextProperty.addValue(Locale.UK, "en_GB String");
+ mlTextProperty.addValue(Locale.FRANCE, "fr_FR String");
+
+ // Store the MLText property
+ nodeService.setProperty(
+ rootNodeRef,
+ BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE,
+ mlTextProperty);
+
+ // Pre-test check that an MLText property has been created with the correct locale/text pairs.
+ Serializable textValue = nodeService.getProperty(
+ rootNodeRef,
+ BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE);
+ assertEquals(2, ((MLText) textValue).size());
+ assertEquals("en_GB String", ((MLText) textValue).getValue(Locale.UK));
+ assertEquals("fr_FR String", ((MLText) textValue).getValue(Locale.FRANCE));
+
+ // Enable MLText filtering - as this is how the repo will be used.
+ MLPropertyInterceptor.setMLAware(false);
+
+ // Retrieve the MLText - but it is filtered into an appropriate String
+ textValue = nodeService.getProperty(
+ rootNodeRef,
+ BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE);
+ assertEquals("en_GB String", (String) textValue);
+
+ // Update the property, only this time using a different English variant
+ Locale.setDefault(Locale.US); // en_US
+ nodeService.setProperty(
+ rootNodeRef,
+ BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE,
+ "Not using MLText for this part.");
+
+ // Check that the text was updated rather than added to
+ MLPropertyInterceptor.setMLAware(true); // no filtering - see real MLText
+ // Check that there are not too many English strings, we don't want one for en_GB and one for en_US
+ textValue = nodeService.getProperty(
+ rootNodeRef,
+ BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE);
+ assertEquals(2, ((MLText) textValue).size());
+ assertEquals("Text wasn't updated correctly",
+ "Not using MLText for this part.",
+ ((MLText) textValue).getValue(Locale.ENGLISH));
+ assertEquals("Failed to get text using locale it was added with",
+ "Not using MLText for this part.",
+ ((MLText) textValue).getClosestValue(Locale.US));
+ assertEquals("Failed to get text using original locale",
+ "Not using MLText for this part.",
+ ((MLText) textValue).getClosestValue(Locale.UK));
+ assertEquals("fr_FR String", ((MLText) textValue).getValue(Locale.FRANCE));
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testMLTextCollectionUpdatedForCorrectLanguage()
+ {
+ Locale.setDefault(Locale.UK);
+ MLPropertyInterceptor.setMLAware(true);
+
+ ArrayList values = new ArrayList();
+ values.add(new MLText(Locale.UK, "en_GB text"));
+ values.add(new MLText(Locale.US, "en_US text"));
+ values.add(new MLText(Locale.FRANCE, "fr_FR text"));
+
+ // Set the property with no MLText filtering
+ nodeService.setProperty(rootNodeRef, PROP_QNAME_MULTI_ML_VALUE, values);
+
+ // Pre-test check
+ List checkValues = (List) nodeService.getProperty(
+ rootNodeRef, PROP_QNAME_MULTI_ML_VALUE);
+ assertEquals("Expected 3 MLText values back", 3, checkValues.size());
+ assertEquals("en_GB text", ((MLText) checkValues.get(0)).getValue(Locale.UK));
+ assertEquals("en_US text", ((MLText) checkValues.get(1)).getValue(Locale.US));
+ assertEquals("fr_FR text", ((MLText) checkValues.get(2)).getValue(Locale.FRANCE));
+
+ // Enable MLText filtering - as this is how the repo will be used.
+ MLPropertyInterceptor.setMLAware(false);
+
+ // Filtering will result in a list containing en_GB only
+ checkValues = (List) nodeService.getProperty(
+ rootNodeRef,
+ PROP_QNAME_MULTI_ML_VALUE);
+ assertEquals("Expected 1 MLText values back", 1, checkValues.size());
+ assertEquals("en_GB text", (String) checkValues.get(0));
+
+ // Update the property, only this time using a different English variant
+ Locale.setDefault(Locale.US); // en_US
+
+ values.clear();
+ values.add("text 1 added using en_US");
+ values.add("text 2 added using en_US");
+ values.add("text 3 added using en_US");
+ values.add("text 4 added using en_US");
+ nodeService.setProperty(rootNodeRef, PROP_QNAME_MULTI_ML_VALUE, values);
+
+ // Check that the text was updated correctly
+ MLPropertyInterceptor.setMLAware(true); // no filtering - see real MLText
+ checkValues = (List) nodeService.getProperty(
+ rootNodeRef,
+ PROP_QNAME_MULTI_ML_VALUE);
+
+ assertEquals("Expected 3 MLText values back", 4, checkValues.size());
+
+ MLText mlText = ((MLText) checkValues.get(0));
+ assertEquals("en_GB should be replaced with new, not added to", 1, mlText.size());
+ assertEquals("text 1 added using en_US", mlText.getValue(Locale.ENGLISH));
+
+ mlText = ((MLText) checkValues.get(1));
+ assertEquals("en_US should be replaced with new, not added to", 1, mlText.size());
+ assertEquals("text 2 added using en_US", mlText.getValue(Locale.ENGLISH));
+
+ mlText = ((MLText) checkValues.get(2));
+ assertEquals("en_US should be added to fr_FR", 2, mlText.size());
+ assertEquals("fr_FR text", mlText.getValue(Locale.FRANCE));
+ assertEquals("text 3 added using en_US", mlText.getValue(Locale.ENGLISH));
+
+ mlText = ((MLText) checkValues.get(3));
+ assertEquals("entirely new text value should be added", 1, mlText.size());
+ assertEquals("text 4 added using en_US", mlText.getValue(Locale.ENGLISH));
+ }
+
public void testLongMLTextValues() throws Exception
{
StringBuilder sb = new StringBuilder();
diff --git a/source/java/org/alfresco/repo/node/MLPropertyInterceptor.java b/source/java/org/alfresco/repo/node/MLPropertyInterceptor.java
index f0c6928942..4795bd4e1e 100644
--- a/source/java/org/alfresco/repo/node/MLPropertyInterceptor.java
+++ b/source/java/org/alfresco/repo/node/MLPropertyInterceptor.java
@@ -25,6 +25,7 @@ import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
@@ -551,7 +552,7 @@ public class MLPropertyInterceptor implements MethodInterceptor
{
newMLValue = new MLText();
}
- newMLValue.addValue(contentLocale, current);
+ replaceTextForLanguage(contentLocale, current, newMLValue);
if(count < returnMLList.size())
{
returnMLList.set(count, newMLValue);
@@ -602,8 +603,8 @@ public class MLPropertyInterceptor implements MethodInterceptor
}
// Force the inbound value to be a String (it isn't MLText)
String inboundValueStr = DefaultTypeConverter.INSTANCE.convert(String.class, inboundValue);
- // Add it to the current MLValue
- returnMLValue.put(contentLocale, inboundValueStr);
+ // Update the text for the appropriate language.
+ replaceTextForLanguage(contentLocale, inboundValueStr, returnMLValue);
// Done
ret = returnMLValue;
}
@@ -641,4 +642,32 @@ public class MLPropertyInterceptor implements MethodInterceptor
}
return ret;
}
+
+ /**
+ * Replace any text in mlText having the same language (but any variant) as contentLocale
+ * with updatedText keyed by the language of contentLocale. This ensures that the mlText
+ * will have no more than one entry for the particular language.
+ *
+ * @param contentLocale
+ * @param updatedText
+ * @param mlText
+ */
+ private void replaceTextForLanguage(Locale contentLocale, String updatedText, MLText mlText)
+ {
+ String language = contentLocale.getLanguage();
+ // Remove all text entries having the same language as the chosen contentLocale
+ // (e.g. if contentLocale is en_GB, then remove text for en, en_GB, en_US etc.
+ Iterator locales = mlText.getLocales().iterator();
+ while (locales.hasNext())
+ {
+ Locale locale = locales.next();
+ if (locale.getLanguage().equals(language))
+ {
+ locales.remove();
+ }
+ }
+
+ // Add the new value for the specific language
+ mlText.addValue(new Locale(language), updatedText);
+ }
}
diff --git a/source/java/org/alfresco/repo/rule/RuleServiceCoverageTest.java b/source/java/org/alfresco/repo/rule/RuleServiceCoverageTest.java
index 22a7832bb9..b6bd092622 100644
--- a/source/java/org/alfresco/repo/rule/RuleServiceCoverageTest.java
+++ b/source/java/org/alfresco/repo/rule/RuleServiceCoverageTest.java
@@ -1767,6 +1767,50 @@ public class RuleServiceCoverageTest extends TestCase
});
}
+ public void testAssociationUpdateRule()
+ {
+ //ALF-9661 test
+ NodeRef sourceFolder = this.nodeService.createNode(
+ this.rootNodeRef,
+ ContentModel.ASSOC_CHILDREN,
+ QName.createQName("{test}sourceFolder"),
+ ContentModel.TYPE_FOLDER).getChildRef();
+ Map params = new HashMap(1);
+ params.put("aspect-name", ContentModel.ASPECT_VERSIONABLE);
+ //create a rule that adds an aspect after a property is updated
+ Rule rule = createRule(
+ RuleType.UPDATE,
+ AddFeaturesActionExecuter.NAME,
+ params,
+ NoConditionEvaluator.NAME,
+ null);
+
+ this.ruleService.saveRule(sourceFolder, rule);
+ //create folders
+ NodeRef testNodeOneRef = this.nodeService.createNode(
+ sourceFolder,
+ ContentModel.ASSOC_CONTAINS,
+ QName.createQName(TEST_NAMESPACE, "original1"),
+ ContentModel.TYPE_CONTENT,
+ getContentProperties()).getChildRef();
+ addContentToNode(testNodeOneRef);
+
+ NodeRef testNodeTwoRef = this.nodeService.createNode(
+ sourceFolder,
+ ContentModel.ASSOC_CONTAINS,
+ QName.createQName(TEST_NAMESPACE, "original2"),
+ ContentModel.TYPE_CONTENT,
+ getContentProperties()).getChildRef();
+ addContentToNode(testNodeTwoRef);
+ //there is no aspect
+ assertFalse(this.nodeService.hasAspect(testNodeOneRef, ContentModel.ASPECT_VERSIONABLE));
+ //create an association
+ this.nodeService.addAspect(testNodeOneRef, ContentModel.ASPECT_REFERENCING, null);
+ this.nodeService.createAssociation(testNodeOneRef, testNodeTwoRef, ContentModel.ASSOC_REFERENCES);
+ //there should be the versionable aspect added
+ assertTrue(this.nodeService.hasAspect(testNodeOneRef, ContentModel.ASPECT_VERSIONABLE));
+ }
+
/**
* Test:
* rule type: outbound
diff --git a/source/java/org/alfresco/repo/rule/ruletrigger/SingleAssocRefPolicyRuleTrigger.java b/source/java/org/alfresco/repo/rule/ruletrigger/SingleAssocRefPolicyRuleTrigger.java
index b020d412b7..4273268519 100644
--- a/source/java/org/alfresco/repo/rule/ruletrigger/SingleAssocRefPolicyRuleTrigger.java
+++ b/source/java/org/alfresco/repo/rule/ruletrigger/SingleAssocRefPolicyRuleTrigger.java
@@ -18,18 +18,23 @@
*/
package org.alfresco.repo.rule.ruletrigger;
+import java.util.List;
+
import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.service.cmr.repository.AssociationRef;
-import org.alfresco.service.cmr.rule.RuleServiceException;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
+import org.alfresco.util.PropertyCheck;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
public class SingleAssocRefPolicyRuleTrigger extends RuleTriggerAbstractBase
{
- private static final String ERR_POLICY_NAME_NOT_SET = "Unable to register rule trigger since policy name has not been set.";
-
+ private static Log logger = LogFactory.getLog(OnPropertyUpdateRuleTrigger.class);
+
private String policyNamespace = NamespaceService.ALFRESCO_URI;
-
private String policyName;
public void setPolicyNamespace(String policyNamespace)
@@ -47,10 +52,8 @@ public class SingleAssocRefPolicyRuleTrigger extends RuleTriggerAbstractBase
*/
public void registerRuleTrigger()
{
- if (policyName == null)
- {
- throw new RuleServiceException(ERR_POLICY_NAME_NOT_SET);
- }
+ PropertyCheck.mandatory(this, "policyNamespace", policyNamespace);
+ PropertyCheck.mandatory(this, "policyName", policyName);
this.policyComponent.bindAssociationBehaviour(
QName.createQName(this.policyNamespace, this.policyName),
@@ -58,8 +61,19 @@ public class SingleAssocRefPolicyRuleTrigger extends RuleTriggerAbstractBase
new JavaBehaviour(this, "policyBehaviour"));
}
- public void policyBehaviour(AssociationRef assocRef)
- {
- triggerRules(assocRef.getSourceRef(), assocRef.getTargetRef());
- }
+ public void policyBehaviour(AssociationRef assocRef)
+ {
+ NodeRef nodeRef = assocRef.getSourceRef();
+ List parentsAssocRefs = this.nodeService.getParentAssocs(nodeRef);
+ for (ChildAssociationRef parentAssocRef : parentsAssocRefs)
+ {
+ triggerRules(parentAssocRef.getParentRef(), nodeRef);
+ if (logger.isDebugEnabled() == true)
+ {
+ logger.debug(
+ "OnUpdateAssoc rule triggered (parent); " +
+ "nodeRef=" + parentAssocRef.getParentRef());
+ }
+ }
+ }
}
diff --git a/source/java/org/alfresco/repo/search/impl/lucene/index/IndexInfo.java b/source/java/org/alfresco/repo/search/impl/lucene/index/IndexInfo.java
index f0b46e18e1..bce6076ba1 100644
--- a/source/java/org/alfresco/repo/search/impl/lucene/index/IndexInfo.java
+++ b/source/java/org/alfresco/repo/search/impl/lucene/index/IndexInfo.java
@@ -32,8 +32,8 @@ import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
-import java.nio.channels.FileLock;
import java.nio.channels.FileChannel.MapMode;
+import java.nio.channels.FileLock;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
@@ -74,16 +74,15 @@ import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
-import org.apache.lucene.index.FilterIndexReader;
import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexReader.FieldOption;
import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.index.LogDocMergePolicy;
import org.apache.lucene.index.MultiReader;
import org.apache.lucene.index.SerialMergeScheduler;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermEnum;
-import org.apache.lucene.index.IndexReader.FieldOption;
-import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
@@ -254,7 +253,7 @@ public class IndexInfo implements IndexMonitor
public static final String MAIN_READER = "MainReader";
- private static Timer timer = new Timer(true);
+ private static Timer timer = new Timer("IndexInfo Cleaner Deamon", true);
/**
* The logger.
diff --git a/source/java/org/alfresco/repo/security/sync/ChainingUserRegistrySynchronizer.java b/source/java/org/alfresco/repo/security/sync/ChainingUserRegistrySynchronizer.java
index 5752903fbe..545735c709 100644
--- a/source/java/org/alfresco/repo/security/sync/ChainingUserRegistrySynchronizer.java
+++ b/source/java/org/alfresco/repo/security/sync/ChainingUserRegistrySynchronizer.java
@@ -642,7 +642,7 @@ public class ChainingUserRegistrySynchronizer extends AbstractLifecycleBean impl
private final Map> groupParentAssocsToDelete = new TreeMap>();
private final Map> finalGroupChildAssocs = new TreeMap>();
private List personsProcessed = new LinkedList();
- private Set allZonePersons;
+ private Set allZonePersons = Collections.emptySet();
private Set deletionCandidates;
private long latestTime;
@@ -1090,9 +1090,10 @@ public class ChainingUserRegistrySynchronizer extends AbstractLifecycleBean impl
public void processGroups(UserRegistry userRegistry, boolean allowDeletions, boolean splitTxns)
{
- // If we got back some groups, we have to cross reference them with the set of known authorities
- if (allowDeletions || !this.groupParentAssocsToDelete.isEmpty())
- {
+ // If we got back some groups, we have to cross reference them with the set of known authorities
+ if (allowDeletions || !this.groupParentAssocsToCreate.isEmpty()
+ || !this.personParentAssocsToCreate.isEmpty())
+ {
final Set allZonePersons = newPersonSet();
final Set allZoneGroups = new TreeSet();
diff --git a/source/java/org/alfresco/repo/site/SiteServiceImpl.java b/source/java/org/alfresco/repo/site/SiteServiceImpl.java
index bb778d18e3..3d7e889336 100644
--- a/source/java/org/alfresco/repo/site/SiteServiceImpl.java
+++ b/source/java/org/alfresco/repo/site/SiteServiceImpl.java
@@ -1461,7 +1461,6 @@ public class SiteServiceImpl extends AbstractLifecycleBean implements SiteServic
// Build an array of name filter tokens pre lowercased to test against person properties
// We require that matching people have at least one match against one of these on
// either their firstname or last name
- // For groups, we require a match against the whole filter on the group name or display name
String nameFilterLower = null;
String[] nameFilters = new String[0];
if (nameFilter != null && nameFilter.length() != 0)
diff --git a/source/java/org/alfresco/repo/usage/ContentUsageImpl.java b/source/java/org/alfresco/repo/usage/ContentUsageImpl.java
index 017e7b2fc7..42958dc200 100644
--- a/source/java/org/alfresco/repo/usage/ContentUsageImpl.java
+++ b/source/java/org/alfresco/repo/usage/ContentUsageImpl.java
@@ -35,6 +35,7 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.security.NoSuchPersonException;
import org.alfresco.service.cmr.security.OwnableService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.usage.ContentQuotaException;
@@ -516,7 +517,14 @@ public class ContentUsageImpl implements ContentUsageService,
public long getUserUsage(String userName)
{
ParameterCheck.mandatoryString("userName", userName);
- return getUserUsage(getPerson(userName), false);
+
+ long currentUsage = 0;
+ NodeRef personNodeRef = getPerson(userName);
+ if (personNodeRef != null)
+ {
+ currentUsage = getUserUsage(personNodeRef, false);
+ }
+ return currentUsage;
}
public long getUserUsage(NodeRef personNodeRef, boolean removeDeltas)
@@ -587,7 +595,15 @@ public class ContentUsageImpl implements ContentUsageService,
NodeRef personNodeRef = null;
try
{
- personNodeRef = personService.getPerson(userName);
+ // false to not force user home creation
+ personNodeRef = personService.getPerson(userName, false);
+ }
+ catch (NoSuchPersonException e)
+ {
+ // Can get this situation where the person does not exist and may not be created.
+ // Had to add this catch when not forcing user home folder creation.
+ // The boolean parameter to getPerson does two things. It should really be split into two booleans.
+ personNodeRef = null;
}
catch (RuntimeException e)
{
diff --git a/source/java/org/alfresco/repo/usage/UsageQuotaProtector.java b/source/java/org/alfresco/repo/usage/UsageQuotaProtector.java
index 1d853150db..a3115c79b4 100644
--- a/source/java/org/alfresco/repo/usage/UsageQuotaProtector.java
+++ b/source/java/org/alfresco/repo/usage/UsageQuotaProtector.java
@@ -92,14 +92,14 @@ public class UsageQuotaProtector implements NodeServicePolicies.OnUpdateProperti
Long sizeQuotaAfter = (Long)after.get(ContentModel.PROP_SIZE_QUOTA);
// Check for change in sizeCurrent
- if ((sizeCurrentBefore != sizeCurrentAfter) && (sizeCurrentBefore != null) &&
+ if ((sizeCurrentBefore != null && !sizeCurrentBefore.equals(sizeCurrentAfter)) && (sizeCurrentBefore != null) &&
(! (authorityService.hasAdminAuthority() || AuthenticationUtil.isRunAsUserTheSystemUser())))
{
throw new AlfrescoRuntimeException("Update failed: protected property 'sizeCurrent'");
}
// Check for change in sizeQuota
- if ((sizeQuotaBefore != sizeQuotaAfter) && (sizeQuotaBefore != null) &&
+ if ((sizeQuotaBefore != null && !sizeQuotaBefore.equals(sizeQuotaAfter)) && (sizeQuotaBefore != null) &&
(! (authorityService.hasAdminAuthority() || AuthenticationUtil.isRunAsUserTheSystemUser())))
{
throw new AlfrescoRuntimeException("Update failed: protected property 'sizeQuota'");
diff --git a/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java b/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java
index 7427300770..bd81c29786 100644
--- a/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java
+++ b/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java
@@ -699,7 +699,8 @@ public class WorkflowServiceImpl implements WorkflowService
// Expand authorities to include associated groups (and parent groups)
List authorities = new ArrayList();
authorities.add(authority);
- Set parents = authorityService.getContainingAuthorities(AuthorityType.GROUP, authority, false);
+ Set parents = authorityService.getContainingAuthoritiesInZone(AuthorityType.GROUP, authority,
+ null, null, 100);
authorities.addAll(parents);
// Retrieve pooled tasks for authorities (from each of the registered
diff --git a/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoJobExecutorThread.java b/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoJobExecutorThread.java
index 9bd874ad52..5913ae8b9f 100644
--- a/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoJobExecutorThread.java
+++ b/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoJobExecutorThread.java
@@ -25,6 +25,8 @@ import java.util.Collections;
import java.util.Date;
import org.alfresco.repo.lock.LockAcquisitionException;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.namespace.NamespaceService;
@@ -37,6 +39,7 @@ import org.jbpm.JbpmContext;
import org.jbpm.db.JobSession;
import org.jbpm.job.Job;
import org.jbpm.job.executor.JobExecutorThread;
+import org.jbpm.taskmgmt.exe.TaskInstance;
/**
@@ -170,6 +173,38 @@ public class AlfrescoJobExecutorThread extends JobExecutorThread
*/
@Override
protected void executeJob(final Job jobIn)
+ {
+ // execute the job as System (ALF-10776) so transaction commit level
+ // operations have a security context.
+ AuthenticationUtil.runAs(new RunAsWork()
+ {
+ public Void doWork() throws Exception
+ {
+ executeJobImpl(jobIn);
+ return null;
+ }
+ }, getActorId(jobIn));
+
+ // clear authentication context for this thread
+ AuthenticationUtil.clearCurrentSecurityContext();
+ }
+
+ private String getActorId(final Job jobIn)
+ {
+ TaskInstance taskInstance = jobIn.getTaskInstance();
+
+ if (taskInstance != null)
+ {
+ String actorId = taskInstance.getActorId();
+ if (actorId != null && actorId.length() > 0)
+ {
+ return actorId;
+ }
+ }
+ return AuthenticationUtil.getSystemUserName();
+ }
+
+ private void executeJobImpl(final Job jobIn)
{
if ((!isActive) || (alfrescoJobExecutor.getTransactionService().isReadOnly()))
{
diff --git a/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoTimer.java b/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoTimer.java
index f3e0691c33..72831b45f1 100644
--- a/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoTimer.java
+++ b/source/java/org/alfresco/repo/workflow/jbpm/AlfrescoTimer.java
@@ -18,8 +18,6 @@
*/
package org.alfresco.repo.workflow.jbpm;
-import org.alfresco.repo.security.authentication.AuthenticationUtil;
-import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.jbpm.JbpmContext;
import org.jbpm.graph.exe.Token;
import org.jbpm.job.Timer;
@@ -66,40 +64,21 @@ public class AlfrescoTimer extends Timer
{
// establish authentication context
final TaskInstance taskInstance = getTaskInstance();
- String username = getActorId(taskInstance);
// execute timer
- return AuthenticationUtil.runAs(new RunAsWork()
+ boolean deleteTimer = AlfrescoTimer.super.execute(jbpmContext);
+
+ // End the task if timer does not repeat.
+ // Note the order is a little odd here as the task will be ended
+ // after the token has been signalled to move to the next node.
+ if (deleteTimer
+ && taskInstance != null
+ && taskInstance.isOpen())
{
- public Boolean doWork() throws Exception
- {
- boolean deleteTimer = AlfrescoTimer.super.execute(jbpmContext);
- // End the task if timer does not repeat.
- // Note the order is a little odd here as the task will be ended
- // after the token has been signalled to move to the next node.
- if (deleteTimer
- && taskInstance != null
- && taskInstance.isOpen())
- {
- taskInstance.setSignalling(false);
- taskInstance.end();
- }
- return deleteTimer;
- }
- }, username);
- }
-
- private String getActorId(TaskInstance taskInstance)
- {
- if (taskInstance != null)
- {
- String actorId = taskInstance.getActorId();
- if (actorId != null && actorId.length() > 0)
- {
- return actorId;
- }
+ taskInstance.setSignalling(false);
+ taskInstance.end();
}
- return AuthenticationUtil.getSystemUserName();
+
+ return deleteTimer;
}
-
}
diff --git a/source/java/org/alfresco/util/ThreadPoolExecutorFactoryBean.java b/source/java/org/alfresco/util/ThreadPoolExecutorFactoryBean.java
index e75d5b43da..f7aa425b16 100644
--- a/source/java/org/alfresco/util/ThreadPoolExecutorFactoryBean.java
+++ b/source/java/org/alfresco/util/ThreadPoolExecutorFactoryBean.java
@@ -26,6 +26,7 @@ import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.alfresco.error.AlfrescoRuntimeException;
+import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
@@ -57,7 +58,7 @@ import org.springframework.beans.factory.InitializingBean;
*
* @author Derek Hulley
*/
-public class ThreadPoolExecutorFactoryBean implements FactoryBean, InitializingBean
+public class ThreadPoolExecutorFactoryBean implements FactoryBean, InitializingBean, DisposableBean
{
private static final int DEFAULT_CORE_POOL_SIZE = 20;
private static final int DEFAULT_MAXIMUM_POOL_SIZE = -1; // -1 is a sign that it must match the core pool size
@@ -244,4 +245,10 @@ public class ThreadPoolExecutorFactoryBean implements FactoryBean, InitializingB
{
this.poolName = poolName;
}
+
+ public void destroy()
+ {
+ this.instance.shutdown();
+ }
+
}
diff --git a/source/test-resources/jbpm-test/test-context.xml b/source/test-resources/jbpm-test/test-context.xml
index 68e5910710..b2efdbd0e1 100644
--- a/source/test-resources/jbpm-test/test-context.xml
+++ b/source/test-resources/jbpm-test/test-context.xml
@@ -14,6 +14,9 @@
${db.url}_test
+
+ false
+