|
@@ -1,2617 +0,0 @@
|
|
|
-/*
|
|
|
- * Copyright (C) 2006-2010 Alfresco Software Limited.
|
|
|
- *
|
|
|
- * This file is part of Alfresco
|
|
|
- *
|
|
|
- * Alfresco is free software: you can redistribute it and/or modify
|
|
|
- * it under the terms of the GNU Lesser General Public License as published by
|
|
|
- * the Free Software Foundation, either version 3 of the License, or
|
|
|
- * (at your option) any later version.
|
|
|
- *
|
|
|
- * Alfresco is distributed in the hope that it will be useful,
|
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
- * GNU Lesser General Public License for more details.
|
|
|
- *
|
|
|
- * You should have received a copy of the GNU Lesser General Public License
|
|
|
- * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
|
|
- */
|
|
|
-
|
|
|
-package org.alfresco.jlan.app;
|
|
|
-
|
|
|
-import java.io.FileInputStream;
|
|
|
-import java.io.IOException;
|
|
|
-import java.io.InputStream;
|
|
|
-import java.io.InputStreamReader;
|
|
|
-import java.io.Reader;
|
|
|
-import java.net.InetAddress;
|
|
|
-import java.net.NetworkInterface;
|
|
|
-import java.net.SocketException;
|
|
|
-import java.net.UnknownHostException;
|
|
|
-import java.text.ParseException;
|
|
|
-import java.text.SimpleDateFormat;
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.Date;
|
|
|
-import java.util.Enumeration;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Locale;
|
|
|
-import java.util.StringTokenizer;
|
|
|
-
|
|
|
-import javax.xml.parsers.DocumentBuilder;
|
|
|
-import javax.xml.parsers.DocumentBuilderFactory;
|
|
|
-
|
|
|
-import org.alfresco.jlan.debug.Debug;
|
|
|
-import org.alfresco.jlan.debug.DebugConfigSection;
|
|
|
-import org.alfresco.jlan.netbios.win32.Win32NetBIOS;
|
|
|
-import org.alfresco.jlan.server.auth.CifsAuthenticator;
|
|
|
-import org.alfresco.jlan.server.auth.UserAccount;
|
|
|
-import org.alfresco.jlan.server.auth.UserAccountList;
|
|
|
-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.config.CoreServerConfigSection;
|
|
|
-import org.alfresco.jlan.server.config.GlobalConfigSection;
|
|
|
-import org.alfresco.jlan.server.config.InvalidConfigurationException;
|
|
|
-import org.alfresco.jlan.server.config.SecurityConfigSection;
|
|
|
-import org.alfresco.jlan.server.config.ServerConfiguration;
|
|
|
-import org.alfresco.jlan.server.core.DeviceContextException;
|
|
|
-import org.alfresco.jlan.server.core.ShareType;
|
|
|
-import org.alfresco.jlan.server.core.SharedDeviceList;
|
|
|
-import org.alfresco.jlan.server.filesys.DiskDeviceContext;
|
|
|
-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.filesys.SrvDiskInfo;
|
|
|
-import org.alfresco.jlan.server.filesys.VolumeInfo;
|
|
|
-import org.alfresco.jlan.server.filesys.cache.FileStateCache;
|
|
|
-import org.alfresco.jlan.server.filesys.cache.StandaloneFileStateCache;
|
|
|
-import org.alfresco.jlan.server.thread.ThreadRequestPool;
|
|
|
-import org.alfresco.jlan.smb.Dialect;
|
|
|
-import org.alfresco.jlan.smb.DialectSelector;
|
|
|
-import org.alfresco.jlan.smb.server.CIFSConfigSection;
|
|
|
-import org.alfresco.jlan.smb.server.SMBSrvSession;
|
|
|
-import org.alfresco.jlan.smb.server.VirtualCircuitList;
|
|
|
-import org.alfresco.jlan.smb.util.DriveMapping;
|
|
|
-import org.alfresco.jlan.smb.util.DriveMappingList;
|
|
|
-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.springframework.extensions.config.ConfigElement;
|
|
|
-import org.springframework.extensions.config.element.GenericConfigElement;
|
|
|
-import org.w3c.dom.Document;
|
|
|
-import org.w3c.dom.Element;
|
|
|
-import org.w3c.dom.NamedNodeMap;
|
|
|
-import org.w3c.dom.Node;
|
|
|
-import org.w3c.dom.NodeList;
|
|
|
-import org.xml.sax.InputSource;
|
|
|
-
|
|
|
-/**
|
|
|
- * Cifs Only XML File Server Configuration Class
|
|
|
- *
|
|
|
- * <p>
|
|
|
- * XML implementation of the SMB server configuration.
|
|
|
- *
|
|
|
- * @author gkspencer
|
|
|
- */
|
|
|
-public class CifsOnlyXMLServerConfiguration extends ServerConfiguration {
|
|
|
-
|
|
|
- // Constants
|
|
|
- //
|
|
|
- // Node type for an Element
|
|
|
-
|
|
|
- private static final int ELEMENT_TYPE = 1;
|
|
|
-
|
|
|
- // CIFS session debug type strings
|
|
|
- //
|
|
|
- // Must match the bit mask order.
|
|
|
-
|
|
|
- private 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", "PKTALLOC" };
|
|
|
-
|
|
|
- // Default session debug flags, if enabled
|
|
|
-
|
|
|
- private static final int DEFAULT_SESSDEBUG = SMBSrvSession.DBG_ERROR + SMBSrvSession.DBG_INFO + SMBSrvSession.DBG_SEARCH
|
|
|
- + SMBSrvSession.DBG_TREE + SMBSrvSession.DBG_TRAN + SMBSrvSession.DBG_STATE;
|
|
|
-
|
|
|
- // Valid drive letter names for mapped drives
|
|
|
-
|
|
|
- private static final String _driveLetters = "CDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
|
-
|
|
|
- // Default thread pool size
|
|
|
-
|
|
|
- private static final int DefaultThreadPoolInit = 25;
|
|
|
- private static final int DefaultThreadPoolMax = 50;
|
|
|
-
|
|
|
- // Default memory pool settings
|
|
|
-
|
|
|
- private static final int[] DefaultMemoryPoolBufSizes = { 256, 4096, 16384, 66000 };
|
|
|
- private static final int[] DefaultMemoryPoolInitAlloc = { 20, 20, 5, 5 };
|
|
|
- private static final int[] DefaultMemoryPoolMaxAlloc = { 100, 50, 50, 50 };
|
|
|
-
|
|
|
- // Memory pool packet size limits
|
|
|
-
|
|
|
- private static final int MemoryPoolMinimumPacketSize = 256;
|
|
|
- private static final int MemoryPoolMaximumPacketSize = 128 * (int) MemorySize.KILOBYTE;
|
|
|
-
|
|
|
- // Memory pool allocation limits
|
|
|
-
|
|
|
- private static final int MemoryPoolMinimumAllocation = 5;
|
|
|
- private static final int MemoryPoolMaximumAllocation = 500;
|
|
|
-
|
|
|
- // Maximum session timeout
|
|
|
-
|
|
|
- private static final int MaxSessionTimeout = 60 * 60; // 1 hour
|
|
|
-
|
|
|
- // Date formatter
|
|
|
-
|
|
|
- private SimpleDateFormat m_dateFmt = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss");
|
|
|
-
|
|
|
- /**
|
|
|
- * Default constructor
|
|
|
- */
|
|
|
- public CifsOnlyXMLServerConfiguration() {
|
|
|
- super("");
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Load the configuration from the specified file.
|
|
|
- *
|
|
|
- * @param fname java.lang.String
|
|
|
- * @exception IOException
|
|
|
- * @exception InvalidConfigurationException
|
|
|
- */
|
|
|
- public final void loadConfiguration(String fname)
|
|
|
- throws IOException, InvalidConfigurationException {
|
|
|
-
|
|
|
- // Open the configuration file
|
|
|
-
|
|
|
- InputStream inFile = new FileInputStream(fname);
|
|
|
- Reader inRead = new InputStreamReader(inFile);
|
|
|
-
|
|
|
- // Call the main parsing method
|
|
|
-
|
|
|
- loadConfiguration(inRead);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Load the configuration from the specified input stream
|
|
|
- *
|
|
|
- * @param in Reader
|
|
|
- * @exception IOException
|
|
|
- * @exception InvalidConfigurationException
|
|
|
- */
|
|
|
- public final void loadConfiguration(Reader in)
|
|
|
- throws IOException, InvalidConfigurationException {
|
|
|
-
|
|
|
- // Reset the current configuration to the default settings
|
|
|
-
|
|
|
- removeAllConfigSections();
|
|
|
-
|
|
|
- // Load and parse the XML configuration document
|
|
|
-
|
|
|
- try {
|
|
|
-
|
|
|
- // Load the configuration from the XML file
|
|
|
-
|
|
|
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
|
|
- DocumentBuilder builder = factory.newDocumentBuilder();
|
|
|
-
|
|
|
- InputSource xmlSource = new InputSource(in);
|
|
|
- Document doc = builder.parse(xmlSource);
|
|
|
-
|
|
|
- // Parse the document
|
|
|
-
|
|
|
- loadConfiguration(doc);
|
|
|
- }
|
|
|
- catch (Exception ex) {
|
|
|
-
|
|
|
- // Rethrow the exception as a configuration exeception
|
|
|
-
|
|
|
- throw new InvalidConfigurationException("XML error", ex);
|
|
|
- }
|
|
|
- finally {
|
|
|
-
|
|
|
- // Close the input file
|
|
|
-
|
|
|
- in.close();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Load the configuration from the specified document
|
|
|
- *
|
|
|
- * @param doc Document
|
|
|
- * @exception IOException
|
|
|
- * @exception InvalidConfigurationException
|
|
|
- */
|
|
|
- public void loadConfiguration(Document doc)
|
|
|
- throws IOException, InvalidConfigurationException {
|
|
|
-
|
|
|
- // Reset the current configuration to the default settings
|
|
|
-
|
|
|
- removeAllConfigSections();
|
|
|
-
|
|
|
- // Parse the XML configuration document
|
|
|
-
|
|
|
- try {
|
|
|
-
|
|
|
- // Access the root of the XML document, get a list of the child nodes
|
|
|
-
|
|
|
- Element root = doc.getDocumentElement();
|
|
|
- NodeList childNodes = root.getChildNodes();
|
|
|
-
|
|
|
- // Process the debug settings element
|
|
|
-
|
|
|
- procDebugElement(findChildNode("debug", childNodes));
|
|
|
-
|
|
|
- // Process the core server configuration settings
|
|
|
-
|
|
|
- procServerCoreElement(findChildNode("server-core", childNodes));
|
|
|
-
|
|
|
- // Process the global configuration settings
|
|
|
-
|
|
|
- procGlobalElement(findChildNode("global", childNodes));
|
|
|
-
|
|
|
- // Process the security element
|
|
|
-
|
|
|
- procSecurityElement(findChildNode("security", childNodes));
|
|
|
-
|
|
|
- // Process the shares element
|
|
|
-
|
|
|
- procSharesElement(findChildNode("shares", childNodes));
|
|
|
-
|
|
|
- // Process the SMB server specific settings
|
|
|
-
|
|
|
- procSMBServerElement(findChildNode("SMB", childNodes));
|
|
|
-
|
|
|
- // Process the drive mappings settings
|
|
|
-
|
|
|
- procDriveMappingsElement(findChildNode("DriveMappings", childNodes));
|
|
|
- }
|
|
|
- catch (Exception ex) {
|
|
|
-
|
|
|
- // Rethrow the exception as a configuration exeception
|
|
|
-
|
|
|
- throw new InvalidConfigurationException("XML error", ex);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Process the server core settings XML element
|
|
|
- *
|
|
|
- * @param srvCore Element
|
|
|
- * @exception InvalidConfigurationException
|
|
|
- */
|
|
|
- protected final void procServerCoreElement(Element srvCore)
|
|
|
- throws InvalidConfigurationException {
|
|
|
-
|
|
|
- // Create the core server configuration section
|
|
|
-
|
|
|
- CoreServerConfigSection coreConfig = new CoreServerConfigSection(this);
|
|
|
-
|
|
|
- // Check if the server core element has been specified
|
|
|
-
|
|
|
- if ( srvCore == 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
|
|
|
-
|
|
|
- Element elem = findChildNode("threadPool", srvCore.getChildNodes());
|
|
|
- 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 ( findChildNode("threadPoolDebug", srvCore.getChildNodes()) != null)
|
|
|
- coreConfig.getThreadPool().setDebug( true);
|
|
|
-
|
|
|
- // Check if the memory pool configuration has been specified
|
|
|
-
|
|
|
- elem = findChildNode("memoryPool", srvCore.getChildNodes());
|
|
|
- if ( elem != null) {
|
|
|
-
|
|
|
- // Check if the packet sizes/allocations have been specified
|
|
|
-
|
|
|
- Element pktElem = findChildNode("packetSizes", elem.getChildNodes());
|
|
|
- if ( pktElem != null) {
|
|
|
-
|
|
|
- // Calculate the array size for the packet size/allocation arrays
|
|
|
-
|
|
|
- NodeList nodeList = pktElem.getChildNodes();
|
|
|
- int elemCnt = 0;
|
|
|
-
|
|
|
- for ( int i = 0; i < nodeList.getLength(); i++) {
|
|
|
- if ( nodeList.item( i).getNodeType() == ELEMENT_TYPE)
|
|
|
- elemCnt++;
|
|
|
- }
|
|
|
-
|
|
|
- // 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 ( int i = 0; i < nodeList.getLength(); i++) {
|
|
|
-
|
|
|
- // Get the current element node
|
|
|
-
|
|
|
- Node curNode = nodeList.item( i);
|
|
|
- if ( curNode.getNodeType() == ELEMENT_TYPE) {
|
|
|
-
|
|
|
- // Get the element and check if it is a packet size element
|
|
|
-
|
|
|
- Element curElem = (Element) curNode;
|
|
|
- if ( curElem.getNodeName().equals("packet")) {
|
|
|
-
|
|
|
- // Get the packet size
|
|
|
-
|
|
|
- int pktSize = -1;
|
|
|
- int initAlloc = -1;
|
|
|
- int maxAlloc = -1;
|
|
|
-
|
|
|
- String pktSizeStr = curElem.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 = curElem.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 = curElem.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 the global settings XML element
|
|
|
- *
|
|
|
- * @param global Element
|
|
|
- * @exception InvalidConfigurationException
|
|
|
- */
|
|
|
- protected final void procGlobalElement(Element global)
|
|
|
- throws InvalidConfigurationException {
|
|
|
-
|
|
|
- // Create the global configuration section
|
|
|
-
|
|
|
- GlobalConfigSection globalConfig = new GlobalConfigSection(this);
|
|
|
-
|
|
|
- // Check if the global element has been specified
|
|
|
-
|
|
|
- if ( global == null)
|
|
|
- return;
|
|
|
-
|
|
|
- // Check if the timezone has been specified
|
|
|
-
|
|
|
- Element elem = findChildNode("timezone", global.getChildNodes());
|
|
|
- if ( elem != null) {
|
|
|
-
|
|
|
- // Check for the timezone name
|
|
|
-
|
|
|
- String tzName = elem.getAttribute("name");
|
|
|
- if ( tzName != null && tzName.length() > 0)
|
|
|
- globalConfig.setTimeZone(tzName);
|
|
|
-
|
|
|
- // Check for the timezone offset value
|
|
|
-
|
|
|
- String tzOffset = elem.getAttribute("offset");
|
|
|
- if ( tzOffset != null && tzOffset.length() > 0 && tzName != null && tzName.length() > 0)
|
|
|
- throw new InvalidConfigurationException("Specify name or offset for timezone");
|
|
|
-
|
|
|
- // Validate the timezone offset
|
|
|
-
|
|
|
- if ( tzOffset != null && tzOffset.length() > 0) {
|
|
|
- int offset = 0;
|
|
|
-
|
|
|
- try {
|
|
|
- offset = Integer.parseInt(tzOffset);
|
|
|
- }
|
|
|
- catch (NumberFormatException ex) {
|
|
|
- throw new InvalidConfigurationException("Invalid timezone offset value, " + tzOffset);
|
|
|
- }
|
|
|
-
|
|
|
- // Range check the timezone offset value
|
|
|
-
|
|
|
- if ( offset < -1440 || offset > 1440)
|
|
|
- throw new InvalidConfigurationException("Invalid timezone offset, value out of valid range, " + tzOffset);
|
|
|
-
|
|
|
- // Set the timezone offset in minutes from UTC
|
|
|
-
|
|
|
- globalConfig.setTimeZoneOffset(offset);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Process the SMB server XML element
|
|
|
- *
|
|
|
- * @param smb Element
|
|
|
- * @exception InvalidConfigurationException
|
|
|
- */
|
|
|
- protected final void procSMBServerElement(Element smb)
|
|
|
- throws InvalidConfigurationException {
|
|
|
-
|
|
|
- // Check if the SMB element is valid
|
|
|
-
|
|
|
- if ( smb == null)
|
|
|
- throw new InvalidConfigurationException("SMB section must be specified");
|
|
|
-
|
|
|
- // Create the CIFS server configuration section
|
|
|
-
|
|
|
- CIFSConfigSection cifsConfig = new CIFSConfigSection(this);
|
|
|
-
|
|
|
- // Process the main SMB server settings
|
|
|
-
|
|
|
- procHostElement(findChildNode("host", smb.getChildNodes()), cifsConfig);
|
|
|
-
|
|
|
- // Debug settings are now specified within the SMB server configuration block
|
|
|
-
|
|
|
- // Check if NetBIOS debug is enabled
|
|
|
-
|
|
|
- Element elem = findChildNode("netbiosDebug", smb.getChildNodes());
|
|
|
- if ( elem != null)
|
|
|
- cifsConfig.setNetBIOSDebug(true);
|
|
|
-
|
|
|
- // Check if host announcement debug is enabled
|
|
|
-
|
|
|
- elem = findChildNode("announceDebug", smb.getChildNodes());
|
|
|
- if ( elem != null)
|
|
|
- cifsConfig.setHostAnnounceDebug(true);
|
|
|
-
|
|
|
- // Check if session debug is enabled
|
|
|
-
|
|
|
- elem = findChildNode("sessionDebug", smb.getChildNodes());
|
|
|
- if ( elem != null) {
|
|
|
-
|
|
|
- // Check for session debug flags
|
|
|
-
|
|
|
- String flags = elem.getAttribute("flags");
|
|
|
- int sessDbg = DEFAULT_SESSDEBUG;
|
|
|
-
|
|
|
- if ( flags != null) {
|
|
|
-
|
|
|
- // Clear the default debug flags
|
|
|
-
|
|
|
- sessDbg = 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 InvalidConfigurationException("Invalid session debug flag, " + dbg);
|
|
|
-
|
|
|
- // Set the debug flag
|
|
|
-
|
|
|
- sessDbg += 1 << idx;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Set the session debug flags
|
|
|
-
|
|
|
- cifsConfig.setSessionDebugFlags(sessDbg);
|
|
|
- }
|
|
|
-
|
|
|
- // Check if NIO based code should be disabled
|
|
|
-
|
|
|
- if ( findChildNode( "disableNIO", smb.getChildNodes()) != null)
|
|
|
- cifsConfig.setDisableNIOCode( true);
|
|
|
-
|
|
|
- // Check if a maximum virtual circuits per session limit has been specified
|
|
|
-
|
|
|
- elem = findChildNode("virtualCircuits", smb.getChildNodes());
|
|
|
- if ( elem != null) {
|
|
|
-
|
|
|
- // Parse and validate the maximum virtual circuits value
|
|
|
-
|
|
|
- String maxVCVal = elem.getAttribute( "maxPerSession");
|
|
|
-
|
|
|
- if ( maxVCVal != null && maxVCVal.length() > 0) {
|
|
|
- try {
|
|
|
-
|
|
|
- // Parse the value, and range check
|
|
|
-
|
|
|
- int maxVC = Integer.parseInt( maxVCVal);
|
|
|
-
|
|
|
- if ( maxVC < VirtualCircuitList.MinCircuits || maxVC > VirtualCircuitList.MaxCircuits)
|
|
|
- throw new InvalidConfigurationException("Maximum virtual circuits value out of range, valid range " + VirtualCircuitList.MinCircuits + " - " +
|
|
|
- VirtualCircuitList.MaxCircuits);
|
|
|
-
|
|
|
- // Set the maximum virtual circuits per session
|
|
|
-
|
|
|
- cifsConfig.setMaximumVirtualCircuits( maxVC);
|
|
|
- }
|
|
|
- catch (NumberFormatException ex) {
|
|
|
- throw new InvalidConfigurationException("Invalid maximum virtual circuits value, " + maxVCVal);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Check if an authenticator has been specified
|
|
|
-
|
|
|
- Element authElem = findChildNode("authenticator", smb.getChildNodes());
|
|
|
- if ( authElem != null) {
|
|
|
-
|
|
|
- // Get the authenticator class and security mode
|
|
|
-
|
|
|
- Element classElem = findChildNode("class", authElem.getChildNodes());
|
|
|
- String authClass = null;
|
|
|
-
|
|
|
- if ( classElem == null) {
|
|
|
-
|
|
|
- // Check if the authenticator type has been specified
|
|
|
-
|
|
|
- String authType = authElem.getAttribute("type");
|
|
|
-
|
|
|
- if ( authType == null)
|
|
|
- throw new InvalidConfigurationException("Authenticator class not specified");
|
|
|
-
|
|
|
- // Check the authenticator type and set the appropriate authenticator class
|
|
|
-
|
|
|
- if ( authType.equalsIgnoreCase("local"))
|
|
|
- authClass = "org.alfresco.jlan.server.auth.LocalAuthenticator";
|
|
|
- else if ( authType.equalsIgnoreCase("passthru"))
|
|
|
- authClass = "org.alfresco.jlan.server.auth.passthru.PassthruAuthenticator";
|
|
|
-
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- // Set the authenticator class
|
|
|
-
|
|
|
- authClass = getText(classElem);
|
|
|
- }
|
|
|
-
|
|
|
- Element modeElem = findChildNode("mode", authElem.getChildNodes());
|
|
|
- int accessMode = CifsAuthenticator.USER_MODE;
|
|
|
-
|
|
|
- if ( modeElem != null) {
|
|
|
-
|
|
|
- // Validate the authenticator mode
|
|
|
-
|
|
|
- String mode = getText(modeElem);
|
|
|
- if ( mode.equalsIgnoreCase("user"))
|
|
|
- accessMode = CifsAuthenticator.USER_MODE;
|
|
|
- else if ( mode.equalsIgnoreCase("share"))
|
|
|
- accessMode = CifsAuthenticator.SHARE_MODE;
|
|
|
- else
|
|
|
- throw new InvalidConfigurationException("Invalid authentication mode, must be USER or SHARE");
|
|
|
- }
|
|
|
-
|
|
|
- // Get the allow guest setting
|
|
|
-
|
|
|
- Element allowGuest = findChildNode("allowGuest", authElem.getChildNodes());
|
|
|
-
|
|
|
- // Get the parameters for the authenticator class
|
|
|
-
|
|
|
- ConfigElement params = buildConfigElement(authElem);
|
|
|
- cifsConfig.setAuthenticator(authClass, params, accessMode, allowGuest != null ? true : false);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Process the host XML element
|
|
|
- *
|
|
|
- * @param host Element 2param cifsConfig CIFSConfigSection
|
|
|
- * @exception InvalidConfigurationException
|
|
|
- */
|
|
|
- protected final void procHostElement(Element host, CIFSConfigSection cifsConfig)
|
|
|
- throws InvalidConfigurationException {
|
|
|
-
|
|
|
- // Check if the host element is valid
|
|
|
-
|
|
|
- if ( host == null)
|
|
|
- throw new InvalidConfigurationException("Host section must be specified");
|
|
|
-
|
|
|
- // Get the host name attribute
|
|
|
-
|
|
|
- String attr = host.getAttribute("name");
|
|
|
- if ( attr == null || attr.length() == 0)
|
|
|
- throw new InvalidConfigurationException("Host name not specified or invalid");
|
|
|
- cifsConfig.setServerName(attr.toUpperCase());
|
|
|
-
|
|
|
- // If the global server name has not been set then use the CIFS server name
|
|
|
-
|
|
|
- if ( getServerName() == null)
|
|
|
- setServerName(cifsConfig.getServerName());
|
|
|
-
|
|
|
- // Get the domain name
|
|
|
-
|
|
|
- attr = host.getAttribute("domain");
|
|
|
- if ( attr != null && attr.length() > 0)
|
|
|
- cifsConfig.setDomainName(attr.toUpperCase());
|
|
|
-
|
|
|
- // Get the enabled SMB dialects
|
|
|
-
|
|
|
- Element elem = findChildNode("smbdialects", host.getChildNodes());
|
|
|
- if ( elem != null) {
|
|
|
-
|
|
|
- // Clear all configured SMB dialects
|
|
|
-
|
|
|
- DialectSelector diaSel = cifsConfig.getEnabledDialects();
|
|
|
- diaSel.ClearAll();
|
|
|
-
|
|
|
- // Parse the SMB dilaects list
|
|
|
-
|
|
|
- StringTokenizer token = new StringTokenizer(getText(elem), ",");
|
|
|
-
|
|
|
- while (token.hasMoreTokens()) {
|
|
|
-
|
|
|
- // Get the current SMB dialect token
|
|
|
-
|
|
|
- String dia = token.nextToken().trim();
|
|
|
-
|
|
|
- // Determine the dialect to be enabled
|
|
|
-
|
|
|
- if ( dia.equalsIgnoreCase("CORE")) {
|
|
|
-
|
|
|
- // Enable core dialects
|
|
|
-
|
|
|
- diaSel.AddDialect(Dialect.Core);
|
|
|
- diaSel.AddDialect(Dialect.CorePlus);
|
|
|
- }
|
|
|
- else if ( dia.equalsIgnoreCase("LANMAN")) {
|
|
|
-
|
|
|
- // Enable the LanMAn dialects
|
|
|
-
|
|
|
- diaSel.AddDialect(Dialect.DOSLanMan1);
|
|
|
- diaSel.AddDialect(Dialect.DOSLanMan2);
|
|
|
- diaSel.AddDialect(Dialect.LanMan1);
|
|
|
- diaSel.AddDialect(Dialect.LanMan2);
|
|
|
- diaSel.AddDialect(Dialect.LanMan2_1);
|
|
|
- }
|
|
|
- else if ( dia.equalsIgnoreCase("NT")) {
|
|
|
-
|
|
|
- // Enable the NT dialect
|
|
|
-
|
|
|
- diaSel.AddDialect(Dialect.NT);
|
|
|
- }
|
|
|
- else
|
|
|
- throw new InvalidConfigurationException("Invalid SMB dialect, " + dia);
|
|
|
- }
|
|
|
-
|
|
|
- // Set the enabled server SMB dialects
|
|
|
-
|
|
|
- cifsConfig.setEnabledDialects(diaSel);
|
|
|
- }
|
|
|
-
|
|
|
- // Check for a server comment
|
|
|
-
|
|
|
- elem = findChildNode("comment", host.getChildNodes());
|
|
|
- if ( elem != null)
|
|
|
- cifsConfig.setComment(getText(elem));
|
|
|
-
|
|
|
- // Check for a bind address
|
|
|
-
|
|
|
- elem = findChildNode("bindto", host.getChildNodes());
|
|
|
- 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 {
|
|
|
-
|
|
|
- // Validate the bind address
|
|
|
-
|
|
|
- String bindText = getText(elem);
|
|
|
-
|
|
|
- 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 InvalidConfigurationException(ex.toString());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Check if the host announcer should be enabled
|
|
|
-
|
|
|
- elem = findChildNode("hostAnnounce", host.getChildNodes());
|
|
|
- if ( elem != null) {
|
|
|
-
|
|
|
- // Check for an announcement interval
|
|
|
-
|
|
|
- attr = elem.getAttribute("interval");
|
|
|
- if ( attr != null && attr.length() > 0) {
|
|
|
- try {
|
|
|
- cifsConfig.setHostAnnounceInterval(Integer.parseInt(attr));
|
|
|
- }
|
|
|
- catch (NumberFormatException ex) {
|
|
|
- throw new InvalidConfigurationException("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 InvalidConfigurationException("Domain name must be specified if host announcement is enabled");
|
|
|
-
|
|
|
- // Enable host announcement
|
|
|
-
|
|
|
- cifsConfig.setHostAnnouncer(true);
|
|
|
- }
|
|
|
-
|
|
|
- // Check for a host announcer port
|
|
|
-
|
|
|
- elem = findChildNode("HostAnnouncerPort", host.getChildNodes());
|
|
|
- if ( elem != null) {
|
|
|
- try {
|
|
|
- cifsConfig.setHostAnnouncerPort(Integer.parseInt(getText(elem)));
|
|
|
- if ( cifsConfig.getHostAnnouncerPort() <= 0 || cifsConfig.getHostAnnouncerPort() >= 65535)
|
|
|
- throw new InvalidConfigurationException("Host announcer port out of valid range");
|
|
|
- }
|
|
|
- catch (NumberFormatException ex) {
|
|
|
- throw new InvalidConfigurationException("Invalid host announcer port");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Check if NetBIOS SMB is enabled
|
|
|
-
|
|
|
- elem = findChildNode("netBIOSSMB", host.getChildNodes());
|
|
|
- if ( elem != null) {
|
|
|
-
|
|
|
- // Check if NetBIOS over TCP/IP is enabled for the current platform
|
|
|
-
|
|
|
- boolean platformOK = false;
|
|
|
-
|
|
|
- if ( elem.hasAttribute("platforms")) {
|
|
|
-
|
|
|
- // Get the list of platforms
|
|
|
-
|
|
|
- String platformsStr = elem.getAttribute("platforms");
|
|
|
-
|
|
|
- // Parse the list of platforms that NetBIOS over TCP/IP is to be enabled for and
|
|
|
- // check if the current platform is included
|
|
|
-
|
|
|
- List<Platform.Type> enabledPlatforms = parsePlatformString(platformsStr);
|
|
|
- if ( enabledPlatforms.contains(getPlatformType()))
|
|
|
- platformOK = true;
|
|
|
- }
|
|
|
- else {
|
|
|
- // No restriction on platforms
|
|
|
-
|
|
|
- platformOK = true;
|
|
|
- }
|
|
|
-
|
|
|
- // Enable the NetBIOS SMB support
|
|
|
-
|
|
|
- cifsConfig.setNetBIOSSMB(platformOK);
|
|
|
-
|
|
|
- // Only parse the other settings if NetBIOS based SMB is enabled for the current
|
|
|
- // platform
|
|
|
-
|
|
|
- if ( platformOK) {
|
|
|
-
|
|
|
- // Check for the session port
|
|
|
-
|
|
|
- attr = elem.getAttribute("sessionPort");
|
|
|
- if ( attr != null && attr.length() > 0) {
|
|
|
- try {
|
|
|
- cifsConfig.setSessionPort(Integer.parseInt(attr));
|
|
|
- if ( cifsConfig.getSessionPort() <= 0 || cifsConfig.getSessionPort() >= 65535)
|
|
|
- throw new InvalidConfigurationException("NetBIOS SMB session port out of valid range");
|
|
|
- }
|
|
|
- catch (NumberFormatException ex) {
|
|
|
- throw new InvalidConfigurationException("Invalid NetBIOS SMB session port");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Check for the datagram port
|
|
|
-
|
|
|
- attr = elem.getAttribute("datagramPort");
|
|
|
- if ( attr != null && attr.length() > 0) {
|
|
|
- try {
|
|
|
- cifsConfig.setDatagramPort(Integer.parseInt(attr));
|
|
|
- if ( cifsConfig.getDatagramPort() <= 0 || cifsConfig.getDatagramPort() >= 65535)
|
|
|
- throw new InvalidConfigurationException("NetBIOS SMB datagram port out of valid range");
|
|
|
- }
|
|
|
- catch (NumberFormatException ex) {
|
|
|
- throw new InvalidConfigurationException("Invalid NetBIOS SMB datagram port");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Check for the name server port
|
|
|
-
|
|
|
- attr = elem.getAttribute("namingPort");
|
|
|
- if ( attr != null && attr.length() > 0) {
|
|
|
- try {
|
|
|
- cifsConfig.setNameServerPort(Integer.parseInt(attr));
|
|
|
- if ( cifsConfig.getNameServerPort() <= 0 || cifsConfig.getNameServerPort() >= 65535)
|
|
|
- throw new InvalidConfigurationException("NetBIOS SMB naming port out of valid range");
|
|
|
- }
|
|
|
- catch (NumberFormatException ex) {
|
|
|
- throw new InvalidConfigurationException("Invalid NetBIOS SMB naming port");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Check for a bind address
|
|
|
-
|
|
|
- attr = elem.getAttribute("bindto");
|
|
|
- if ( attr != null && attr.length() > 0) {
|
|
|
-
|
|
|
- // 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 = findChildNode("tcpipSMB", host.getChildNodes());
|
|
|
- if ( elem != null) {
|
|
|
-
|
|
|
- // Check if native SMB is enabled for the current platform
|
|
|
-
|
|
|
- boolean platformOK = false;
|
|
|
-
|
|
|
- if ( elem.hasAttribute("platforms")) {
|
|
|
-
|
|
|
- // Get the list of platforms
|
|
|
-
|
|
|
- String platformsStr = elem.getAttribute("platforms");
|
|
|
-
|
|
|
- // Parse the list of platforms that NetBIOS over TCP/IP is to be enabled for and
|
|
|
- // check if the current platform is included
|
|
|
-
|
|
|
- List<Platform.Type> enabledPlatforms = parsePlatformString(platformsStr);
|
|
|
- if ( enabledPlatforms.contains(getPlatformType()))
|
|
|
- platformOK = true;
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- // No restriction on platforms
|
|
|
-
|
|
|
- platformOK = true;
|
|
|
- }
|
|
|
-
|
|
|
- // Enable the TCP/IP SMB support
|
|
|
-
|
|
|
- cifsConfig.setTcpipSMB(platformOK);
|
|
|
-
|
|
|
- // Check if the port has been specified
|
|
|
-
|
|
|
- attr = elem.getAttribute("port");
|
|
|
- if ( attr != null && attr.length() > 0) {
|
|
|
- try {
|
|
|
- cifsConfig.setTcpipSMBPort(Integer.parseInt(attr));
|
|
|
- if ( cifsConfig.getTcpipSMBPort() <= 0 || cifsConfig.getTcpipSMBPort() >= 65535)
|
|
|
- throw new InvalidConfigurationException("TCP/IP SMB port out of valid range");
|
|
|
- }
|
|
|
- catch (NumberFormatException ex) {
|
|
|
- throw new InvalidConfigurationException("Invalid TCP/IP SMB port");
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- // Disable TCP/IP SMB support
|
|
|
-
|
|
|
- cifsConfig.setTcpipSMB(false);
|
|
|
- }
|
|
|
-
|
|
|
- // Check that the broadcast mask has been set if TCP/IP NetBIOS and/or the host announcer is
|
|
|
- // enabled
|
|
|
-
|
|
|
- if ( cifsConfig.hasNetBIOSSMB() || cifsConfig.hasEnableAnnouncer()) {
|
|
|
-
|
|
|
- // Parse the broadcast mask
|
|
|
-
|
|
|
- elem = findChildNode("broadcast", host.getChildNodes());
|
|
|
- if ( elem != null) {
|
|
|
-
|
|
|
- // Check if the broadcast mask is a valid numeric IP address
|
|
|
-
|
|
|
- if ( IPAddress.isNumericAddress(getText(elem)) == false)
|
|
|
- throw new InvalidConfigurationException("Invalid broadcast mask, must be n.n.n.n format");
|
|
|
-
|
|
|
- // Set the network broadcast mask
|
|
|
-
|
|
|
- cifsConfig.setBroadcastMask(getText(elem));
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- // Broadcast mask not configured
|
|
|
-
|
|
|
- throw new InvalidConfigurationException("Network broadcast mask not specified");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Check if Win32 NetBIOS is enabled
|
|
|
-
|
|
|
- elem = findChildNode("Win32NetBIOS", host.getChildNodes());
|
|
|
- if ( elem != null) {
|
|
|
-
|
|
|
- // Check if the Win32 NetBIOS server name has been specified
|
|
|
-
|
|
|
- attr = elem.getAttribute("name");
|
|
|
- if ( attr != null && attr.length() > 0) {
|
|
|
-
|
|
|
- // Validate the name
|
|
|
-
|
|
|
- if ( attr.length() > 16)
|
|
|
- throw new InvalidConfigurationException("Invalid Win32 NetBIOS name, " + attr);
|
|
|
-
|
|
|
- // Set the Win32 NetBIOS file server name
|
|
|
-
|
|
|
- cifsConfig.setWin32NetBIOSName(attr);
|
|
|
- }
|
|
|
-
|
|
|
- // Check if the Win32 NetBIOS client accept name has been specified
|
|
|
-
|
|
|
- attr = elem.getAttribute("accept");
|
|
|
- if ( attr != null && attr.length() > 0) {
|
|
|
-
|
|
|
- // Validate the client accept name
|
|
|
-
|
|
|
- if ( attr.length() > 15)
|
|
|
- throw new InvalidConfigurationException("Invalid Win32 NetBIOS accept name, " + attr);
|
|
|
-
|
|
|
- // Set the client accept string
|
|
|
-
|
|
|
- cifsConfig.setWin32NetBIOSClientAccept(attr);
|
|
|
- }
|
|
|
-
|
|
|
- // Check if the Win32 NetBIOS LANA has been specified
|
|
|
-
|
|
|
- attr = elem.getAttribute("lana");
|
|
|
- if ( attr != null && attr.length() > 0) {
|
|
|
-
|
|
|
- // Check if the LANA has been specified as an IP address or adapter name
|
|
|
-
|
|
|
- int lana = -1;
|
|
|
-
|
|
|
- if ( IPAddress.isNumericAddress(attr)) {
|
|
|
-
|
|
|
- // Convert the IP address to a LANA id
|
|
|
-
|
|
|
- lana = Win32NetBIOS.getLANAForIPAddress(attr);
|
|
|
- if ( lana == -1)
|
|
|
- throw new InvalidConfigurationException("Failed to convert IP address " + attr + " to a LANA");
|
|
|
- }
|
|
|
- else if ( attr.length() > 1 && Character.isLetter(attr.charAt(0))) {
|
|
|
-
|
|
|
- // Convert the network adapter to a LANA id
|
|
|
-
|
|
|
- lana = Win32NetBIOS.getLANAForAdapterName(attr);
|
|
|
- if ( lana == -1)
|
|
|
- throw new InvalidConfigurationException("Failed to convert network adapter " + attr + " to a LANA");
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- // Validate the LANA number
|
|
|
-
|
|
|
- try {
|
|
|
- lana = Integer.parseInt(attr);
|
|
|
- }
|
|
|
- catch (NumberFormatException ex) {
|
|
|
- throw new InvalidConfigurationException("Invalid Win32 NetBIOS LANA specified");
|
|
|
- }
|
|
|
-
|
|
|
- // LANA should be in the range 0-255
|
|
|
-
|
|
|
- if ( lana < 0 || lana > 255)
|
|
|
- throw new InvalidConfigurationException("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'
|
|
|
-
|
|
|
- attr = elem.getAttribute("api");
|
|
|
-
|
|
|
- if ( attr != null && attr.length() > 0) {
|
|
|
- // Validate the API type
|
|
|
-
|
|
|
- boolean useWinsock = true;
|
|
|
-
|
|
|
- if ( attr.equalsIgnoreCase("netbios"))
|
|
|
- useWinsock = false;
|
|
|
- else if ( attr.equalsIgnoreCase("winsock") == false)
|
|
|
- throw new InvalidConfigurationException("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 as Winsock NetBIOS is
|
|
|
- // not available
|
|
|
-
|
|
|
- if ( cifsConfig.useWinsockNetBIOS() == true && X64.isWindows64()) {
|
|
|
-
|
|
|
- // Log a warning
|
|
|
-
|
|
|
- Debug.println("Using older Netbios() API code, Winsock NetBIOS not available on x64");
|
|
|
-
|
|
|
- // 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)) {
|
|
|
-
|
|
|
- // Enable Win32 NetBIOS
|
|
|
-
|
|
|
- cifsConfig.setWin32NetBIOS(true);
|
|
|
- }
|
|
|
- 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 = findChildNode("Win32Announce", host.getChildNodes());
|
|
|
- if ( elem != null) {
|
|
|
-
|
|
|
- // Check for an announcement interval
|
|
|
-
|
|
|
- attr = elem.getAttribute("interval");
|
|
|
- if ( attr != null && attr.length() > 0) {
|
|
|
- try {
|
|
|
- cifsConfig.setWin32HostAnnounceInterval(Integer.parseInt(attr));
|
|
|
- }
|
|
|
- catch (NumberFormatException ex) {
|
|
|
- throw new InvalidConfigurationException("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 InvalidConfigurationException("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 InvalidConfigurationException("NetBIOS SMB, TCP/IP SMB or Win32 NetBIOS must be enabled");
|
|
|
-
|
|
|
- // Check if server alias name(s) have been specified
|
|
|
-
|
|
|
- elem = findChildNode("alias", host.getChildNodes());
|
|
|
- if ( elem != null) {
|
|
|
-
|
|
|
- // Get the alias name list
|
|
|
-
|
|
|
- attr = elem.getAttribute("names");
|
|
|
- if ( attr == null || attr.length() == 0)
|
|
|
- throw new InvalidConfigurationException("Alias name(s) not specified");
|
|
|
-
|
|
|
- // Split the alias name list
|
|
|
-
|
|
|
- StringList names = new StringList();
|
|
|
- StringTokenizer nameTokens = new StringTokenizer(attr, ",");
|
|
|
-
|
|
|
- while (nameTokens.hasMoreTokens()) {
|
|
|
-
|
|
|
- // Get the current alias name
|
|
|
-
|
|
|
- String alias = nameTokens.nextToken().trim().toUpperCase();
|
|
|
-
|
|
|
- // Check if the name already exists in the alias list, or matches the main server
|
|
|
- // name
|
|
|
-
|
|
|
- if ( alias.equalsIgnoreCase(getServerName()))
|
|
|
- throw new InvalidConfigurationException("Alias is the same as the main server name");
|
|
|
- else if ( names.containsString(alias))
|
|
|
- throw new InvalidConfigurationException("Same alias specified twice, " + alias);
|
|
|
- else
|
|
|
- names.addString(alias);
|
|
|
- }
|
|
|
-
|
|
|
- // Set the server alias names
|
|
|
-
|
|
|
- cifsConfig.addAliasNames(names);
|
|
|
- }
|
|
|
-
|
|
|
- // Check if Macintosh extension SMBs should be enabled
|
|
|
-
|
|
|
- elem = findChildNode("macExtensions", host.getChildNodes());
|
|
|
- if ( elem != null) {
|
|
|
-
|
|
|
- // Enable Macintosh extension SMBs
|
|
|
-
|
|
|
- cifsConfig.setMacintoshExtensions(true);
|
|
|
- }
|
|
|
-
|
|
|
- // Check if WINS servers are configured
|
|
|
-
|
|
|
- elem = findChildNode("WINS", host.getChildNodes());
|
|
|
-
|
|
|
- if ( elem != null) {
|
|
|
-
|
|
|
- // Get the primary WINS server
|
|
|
-
|
|
|
- Element winsSrv = findChildNode("primary", elem.getChildNodes());
|
|
|
- if ( winsSrv == null)
|
|
|
- throw new InvalidConfigurationException("No primary WINS server configured");
|
|
|
-
|
|
|
- // Validate the WINS server address
|
|
|
-
|
|
|
- InetAddress primaryWINS = null;
|
|
|
-
|
|
|
- try {
|
|
|
- primaryWINS = InetAddress.getByName(getText(winsSrv));
|
|
|
- }
|
|
|
- catch (UnknownHostException ex) {
|
|
|
- throw new InvalidConfigurationException("Invalid primary WINS server address, " + winsSrv.getNodeValue());
|
|
|
- }
|
|
|
-
|
|
|
- // Check if a secondary WINS server has been specified
|
|
|
-
|
|
|
- winsSrv = findChildNode("secondary", elem.getChildNodes());
|
|
|
- InetAddress secondaryWINS = null;
|
|
|
-
|
|
|
- if ( winsSrv != null) {
|
|
|
-
|
|
|
- // Validate the secondary WINS server address
|
|
|
-
|
|
|
- try {
|
|
|
- secondaryWINS = InetAddress.getByName(getText(winsSrv));
|
|
|
- }
|
|
|
- catch (UnknownHostException ex) {
|
|
|
- throw new InvalidConfigurationException("Invalid secondary WINS server address, " + winsSrv.getNodeValue());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Set the WINS server address(es)
|
|
|
-
|
|
|
- cifsConfig.setPrimaryWINSServer(primaryWINS);
|
|
|
- if ( secondaryWINS != null)
|
|
|
- cifsConfig.setSecondaryWINSServer(secondaryWINS);
|
|
|
- }
|
|
|
-
|
|
|
- // Check if a session timeout is configured
|
|
|
-
|
|
|
- elem = findChildNode("sessionTimeout", host.getChildNodes());
|
|
|
- if ( elem != null) {
|
|
|
-
|
|
|
- // Validate the session timeout value
|
|
|
-
|
|
|
- String sessTmo = getText( elem);
|
|
|
- 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 InvalidConfigurationException("Session timeout out of range (0 - " + MaxSessionTimeout + ")");
|
|
|
-
|
|
|
- // Convert the session timeout to milliseconds
|
|
|
-
|
|
|
- cifsConfig.setSocketTimeout( tmo * 1000);
|
|
|
- }
|
|
|
- catch (NumberFormatException ex) {
|
|
|
- throw new InvalidConfigurationException("Invalid session timeout value, " + sessTmo);
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- throw new InvalidConfigurationException("Session timeout value not specified");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Process the debug XML element
|
|
|
- *
|
|
|
- * @param debug Element
|
|
|
- * @exception InvalidConfigurationException
|
|
|
- */
|
|
|
- protected final void procDebugElement(Element debug)
|
|
|
- throws InvalidConfigurationException {
|
|
|
-
|
|
|
- // Check if the debug section has been specified
|
|
|
-
|
|
|
- if ( debug == null)
|
|
|
- return;
|
|
|
-
|
|
|
- // Create the debug configuration section
|
|
|
-
|
|
|
- DebugConfigSection debugConfig = new DebugConfigSection(this);
|
|
|
-
|
|
|
- // Get the debug output class and parameters
|
|
|
-
|
|
|
- Element elem = findChildNode("output", debug.getChildNodes());
|
|
|
- if ( elem == null)
|
|
|
- throw new InvalidConfigurationException("Output class must be specified to enable debug output");
|
|
|
-
|
|
|
- // Get the debug output class
|
|
|
-
|
|
|
- Element debugClass = findChildNode("class", elem.getChildNodes());
|
|
|
- if ( debugClass == null)
|
|
|
- throw new InvalidConfigurationException("Class must be specified for debug output");
|
|
|
-
|
|
|
- // Get the parameters for the debug class
|
|
|
-
|
|
|
- ConfigElement params = buildConfigElement(elem);
|
|
|
- debugConfig.setDebug(getText(debugClass), params);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Process the shares XML element
|
|
|
- *
|
|
|
- * @param shares Element
|
|
|
- * @exception InvalidConfigurationException
|
|
|
- */
|
|
|
- protected final void procSharesElement(Element shares)
|
|
|
- throws InvalidConfigurationException {
|
|
|
-
|
|
|
- // Check if the shares element is valid
|
|
|
-
|
|
|
- if ( shares == null)
|
|
|
- return;
|
|
|
-
|
|
|
- // Create the filesystems configuration section
|
|
|
-
|
|
|
- FilesystemsConfigSection filesysConfig = new FilesystemsConfigSection(this);
|
|
|
-
|
|
|
- // Iterate the child elements
|
|
|
-
|
|
|
- NodeList children = shares.getChildNodes();
|
|
|
-
|
|
|
- if ( children != null) {
|
|
|
-
|
|
|
- // Iterate the child elements and process the disk/print share elements
|
|
|
-
|
|
|
- for (int i = 0; i < children.getLength(); i++) {
|
|
|
-
|
|
|
- // Get the current child node
|
|
|
-
|
|
|
- Node node = children.item(i);
|
|
|
-
|
|
|
- if ( node.getNodeType() == ELEMENT_TYPE) {
|
|
|
-
|
|
|
- // Get the next element from the list
|
|
|
-
|
|
|
- Element child = (Element) node;
|
|
|
-
|
|
|
- // Check if this is a disk or print share element
|
|
|
-
|
|
|
- if ( child.getNodeName().equalsIgnoreCase("diskshare"))
|
|
|
- addDiskShare(child, filesysConfig);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Process the security XML element
|
|
|
- *
|
|
|
- * @param security Element
|
|
|
- * @exception InvalidConfigurationException
|
|
|
- */
|
|
|
- protected final void procSecurityElement(Element security)
|
|
|
- throws InvalidConfigurationException {
|
|
|
-
|
|
|
- // Check if the security element is valid
|
|
|
-
|
|
|
- if ( security == null)
|
|
|
- return;
|
|
|
-
|
|
|
- // Create the security configuration section
|
|
|
-
|
|
|
- SecurityConfigSection secConfig = new SecurityConfigSection(this);
|
|
|
-
|
|
|
- // Check if an access control manager has been specified
|
|
|
-
|
|
|
- Element aclElem = findChildNode("accessControlManager", security.getChildNodes());
|
|
|
- if ( aclElem != null) {
|
|
|
-
|
|
|
- // Get the access control manager class and security mode
|
|
|
-
|
|
|
- Element classElem = findChildNode("class", aclElem.getChildNodes());
|
|
|
- if ( classElem == null)
|
|
|
- throw new InvalidConfigurationException("Access control manager class not specified");
|
|
|
-
|
|
|
- // Get the parameters for the access control manager class
|
|
|
-
|
|
|
- ConfigElement params = buildConfigElement(aclElem);
|
|
|
- secConfig.setAccessControlManager(getText(classElem), params);
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- // Use the default access control manager
|
|
|
-
|
|
|
- secConfig.setAccessControlManager("org.alfresco.jlan.server.auth.acl.DefaultAccessControlManager",
|
|
|
- new GenericConfigElement("aclManager"));
|
|
|
- }
|
|
|
-
|
|
|
- // Check if global access controls have been specified
|
|
|
-
|
|
|
- Element globalACLs = findChildNode("globalAccessControl", security.getChildNodes());
|
|
|
- if ( globalACLs != null) {
|
|
|
-
|
|
|
- // Parse the access control list
|
|
|
-
|
|
|
- AccessControlList acls = procAccessControlElement(globalACLs, secConfig);
|
|
|
- if ( acls != null)
|
|
|
- secConfig.setGlobalAccessControls(acls);
|
|
|
- }
|
|
|
-
|
|
|
- // Check if a JCE provider class has been specified
|
|
|
-
|
|
|
- Element jceElem = findChildNode("JCEProvider", security.getChildNodes());
|
|
|
- if ( jceElem != null) {
|
|
|
-
|
|
|
- // Set the JCE provider
|
|
|
-
|
|
|
- secConfig.setJCEProvider(getText(jceElem));
|
|
|
- }
|
|
|
-
|
|
|
- // Add the users
|
|
|
-
|
|
|
- Element usersElem = findChildNode("users", security.getChildNodes());
|
|
|
- if ( usersElem != null) {
|
|
|
-
|
|
|
- // Get the list of user elements
|
|
|
-
|
|
|
- NodeList userList = usersElem.getChildNodes();
|
|
|
-
|
|
|
- for (int i = 0; i < userList.getLength(); i++) {
|
|
|
-
|
|
|
- // Get the current user node
|
|
|
-
|
|
|
- Node node = userList.item(i);
|
|
|
-
|
|
|
- if ( node.getNodeType() == ELEMENT_TYPE) {
|
|
|
- Element userElem = (Element) node;
|
|
|
- addUser(userElem, secConfig);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Check if a share mapper has been specified
|
|
|
-
|
|
|
- Element mapper = findChildNode("shareMapper", security.getChildNodes());
|
|
|
-
|
|
|
- if ( mapper != null) {
|
|
|
-
|
|
|
- // Get the share mapper class
|
|
|
-
|
|
|
- Element classElem = findChildNode("class", mapper.getChildNodes());
|
|
|
- if ( classElem == null)
|
|
|
- throw new InvalidConfigurationException("Share mapper class not specified");
|
|
|
-
|
|
|
- // Get the parameters for the share mapper class
|
|
|
-
|
|
|
- ConfigElement params = buildConfigElement(mapper);
|
|
|
- secConfig.setShareMapper(getText(classElem), params);
|
|
|
- }
|
|
|
-
|
|
|
- // Check if the users interface has been specified
|
|
|
-
|
|
|
- Element usersIface = findChildNode("usersInterface", security.getChildNodes());
|
|
|
-
|
|
|
- if ( usersIface != null) {
|
|
|
-
|
|
|
- // Get the users interface class
|
|
|
-
|
|
|
- Element classElem = findChildNode("class", usersIface.getChildNodes());
|
|
|
- if ( classElem == null)
|
|
|
- throw new InvalidConfigurationException("Users interface class not specified");
|
|
|
-
|
|
|
- // Get the parameters for the users interface class
|
|
|
-
|
|
|
- ConfigElement params = buildConfigElement(usersIface);
|
|
|
- secConfig.setUsersInterface(getText(classElem), params);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Process the drive mappings XML element
|
|
|
- *
|
|
|
- * @param mappings Element
|
|
|
- * @exception InvalidConfigurationException
|
|
|
- */
|
|
|
- protected final void procDriveMappingsElement(Element mappings)
|
|
|
- throws InvalidConfigurationException {
|
|
|
-
|
|
|
- // Check if the drive mappings element is valid
|
|
|
-
|
|
|
- if ( mappings == null)
|
|
|
- return;
|
|
|
-
|
|
|
- // Create the drive mappings configuration section
|
|
|
-
|
|
|
- DriveMappingsConfigSection mapConfig = new DriveMappingsConfigSection(this);
|
|
|
-
|
|
|
- // Parse each drive mapping element
|
|
|
-
|
|
|
- NodeList mapElems = mappings.getChildNodes();
|
|
|
- DriveMappingList mapList = null;
|
|
|
-
|
|
|
- if ( mapElems != null && mapElems.getLength() > 0) {
|
|
|
-
|
|
|
- // Create the mapped drive list
|
|
|
-
|
|
|
- mapList = new DriveMappingList();
|
|
|
-
|
|
|
- // Access the CIFS server configuration
|
|
|
-
|
|
|
- CIFSConfigSection cifsConfig = (CIFSConfigSection) getConfigSection(CIFSConfigSection.SectionName);
|
|
|
-
|
|
|
- // Get a list of the available shares
|
|
|
-
|
|
|
- SecurityConfigSection secConfig = (SecurityConfigSection) getConfigSection(SecurityConfigSection.SectionName);
|
|
|
- SharedDeviceList shareList = secConfig.getShareMapper().getShareList(getServerName(), null, false);
|
|
|
-
|
|
|
- // Process each drive mapping element
|
|
|
-
|
|
|
- for (int i = 0; i < mapElems.getLength(); i++) {
|
|
|
-
|
|
|
- // Get the current mapped drive details
|
|
|
-
|
|
|
- Node node = mapElems.item(i);
|
|
|
-
|
|
|
- if ( node.getNodeType() == ELEMENT_TYPE) {
|
|
|
-
|
|
|
- // Access the mapped drive element
|
|
|
-
|
|
|
- Element elem = (Element) node;
|
|
|
-
|
|
|
- if ( elem.getNodeName().equals("mapDrive")) {
|
|
|
-
|
|
|
- // Get the mapped drive local drive and remote path details
|
|
|
-
|
|
|
- String localPath = elem.getAttribute("drive").toUpperCase();
|
|
|
- String shareName = elem.getAttribute("share");
|
|
|
-
|
|
|
- // Check the local path string
|
|
|
-
|
|
|
- if ( localPath.length() != 2)
|
|
|
- throw new InvalidConfigurationException("Invalid local drive specified, " + localPath);
|
|
|
-
|
|
|
- if ( localPath.charAt(1) != ':' || _driveLetters.indexOf(localPath.charAt(0)) == -1)
|
|
|
- throw new InvalidConfigurationException("Invalid local drive specified, " + localPath);
|
|
|
-
|
|
|
- // Check if the share name is a valid local disk share
|
|
|
-
|
|
|
- if ( shareName.length() == 0)
|
|
|
- throw new InvalidConfigurationException("Empty share name for mapped drive, " + localPath);
|
|
|
-
|
|
|
- if ( shareList.findShare(shareName, ShareType.DISK, true) == null)
|
|
|
- throw new InvalidConfigurationException("Mapped drive share " + shareName + " does not exist");
|
|
|
-
|
|
|
- // Get the username/password to be used to connect the mapped drive
|
|
|
-
|
|
|
- String userName = null;
|
|
|
- String password = null;
|
|
|
-
|
|
|
- if ( elem.hasAttribute("username"))
|
|
|
- userName = elem.getAttribute("username");
|
|
|
-
|
|
|
- if ( elem.hasAttribute("password"))
|
|
|
- password = elem.getAttribute("password");
|
|
|
-
|
|
|
- // Get the options flags
|
|
|
-
|
|
|
- boolean interact = false;
|
|
|
- boolean prompt = false;
|
|
|
-
|
|
|
- if ( elem.hasAttribute("interactive")) {
|
|
|
- if ( elem.getAttribute("interactive").equalsIgnoreCase("YES"))
|
|
|
- interact = true;
|
|
|
- }
|
|
|
-
|
|
|
- if ( elem.hasAttribute("prompt")) {
|
|
|
- if ( elem.getAttribute("prompt").equalsIgnoreCase("YES"))
|
|
|
- prompt = true;
|
|
|
- }
|
|
|
-
|
|
|
- // Build the remote path
|
|
|
-
|
|
|
- StringBuffer remPath = new StringBuffer();
|
|
|
- remPath.append("\\\\");
|
|
|
-
|
|
|
- if ( cifsConfig.hasWin32NetBIOS() && cifsConfig.getWin32ServerName() != null)
|
|
|
- remPath.append(cifsConfig.getWin32ServerName());
|
|
|
- else
|
|
|
- remPath.append(getServerName());
|
|
|
- remPath.append("\\");
|
|
|
- remPath.append(shareName.toUpperCase());
|
|
|
-
|
|
|
- // Add a drive mapping
|
|
|
-
|
|
|
- mapList.addMapping(new DriveMapping(localPath, remPath.toString(), userName, password, interact, prompt));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Set the mapped drive list
|
|
|
-
|
|
|
- mapConfig.setMappedDrives(mapList);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Process an access control sub-section and return the access control list
|
|
|
- *
|
|
|
- * @param acl Element
|
|
|
- * @param secConfig SecutiryConfigSection
|
|
|
- * @throws InvalidConfigurationException
|
|
|
- */
|
|
|
- protected final AccessControlList procAccessControlElement(Element acl, SecurityConfigSection secConfig)
|
|
|
- throws InvalidConfigurationException {
|
|
|
-
|
|
|
- // Check if there is an access control manager configured
|
|
|
-
|
|
|
- if ( secConfig.getAccessControlManager() == null)
|
|
|
- throw new InvalidConfigurationException("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 = acl.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 InvalidConfigurationException("Default access level error, " + ex.toString());
|
|
|
- }
|
|
|
- catch (ACLParseException ex) {
|
|
|
- throw new InvalidConfigurationException("Default access level error, " + ex.toString());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Parse each access control element and create the required access control
|
|
|
-
|
|
|
- NodeList aclElems = acl.getChildNodes();
|
|
|
-
|
|
|
- if ( aclElems != null && aclElems.getLength() > 0) {
|
|
|
-
|
|
|
- // Create the access controls
|
|
|
-
|
|
|
- GenericConfigElement params = null;
|
|
|
- String type = null;
|
|
|
-
|
|
|
- for (int i = 0; i < aclElems.getLength(); i++) {
|
|
|
-
|
|
|
- // Get the current ACL details
|
|
|
-
|
|
|
- Node node = aclElems.item(i);
|
|
|
-
|
|
|
- if ( node.getNodeType() == ELEMENT_TYPE) {
|
|
|
-
|
|
|
- // Access the ACL element
|
|
|
-
|
|
|
- Element elem = (Element) node;
|
|
|
- type = elem.getNodeName();
|
|
|
-
|
|
|
- // Create a new config element
|
|
|
-
|
|
|
- params = new GenericConfigElement("acl");
|
|
|
-
|
|
|
- // Convert the element attributes into a list of name value pairs
|
|
|
-
|
|
|
- NamedNodeMap attrs = elem.getAttributes();
|
|
|
-
|
|
|
- if ( attrs == null || attrs.getLength() == 0)
|
|
|
- throw new InvalidConfigurationException("Missing attribute(s) for access control " + type);
|
|
|
-
|
|
|
- for (int j = 0; j < attrs.getLength(); j++) {
|
|
|
-
|
|
|
- // Create a name/value pair from the current attribute and add to the
|
|
|
- // parameter list
|
|
|
-
|
|
|
- Node attr = attrs.item(j);
|
|
|
- params.addAttribute( attr.getNodeName(), attr.getNodeValue());
|
|
|
- }
|
|
|
-
|
|
|
- try {
|
|
|
-
|
|
|
- // Create the access control and add to the list
|
|
|
-
|
|
|
- acls.addControl(secConfig.getAccessControlManager().createAccessControl(type, params));
|
|
|
- }
|
|
|
- catch (InvalidACLTypeException ex) {
|
|
|
- throw new InvalidConfigurationException("Invalid access control type - " + type);
|
|
|
- }
|
|
|
- catch (ACLParseException ex) {
|
|
|
- throw new InvalidConfigurationException("Access control parse error (" + type + "), " + ex.toString());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 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 InvalidConfigurationException("Empty access control list and default access 'None' not allowed");
|
|
|
-
|
|
|
- // Return the access control list
|
|
|
-
|
|
|
- return acls;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Add a user
|
|
|
- *
|
|
|
- * @param user Element
|
|
|
- * @param secConfig SecurityConfigSection
|
|
|
- * @exception InvalidConfigurationException
|
|
|
- */
|
|
|
- protected final void addUser(Element user, SecurityConfigSection secConfig)
|
|
|
- throws InvalidConfigurationException {
|
|
|
-
|
|
|
- // Get the username
|
|
|
-
|
|
|
- String attr = user.getAttribute("name");
|
|
|
- if ( attr == null || attr.length() == 0)
|
|
|
- throw new InvalidConfigurationException("User name not specified, or zero length");
|
|
|
-
|
|
|
- // Check if the user already exists
|
|
|
-
|
|
|
- String userName = attr;
|
|
|
-
|
|
|
- if ( secConfig.hasUserAccounts() && secConfig.getUserAccounts().findUser(userName) != null)
|
|
|
- throw new InvalidConfigurationException("User " + userName + " already defined");
|
|
|
-
|
|
|
- // Get the MD4 hashed password
|
|
|
-
|
|
|
- byte[] md4 = null;
|
|
|
- String password = null;
|
|
|
-
|
|
|
- Element elem = findChildNode("md4", user.getChildNodes());
|
|
|
- if ( elem != null) {
|
|
|
-
|
|
|
- // Get the MD4 hashed password string
|
|
|
-
|
|
|
- String md4Str = getText(elem);
|
|
|
- if ( md4Str == null || md4Str.length() != 32)
|
|
|
- throw new InvalidConfigurationException("Invalid MD4 hashed password for user " + userName);
|
|
|
-
|
|
|
- // Decode the MD4 string
|
|
|
-
|
|
|
- md4 = new byte[16];
|
|
|
- for (int i = 0; i < 16; i++) {
|
|
|
-
|
|
|
- // Get a hex pair and convert
|
|
|
-
|
|
|
- String hexPair = md4Str.substring(i * 2, (i * 2) + 2);
|
|
|
- md4[i] = (byte) Integer.parseInt(hexPair, 16);
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- // Get the password for the account
|
|
|
-
|
|
|
- elem = findChildNode("password", user.getChildNodes());
|
|
|
- if ( elem == null)
|
|
|
- throw new InvalidConfigurationException("No password specified for user " + userName);
|
|
|
-
|
|
|
- // Get the plaintext password
|
|
|
-
|
|
|
- password = getText(elem);
|
|
|
- }
|
|
|
-
|
|
|
- // Create the user account
|
|
|
-
|
|
|
- UserAccount userAcc = new UserAccount(userName, password);
|
|
|
- userAcc.setMD4Password(md4);
|
|
|
-
|
|
|
- // Check if the user in an administrator
|
|
|
-
|
|
|
- elem = findChildNode("administrator", user.getChildNodes());
|
|
|
- if ( elem != null)
|
|
|
- userAcc.setAdministrator(true);
|
|
|
-
|
|
|
- // Get the real user name and comment
|
|
|
-
|
|
|
- elem = findChildNode("realname", user.getChildNodes());
|
|
|
- if ( elem != null)
|
|
|
- userAcc.setRealName(getText(elem));
|
|
|
-
|
|
|
- elem = findChildNode("comment", user.getChildNodes());
|
|
|
- if ( elem != null)
|
|
|
- userAcc.setComment(getText(elem));
|
|
|
-
|
|
|
- // Get the home directory
|
|
|
-
|
|
|
- elem = findChildNode("home", user.getChildNodes());
|
|
|
- if ( elem != null)
|
|
|
- userAcc.setHomeDirectory(getText(elem));
|
|
|
-
|
|
|
- // Add the user account
|
|
|
-
|
|
|
- UserAccountList accList = secConfig.getUserAccounts();
|
|
|
- if ( accList == null)
|
|
|
- secConfig.setUserAccounts(new UserAccountList());
|
|
|
- secConfig.getUserAccounts().addUser(userAcc);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Add a disk share
|
|
|
- *
|
|
|
- * @param disk Element 2param filesysConfig FilesystemConfigSection
|
|
|
- * @exception InvalidConfigurationException
|
|
|
- */
|
|
|
- protected final void addDiskShare(Element disk, FilesystemsConfigSection filesysConfig)
|
|
|
- throws InvalidConfigurationException {
|
|
|
-
|
|
|
- // Get the share name and comment attributes
|
|
|
-
|
|
|
- String attr = disk.getAttribute("name");
|
|
|
- if ( attr == null || attr.length() == 0)
|
|
|
- throw new InvalidConfigurationException("Disk share name must be specified");
|
|
|
-
|
|
|
- String name = attr;
|
|
|
- String comment = null;
|
|
|
-
|
|
|
- attr = disk.getAttribute("comment");
|
|
|
- if ( attr != null && attr.length() > 0)
|
|
|
- comment = attr;
|
|
|
-
|
|
|
- // Get the disk driver details
|
|
|
-
|
|
|
- Element driverElem = findChildNode("driver", disk.getChildNodes());
|
|
|
- if ( driverElem == null)
|
|
|
- throw new InvalidConfigurationException("No driver specified for disk share " + name);
|
|
|
-
|
|
|
- Element classElem = findChildNode("class", driverElem.getChildNodes());
|
|
|
- if ( classElem == null || getText(classElem).length() == 0)
|
|
|
- throw new InvalidConfigurationException("No driver class specified for disk share " + name);
|
|
|
-
|
|
|
- // Get the security configuration section
|
|
|
-
|
|
|
- SecurityConfigSection secConfig = (SecurityConfigSection) getConfigSection(SecurityConfigSection.SectionName);
|
|
|
-
|
|
|
- // Check if an access control list has been specified
|
|
|
-
|
|
|
- AccessControlList acls = null;
|
|
|
- Element aclElem = findChildNode("accessControl", disk.getChildNodes());
|
|
|
-
|
|
|
- if ( aclElem != null) {
|
|
|
-
|
|
|
- // Parse the access control list
|
|
|
-
|
|
|
- acls = procAccessControlElement(aclElem, secConfig);
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- // Use the global access control list for this disk share
|
|
|
-
|
|
|
- acls = secConfig.getGlobalAccessControls();
|
|
|
- }
|
|
|
-
|
|
|
- // Get the parameters for the driver
|
|
|
-
|
|
|
- ConfigElement params = buildConfigElement(driverElem);
|
|
|
-
|
|
|
- // Check if change notification should be disabled for this device
|
|
|
-
|
|
|
- boolean changeNotify = findChildNode("disableChangeNotification", disk.getChildNodes()) != null ? false : true;
|
|
|
-
|
|
|
- // Check if the volume information has been specified
|
|
|
-
|
|
|
- Element volElem = findChildNode("volume", disk.getChildNodes());
|
|
|
- VolumeInfo volInfo = null;
|
|
|
-
|
|
|
- if ( volElem != null) {
|
|
|
-
|
|
|
- // Create the volume information
|
|
|
-
|
|
|
- volInfo = new VolumeInfo("");
|
|
|
-
|
|
|
- // Get the volume label
|
|
|
-
|
|
|
- attr = volElem.getAttribute("label");
|
|
|
- if ( attr != null && attr.length() > 0)
|
|
|
- volInfo.setVolumeLabel(attr);
|
|
|
-
|
|
|
- // Get the serial number
|
|
|
-
|
|
|
- attr = volElem.getAttribute("serial");
|
|
|
- if ( attr != null && attr.length() > 0) {
|
|
|
- try {
|
|
|
- volInfo.setSerialNumber(Integer.parseInt(attr));
|
|
|
- }
|
|
|
- catch (NumberFormatException ex) {
|
|
|
- throw new InvalidConfigurationException("Volume serial number invalid, " + attr);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Get the creation date/time
|
|
|
-
|
|
|
- attr = volElem.getAttribute("created");
|
|
|
- if ( attr != null && attr.length() > 0) {
|
|
|
- try {
|
|
|
- volInfo.setCreationDateTime(m_dateFmt.parse(attr));
|
|
|
- }
|
|
|
- catch (ParseException ex) {
|
|
|
- throw new InvalidConfigurationException("Volume creation date/time invalid, " + attr);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- // Create volume information using the share name
|
|
|
-
|
|
|
- volInfo = new VolumeInfo(name, (int) System.currentTimeMillis(), new Date(System.currentTimeMillis()));
|
|
|
- }
|
|
|
-
|
|
|
- // Check if the disk sizing information has been specified
|
|
|
-
|
|
|
- SrvDiskInfo diskInfo = null;
|
|
|
- Element sizeElem = findChildNode("size", disk.getChildNodes());
|
|
|
-
|
|
|
- if ( sizeElem != null) {
|
|
|
-
|
|
|
- // Get the total disk size in bytes
|
|
|
-
|
|
|
- long totSize = -1L;
|
|
|
- long freeSize = 0;
|
|
|
-
|
|
|
- attr = sizeElem.getAttribute("totalSize");
|
|
|
- if ( attr != null && attr.length() > 0)
|
|
|
- totSize = MemorySize.getByteValue(attr);
|
|
|
-
|
|
|
- if ( totSize == -1L)
|
|
|
- throw new InvalidConfigurationException("Total disk size invalid or not specified");
|
|
|
-
|
|
|
- // Get the free size in bytes
|
|
|
-
|
|
|
- attr = sizeElem.getAttribute("freeSize");
|
|
|
- if ( attr != null && attr.length() > 0)
|
|
|
- freeSize = MemorySize.getByteValue(attr);
|
|
|
- else
|
|
|
- freeSize = (totSize / 10L) * 9L;
|
|
|
-
|
|
|
- if ( freeSize == -1L)
|
|
|
- throw new InvalidConfigurationException("Free disk size invalid or not specified");
|
|
|
-
|
|
|
- // Get the block size and blocks per unit values, if specified
|
|
|
-
|
|
|
- long blockSize = 512L;
|
|
|
- long blocksPerUnit = 64L; // 32Kb units
|
|
|
-
|
|
|
- attr = sizeElem.getAttribute("blockSize");
|
|
|
- if ( attr != null && attr.length() > 0) {
|
|
|
- try {
|
|
|
- blockSize = Long.parseLong(attr);
|
|
|
-
|
|
|
- // Check for a multiple of 512 bytes
|
|
|
-
|
|
|
- if ( blockSize <= 0 || blockSize % 512 != 0)
|
|
|
- throw new InvalidConfigurationException("Block size must be a multiple of 512");
|
|
|
- }
|
|
|
- catch (NumberFormatException ex) {
|
|
|
- throw new InvalidConfigurationException("Invalid block size specified, " + attr);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- attr = sizeElem.getAttribute("blocksPerUnit");
|
|
|
- if ( attr != null && attr.length() > 0) {
|
|
|
- try {
|
|
|
- blocksPerUnit = Long.parseLong(attr);
|
|
|
-
|
|
|
- // Check for a valid blocks per unit value
|
|
|
-
|
|
|
- if ( blocksPerUnit <= 0)
|
|
|
- throw new InvalidConfigurationException("Invalid blocks per unit, must be greater than zero");
|
|
|
- }
|
|
|
- catch (NumberFormatException ex) {
|
|
|
- throw new InvalidConfigurationException("Invalid blocks per unit value");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Calculate the sizes and set the disk sizing information
|
|
|
-
|
|
|
- long unitSize = blockSize * blocksPerUnit;
|
|
|
- long totUnits = totSize / unitSize;
|
|
|
- long freeUnits = freeSize / unitSize;
|
|
|
-
|
|
|
- diskInfo = new SrvDiskInfo(totUnits, blocksPerUnit, blockSize, freeUnits);
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- // Default to a 80Gb sized disk with 90% free space
|
|
|
-
|
|
|
- diskInfo = new SrvDiskInfo(2560000, 64, 512, 2304000);
|
|
|
- }
|
|
|
-
|
|
|
- // Check if a state cache is configured
|
|
|
-
|
|
|
- Element cacheElem = findChildNode("stateCache", disk.getChildNodes());
|
|
|
- FileStateCache stateCache = null;
|
|
|
-
|
|
|
- if ( cacheElem != null) {
|
|
|
-
|
|
|
- // Convert the state cache configuration
|
|
|
-
|
|
|
- ConfigElement cacheConfig = buildConfigElement( cacheElem);
|
|
|
-
|
|
|
- // Get the cache type
|
|
|
-
|
|
|
- attr = cacheElem.getAttribute( "type");
|
|
|
- if ( attr.equalsIgnoreCase( "standalone")) {
|
|
|
-
|
|
|
- // Create a standalone file state cache
|
|
|
-
|
|
|
- stateCache = new StandaloneFileStateCache();
|
|
|
- }
|
|
|
- else if ( attr.equalsIgnoreCase( "cluster")) {
|
|
|
-
|
|
|
- // Create a clustered file state cache, need to load the class to avoid a reference to it
|
|
|
-
|
|
|
- try {
|
|
|
- stateCache = (FileStateCache) Class.forName( "org.alfresco.jlan.server.filesys.cache.hazelcast.HazelCastClusterFileStateCache").newInstance();
|
|
|
- }
|
|
|
- catch ( ClassNotFoundException ex) {
|
|
|
- throw new InvalidConfigurationException( "Clustered file state cache not available, check build/Jar");
|
|
|
- }
|
|
|
- catch ( Exception ex) {
|
|
|
- throw new InvalidConfigurationException( "Failed to load clustered file state cache class, " + ex);
|
|
|
- }
|
|
|
- }
|
|
|
- else if ( attr.equalsIgnoreCase( "custom")) {
|
|
|
-
|
|
|
- // Get the custom state cache class name
|
|
|
-
|
|
|
- Element cacheClass = findChildNode( "class", cacheElem.getChildNodes());
|
|
|
- if ( cacheClass == null || getText( cacheClass).length() == 0)
|
|
|
- throw new InvalidConfigurationException( "Custom state cache class not specified");
|
|
|
-
|
|
|
- // Create a custom file state cache
|
|
|
-
|
|
|
- try {
|
|
|
- Object cacheObj = Class.forName( getText( cacheClass)).newInstance();
|
|
|
- if ( cacheObj instanceof FileStateCache == false)
|
|
|
- throw new InvalidConfigurationException( "State cache class is not a FileStateCache based class");
|
|
|
-
|
|
|
- stateCache = (FileStateCache) cacheObj;
|
|
|
- }
|
|
|
- catch ( ClassNotFoundException ex) {
|
|
|
- throw new InvalidConfigurationException( "Clustered file state cache not available, check build/Jar");
|
|
|
- }
|
|
|
- catch ( Exception ex) {
|
|
|
- throw new InvalidConfigurationException( "Failed to load clustered file state cache class, " + ex);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Initialize the cache
|
|
|
-
|
|
|
- if ( stateCache != null)
|
|
|
- stateCache.initializeCache( cacheConfig, this);
|
|
|
- else
|
|
|
- throw new InvalidConfigurationException( "Failed to initialize state cache for filesystem " + name);
|
|
|
- }
|
|
|
-
|
|
|
- // Check if a share with this name already exists
|
|
|
-
|
|
|
- if ( filesysConfig.getShares().findShare(name) != null)
|
|
|
- throw new InvalidConfigurationException("Share " + name + " already exists");
|
|
|
-
|
|
|
- // Validate the driver class, create a device context and add the new disk share
|
|
|
-
|
|
|
- try {
|
|
|
-
|
|
|
- // Load the driver class
|
|
|
-
|
|
|
- Object drvObj = Class.forName(getText(classElem)).newInstance();
|
|
|
- if ( drvObj instanceof DiskInterface) {
|
|
|
-
|
|
|
- // Create the driver
|
|
|
-
|
|
|
- DiskInterface diskDrv = (DiskInterface) drvObj;
|
|
|
-
|
|
|
- // Create a context for this share instance, save the configuration parameters as
|
|
|
- // part of the context
|
|
|
-
|
|
|
- DiskDeviceContext devCtx = (DiskDeviceContext) diskDrv.createContext(name, params);
|
|
|
- devCtx.setConfigurationParameters(params);
|
|
|
-
|
|
|
- // Enable/disable change notification for this device
|
|
|
-
|
|
|
- devCtx.enableChangeHandler(changeNotify);
|
|
|
-
|
|
|
- // Set the volume information, may be null
|
|
|
-
|
|
|
- devCtx.setVolumeInformation(volInfo);
|
|
|
-
|
|
|
- // Set the disk sizing information, may be null
|
|
|
-
|
|
|
- devCtx.setDiskInformation(diskInfo);
|
|
|
-
|
|
|
- // Set the share name in the context
|
|
|
-
|
|
|
- devCtx.setShareName(name);
|
|
|
-
|
|
|
- // Create the default file state cache type if the filesystem requires it, for backwards compatability
|
|
|
-
|
|
|
- if ( devCtx.requiresStateCache() && stateCache == null) {
|
|
|
- stateCache = new StandaloneFileStateCache();
|
|
|
- stateCache.initializeCache( new GenericConfigElement( "stateCache"), this);
|
|
|
- }
|
|
|
-
|
|
|
- if ( devCtx.requiresStateCache() == false && stateCache != null)
|
|
|
- throw new InvalidConfigurationException( "Filesystem does not use state caching");
|
|
|
-
|
|
|
- devCtx.setStateCache( stateCache);
|
|
|
-
|
|
|
- // Create the disk shared device and add to the server's list of shares
|
|
|
-
|
|
|
- DiskSharedDevice diskDev = new DiskSharedDevice(name, diskDrv, devCtx);
|
|
|
- diskDev.setComment(comment);
|
|
|
- diskDev.setConfiguration( this);
|
|
|
-
|
|
|
- // Add any access controls to the share
|
|
|
-
|
|
|
- diskDev.setAccessControlList(acls);
|
|
|
-
|
|
|
- // Check if the filesystem uses the file state cache, if so then add to the file state reaper
|
|
|
-
|
|
|
- if ( devCtx.hasStateCache()) {
|
|
|
-
|
|
|
- // Register the state cache with the reaper thread
|
|
|
-
|
|
|
- filesysConfig.addFileStateCache( name, devCtx.getStateCache());
|
|
|
- }
|
|
|
-
|
|
|
- // Start the filesystem
|
|
|
-
|
|
|
- devCtx.startFilesystem(diskDev);
|
|
|
-
|
|
|
- // Pass the driver/context details to the state cache
|
|
|
-
|
|
|
- if ( devCtx.hasStateCache())
|
|
|
- devCtx.getStateCache().setDriverDetails(diskDev);
|
|
|
-
|
|
|
- // Add the new share to the list of available shares
|
|
|
-
|
|
|
- filesysConfig.addShare(diskDev);
|
|
|
- }
|
|
|
- }
|
|
|
- catch (ClassNotFoundException ex) {
|
|
|
- throw new InvalidConfigurationException("Disk driver class " + getText(classElem) + " not found");
|
|
|
- }
|
|
|
- catch (DeviceContextException ex) {
|
|
|
- throw new InvalidConfigurationException("Driver context error", ex);
|
|
|
- }
|
|
|
- catch (Exception ex) {
|
|
|
- throw new InvalidConfigurationException("Disk share setup error", ex);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Find the specified child node in the node list
|
|
|
- *
|
|
|
- * @param name String
|
|
|
- * @param list NodeList
|
|
|
- * @return Element
|
|
|
- */
|
|
|
- protected final Element findChildNode(String name, NodeList list) {
|
|
|
-
|
|
|
- // Check if the list is valid
|
|
|
-
|
|
|
- if ( list == null)
|
|
|
- return null;
|
|
|
-
|
|
|
- // Search for the required element
|
|
|
-
|
|
|
- for (int i = 0; i < list.getLength(); i++) {
|
|
|
-
|
|
|
- // Get the current child node
|
|
|
-
|
|
|
- Node child = list.item(i);
|
|
|
- if ( child.getNodeName().equals(name) && child.getNodeType() == ELEMENT_TYPE)
|
|
|
- return (Element) child;
|
|
|
- }
|
|
|
-
|
|
|
- // Element not found
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Get the value text for the specified element
|
|
|
- *
|
|
|
- * @param elem Element
|
|
|
- * @return String
|
|
|
- */
|
|
|
- protected final String getText(Element elem) {
|
|
|
-
|
|
|
- // Check if the element has children
|
|
|
-
|
|
|
- NodeList children = elem.getChildNodes();
|
|
|
- String text = "";
|
|
|
-
|
|
|
- if ( children != null && children.getLength() > 0 && children.item(0).getNodeType() != ELEMENT_TYPE)
|
|
|
- text = children.item(0).getNodeValue();
|
|
|
-
|
|
|
- // Return the element text value
|
|
|
-
|
|
|
- return text;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Build a configuration element list from an elements child nodes
|
|
|
- *
|
|
|
- * @param root Element
|
|
|
- * @return GenericConfigElement
|
|
|
- */
|
|
|
- protected final GenericConfigElement buildConfigElement(Element root) {
|
|
|
- return buildConfigElement(root, null);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Build a configuration element list from an elements child nodes
|
|
|
- *
|
|
|
- * @param root Element
|
|
|
- * @param cfgElem GenericConfigElement
|
|
|
- * @return GenericConfigElement
|
|
|
- */
|
|
|
- protected final GenericConfigElement buildConfigElement(Element root, GenericConfigElement cfgElem) {
|
|
|
-
|
|
|
- // Create the top level element, if not specified
|
|
|
-
|
|
|
- GenericConfigElement rootElem = cfgElem;
|
|
|
-
|
|
|
- if ( rootElem == null) {
|
|
|
-
|
|
|
- // Create the root element
|
|
|
-
|
|
|
- rootElem = new GenericConfigElement(root.getNodeName());
|
|
|
-
|
|
|
- // Add any attributes
|
|
|
-
|
|
|
- NamedNodeMap attribs = root.getAttributes();
|
|
|
- if ( attribs != null) {
|
|
|
- for (int i = 0; i < attribs.getLength(); i++) {
|
|
|
- Node attribNode = attribs.item(i);
|
|
|
- rootElem.addAttribute(attribNode.getNodeName(), attribNode.getNodeValue());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Get the child node list
|
|
|
-
|
|
|
- NodeList nodes = root.getChildNodes();
|
|
|
- if ( nodes == null)
|
|
|
- return rootElem;
|
|
|
-
|
|
|
- // Process the child node list
|
|
|
-
|
|
|
- GenericConfigElement childElem = null;
|
|
|
-
|
|
|
- for (int i = 0; i < nodes.getLength(); i++) {
|
|
|
-
|
|
|
- // Get the current node
|
|
|
-
|
|
|
- Node node = nodes.item(i);
|
|
|
-
|
|
|
- if ( node.getNodeType() == ELEMENT_TYPE) {
|
|
|
-
|
|
|
- // Access the Element
|
|
|
-
|
|
|
- Element elem = (Element) node;
|
|
|
-
|
|
|
- // Check if the element has any child nodes
|
|
|
-
|
|
|
- NodeList children = elem.getChildNodes();
|
|
|
-
|
|
|
- if ( children != null && children.getLength() > 1) {
|
|
|
-
|
|
|
- // Add the child nodes as child configuration elements
|
|
|
-
|
|
|
- childElem = buildConfigElement(elem, null);
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- // Create a normal name/value
|
|
|
-
|
|
|
- if ( children.getLength() > 0) {
|
|
|
- childElem = new GenericConfigElement(elem.getNodeName());
|
|
|
- childElem.setValue(children.item(0).getNodeValue());
|
|
|
- }
|
|
|
- else
|
|
|
- childElem = new GenericConfigElement(elem.getNodeName());
|
|
|
-
|
|
|
- // Add any attributes
|
|
|
-
|
|
|
- NamedNodeMap attribs = elem.getAttributes();
|
|
|
- if ( attribs != null) {
|
|
|
- for (int j = 0; j < attribs.getLength(); j++) {
|
|
|
- Node attribNode = attribs.item(j);
|
|
|
- childElem.addAttribute(attribNode.getNodeName(), attribNode.getNodeValue());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Add the child configuration element
|
|
|
-
|
|
|
- rootElem.addChild(childElem);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Return the configuration element
|
|
|
-
|
|
|
- return rootElem;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Add a configuration element
|
|
|
- */
|
|
|
- /**
|
|
|
- * Parse a platform type string into a list of platform ids
|
|
|
- *
|
|
|
- * @param platforms String
|
|
|
- * @return List<Integer>
|
|
|
- * @exception InvalidConfigurationException
|
|
|
- */
|
|
|
- protected final List<Platform.Type> parsePlatformString(String platforms)
|
|
|
- throws InvalidConfigurationException {
|
|
|
- // Create the list to hold the platform ids
|
|
|
-
|
|
|
- List<Platform.Type> platformIds = new ArrayList<Platform.Type>();
|
|
|
-
|
|
|
- if ( platforms == null)
|
|
|
- return platformIds;
|
|
|
-
|
|
|
- // Split the platform list
|
|
|
-
|
|
|
- StringTokenizer tokens = new StringTokenizer(platforms.toUpperCase(Locale.ENGLISH), ",");
|
|
|
-
|
|
|
- while (tokens.hasMoreTokens()) {
|
|
|
-
|
|
|
- // Get the current platform token and validate
|
|
|
-
|
|
|
- String platform = tokens.nextToken().trim();
|
|
|
-
|
|
|
- // Validate the platform id
|
|
|
-
|
|
|
- Platform.Type id = Platform.Type.Unknown;
|
|
|
-
|
|
|
- if ( platform.equalsIgnoreCase("WINDOWS"))
|
|
|
- id = Platform.Type.WINDOWS;
|
|
|
- else if ( platform.equalsIgnoreCase("LINUX"))
|
|
|
- id = Platform.Type.LINUX;
|
|
|
- else if ( platform.equalsIgnoreCase("MACOSX"))
|
|
|
- id = Platform.Type.MACOSX;
|
|
|
- else if ( platform.equalsIgnoreCase("SOLARIS"))
|
|
|
- id = Platform.Type.SOLARIS;
|
|
|
-
|
|
|
- if ( id == Platform.Type.Unknown)
|
|
|
- throw new InvalidConfigurationException("Invalid platform type '" + platform + "'");
|
|
|
-
|
|
|
- // Add the platform id to the list
|
|
|
-
|
|
|
- platformIds.add(id);
|
|
|
- }
|
|
|
-
|
|
|
- // Return the platform id list
|
|
|
-
|
|
|
- return platformIds;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 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;
|
|
|
- }
|
|
|
-}
|