org.alfresco.filesys.AbstractServerConfigurationBean.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.filesys.AbstractServerConfigurationBean.java

Source

/*
 * #%L
 * Alfresco Repository
 * %%
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 * %%
 * This file is part of the Alfresco software. 
 * If the software was purchased under a paid Alfresco license, the terms of 
 * the paid license agreement will prevail.  Otherwise, the software is 
 * provided under the following open source license terms:
 * 
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */
package org.alfresco.filesys;

import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.EnumSet;
import java.util.Enumeration;
import java.util.Locale;
import java.util.StringTokenizer;

import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.filesys.alfresco.AlfrescoClientInfoFactory;
import org.alfresco.filesys.alfresco.ExtendedDiskInterface;
import org.alfresco.jlan.debug.DebugConfigSection;
import org.alfresco.jlan.ftp.FTPConfigSection;
import org.alfresco.jlan.netbios.NetBIOSName;
import org.alfresco.jlan.netbios.NetBIOSNameList;
import org.alfresco.jlan.netbios.NetBIOSSession;
import org.alfresco.jlan.netbios.win32.Win32NetBIOS;
import org.alfresco.jlan.oncrpc.nfs.NFSConfigSection;
import org.alfresco.jlan.server.auth.ClientInfo;
import org.alfresco.jlan.server.config.GlobalConfigSection;
import org.alfresco.jlan.server.config.InvalidConfigurationException;
import org.alfresco.jlan.server.config.ServerConfiguration;
import org.alfresco.jlan.smb.server.CIFSConfigSection;
import org.alfresco.jlan.util.IPAddress;
import org.alfresco.jlan.util.Platform;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.extensions.config.element.GenericConfigElement;

/**
 * Alfresco File Server Configuration Bean Class
 * 
 * @author gkspencer
 */
public abstract class AbstractServerConfigurationBean extends ServerConfiguration
        implements ExtendedServerConfigurationAccessor, ApplicationListener, ApplicationContextAware {

    // Debug logging

    protected static final Log logger = LogFactory.getLog("org.alfresco.fileserver");

    // IP address representing null

    public static final String BIND_TO_IGNORE = "0.0.0.0";

    // SMB/CIFS session debug type strings
    //
    // Must match the bit mask order

    protected static final String m_sessDbgStr[] = { "NETBIOS", "STATE", "RXDATA", "TXDATA", "DUMPDATA",
            "NEGOTIATE", "TREE", "SEARCH", "INFO", "FILE", "FILEIO", "TRANSACT", "ECHO", "ERROR", "IPC", "LOCK",
            "PKTTYPE", "DCERPC", "STATECACHE", "TIMING", "NOTIFY", "STREAMS", "SOCKET", "PKTPOOL", "PKTSTATS",
            "THREADPOOL", "BENCHMARK", "OPLOCK" };

    // FTP server debug type strings

    protected static final String m_ftpDebugStr[] = { "STATE", "RXDATA", "TXDATA", "DUMPDATA", "SEARCH", "INFO",
            "FILE", "FILEIO", "ERROR", "PKTTYPE", "TIMING", "DATAPORT", "DIRECTORY", "SSL" };

    // Default FTP server port

    protected static final int DefaultFTPServerPort = 21;

    // Default FTP server session timeout
    protected static final int DefaultFTPSrvSessionTimeout = 5000;

    // Default FTP anonymous account name

    protected static final String DefaultFTPAnonymousAccount = "anonymous";

    //  NFS server debug type strings

    protected static final String m_nfsDebugStr[] = { "RXDATA", "TXDATA", "DUMPDATA", "SEARCH", "INFO", "FILE",
            "FILEIO", "ERROR", "TIMING", "DIRECTORY", "SESSION" };

    // Token name to substitute current server name into the CIFS server name

    protected static final String TokenLocalName = "${localname}";

    // Default thread pool size

    protected static final int DefaultThreadPoolInit = 25;
    protected static final int DefaultThreadPoolMax = 50;

    // Default memory pool settings

    protected static final int[] DefaultMemoryPoolBufSizes = { 256, 4096, 16384, 66000 };
    protected static final int[] DefaultMemoryPoolInitAlloc = { 20, 20, 5, 5 };
    protected static final int[] DefaultMemoryPoolMaxAlloc = { 100, 50, 50, 50 };

    // Memory pool allocation limits

    protected static final int MemoryPoolMinimumAllocation = 5;
    protected static final int MemoryPoolMaximumAllocation = 500;

    // Maximum session timeout

    public static final int MaxSessionTimeout = 60 * 60; // 1 hour

    // Disk interface to use for shared filesystems

    private ExtendedDiskInterface m_repoDiskInterface;

    // Runtime platform type

    private Platform.Type m_platform = Platform.Type.Unchecked;

    // flag to indicate successful initialization

    private boolean m_initialised;

    // Main authentication service, public API

    private AuthenticationService m_authenticationService;

    // Authentication component, for internal functions

    protected AuthenticationComponent m_authenticationComponent;

    // Various services

    private NodeService m_nodeService;
    private PersonService m_personService;
    private TransactionService m_transactionService;
    protected TenantService m_tenantService;
    private SearchService m_searchService;
    private NamespaceService m_namespaceService;
    private AuthorityService m_authorityService;

    // Local server name and domain/workgroup name

    private String m_localName;
    private String m_localNameFull;
    private String m_localDomain;

    // Disable use of native code on Windows, do not use any JNI calls

    protected boolean m_disableNativeCode = false;

    /**
     * Default constructor
     */
    public AbstractServerConfigurationBean() {
        super("");
    }

    /**
     * Class constructor
     * 
     * @param srvName String
     */
    public AbstractServerConfigurationBean(String srvName) {
        super(srvName);
    }

    /**
     * Set the authentication service
     * 
     * @param authenticationService AuthenticationService
     */
    public void setAuthenticationService(AuthenticationService authenticationService) {
        m_authenticationService = authenticationService;
    }

    /**
     * Set the filesystem driver for the node service based filesystem
     * 
     * @param diskInterface DiskInterface
     */
    public void setDiskInterface(ExtendedDiskInterface diskInterface) {
        m_repoDiskInterface = diskInterface;
    }

    /**
     * Set the authentication component
     * 
     * @param component AuthenticationComponent
     */
    public void setAuthenticationComponent(AuthenticationComponent component) {
        m_authenticationComponent = component;
    }

    /**
     * Set the node service
     * 
     * @param service NodeService
     */
    public void setNodeService(NodeService service) {
        m_nodeService = service;
    }

    /**
     * Set the person service
     * 
     * @param service PersonService
     */
    public void setPersonService(PersonService service) {
        m_personService = service;
    }

    /**
     * Set the transaction service
     * 
     * @param service TransactionService
     */
    public void setTransactionService(TransactionService service) {
        m_transactionService = service;
    }

    /**
     * Set the tenant service
     * 
     * @param tenantService TenantService
     */
    public void setTenantService(TenantService tenantService) {
        m_tenantService = tenantService;
    }

    /**
     * Set the search service
     * 
     * @param searchService SearchService
     */
    public void setSearchService(SearchService searchService) {
        m_searchService = searchService;
    }

    /**
     * Set the namespace service
     * 
     * @param namespaceService NamespaceService
     */
    public void setNamespaceService(NamespaceService namespaceService) {
        m_namespaceService = namespaceService;
    }

    /**
     * Set the authority service
     * 
     * @param authService AuthorityService
     */
    public void setAuthorityService(AuthorityService authService) {
        m_authorityService = authService;
    }

    /**
     * Check if the configuration has been initialized
     * 
     * @return Returns true if the configuration was fully initialised
     */
    public boolean isInitialised() {
        return m_initialised;
    }

    /**
     * Check if the SMB server is enabled
     * 
     * @return boolean
     */
    public final boolean isSMBServerEnabled() {
        return hasConfigSection(CIFSConfigSection.SectionName);
    }

    /**
     * Check if the FTP server is enabled
     * 
     * @return boolean
     */
    public final boolean isFTPServerEnabled() {
        return hasConfigSection(FTPConfigSection.SectionName);
    }

    /**
     * Check if the NFS server is enabled
     * 
     * @return boolean
     */
    public final boolean isNFSServerEnabled() {
        return hasConfigSection(NFSConfigSection.SectionName);
    }

    /**
     * Return the repository disk interface to be used to create shares
     * 
     * @return DiskInterface
     */
    public final ExtendedDiskInterface getRepoDiskInterface() {
        return m_repoDiskInterface;
    }

    /**
     * Initialize the configuration using the configuration service
     */
    public void init() {
        // Check that all required properties have been set

        if (m_authenticationComponent == null) {
            throw new AlfrescoRuntimeException("Property 'authenticationComponent' not set");
        } else if (m_authenticationService == null) {
            throw new AlfrescoRuntimeException("Property 'authenticationService' not set");
        } else if (m_nodeService == null) {
            throw new AlfrescoRuntimeException("Property 'nodeService' not set");
        } else if (m_personService == null) {
            throw new AlfrescoRuntimeException("Property 'personService' not set");
        } else if (m_transactionService == null) {
            throw new AlfrescoRuntimeException("Property 'transactionService' not set");
        } else if (m_repoDiskInterface == null) {
            throw new AlfrescoRuntimeException("Property 'diskInterface' not set");
        } else if (m_authorityService == null) {
            throw new AlfrescoRuntimeException("Property 'authorityService' not set");
        }

        // Set the platform type

        determinePlatformType();

        // Create the debug output configuration using a logger for all file server debug output

        DebugConfigSection debugConfig = new DebugConfigSection(this);
        try {
            debugConfig.setDebug("org.alfresco.filesys.debug.FileServerDebugInterface",
                    new GenericConfigElement("params"));
        } catch (InvalidConfigurationException ex) {
        }

        // Create the global configuration and Alfresco configuration sections

        new GlobalConfigSection(this);
        new AlfrescoConfigSection(this);

        // Install the Alfresco client information factory

        ClientInfo.setFactory(new AlfrescoClientInfoFactory());

        // We need to check for a WINS server configuration in the CIFS server config section to initialize
        // the NetBIOS name lookups to use WINS rather broadcast lookups, which may be used to get the local
        // domain

        try {

            // Get the CIFS server config section and extract the WINS server config, if available

            processWINSServerConfig();
        } catch (Exception ex) {

            // Configuration error

            logger.error("File server configuration error (WINS), " + ex.getMessage(), ex);
        }

        // Initialize the filesystems

        try {
            // Process the core server configuration
            processCoreServerConfig();

            // Process the security configuration
            processSecurityConfig();

            // Process the Cluster  configuration
            processClusterConfig();

            // Process the filesystems configuration
            processFilesystemsConfig();
        } catch (Exception ex) {
            // Configuration error
            throw new AlfrescoRuntimeException("File server configuration error, " + ex.getMessage(), ex);
        }

        // Initialize the CIFS and FTP servers, if the filesystem(s) initialized successfully

        // Initialize the CIFS server

        try {

            // Process the CIFS server configuration
            processCIFSServerConfig();

            // Log the successful startup
            logger.info("CIFS server " + (isSMBServerEnabled() ? "" : "NOT ") + "started");
        } catch (UnsatisfiedLinkError ex) {
            // Error accessing the Win32NetBIOS DLL code

            logger.error("Error accessing Win32 NetBIOS, check DLL is on the path");

            // Disable the CIFS server

            removeConfigSection(CIFSConfigSection.SectionName);
        } catch (Throwable ex) {
            // Configuration error

            logger.error("CIFS server configuration error, " + ex.getMessage(), ex);

            // Disable the CIFS server

            removeConfigSection(CIFSConfigSection.SectionName);
        }

        // Initialize the FTP server

        try {
            // Process the FTP server configuration
            processFTPServerConfig();

            // Log the successful startup

            logger.info("FTP server " + (isFTPServerEnabled() ? "" : "NOT ") + "started");
        } catch (Exception ex) {
            // Configuration error

            logger.error("FTP server configuration error, " + ex.getMessage(), ex);
        }
    }

    protected abstract void processCoreServerConfig() throws InvalidConfigurationException;

    protected abstract void processSecurityConfig();

    protected abstract void processFilesystemsConfig();

    protected abstract void processCIFSServerConfig();

    protected abstract void processFTPServerConfig();

    protected abstract void processClusterConfig() throws InvalidConfigurationException;

    protected void processWINSServerConfig() {
    }

    /**
     * Close the configuration bean
     */
    public final void closeConfiguration() {
        super.closeConfiguration();
    }

    /**
     * Determine the platform type
     */
    private final void determinePlatformType() {
        if (m_platform == Platform.Type.Unchecked)
            m_platform = Platform.isPlatformType();
    }

    /**
     * Parse the platforms attribute returning the set of platform ids
     * 
     * @param platformStr String
     */
    protected final EnumSet<Platform.Type> parsePlatformString(String platformStr) {
        // Split the platform string and build up a set of platform types

        EnumSet<Platform.Type> platformTypes = EnumSet.noneOf(Platform.Type.class);
        if (platformStr == null || platformStr.length() == 0)
            return platformTypes;

        StringTokenizer token = new StringTokenizer(platformStr.toUpperCase(Locale.ENGLISH), ",");
        String typ = null;

        try {
            while (token.hasMoreTokens()) {

                // Get the current platform type string and validate

                typ = token.nextToken().trim();
                Platform.Type platform = Platform.Type.valueOf(typ);

                if (platform != Platform.Type.Unknown)
                    platformTypes.add(platform);
                else
                    throw new AlfrescoRuntimeException("Invalid platform type, " + typ);
            }
        } catch (IllegalArgumentException ex) {
            throw new AlfrescoRuntimeException("Invalid platform type, " + typ);
        }

        // Return the platform types

        return platformTypes;
    }

    /**
     * Get the local server name and optionally trim the domain name
     * 
     * @param trimDomain boolean
     * @return String
     */
    public final String getLocalServerName(boolean trimDomain) {
        // Use cached untrimmed version if necessary
        if (!trimDomain) {
            return getLocalServerName();
        }

        // Check if the name has already been set
        if (m_localName != null)
            return m_localName;

        // Find the local server name
        String srvName = getLocalServerName();

        // Strip the domain name

        if (trimDomain && srvName != null) {
            int pos = srvName.indexOf(".");
            if (pos != -1)
                srvName = srvName.substring(0, pos);
        }

        // Save the local server name

        m_localName = srvName;

        // Return the local server name

        return srvName;
    }

    /**
     * Get the local server name (untrimmed)
     * 
     * @return String
     */
    private String getLocalServerName() {
        // Check if the name has already been set

        if (m_localNameFull != null)
            return m_localNameFull;

        // Find the local server name

        String srvName = null;

        if (getPlatformType() == Platform.Type.WINDOWS && !isNativeCodeDisabled()) {
            // Get the local name via JNI

            srvName = Win32NetBIOS.GetLocalNetBIOSName();
        } else {
            // Get the DNS name of the local system

            try {
                srvName = InetAddress.getLocalHost().getHostName();
            } catch (UnknownHostException ex) {
            }
        }

        // Save the local server name

        m_localNameFull = srvName;

        // Return the local server name

        return srvName;
    }

    /**
     * Get the local domain/workgroup name
     * 
     * @return String
     */
    public final String getLocalDomainName() {
        // Check if the local domain has been set

        if (m_localDomain != null)
            return m_localDomain;

        // Find the local domain name

        String domainName = null;

        if (getPlatformType() == Platform.Type.WINDOWS && !isNativeCodeDisabled()) {
            // Get the local domain/workgroup name via JNI

            domainName = Win32NetBIOS.GetLocalDomainName();

            // Debug

            if (logger.isDebugEnabled())
                logger.debug("Local domain name is " + domainName + " (via JNI)");
        } else {
            NetBIOSName nbName = null;

            try {
                // Try and find the browse master on the local network

                nbName = NetBIOSSession.FindName(NetBIOSName.BrowseMasterName, NetBIOSName.BrowseMasterGroup, 5000);

                // Log the browse master details

                if (logger.isDebugEnabled())
                    logger.debug("Found browse master at " + nbName.getIPAddressString(0));

                // Get the NetBIOS name list from the browse master

                NetBIOSNameList nbNameList = NetBIOSSession.FindNamesForAddress(nbName.getIPAddressString(0));
                if (nbNameList != null) {
                    nbName = nbNameList.findName(NetBIOSName.MasterBrowser, false);
                    // Set the domain/workgroup name
                    if (nbName != null)
                        domainName = nbName.getName();
                }
            } catch (IOException ex) {
            }
        }

        // Save the local domain name

        m_localDomain = domainName;

        // Return the local domain/workgroup name

        return domainName;
    }

    /**
     * Parse an adapter name string and return the matching address
     * 
     * @param adapter String
     * @return InetAddress
     * @exception InvalidConfigurationException
     */
    protected final InetAddress parseAdapterName(String adapter) throws InvalidConfigurationException {

        NetworkInterface ni = null;

        try {
            ni = NetworkInterface.getByName(adapter);
        } catch (SocketException ex) {
            throw new InvalidConfigurationException("Invalid adapter name, " + adapter);
        }

        if (ni == null)
            throw new InvalidConfigurationException("Invalid network adapter name, " + adapter);

        // Get the IP address for the adapter

        InetAddress adapAddr = null;
        Enumeration<InetAddress> addrEnum = ni.getInetAddresses();

        while (addrEnum.hasMoreElements() && adapAddr == null) {

            // Get the current address

            InetAddress addr = addrEnum.nextElement();
            if (IPAddress.isNumericAddress(addr.getHostAddress()))
                adapAddr = addr;
        }

        // Check if we found the IP address to bind to

        if (adapAddr == null)
            throw new InvalidConfigurationException("Adapter " + adapter + " does not have a valid IP address");

        // Return the adapter address

        return adapAddr;
    }

    private ApplicationContext applicationContext = null;

    /* (non-Javadoc)
     * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
     */
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            ContextRefreshedEvent refreshEvent = (ContextRefreshedEvent) event;
            ApplicationContext refreshContext = refreshEvent.getApplicationContext();
            if (refreshContext != null && refreshContext.equals(applicationContext)) {
                // Initialize the bean

                init();
            }
        }
    }

    /* (non-Javadoc)
     * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
     */
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * Return the authentication service
     * 
     * @return AuthenticationService
     */
    protected final AuthenticationService getAuthenticationService() {
        return m_authenticationService;
    }

    /**
     * Return the authentication component
     * 
     * @return AuthenticationComponent
     */
    protected final AuthenticationComponent getAuthenticationComponent() {
        return m_authenticationComponent;
    }

    /**
     * Return the node service
     * 
     * @return NodeService
     */
    protected final NodeService getNodeService() {
        return m_nodeService;
    }

    /**
     * Return the person service
     * 
     * @return PersonService
     */
    protected final PersonService getPersonService() {
        return m_personService;
    }

    /**
     * Return the transaction service
     * 
     * @return TransactionService
     */
    protected final TransactionService getTransactionService() {
        return m_transactionService;
    }

    /**
     * Return the tenant service
     * 
     * @return TenantService
     */
    protected final TenantService getTenantService() {
        return m_tenantService;
    }

    /**
     * Return the search service
     * 
     * @return SearchService
     */
    protected final SearchService getSearchService() {
        return m_searchService;
    }

    /**
     * Return the namespace service
     * 
     * @return NamespaceService
     */
    protected final NamespaceService getNamespaceService() {
        return m_namespaceService;
    }

    /**
     * Check if native code calls are disabled
     * 
     * @return boolean
     */
    public final boolean isNativeCodeDisabled() {
        return m_disableNativeCode;
    }

    /**
     * Return the named bean
     * 
     * @param beanName String
     * @return Object
     */
    public final Object getBean(String beanName) {
        return applicationContext.getBean(beanName);
    }

    /**
     * Return the applicatin context
     * 
     * @return ApplicationContext
     */
    public final ApplicationContext getApplicationsContext() {
        return applicationContext;
    }

    /**
     * Return the authority service
     * 
     * @return AuthorityService
     */
    public final AuthorityService getAuthorityService() {
        return m_authorityService;
    }
}