alfresco-community-repo/source/java/org/alfresco/filesys/ServerConfigurationBean.java
Dave Ward 972dd9a4ba MOB-651: Decouple File Servers from Config Service and Authenticators
- Minor JLAN changes (backward compatible)
   - CIFSAuthenticator implements an interface (to allow dynamic proxying to authentication subsystem)
   - CIFSAuthenticator accesses ServerConfiguration via ServerConfigurationAccessor interface and doesn't retain references to config sections (again to allow dynamic proxying and hot swapping)
   - ConfigSections have way of directly setting container initialised authenticators, sharemappers, etc.
   - Authenticators, etc. still support initialisation from config service in backward compatible manner.
- Most of ServerConfigurationBean moved to AbstractServerConfigurationBean superclass.
- New org.alfresco.filesys.config package with ServerConfigurationBean implementation and supporting classes that can be initialised by a Spring container.
- File server authenticators moved into authentication subsystem. TODO: Kerberos and NTLM

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13795 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
2009-04-01 13:22:06 +00:00

2591 lines
87 KiB
Java

/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.filesys;
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.ArrayList;
import java.util.EnumSet;
import java.util.Enumeration;
import java.util.List;
import java.util.StringTokenizer;
import org.alfresco.config.Config;
import org.alfresco.config.ConfigElement;
import org.alfresco.config.ConfigLookupContext;
import org.alfresco.config.ConfigService;
import org.alfresco.config.element.GenericConfigElement;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.filesys.alfresco.DesktopAction;
import org.alfresco.filesys.alfresco.DesktopActionException;
import org.alfresco.filesys.alfresco.DesktopActionTable;
import org.alfresco.filesys.avm.AVMContext;
import org.alfresco.filesys.avm.AVMDiskDriver;
import org.alfresco.filesys.repo.ContentContext;
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.nfs.NFSConfigSection;
import org.alfresco.jlan.server.auth.ICifsAuthenticator;
import org.alfresco.jlan.server.auth.acl.ACLParseException;
import org.alfresco.jlan.server.auth.acl.AccessControl;
import org.alfresco.jlan.server.auth.acl.AccessControlList;
import org.alfresco.jlan.server.auth.acl.AccessControlParser;
import org.alfresco.jlan.server.auth.acl.InvalidACLTypeException;
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.DeviceContextException;
import org.alfresco.jlan.server.core.ShareType;
import org.alfresco.jlan.server.filesys.DiskInterface;
import org.alfresco.jlan.server.filesys.DiskSharedDevice;
import org.alfresco.jlan.server.filesys.FilesystemsConfigSection;
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.security.authentication.NTLMMode;
/**
* Alfresco File Server Configuration Bean Class
*
* @author gkspencer
*/
public class ServerConfigurationBean extends AbstractServerConfigurationBean {
// Filesystem configuration constants
private static final String ConfigArea = "file-servers";
private static final String ConfigCIFS = "CIFS Server";
private static final String ConfigFTP = "FTP Server";
private static final String ConfigNFS = "NFS Server";
private static final String ConfigFilesystems = "Filesystems";
private static final String ConfigSecurity = "Filesystem Security";
private static final String ConfigCoreServer = "Server Core";
// Server configuration bean name
public static final String SERVER_CONFIGURATION = "fileServerConfiguration";
// Configuration service
private ConfigService m_configService;
private ConfigLookupContext configCtx;
/**
* Default constructor
*/
public ServerConfigurationBean()
{
super ( "");
}
/**
* Class constructor
*
* @param srvName String
*/
public ServerConfigurationBean( String srvName)
{
super( srvName);
}
/**
* Set the configuration service
*
* @param configService ConfigService
*/
public void setConfigService(ConfigService configService)
{
m_configService = configService;
}
/**
* Initialize the configuration using the configuration service
*/
public void init()
{
// Check that all required properties have been set
if (m_configService == null)
{
throw new AlfrescoRuntimeException("Property 'configService' not set");
}
// Create the configuration context
configCtx = new ConfigLookupContext(ConfigArea);
super.init();
}
/**
* Process the CIFS server configuration
*/
protected void processCIFSServerConfig()
{
processCIFSServerConfig(m_configService.getConfig(ConfigCIFS, configCtx));
}
/**
* Process the CIFS server configuration
*
* @param config Config
*/
protected void processCIFSServerConfig(Config config)
{
// If the configuration section is not valid then CIFS is disabled
if ( config == null)
{
removeConfigSection( CIFSConfigSection.SectionName);
return;
}
// Check if the server has been disabled
ConfigElement elem = config.getConfigElement( "serverEnable");
if ( elem != null)
{
// Check for the enabled attribute
String srvEnable = elem.getAttribute( "enabled");
if ( srvEnable != null && srvEnable.equalsIgnoreCase( "false"))
{
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
elem = config.getConfigElement( "disableNativeCode");
if ( elem != null)
{
// 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.
elem = config.getConfigElement("broadcast");
if (elem != null)
{
// Check if the broadcast mask is a valid numeric IP address
if (IPAddress.isNumericAddress(elem.getValue()) == false)
throw new AlfrescoRuntimeException("Invalid broadcast mask, must be n.n.n.n format");
// Set the network broadcast mask
cifsConfig.setBroadcastMask(elem.getValue());
}
// Get the host configuration
elem = config.getConfigElement("host");
if (elem == null)
throw new AlfrescoRuntimeException("CIFS server host settings not specified");
String hostName = elem.getAttribute("name");
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 = elem.getAttribute("domain");
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 <broadcast> setting)");
}
// Set the local domain/workgroup that the CIFS server belongs to
cifsConfig.setDomainName( localDomain);
}
// Check for a server comment
elem = config.getConfigElement("comment");
if (elem != null)
cifsConfig.setComment(elem.getValue());
// Check for a bind address
elem = config.getConfigElement("bindto");
if (elem != null)
{
// Check if the network adapter name has been specified
if ( elem.hasAttribute("adapter")) {
// Get the IP address for the adapter
InetAddress bindAddr = parseAdapterName( elem.getAttribute("adapter"));
// Set the bind address for the server
cifsConfig.setSMBBindAddress(bindAddr);
}
else if (!elem.getValue().equals(BIND_TO_IGNORE))
{
// Validate the bind address
String bindText = elem.getValue();
try
{
// Check the bind address
InetAddress bindAddr = InetAddress.getByName(bindText);
// Set the bind address for the server
cifsConfig.setSMBBindAddress(bindAddr);
}
catch (UnknownHostException ex)
{
throw new AlfrescoRuntimeException("Invalid CIFS server bind address");
}
}
}
// Check if an authenticator has been specified
ConfigElement authElem = config.getConfigElement("authenticator");
if (authElem != null)
{
// Get the authenticator type
String authType = authElem.getAttribute("type");
if (authType == null)
authType = "alfresco";
// Get the authentication component type
NTLMMode ntlmMode = m_authenticationComponent.getNTLMMode();
// Set the authenticator class to use
String authClass = "org.alfresco.filesys.auth.cifs.AlfrescoCifsAuthenticator";
if (authType.equalsIgnoreCase("passthru"))
{
// Check if the appropriate authentication component type is configured
if ( ntlmMode == NTLMMode.MD4_PROVIDER)
throw new AlfrescoRuntimeException("Wrong authentication setup for passthru authenticator (cannot be used with Alfresco users)");
// Use the passthru authenticator class
authClass = "org.alfresco.filesys.auth.cifs.PassthruCifsAuthenticator";
}
else if (authType.equalsIgnoreCase("alfresco"))
{
// Standard authenticator requires MD4 or passthru based authentication
if ( ntlmMode == NTLMMode.NONE)
throw new AlfrescoRuntimeException("Wrong authentication setup for alfresco authenticator");
}
else if( authType.equalsIgnoreCase("enterprise"))
{
// Load the Enterprise authenticator dynamically
authClass = "org.alfresco.filesys.auth.cifs.EnterpriseCifsAuthenticator";
}
else if ( authType.equalsIgnoreCase( "custom"))
{
// Get the authenticator class
ConfigElement authClassElem = authElem.getChild("class");
authClass = authClassElem.getValue();
}
else
throw new AlfrescoRuntimeException("Invalid authenticator type, " + authType);
// Get the allow guest and map unknown user to guest settings
boolean allowGuest = authElem.getChild("allowGuest") != null ? true : false;
// Initialize and set the authenticator class
cifsConfig.setAuthenticator(authClass, authElem, ICifsAuthenticator.USER_MODE, allowGuest);
}
else
throw new AlfrescoRuntimeException("CIFS authenticator not specified");
// Check if the host announcer should be enabled
elem = config.getConfigElement("hostAnnounce");
if (elem != null)
{
// Check if the host announcer has been disabled
String enabled = elem.getAttribute("enabled");
if ( enabled != null && enabled.equalsIgnoreCase( "false"))
{
// 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
String interval = elem.getAttribute("interval");
if (interval != null && interval.length() > 0)
{
try
{
cifsConfig.setHostAnnounceInterval(Integer.parseInt(interval));
}
catch (NumberFormatException ex)
{
throw new AlfrescoRuntimeException("Invalid host announcement 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
elem = config.getConfigElement("netBIOSSMB");
if (elem != null)
{
// Check if NetBIOS over TCP/IP is enabled for the current platform
String platformsStr = elem.getAttribute("platforms");
boolean platformOK = false;
if (platformsStr != null)
{
// Parse the list of platforms that NetBIOS over TCP/IP is to be enabled for and
// check if the current platform is included
EnumSet<Platform.Type> 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 = elem.getAttribute("bindto");
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<NetworkInterface> 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<InetAddress> 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
String portNum = elem.getAttribute("sessionPort");
if ( portNum != null && portNum.length() > 0) {
try {
cifsConfig.setSessionPort(Integer.parseInt(portNum));
if ( cifsConfig.getSessionPort() <= 0 || cifsConfig.getSessionPort() >= 65535)
throw new AlfrescoRuntimeException("NetBIOS session port out of valid range");
}
catch (NumberFormatException ex) {
throw new AlfrescoRuntimeException("Invalid NetBIOS session port");
}
}
// Check if the name port has been specified
portNum = elem.getAttribute("namePort");
if ( portNum != null && portNum.length() > 0) {
try {
cifsConfig.setNameServerPort(Integer.parseInt(portNum));
if ( cifsConfig.getNameServerPort() <= 0 || cifsConfig.getNameServerPort() >= 65535)
throw new AlfrescoRuntimeException("NetBIOS name port out of valid range");
}
catch (NumberFormatException ex) {
throw new AlfrescoRuntimeException("Invalid NetBIOS name port");
}
}
// Check if the datagram port has been specified
portNum = elem.getAttribute("datagramPort");
if ( portNum != null && portNum.length() > 0) {
try {
cifsConfig.setDatagramPort(Integer.parseInt(portNum));
if ( cifsConfig.getDatagramPort() <= 0 || cifsConfig.getDatagramPort() >= 65535)
throw new AlfrescoRuntimeException("NetBIOS datagram port out of valid range");
}
catch (NumberFormatException ex) {
throw new AlfrescoRuntimeException("Invalid NetBIOS datagram port");
}
}
// Check for a bind address
String attr = elem.getAttribute("bindto");
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 ( elem.hasAttribute("adapter")) {
// Get the bind address via the network adapter name
InetAddress bindAddr = parseAdapterName( elem.getAttribute("adapter"));
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
elem = config.getConfigElement("tcpipSMB");
if (elem != null)
{
// Check if native SMB is enabled for the current platform
String platformsStr = elem.getAttribute("platforms");
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<Platform.Type> 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
String portNum = elem.getAttribute("port");
if ( portNum != null && portNum.length() > 0) {
try {
cifsConfig.setTcpipSMBPort(Integer.parseInt(portNum));
if ( cifsConfig.getTcpipSMBPort() <= 0 || cifsConfig.getTcpipSMBPort() >= 65535)
throw new AlfrescoRuntimeException("TCP/IP SMB port out of valid range");
}
catch (NumberFormatException ex) {
throw new AlfrescoRuntimeException("Invalid TCP/IP SMB port");
}
}
// Check if IPv6 support should be enabled
String ipv6 = elem.getAttribute("ipv6");
if ( ipv6 != null && ipv6.equalsIgnoreCase( "enabled"))
{
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
elem = config.getConfigElement("Win32NetBIOS");
if (elem != null)
{
// Check if the Win32 NetBIOS server name has been specified
String win32Name = elem.getAttribute("name");
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 = elem.getAttribute("lana");
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 = elem.getAttribute("api");
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 host announcer should be enabled
elem = config.getConfigElement("Win32Announce");
if (elem != null)
{
// Check if the Win32 host announcer has been disabled
String enabled = elem.getAttribute("enabled");
if ( enabled != null && enabled.equalsIgnoreCase( "false"))
{
// 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
String interval = elem.getAttribute("interval");
if (interval != null && interval.length() > 0)
{
try
{
cifsConfig.setWin32HostAnnounceInterval(Integer.parseInt(interval));
}
catch (NumberFormatException ex)
{
throw new AlfrescoRuntimeException("Invalid host announcement 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
elem = config.getConfigElement("WINS");
if (elem != null)
{
// Get the primary WINS server
ConfigElement priWinsElem = elem.getChild("primary");
if (priWinsElem == null || priWinsElem.getValue().length() == 0)
throw new AlfrescoRuntimeException("No primary WINS server configured");
// Validate the WINS server address
InetAddress primaryWINS = null;
try
{
primaryWINS = InetAddress.getByName(priWinsElem.getValue());
}
catch (UnknownHostException ex)
{
throw new AlfrescoRuntimeException("Invalid primary WINS server address, " + priWinsElem.getValue());
}
// Check if a secondary WINS server has been specified
ConfigElement secWinsElem = elem.getChild("secondary");
InetAddress secondaryWINS = null;
if (secWinsElem != null)
{
// Validate the secondary WINS server address
try
{
secondaryWINS = InetAddress.getByName(secWinsElem.getValue());
}
catch (UnknownHostException ex)
{
throw new AlfrescoRuntimeException("Invalid secondary WINS server address, "
+ secWinsElem.getValue());
}
}
// 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 if session debug is enabled
elem = config.getConfigElement("sessionDebug");
if (elem != null)
{
// Check for session debug flags
String flags = elem.getAttribute("flags");
int sessDbg = 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_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 ( config.getConfigElement( "disableNIO") != null) {
// 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
elem = config.getConfigElement("sessionTimeout");
if ( elem != null) {
// Validate the session timeout value
String sessTmo = elem.getValue();
if ( sessTmo != null && sessTmo.length() > 0) {
try {
// Convert the timeout value to milliseconds
int tmo = Integer.parseInt(sessTmo);
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 (NumberFormatException ex) {
throw new AlfrescoRuntimeException("Invalid session timeout value, " + sessTmo);
}
}
else
throw new AlfrescoRuntimeException("Session timeout value not specified");
}
}
catch ( InvalidConfigurationException ex)
{
throw new AlfrescoRuntimeException( ex.getMessage());
}
}
/**
* Process the FTP server configuration
*/
protected void processFTPServerConfig()
{
processFTPServerConfig(m_configService.getConfig(ConfigFTP, configCtx));
}
/**
* Process the FTP server configuration
*
* @param config Config
*/
protected void processFTPServerConfig(Config config)
{
// If the configuration section is not valid then FTP is disabled
if ( config == null)
{
removeConfigSection( FTPConfigSection.SectionName);
return;
}
// Check if the server has been disabled
ConfigElement elem = config.getConfigElement( "serverEnable");
if ( elem != null)
{
// Check for the enabled attribute
String srvEnable = elem.getAttribute( "enabled");
if ( srvEnable != null && srvEnable.equalsIgnoreCase( "false"))
{
removeConfigSection( FTPConfigSection.SectionName);
return;
}
}
// Create the FTP configuration section
FTPConfigSection ftpConfig = new FTPConfigSection( this);
try
{
// Check for a bind address
elem = config.getConfigElement("bindto");
if ( elem != null && !elem.getValue().equals(BIND_TO_IGNORE)) {
// Validate the bind address
String bindText = elem.getValue();
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, " + elem.getValue());
}
}
// Check for an FTP server port
elem = config.getConfigElement("port");
if ( elem != null) {
try {
ftpConfig.setFTPPort(Integer.parseInt(elem.getValue()));
if ( ftpConfig.getFTPPort() <= 0 || ftpConfig.getFTPPort() >= 65535)
throw new AlfrescoRuntimeException("FTP server port out of valid range");
}
catch (NumberFormatException ex) {
throw new AlfrescoRuntimeException("Invalid FTP server port");
}
}
else {
// Use the default FTP port
ftpConfig.setFTPPort(DefaultFTPServerPort);
}
// Check if anonymous login is allowed
elem = config.getConfigElement("allowAnonymous");
if ( elem != null) {
// Enable anonymous login to the FTP server
ftpConfig.setAllowAnonymousFTP(true);
// Check if an anonymous account has been specified
String anonAcc = elem.getAttribute("user");
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
elem = config.getConfigElement("rootDirectory");
if ( elem != null) {
// Get the root path
String rootPath = elem.getValue();
// Validate the root path
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 if FTP debug is enabled
elem = config.getConfigElement("debug");
if (elem != null) {
// Check for FTP debug flags
String flags = elem.getAttribute("flags");
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
elem = config.getConfigElement( "charSet");
if ( elem != null) {
try {
// Validate the character set name
Charset.forName( elem.getValue());
// Set the FTP character set
ftpConfig.setFTPCharacterSet( elem.getValue());
}
catch ( IllegalCharsetNameException ex) {
throw new AlfrescoRuntimeException("Illegal character set name, " + elem.getValue());
}
catch ( UnsupportedCharsetException ex) {
throw new AlfrescoRuntimeException("Unsupported character set name, " + elem.getValue());
}
}
// Check if an authenticator has been specified
ConfigElement authElem = config.getConfigElement("authenticator");
if (authElem != null)
{
// Get the authenticator type
String authType = authElem.getAttribute("type");
if (authType == null)
authType = "alfresco";
// Get the authentication component type
NTLMMode ntlmMode = m_authenticationComponent.getNTLMMode();
// Set the authenticator class to use
String authClass = "org.alfresco.filesys.auth.ftp.AlfrescoFtpAuthenticator";
if (authType.equalsIgnoreCase("passthru"))
{
// Check if the appropriate authentication component type is configured
if ( ntlmMode == NTLMMode.MD4_PROVIDER)
throw new AlfrescoRuntimeException("Wrong authentication setup for passthru authenticator (cannot be used with Alfresco users)");
// Use the passthru authenticator class
authClass = "org.alfresco.filesys.auth.ftp.PassthruFtpAuthenticator";
}
else if (authType.equalsIgnoreCase("alfresco"))
{
// Do nothing, uses the authentication component as it has the plaintext password from the user
}
else if ( authType.equalsIgnoreCase( "custom"))
{
// Get the authenticator class
ConfigElement authClassElem = authElem.getChild("class");
authClass = authClassElem.getValue();
}
else
throw new AlfrescoRuntimeException("Invalid authenticator type, " + authType);
// Initialize and set the authenticator class
ftpConfig.setAuthenticator(authClass, authElem);
}
else
throw new AlfrescoRuntimeException("FTP authenticator not specified");
}
catch (InvalidConfigurationException ex)
{
throw new AlfrescoRuntimeException( ex.getMessage());
}
}
/**
* Process the NFS server configuration
*/
protected void processNFSServerConfig()
{
processNFSServerConfig(m_configService.getConfig(ConfigNFS, configCtx));
}
/**
* Process the NFS server configuration
*
* @param config Config
*/
protected void processNFSServerConfig(Config config)
{
// If the configuration section is not valid then NFS is disabled
if ( config == null)
{
removeConfigSection( NFSConfigSection.SectionName);
return;
}
// Check if the server has been disabled
ConfigElement elem = config.getConfigElement( "serverEnable");
if ( elem != null)
{
// Check for the enabled attribute
String srvEnable = elem.getAttribute( "enabled");
if ( srvEnable != null && srvEnable.equalsIgnoreCase( "false"))
{
removeConfigSection( NFSConfigSection.SectionName);
return;
}
}
// Create the NFS configuration section
NFSConfigSection nfsConfig = new NFSConfigSection( this);
try
{
// Check if the port mapper is enabled
if ( config.getConfigElement("enablePortMapper") != null)
nfsConfig.setNFSPortMapper( true);
// Check for the thread pool size
elem = config.getConfigElement("ThreadPool");
if ( elem != null) {
try {
// Convert the pool size value
int poolSize = Integer.parseInt(elem.getValue());
// 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);
}
catch (NumberFormatException ex) {
throw new AlfrescoRuntimeException("Invalid NFS thread pool size setting, " + elem.getValue());
}
}
// NFS packet pool size
elem = config.getConfigElement("PacketPool");
if ( elem != null) {
try {
// Convert the packet pool size value
int pktPoolSize = Integer.parseInt(elem.getValue());
// 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);
}
catch (NumberFormatException ex) {
throw new AlfrescoRuntimeException("Invalid NFS packet pool size setting, " + elem.getValue());
}
}
// Check for a port mapper server port
elem = config.getConfigElement("PortMapperPort");
if ( elem != null) {
try {
nfsConfig.setPortMapperPort( Integer.parseInt(elem.getValue()));
if ( nfsConfig.getPortMapperPort() <= 0 || nfsConfig.getPortMapperPort() >= 65535)
throw new AlfrescoRuntimeException("Port mapper server port out of valid range");
}
catch (NumberFormatException ex) {
throw new AlfrescoRuntimeException("Invalid port mapper server port");
}
}
// Check for a mount server port
elem = config.getConfigElement("MountServerPort");
if ( elem != null) {
try {
nfsConfig.setMountServerPort( Integer.parseInt(elem.getValue()));
if ( nfsConfig.getMountServerPort() <= 0 || nfsConfig.getMountServerPort() >= 65535)
throw new AlfrescoRuntimeException("Mount server port out of valid range");
}
catch (NumberFormatException ex) {
throw new AlfrescoRuntimeException("Invalid mount server port");
}
}
// Check for an NFS server port
elem = config.getConfigElement("NFSServerPort");
if ( elem != null) {
try {
nfsConfig.setNFSServerPort( Integer.parseInt(elem.getValue()));
if ( nfsConfig.getNFSServerPort() <= 0 || nfsConfig.getNFSServerPort() >= 65535)
throw new AlfrescoRuntimeException("NFS server port out of valid range");
}
catch (NumberFormatException ex) {
throw new AlfrescoRuntimeException("Invalid NFS server port");
}
}
// Check if NFS debug is enabled
elem = config.getConfigElement("debug");
if (elem != null) {
// Check for NFS debug flags
String flags = elem.getAttribute("flags");
int nfsDbg = 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_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
elem = config.getConfigElement("mountServerDebug");
if ( elem != null)
nfsConfig.setMountServerDebug( true);
// Check if portmapper debug output is enabled
elem = config.getConfigElement("portMapperDebug");
if ( elem != null)
nfsConfig.setPortMapperDebug(true);
// Create the RPC authenticator
elem = config.getConfigElement("rpcAuthenticator");
if ( elem != null)
{
try
{
// Default RPC authenticator class
String authClass = "org.alfresco.filesys.auth.nfs.AlfrescoRpcAuthenticator";
// Check if a custom NFS authentictor class has been specified
ConfigElement authClassElem = elem.getChild("class");
if ( authClassElem != null)
authClass = authClassElem.getValue();
// Create the RPC authenticator
nfsConfig.setRpcAuthenticator( authClass, elem);
}
catch ( InvalidConfigurationException ex)
{
throw new AlfrescoRuntimeException( ex.getMessage());
}
}
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()
{
processFilesystemsConfig(m_configService.getConfig(ConfigFilesystems, configCtx));
}
/**
* Process the filesystems configuration
*
* @param config Config
*/
protected void processFilesystemsConfig(Config config)
{
// Get the top level filesystems configuration element
ConfigElement filesystems = config.getConfigElement("filesystems");
// Get the filesystem configuration elements
List<ConfigElement> filesysElems = null;
if ( filesystems != null)
{
// Get the list of filesystems
filesysElems = filesystems.getChildren();
}
else
{
// Check for the old style configuration
ConfigElement filesysElem = config.getConfigElement( "filesystem");
if (filesysElem != null)
{
// create a list with the single filesys element in
filesysElems = new ArrayList<ConfigElement>(1);
filesysElems.add(filesysElem);
}
// Warn that the configuration is using the old format
logger.warn("Old style file-servers.xml configuration being used");
}
// 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 (filesysElems != null)
{
// Add the filesystems
for (int i = 0; i < filesysElems.size(); i++)
{
// Get the current filesystem configuration
ConfigElement elem = filesysElems.get(i);
String filesysType = elem.getName();
String filesysName = elem.getAttribute("name");
try
{
// Check the filesystem type and use the appropriate driver
DiskSharedDevice filesys = null;
if ( filesysType.equalsIgnoreCase("avmfilesystem"))
{
// Create a new filesystem driver instance and create a context for
// the new filesystem
DiskInterface filesysDriver = getAvmDiskInterface();
AVMContext filesysContext = (AVMContext) filesysDriver.createContext( filesysName, elem);
// Create the shared filesystem
filesys = new DiskSharedDevice(filesysName, filesysDriver, filesysContext);
// Start the filesystem
filesysContext.startFilesystem(filesys);
}
else
{
// Create a new filesystem driver instance and create a context for
// the new filesystem
DiskInterface filesysDriver = getRepoDiskInterface();
ContentContext filesysContext = (ContentContext) filesysDriver.createContext( filesysName, elem);
// Check if an access control list has been specified
AccessControlList acls = null;
ConfigElement aclElem = elem.getChild("accessControl");
if (aclElem != null)
{
// Parse the access control list
acls = processAccessControlList(secConfig, aclElem);
}
else if (secConfig.hasGlobalAccessControls())
{
// Use the global access control list for this disk share
acls = secConfig.getGlobalAccessControls();
}
// Check if change notifications are disabled
boolean changeNotify = elem.getChild("disableChangeNotification") == null ? true : false;
// Create the shared filesystem
filesys = new DiskSharedDevice(filesysName, filesysDriver, filesysContext);
// Attach desktop actions to the filesystem
ConfigElement deskActionsElem = elem.getChild("desktopActions");
if ( deskActionsElem != null)
{
// Get the desktop actions list
DesktopActionTable desktopActions = processDesktopActions(deskActionsElem, filesys);
if ( desktopActions != null)
filesysContext.setDesktopActions( desktopActions, filesysDriver);
}
// Add any access controls to the share
filesys.setAccessControlList(acls);
// Enable/disable change notification for this device
filesysContext.enableChangeHandler(changeNotify);
// Start the filesystem
filesysContext.startFilesystem(filesys);
}
// Add the new filesystem
fsysConfig.addShare( filesys);
}
catch (DeviceContextException ex)
{
throw new AlfrescoRuntimeException("Error creating filesystem " + filesysName, ex);
}
}
}
else
{
// No filesystems defined
logger.warn("No filesystems defined");
}
// Check if shares should be added for all AVM stores
ConfigElement avmAllStoresElem = config.getConfigElement( "avmAllStores");
if ( avmAllStoresElem != null && 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.enableStateTable( true, avmDriver.getStateReaper());
// Create the shared filesystem
fsysConfig.addShare( new DiskSharedDevice( storeName, avmDriver, avmContext));
// DEBUG
if ( logger.isDebugEnabled())
logger.debug( "Added AVM share " + storeName);
}
}
}
}
// Check for the home folder filesystem
ConfigElement homeElem = config.getConfigElement("homeFolder");
if ( homeElem != null)
{
try
{
// Initialize the home folder share mapper
secConfig.setShareMapper( "org.alfresco.filesys.alfresco.HomeShareMapper", homeElem);
// Debug
if ( logger.isDebugEnabled())
logger.debug("Using home folder share mapper");
}
catch (InvalidConfigurationException ex)
{
throw new AlfrescoRuntimeException("Failed to initialize home folder share mapper", ex);
}
}
}
/**
* Process the security configuration
*/
protected void processSecurityConfig()
{
processSecurityConfig(m_configService.getConfig(ConfigSecurity, configCtx));
}
/**
* Process the security configuration
*
* @param config Config
*/
protected void processSecurityConfig(Config config)
{
// Create the security configuration section
SecurityConfigSection secConfig = new SecurityConfigSection( this);
try
{
// Check if global access controls have been specified
ConfigElement globalACLs = config.getConfigElement("globalAccessControl");
if (globalACLs != null)
{
// Parse the access control list
AccessControlList acls = processAccessControlList(secConfig, globalACLs);
if (acls != null)
secConfig.setGlobalAccessControls(acls);
}
// Check if a JCE provider class has been specified
ConfigElement jceElem = config.getConfigElement("JCEProvider");
if (jceElem != null)
{
// Set the JCE provider
secConfig.setJCEProvider(jceElem.getValue());
}
else
{
// Use the default Bouncy Castle JCE provider
secConfig.setJCEProvider("org.bouncycastle.jce.provider.BouncyCastleProvider");
}
// Check if a share mapper has been specified
ConfigElement mapperElem = config.getConfigElement("shareMapper");
if ( mapperElem != null) {
// Check if the share mapper type has been specified
String mapperType = mapperElem.getAttribute( "type");
String mapperClass = null;
if ( mapperType.equalsIgnoreCase( "multi-tenant"))
mapperClass = "org.alfresco.filesys.alfresco.MultiTenantShareMapper";
else if ( mapperType.equalsIgnoreCase( "home-folder"))
mapperClass = "org.alfresco.filesys.alfresco.HomeShareMapper";
else
{
// Get the share mapper class
ConfigElement classElem = mapperElem.getChild( "class");
if ( classElem == null)
throw new InvalidConfigurationException("Share mapper class not specified");
mapperClass = classElem.getValue();
}
// Initialize the share mapper
secConfig.setShareMapper(mapperClass, mapperElem);
}
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
ConfigElement domainMappings = config.getConfigElement( "DomainMappings");
if ( domainMappings != null)
{
// Get the domain mapping elements
List<ConfigElement> mappings = domainMappings.getChildren();
if ( mappings != null)
{
DomainMapping mapping = null;
for ( ConfigElement domainMap : mappings)
{
if ( domainMap.getName().equals( "Domain"))
{
// Get the domain name
String name = domainMap.getAttribute( "name");
// Check if the domain is specified by subnet or range
if ( domainMap.hasAttribute( "subnet"))
{
String subnetStr = domainMap.getAttribute( "subnet");
String maskStr = domainMap.getAttribute( "mask");
// 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 ( domainMap.hasAttribute( "rangeFrom"))
{
String rangeFromStr = domainMap.getAttribute( "rangeFrom");
String rangeToStr = domainMap.getAttribute( "rangeTo");
// 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
*
* @param config Config
* @exception InvalidConfigurationException
*/
protected void processCoreServerConfig()
throws InvalidConfigurationException
{
processCoreServerConfig(m_configService.getConfig(ConfigCoreServer, configCtx));
}
/**
* Process the core server configuration
*
* @param config Config
* @exception InvalidConfigurationException
*/
protected void processCoreServerConfig(Config config)
throws InvalidConfigurationException
{
// Create the core server configuration section
CoreServerConfigSection coreConfig = new CoreServerConfigSection(this);
// Check if the server core element has been specified
if ( config == 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
ConfigElement elem = config.getConfigElement("threadPool");
if ( elem != null) {
// Get the initial thread pool size
String initSizeStr = elem.getAttribute("init");
if ( initSizeStr == null || initSizeStr.length() == 0)
throw new InvalidConfigurationException("Thread pool initial size not specified");
// Validate the initial thread pool size
int initSize = 0;
try {
initSize = Integer.parseInt( initSizeStr);
}
catch (NumberFormatException ex) {
throw new InvalidConfigurationException("Invalid thread pool size value, " + initSizeStr);
}
// 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");
// Get the maximum thread pool size
String maxSizeStr = elem.getAttribute("max");
int maxSize = initSize;
if ( maxSizeStr.length() > 0) {
// Validate the maximum thread pool size
try {
maxSize = Integer.parseInt( maxSizeStr);
}
catch (NumberFormatException ex) {
throw new InvalidConfigurationException(" Invalid thread pool maximum size value, " + maxSizeStr);
}
// 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");
}
else if ( maxSizeStr != null)
throw new InvalidConfigurationException("Thread pool maximum size not specified");
// Configure the thread pool
coreConfig.setThreadPool( initSize, maxSize);
}
else {
// Configure a default thread pool size
coreConfig.setThreadPool( DefaultThreadPoolInit, DefaultThreadPoolMax);
}
// Check if thread pool debug output is enabled
if ( config.getConfigElement( "threadPoolDebug") != null)
coreConfig.getThreadPool().setDebug( true);
// Check if the memory pool configuration has been specified
elem = config.getConfigElement( "memoryPool");
if ( elem != null) {
// Check if the packet sizes/allocations have been specified
ConfigElement pktElem = elem.getChild( "packetSizes");
if ( pktElem != null) {
// Calculate the array size for the packet size/allocation arrays
int elemCnt = pktElem.getChildCount();
// 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
List<ConfigElement> pktSizeList = pktElem.getChildren();
for ( int i = 0; i < pktSizeList.size(); i++) {
// Get the current element
ConfigElement curChild = pktSizeList.get( i);
if ( curChild.getName().equals( "packet")) {
// Get the packet size
int pktSize = -1;
int initAlloc = -1;
int maxAlloc = -1;
String pktSizeStr = curChild.getAttribute("size");
if ( pktSizeStr == null || pktSizeStr.length() == 0)
throw new InvalidConfigurationException("Memory pool packet size not specified");
// Parse the packet size
try {
pktSize = MemorySize.getByteValueInt( pktSizeStr);
}
catch ( NumberFormatException ex) {
throw new InvalidConfigurationException("Memory pool packet size, invalid size value, " + pktSizeStr);
}
// 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
String initSizeStr = curChild.getAttribute("init");
if ( initSizeStr == null || initSizeStr.length() == 0)
throw new InvalidConfigurationException("Memory pool initial allocation not specified");
// Parse the initial allocation
try {
initAlloc = Integer.parseInt( initSizeStr);
}
catch (NumberFormatException ex) {
throw new InvalidConfigurationException("Invalid initial allocation, " + initSizeStr);
}
// 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
String maxSizeStr = curChild.getAttribute("max");
if ( maxSizeStr == null || maxSizeStr.length() == 0)
throw new InvalidConfigurationException("Memory pool maximum allocation not specified");
// Parse the maximum allocation
try {
maxAlloc = Integer.parseInt( maxSizeStr);
}
catch (NumberFormatException ex) {
throw new InvalidConfigurationException("Invalid maximum allocation, " + maxSizeStr);
}
// 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);
}
}
/**
* Process an access control sub-section and return the access control list
*
* @param secConfig SecurityConfigSection
* @param aclsElem ConfigElement
*/
protected AccessControlList processAccessControlList(SecurityConfigSection secConfig, ConfigElement aclsElem)
{
// Check if there is an access control manager configured
if (secConfig.getAccessControlManager() == null)
throw new AlfrescoRuntimeException("No access control manager configured");
// Create the access control list
AccessControlList acls = new AccessControlList();
// Check if there is a default access level for the ACL group
String attrib = aclsElem.getAttribute("default");
if (attrib != null && attrib.length() > 0)
{
// Get the access level and validate
try
{
// Parse the access level name
int access = AccessControlParser.parseAccessTypeString(attrib);
// Set the default access level for the access control list
acls.setDefaultAccessLevel(access);
}
catch (InvalidACLTypeException ex)
{
throw new AlfrescoRuntimeException("Default access level error", ex);
}
catch (ACLParseException ex)
{
throw new AlfrescoRuntimeException("Default access level error", ex);
}
}
// Parse each access control element
List<ConfigElement> aclElemList = aclsElem.getChildren();
if (aclElemList != null && aclElemList.size() > 0)
{
// Create the access controls
for (int i = 0; i < aclsElem.getChildCount(); i++)
{
// Get the current ACL element
ConfigElement curAclElem = aclElemList.get(i);
try
{
// Create the access control and add to the list
acls.addControl(secConfig.getAccessControlManager().createAccessControl(curAclElem.getName(), curAclElem));
}
catch (InvalidACLTypeException ex)
{
throw new AlfrescoRuntimeException("Invalid access control type - " + curAclElem.getName());
}
catch (ACLParseException ex)
{
throw new AlfrescoRuntimeException("Access control parse error (" + curAclElem.getName() + ")", ex);
}
}
}
// Check if there are no access control rules but the default access level is set to 'None',
// this is not allowed as the share would not be accessible or visible.
if (acls.getDefaultAccessLevel() == AccessControl.NoAccess && acls.numberOfControls() == 0)
throw new AlfrescoRuntimeException("Empty access control list and default access 'None' not allowed");
// Return the access control list
return acls;
}
/**
* Process a desktop actions sub-section and return the desktop action table
*
* @param deskActionElem ConfigElement
* @param fileSys DiskSharedDevice
*/
protected DesktopActionTable processDesktopActions(ConfigElement deskActionElem, DiskSharedDevice fileSys)
{
// Get the desktop action configuration elements
DesktopActionTable desktopActions = null;
List<ConfigElement> actionElems = deskActionElem.getChildren();
if ( actionElems != null)
{
// Check for the global configuration section
ConfigElement globalConfig = deskActionElem.getChild("global");
// Allocate the actions table
desktopActions = new DesktopActionTable();
// Process the desktop actions list
for ( ConfigElement actionElem : actionElems)
{
if ( actionElem.getName().equals("action"))
{
// Get the desktop action class name or bean id
ConfigElement className = actionElem.getChild("class");
if ( className != null)
{
// Load the desktop action class, create a new instance
Object actionObj = null;
try
{
// Create a new desktop action instance
actionObj = Class.forName(className.getValue()).newInstance();
// Make sure the object is a desktop action
if ( actionObj instanceof DesktopAction)
{
// Initialize the desktop action
DesktopAction deskAction = (DesktopAction) actionObj;
deskAction.initializeAction(globalConfig, actionElem, fileSys);
// Add the action to the list of desktop actions
desktopActions.addAction(deskAction);
// DEBUG
if ( logger.isDebugEnabled())
logger.debug("Added desktop action " + deskAction.getName());
}
else
throw new AlfrescoRuntimeException("Desktop action does not extend DesktopAction class, " + className.getValue());
}
catch ( ClassNotFoundException ex)
{
throw new AlfrescoRuntimeException("Desktop action class not found, " + className.getValue());
}
catch (IllegalAccessException ex)
{
throw new AlfrescoRuntimeException("Failed to create desktop action instance, " + className.getValue(), ex);
}
catch ( InstantiationException ex)
{
throw new AlfrescoRuntimeException("Failed to create desktop action instance, " + className.getValue(), ex);
}
catch (DesktopActionException ex)
{
throw new AlfrescoRuntimeException("Failed to initialize desktop action", ex);
}
}
}
else if ( actionElem.getName().equals("global") == false)
throw new AlfrescoRuntimeException("Invalid configuration element in desktopActions section, " + actionElem.getName());
}
}
// Return the desktop actions list
return desktopActions;
}
}