/**
* Copyright 2009, Frederic Bregier, and individual contributors by the @author tags. See the
* COPYRIGHT.txt in the distribution for a full listing of individual contributors.
*
* This 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.0 of the
* License, or (at your option) any later version.
*
* This software 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 this
* software; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.waarp.gateway.ftp.config;
import java.io.File;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.ChannelGroupFuture;
import io.netty.channel.group.ChannelGroupFutureListener;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.handler.traffic.AbstractTrafficShapingHandler;
import io.netty.util.concurrent.EventExecutorGroup;
import org.waarp.common.crypto.Des;
import org.waarp.common.crypto.ssl.WaarpSecureKeyStore;
import org.waarp.common.crypto.ssl.WaarpSslContextFactory;
import org.waarp.common.database.DbAdmin;
import org.waarp.common.database.DbPreparedStatement;
import org.waarp.common.database.exception.WaarpDatabaseNoConnectionException;
import org.waarp.common.database.exception.WaarpDatabaseSqlException;
import org.waarp.common.digest.FilesystemBasedDigest;
import org.waarp.common.exception.CryptoException;
import org.waarp.common.exception.InvalidArgumentException;
import org.waarp.common.file.DirInterface;
import org.waarp.common.file.FileParameterInterface;
import org.waarp.common.file.filesystembased.FilesystemBasedDirImpl;
import org.waarp.common.file.filesystembased.FilesystemBasedFileParameterImpl;
import org.waarp.common.file.filesystembased.specific.FilesystemBasedDirJdkAbstract;
import org.waarp.common.logging.WaarpLogger;
import org.waarp.common.logging.WaarpLoggerFactory;
import org.waarp.common.utility.WaarpNettyUtil;
import org.waarp.common.utility.WaarpStringUtils;
import org.waarp.common.utility.WaarpThreadFactory;
import org.waarp.common.xml.XmlDecl;
import org.waarp.common.xml.XmlHash;
import org.waarp.common.xml.XmlType;
import org.waarp.common.xml.XmlUtil;
import org.waarp.common.xml.XmlValue;
import org.waarp.ftp.core.config.FtpConfiguration;
import org.waarp.ftp.core.control.BusinessHandler;
import org.waarp.ftp.core.control.ftps.FtpsInitializer;
import org.waarp.ftp.core.data.handler.DataBusinessHandler;
import org.waarp.ftp.core.exception.FtpNoConnectionException;
import org.waarp.ftp.core.exception.FtpUnknownFieldException;
import org.waarp.gateway.ftp.adminssl.HttpSslInitializer;
import org.waarp.gateway.ftp.control.FtpConstraintLimitHandler;
import org.waarp.gateway.ftp.database.DbConstant;
import org.waarp.gateway.ftp.database.data.DbTransferLog;
import org.waarp.gateway.ftp.database.model.DbModelFactory;
import org.waarp.gateway.ftp.file.SimpleAuth;
import org.waarp.gateway.ftp.snmp.FtpMonitoring;
import org.waarp.gateway.ftp.snmp.FtpPrivateMib;
import org.waarp.gateway.ftp.snmp.FtpVariableFactory;
import org.waarp.gateway.kernel.exec.AbstractExecutor;
import org.waarp.gateway.kernel.exec.LocalExecClient;
import org.waarp.snmp.SnmpConfiguration;
import org.waarp.snmp.WaarpMOFactory;
import org.waarp.snmp.WaarpSnmpAgent;
/**
* FtpConfiguration based on a XML file
*
* @author Frederic Bregier
*
*/
public class FileBasedConfiguration extends FtpConfiguration {
/**
* Internal Logger
*/
private static final WaarpLogger logger = WaarpLoggerFactory.getLogger(FileBasedConfiguration.class);
/**
* SERVER HOSTID
*/
private static final String XML_SERVER_HOSTID = "hostid";
/**
* Authentication
*/
private static final String XML_AUTHENTIFICATION_FILE = "authentfile";
/**
* SERVER CRYPTO for Password
*/
private static final String XML_PATH_CRYPTOKEY = "cryptokey";
/**
* Structure of the Configuration file
*
*/
private static final XmlDecl[] configIdentityDecls = {
// identity
new XmlDecl(XmlType.STRING, XML_SERVER_HOSTID),
new XmlDecl(XmlType.STRING, XML_PATH_CRYPTOKEY),
new XmlDecl(XmlType.STRING, XML_AUTHENTIFICATION_FILE)
};
/**
* Use HTTP compression for R66 HTTP connection
*/
private static final String XML_USEHTTPCOMP = "usehttpcomp";
/**
* Use external Waarp Local Exec for ExecTask and ExecMoveTask
*/
private static final String XML_USELOCALEXEC = "uselocalexec";
/**
* Address of Waarp Local Exec for ExecTask and ExecMoveTask
*/
private static final String XML_LEXECADDR = "lexecaddr";
/**
* Port of Waarp Local Exec for ExecTask and ExecMoveTask
*/
private static final String XML_LEXECPORT = "lexecport";
/**
* ADMINISTRATOR SERVER NAME (shutdown)
*/
private static final String XML_SERVER_ADMIN = "serveradmin";
/**
* SERVER PASSWORD (shutdown)
*/
private static final String XML_SERVER_PASSWD = "serverpasswd";
/**
* SERVER SSL STOREKEY PATH ADMIN
*/
private static final String XML_PATH_ADMIN_KEYPATH = "admkeypath";
/**
* SERVER SSL KEY PASS ADMIN
*/
private static final String XML_PATH_ADMIN_KEYPASS = "admkeypass";
/**
* SERVER SSL STOREKEY PASS ADMIN
*/
private static final String XML_PATH_ADMIN_KEYSTOREPASS = "admkeystorepass";
/**
* HTTP Admin Directory
*/
private static final String XML_HTTPADMINPATH = "httpadmin";
/**
* Monitoring: snmp configuration file (if empty, no snmp support)
*/
private static final String XML_MONITOR_SNMP_CONFIG = "snmpconfig";
/**
* Structure of the Configuration file
*
*/
private static final XmlDecl[] configServerParamDecls = {
// server
new XmlDecl(XmlType.BOOLEAN, XML_USELOCALEXEC),
new XmlDecl(XmlType.STRING, XML_LEXECADDR),
new XmlDecl(XmlType.INTEGER, XML_LEXECPORT),
new XmlDecl(XmlType.STRING, XML_SERVER_ADMIN),
new XmlDecl(XmlType.STRING, XML_SERVER_PASSWD),
new XmlDecl(XmlType.BOOLEAN, XML_USEHTTPCOMP),
new XmlDecl(XmlType.STRING, XML_HTTPADMINPATH),
new XmlDecl(XmlType.STRING, XML_PATH_ADMIN_KEYPATH),
new XmlDecl(XmlType.STRING, XML_PATH_ADMIN_KEYSTOREPASS),
new XmlDecl(XmlType.STRING, XML_PATH_ADMIN_KEYPASS),
new XmlDecl(XmlType.STRING, XML_MONITOR_SNMP_CONFIG)
};
/**
* SERVER PORT
*/
private static final String XML_SERVER_PORT = "serverport";
/**
* SERVER ADDRESS if any
*/
private static final String XML_SERVER_ADDRESS = "serveraddress";
/**
* RANGE of PORT for Passive Mode
*/
private static final String XML_RANGE_PORT_MIN = "portmin";
/**
* RANGE of PORT for Passive Mode
*/
private static final String XML_RANGE_PORT_MAX = "portmax";
/**
* SERVER HTTP PORT MONITORING
*/
private static final String XML_SERVER_HTTP_PORT = "serverhttpport";
/**
* SERVER HTTPS PORT ADMINISTRATION
*/
private static final String XML_SERVER_HTTPS_PORT = "serverhttpsport";
/**
* Structure of the Configuration file
*
*/
private static final XmlDecl[] configNetworkServerDecls = {
// network
new XmlDecl(XmlType.INTEGER, XML_SERVER_PORT),
new XmlDecl(XmlType.STRING, XML_SERVER_ADDRESS),
new XmlDecl(XmlType.INTEGER, XML_RANGE_PORT_MIN),
new XmlDecl(XmlType.INTEGER, XML_RANGE_PORT_MAX),
new XmlDecl(XmlType.INTEGER, XML_SERVER_HTTP_PORT),
new XmlDecl(XmlType.INTEGER, XML_SERVER_HTTPS_PORT)
};
/**
* Database Driver as of oracle, mysql, postgresql, h2
*/
private static final String XML_DBDRIVER = "dbdriver";
/**
* Database Server connection string as of jdbc:type://[host:port],[failoverhost:port]
* .../[database][?propertyName1][ =propertyValue1][&propertyName2][=propertyValue2]...
*/
private static final String XML_DBSERVER = "dbserver";
/**
* Database User
*/
private static final String XML_DBUSER = "dbuser";
/**
* Database Password
*/
private static final String XML_DBPASSWD = "dbpasswd";
/**
* Structure of the Configuration file
*
*/
private static final XmlDecl[] configDbDecls = {
// db
new XmlDecl(XmlType.STRING, XML_DBDRIVER),
new XmlDecl(XmlType.STRING, XML_DBSERVER),
new XmlDecl(XmlType.STRING, XML_DBUSER),
new XmlDecl(XmlType.STRING, XML_DBPASSWD)
};
/**
* Should a file be deleted when a Store like command is aborted
*/
private static final String XML_DELETEONABORT = "deleteonabort";
/**
* Default number of threads in pool for Server.
*/
private static final String XML_SERVER_THREAD = "serverthread";
/**
* Default number of threads in pool for Client.
*/
private static final String XML_CLIENT_THREAD = "clientthread";
/**
* Memory Limit to use.
*/
private static final String XML_MEMORY_LIMIT = "memorylimit";
/**
* Limit for Session
*/
private static final String XML_LIMITSESSION = "sessionlimit";
/**
* Limit for Global
*/
private static final String XML_LIMITGLOBAL = "globallimit";
/**
* Delay between two checks for Limit
*/
private static final String XML_LIMITDELAY = "delaylimit";
/**
* Nb of milliseconds after connection is in timeout
*/
private static final String XML_TIMEOUTCON = "timeoutcon";
/**
* Size by default of block size for receive/sending files. Should be a multiple of 8192
* (maximum = 64K due to block limitation to 2 bytes)
*/
private static final String XML_BLOCKSIZE = "blocksize";
/**
* Should a file MD5 SHA1 be computed using NIO
*/
private static final String XML_USENIO = "usenio";
/**
* Should a file MD5 be computed using FastMD5
*/
private static final String XML_USEFASTMD5 = "usefastmd5";
/**
* If using Fast MD5, should we used the binary JNI library, empty meaning no
*/
private static final String XML_FASTMD5 = "fastmd5";
/**
* Usage of CPU Limit
*/
private static final String XML_CSTRT_USECPULIMIT = "usecpulimit";
/**
* Usage of JDK CPU Limit (True) or SysMon CPU Limit
*/
private static final String XML_CSTRT_USECPUJDKLIMIT = "usejdkcpulimit";
/**
* CPU LIMIT between 0 and 1, where 1 stands for no limit
*/
private static final String XML_CSTRT_CPULIMIT = "cpulimit";
/**
* Connection limit where 0 stands for no limit
*/
private static final String XML_CSTRT_CONNLIMIT = "connlimit";
/**
* CPU LOW limit to apply increase of throttle
*/
private static final String XML_CSTRT_LOWCPULIMIT = "lowcpulimit";
/**
* CPU HIGH limit to apply decrease of throttle, 0 meaning no throttle activated
*/
private static final String XML_CSTRT_HIGHCPULIMIT = "highcpulimit";
/**
* PERCENTAGE DECREASE of Bandwidth
*/
private static final String XML_CSTRT_PERCENTDECREASE = "percentdecrease";
/**
* Delay between 2 checks of throttle test
*/
private static final String XML_CSTRT_DELAYTHROTTLE = "delaythrottle";
/**
* Bandwidth low limit to not got below
*/
private static final String XML_CSTRT_LIMITLOWBANDWIDTH = "limitlowbandwidth";
/**
* Structure of the Configuration file
*
*/
private static final XmlDecl[] configLimitDecls = {
// limit
new XmlDecl(XmlType.BOOLEAN, XML_DELETEONABORT),
new XmlDecl(XmlType.LONG, XML_LIMITSESSION),
new XmlDecl(XmlType.LONG, XML_LIMITGLOBAL),
new XmlDecl(XmlType.LONG, XML_LIMITDELAY),
new XmlDecl(XmlType.INTEGER, XML_SERVER_THREAD),
new XmlDecl(XmlType.INTEGER, XML_CLIENT_THREAD),
new XmlDecl(XmlType.LONG, XML_MEMORY_LIMIT),
new XmlDecl(XmlType.BOOLEAN, XML_CSTRT_USECPULIMIT),
new XmlDecl(XmlType.BOOLEAN, XML_CSTRT_USECPUJDKLIMIT),
new XmlDecl(XmlType.DOUBLE, XML_CSTRT_CPULIMIT),
new XmlDecl(XmlType.INTEGER, XML_CSTRT_CONNLIMIT),
new XmlDecl(XmlType.DOUBLE, XML_CSTRT_LOWCPULIMIT),
new XmlDecl(XmlType.DOUBLE, XML_CSTRT_HIGHCPULIMIT),
new XmlDecl(XmlType.DOUBLE, XML_CSTRT_PERCENTDECREASE),
new XmlDecl(XmlType.LONG, XML_CSTRT_LIMITLOWBANDWIDTH),
new XmlDecl(XmlType.LONG, XML_CSTRT_DELAYTHROTTLE),
new XmlDecl(XmlType.LONG, XML_TIMEOUTCON),
new XmlDecl(XmlType.BOOLEAN, XML_USENIO),
new XmlDecl(XmlType.BOOLEAN, XML_USEFASTMD5),
new XmlDecl(XmlType.STRING, XML_FASTMD5),
new XmlDecl(XmlType.INTEGER, XML_BLOCKSIZE)
};
/**
* RETRIEVE COMMAND
*/
public static final String XML_RETRIEVE_COMMAND = "retrievecmd";
/**
* STORE COMMAND
*/
public static final String XML_STORE_COMMAND = "storecmd";
/**
* DELAY RETRIEVE COMMAND
*/
public static final String XML_DELAYRETRIEVE_COMMAND = "retrievedelay";
/**
* DELAY STORE COMMAND
*/
public static final String XML_DELAYSTORE_COMMAND = "storedelay";
/**
* Structure of the Configuration file
*
*/
private static final XmlDecl[] configExecDecls = {
// Exec
new XmlDecl(XmlType.STRING, XML_RETRIEVE_COMMAND),
new XmlDecl(XmlType.LONG, XML_DELAYRETRIEVE_COMMAND),
new XmlDecl(XmlType.STRING, XML_STORE_COMMAND),
new XmlDecl(XmlType.LONG, XML_DELAYSTORE_COMMAND)
};
/**
* Base Directory
*/
private static final String XML_SERVER_HOME = "serverhome";
/**
* Structure of the Configuration file
*
*/
private static final XmlDecl[] configDirectoryDecls = {
// directory
new XmlDecl(XmlType.STRING, XML_SERVER_HOME)
};
/**
* SERVER SSL STOREKEY PATH
*/
private static final String XML_PATH_KEYPATH = "keypath";
/**
* SERVER SSL KEY PASS
*/
private static final String XML_PATH_KEYPASS = "keypass";
/**
* SERVER SSL STOREKEY PASS
*/
private static final String XML_PATH_KEYSTOREPASS = "keystorepass";
/**
* SERVER SSL TRUSTSTOREKEY PATH
*/
private static final String XML_PATH_TRUSTKEYPATH = "trustkeypath";
/**
* SERVER SSL TRUSTSTOREKEY PASS
*/
private static final String XML_PATH_TRUSTKEYSTOREPASS = "trustkeystorepass";
/**
* SERVER SSL Use TrustStore for Client Authentication
*/
private static final String XML_USECLIENT_AUTHENT = "trustuseclientauthenticate";
/**
* SERVER SSL Use Implicit FTPS
*/
private static final String XML_IMPLICIT_FTPS = "useimplicitftps";
/**
* SERVER SSL Use Explicit FTPS
*/
private static final String XML_EXPLICIT_FTPS = "useexplicitftps";
/**
* Structure of the Configuration file
*
*/
private static final XmlDecl[] configSslDecls = {
// ssl
new XmlDecl(XmlType.STRING, XML_PATH_KEYPATH),
new XmlDecl(XmlType.STRING, XML_PATH_KEYSTOREPASS),
new XmlDecl(XmlType.STRING, XML_PATH_KEYPASS),
new XmlDecl(XmlType.STRING, XML_PATH_TRUSTKEYPATH),
new XmlDecl(XmlType.STRING, XML_PATH_TRUSTKEYSTOREPASS),
new XmlDecl(XmlType.BOOLEAN, XML_USECLIENT_AUTHENT),
new XmlDecl(XmlType.BOOLEAN, XML_IMPLICIT_FTPS),
new XmlDecl(XmlType.BOOLEAN, XML_EXPLICIT_FTPS)
};
/**
* Overall structure of the Configuration file
*/
private static final String XML_ROOT = "/config/";
private static final String XML_IDENTITY = "identity";
private static final String XML_SERVER = "server";
private static final String XML_DIRECTORY = "directory";
private static final String XML_LIMIT = "limit";
private static final String XML_NETWORK = "network";
private static final String XML_EXEC = "exec";
private static final String XML_DB = "db";
private static final String XML_SSL = "ssl";
/**
* Global Structure for Server Configuration
*/
private static final XmlDecl[] configServer = {
new XmlDecl(XML_IDENTITY, XmlType.XVAL, XML_ROOT + XML_IDENTITY, configIdentityDecls,
false),
new XmlDecl(XML_SERVER, XmlType.XVAL, XML_ROOT + XML_SERVER, configServerParamDecls,
false),
new XmlDecl(XML_NETWORK, XmlType.XVAL, XML_ROOT + XML_NETWORK,
configNetworkServerDecls, false),
new XmlDecl(XML_EXEC, XmlType.XVAL, XML_ROOT + XML_EXEC, configExecDecls, false),
new XmlDecl(XML_DIRECTORY, XmlType.XVAL, XML_ROOT + XML_DIRECTORY,
configDirectoryDecls, false),
new XmlDecl(XML_LIMIT, XmlType.XVAL, XML_ROOT + XML_LIMIT, configLimitDecls, false),
new XmlDecl(XML_DB, XmlType.XVAL, XML_ROOT + XML_DB, configDbDecls, false),
new XmlDecl(XML_SSL, XmlType.XVAL, XML_ROOT + XML_SSL, configSslDecls, false)
};
/**
* Authentication Fields
*/
private static final String XML_AUTHENTIFICATION_ROOT = "authent";
/**
* Authentication Fields
*/
private static final String XML_AUTHENTIFICATION_ENTRY = "entry";
/**
* Authentication Fields
*/
private static final String XML_AUTHENTIFICATION_BASED = "/" +
XML_AUTHENTIFICATION_ROOT + "/" + XML_AUTHENTIFICATION_ENTRY;
/**
* Authentication Fields
*/
private static final String XML_AUTHENTICATION_USER = "user";
/**
* Authentication Fields
*/
private static final String XML_AUTHENTICATION_PASSWD = "passwd";
/**
* Authentication Fields
*/
private static final String XML_AUTHENTICATION_PASSWDFILE = "passwdfile";
/**
* Authentication Fields
*/
private static final String XML_AUTHENTICATION_ACCOUNT = "account";
/**
* Authentication Fields
*/
private static final String XML_AUTHENTICATION_ADMIN = "admin";
/**
* Structure of the Configuration file
*
*/
private static final XmlDecl[] configAuthenticationDecls = {
// identity
new XmlDecl(XmlType.STRING, XML_AUTHENTICATION_USER),
new XmlDecl(XmlType.STRING, XML_AUTHENTICATION_PASSWDFILE),
new XmlDecl(XmlType.STRING, XML_AUTHENTICATION_PASSWD),
new XmlDecl(XML_AUTHENTICATION_ACCOUNT, XmlType.STRING, XML_AUTHENTICATION_ACCOUNT,
true),
new XmlDecl(XmlType.BOOLEAN, XML_AUTHENTICATION_ADMIN),
// Exec
new XmlDecl(XmlType.STRING, XML_RETRIEVE_COMMAND),
new XmlDecl(XmlType.LONG, XML_DELAYRETRIEVE_COMMAND),
new XmlDecl(XmlType.STRING, XML_STORE_COMMAND),
new XmlDecl(XmlType.LONG, XML_DELAYSTORE_COMMAND)
};
/**
* Global Structure for Server Configuration
*/
private static final XmlDecl[] authentElements = {
new XmlDecl(XML_AUTHENTIFICATION_ENTRY, XmlType.XVAL, XML_AUTHENTIFICATION_BASED,
configAuthenticationDecls, true)
};
/**
* RANGE of PORT for Passive Mode
*/
private static final String RANGE_PORT = "FTP_RANGE_PORT";
/**
* Use to access directly the configuration
*/
public static FileBasedConfiguration fileBasedConfiguration;
/**
* All authentications
*/
private ConcurrentHashMap<String, SimpleAuth> authentications = new ConcurrentHashMap<String, SimpleAuth>();
/**
* File containing the authentications
*/
private String authenticationFile;
/**
* Default HTTP server port
*/
private int SERVER_HTTPSPORT = 8067;
/**
* Http Admin base
*/
public String httpBasePath = "src/main/admin/";
/**
* Delay in ms between two checks
*/
public long delayLimit = 10000;
/**
* Does this server will try to compress HTTP connections
*/
public boolean useHttpCompression = false;
/**
* Does this server will use Waarp LocalExec Daemon for Execute
*/
public boolean useLocalExec = false;
/**
* Crypto Key
*/
public Des cryptoKey = null;
/**
* Server Administration Key
*/
private byte[] SERVERADMINKEY = null;
/**
* FTP server ID
*/
public String HOST_ID = "noId";
/**
* Admin name Id
*/
public String ADMINNAME = "noAdmin";
/**
* Limit on CPU and Connection
*/
public FtpConstraintLimitHandler constraintLimitHandler = null;
/**
* List of all Http Channels to enable the close call on them using Netty ChannelGroup
*/
private ChannelGroup httpChannelGroup = null;
/**
* Bootstrap for Https server
*/
private ServerBootstrap httpsBootstrap = null;
/**
* Boss Group for Http
*/
private EventLoopGroup bossGroup = null;
/**
* Worker Group for Http
*/
private EventLoopGroup workerGroup = null;
/**
* ThreadPoolExecutor for Http and Https Server
*/
private EventExecutorGroup httpExecutor;
/**
* Monitoring: snmp configuration file (empty means no snmp support)
*/
public String snmpConfig = null;
/**
* SNMP Agent (if any)
*/
public WaarpSnmpAgent agentSnmp = null;
/**
* Associated MIB
*/
public FtpPrivateMib ftpMib = null;
/**
* Monitoring object
*/
public FtpMonitoring monitoring = null;
/**
* @param classtype
* @param businessHandler
* class that will be used for BusinessHandler
* @param dataBusinessHandler
* class that will be used for DataBusinessHandler
* @param fileParameter
* the FileParameter to use
*/
public FileBasedConfiguration(Class<?> classtype,
Class<? extends BusinessHandler> businessHandler,
Class<? extends DataBusinessHandler> dataBusinessHandler,
FileParameterInterface fileParameter) {
super(classtype, businessHandler, dataBusinessHandler, fileParameter);
computeNbThreads();
}
private static XmlValue[] configuration = null;
private static XmlHash hashConfig = null;
private boolean loadIdentity() {
XmlValue value = hashConfig.get(XML_SERVER_HOSTID);
if (value != null && (!value.isEmpty())) {
HOST_ID = value.getString();
} else {
logger.error("Unable to find Host ID in Config file");
return false;
}
return setCryptoKey();
}
private boolean loadAuthentication() {
// if no database, must load authentication from file
XmlValue value = hashConfig.get(XML_AUTHENTIFICATION_FILE);
if (value != null && (!value.isEmpty())) {
setAuthenticationFile(value.getString());
if (!initializeAuthent(getAuthenticationFile(), false)) {
return false;
}
} else {
logger.warn("Unable to find Authentication file in Config file");
return false;
}
return true;
}
private boolean loadServerParam() {
XmlValue value = hashConfig.get(XML_USEHTTPCOMP);
if (value != null && (!value.isEmpty())) {
useHttpCompression = value.getBoolean();
}
value = hashConfig.get(XML_USELOCALEXEC);
if (value != null && (!value.isEmpty())) {
useLocalExec = value.getBoolean();
if (useLocalExec) {
value = hashConfig.get(XML_LEXECADDR);
String saddr;
InetAddress addr;
if (value != null && (!value.isEmpty())) {
saddr = value.getString();
try {
addr = InetAddress.getByName(saddr);
} catch (UnknownHostException e) {
logger.error("Unable to find LocalExec Address in Config file");
return false;
}
} else {
logger.warn("Unable to find LocalExec Address in Config file");
try {
addr = InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 });
} catch (UnknownHostException e) {
logger.error("Unable to find LocalExec Address in Config file");
return false;
}
}
value = hashConfig.get(XML_LEXECPORT);
int port;
if (value != null && (!value.isEmpty())) {
port = value.getInteger();
} else {
port = 9999;
}
LocalExecClient.setAddress(new InetSocketAddress(addr, port));
}
}
value = hashConfig.get(XML_SERVER_ADMIN);
if (value != null && (!value.isEmpty())) {
ADMINNAME = value.getString();
} else {
logger.error("Unable to find Administrator name in Config file");
return false;
}
if (cryptoKey == null) {
if (!setCryptoKey()) {
logger.error("Unable to find Crypto Key in Config file");
return false;
}
}
String passwd;
value = hashConfig.get(XML_SERVER_PASSWD);
if (value != null && (!value.isEmpty())) {
passwd = value.getString();
} else {
logger.error("Unable to find Password in Config file");
return false;
}
byte[] decodedByteKeys = null;
try {
decodedByteKeys =
cryptoKey.decryptHexInBytes(passwd);
} catch (Exception e) {
logger.error(
"Unable to Decrypt Server Password in Config file from: " +
passwd, e);
return false;
}
setSERVERKEY(decodedByteKeys);
value = hashConfig.get(XML_HTTPADMINPATH);
if (value == null || (value.isEmpty())) {
logger.error("Unable to find Http Admin Base in Config file");
return false;
}
String path = value.getString();
if (path == null || path.length() == 0) {
logger.warn("Unable to set correct Http Admin Base in Config file. No HTTPS support will be used.");
httpBasePath = null;
} else {
File file = new File(path);
if (!file.isDirectory()) {
logger.error("Http Admin is not a directory in Config file");
return false;
}
try {
httpBasePath =
FilesystemBasedDirImpl.normalizePath(file.getCanonicalPath()) +
DirInterface.SEPARATOR;
} catch (IOException e1) {
logger.error("Unable to set Http Admin Path in Config file");
return false;
}
}
if (httpBasePath != null) {
// Key for HTTPS
value = hashConfig.get(XML_PATH_ADMIN_KEYPATH);
if (value != null && (!value.isEmpty())) {
String keypath = value.getString();
if ((keypath == null) || (keypath.length() == 0)) {
logger.error("Bad Key Path");
return false;
}
value = hashConfig.get(XML_PATH_ADMIN_KEYSTOREPASS);
if (value == null || (value.isEmpty())) {
logger.error("Unable to find KeyStore Passwd");
return false;
}
String keystorepass = value.getString();
if ((keystorepass == null) || (keystorepass.length() == 0)) {
logger.error("Bad KeyStore Passwd");
return false;
}
value = hashConfig.get(XML_PATH_ADMIN_KEYPASS);
if (value == null || (value.isEmpty())) {
logger.error("Unable to find Key Passwd");
return false;
}
String keypass = value.getString();
if ((keypass == null) || (keypass.length() == 0)) {
logger.error("Bad Key Passwd");
return false;
}
try {
HttpSslInitializer.waarpSecureKeyStore =
new WaarpSecureKeyStore(keypath, keystorepass,
keypass);
} catch (CryptoException e) {
logger.error("Bad SecureKeyStore construction for AdminSsl");
return false;
}
// No client authentication
HttpSslInitializer.waarpSecureKeyStore.initEmptyTrustStore();
HttpSslInitializer.waarpSslContextFactory =
new WaarpSslContextFactory(
HttpSslInitializer.waarpSecureKeyStore, true);
}
}
value = hashConfig.get(XML_MONITOR_SNMP_CONFIG);
if (value != null && (!value.isEmpty())) {
snmpConfig = value.getString();
logger.warn("SNMP configuration file: " + snmpConfig);
File snmpfile = new File(snmpConfig);
if (snmpfile.canRead()) {
if (!SnmpConfiguration.setConfigurationFromXml(snmpfile)) {
logger.warn("Bad SNMP configuration file: " + snmpConfig);
snmpConfig = null;
}
} else {
logger.warn("Cannot read SNMP configuration file: " + snmpConfig);
snmpConfig = null;
}
} else {
logger.warn("NO SNMP configuration file");
}
return true;
}
private boolean loadDirectory() {
XmlValue value = hashConfig.get(XML_SERVER_HOME);
if (value == null || (value.isEmpty())) {
logger.error("Unable to find Home in Config file");
return false;
}
String path = value.getString();
File file = new File(path);
if (!file.isDirectory()) {
logger.error("Home is not a directory in Config file");
return false;
}
try {
setBaseDirectory(FilesystemBasedDirImpl.normalizePath(file
.getCanonicalPath()));
} catch (IOException e1) {
logger.error("Unable to set Home in Config file: " + path);
return false;
}
return true;
}
private boolean loadLimit(boolean updateLimit) {
XmlValue value = hashConfig.get(XML_LIMITGLOBAL);
if (value != null && (!value.isEmpty())) {
serverGlobalReadLimit = value.getLong();
if (serverGlobalReadLimit <= 0) {
serverGlobalReadLimit = 0;
}
serverGlobalWriteLimit = serverGlobalReadLimit;
logger.info("Global Limit: {}",
serverGlobalReadLimit);
}
value = hashConfig.get(XML_LIMITSESSION);
if (value != null && (!value.isEmpty())) {
serverChannelReadLimit = value.getLong();
if (serverChannelReadLimit <= 0) {
serverChannelReadLimit = 0;
}
serverChannelWriteLimit = serverChannelReadLimit;
logger.info("SessionInterface Limit: {}",
serverChannelReadLimit);
}
delayLimit = AbstractTrafficShapingHandler.DEFAULT_CHECK_INTERVAL;
value = hashConfig.get(XML_LIMITDELAY);
if (value != null && (!value.isEmpty())) {
delayLimit = (value.getLong() / 10) * 10;
if (delayLimit <= 0) {
delayLimit = 0;
}
logger.info("Delay Limit: {}",
delayLimit);
}
boolean useCpuLimit = false;
boolean useCpuLimitJDK = false;
double cpulimit = 1.0;
value = hashConfig.get(XML_CSTRT_USECPULIMIT);
if (value != null && (!value.isEmpty())) {
useCpuLimit = value.getBoolean();
value = hashConfig.get(XML_CSTRT_USECPUJDKLIMIT);
if (value != null && (!value.isEmpty())) {
useCpuLimitJDK = value.getBoolean();
}
value = hashConfig.get(XML_CSTRT_CPULIMIT);
if (value != null && (!value.isEmpty())) {
cpulimit = value.getDouble();
}
}
int connlimit = 0;
value = hashConfig.get(XML_CSTRT_CONNLIMIT);
if (value != null && (!value.isEmpty())) {
connlimit = value.getInteger();
}
double lowcpuLimit = 0;
double highcpuLimit = 0;
double percentageDecrease = 0;
long delay = 1000000;
long limitLowBandwidth = 4096;
value = hashConfig.get(XML_CSTRT_LOWCPULIMIT);
if (value != null && (!value.isEmpty())) {
lowcpuLimit = value.getDouble();
}
value = hashConfig.get(XML_CSTRT_HIGHCPULIMIT);
if (value != null && (!value.isEmpty())) {
highcpuLimit = value.getDouble();
}
value = hashConfig.get(XML_CSTRT_PERCENTDECREASE);
if (value != null && (!value.isEmpty())) {
percentageDecrease = value.getDouble();
}
value = hashConfig.get(XML_CSTRT_DELAYTHROTTLE);
if (value != null && (!value.isEmpty())) {
delay = (value.getLong() / 10) * 10;
}
value = hashConfig.get(XML_CSTRT_LIMITLOWBANDWIDTH);
if (value != null && (!value.isEmpty())) {
limitLowBandwidth = value.getLong();
}
value = hashConfig.get(XML_TIMEOUTCON);
if (value != null && (!value.isEmpty())) {
setTIMEOUTCON((value.getLong() / 10) * 10);
}
if (highcpuLimit > 0) {
constraintLimitHandler =
new FtpConstraintLimitHandler(getTIMEOUTCON(), useCpuLimit, useCpuLimitJDK,
cpulimit, connlimit,
lowcpuLimit, highcpuLimit, percentageDecrease, null, delay,
limitLowBandwidth);
} else {
constraintLimitHandler =
new FtpConstraintLimitHandler(getTIMEOUTCON(), useCpuLimit, useCpuLimitJDK,
cpulimit, connlimit);
}
value = hashConfig.get(XML_SERVER_THREAD);
if (value != null && (!value.isEmpty())) {
setSERVER_THREAD(value.getInteger());
}
value = hashConfig.get(XML_CLIENT_THREAD);
if (value != null && (!value.isEmpty())) {
setCLIENT_THREAD(value.getInteger());
}
if (getSERVER_THREAD() == 0 || getCLIENT_THREAD() == 0) {
computeNbThreads();
}
value = hashConfig.get(XML_MEMORY_LIMIT);
if (value != null && (!value.isEmpty())) {
setMaxGlobalMemory(value.getLong());
}
((FilesystemBasedFileParameterImpl) getFileParameter()).deleteOnAbort = false;
value = hashConfig.get(XML_USENIO);
if (value != null && (!value.isEmpty())) {
FilesystemBasedFileParameterImpl.useNio = value.getBoolean();
}
value = hashConfig.get(XML_USEFASTMD5);
if (value != null && (!value.isEmpty())) {
FilesystemBasedDigest.setUseFastMd5(value.getBoolean());
}
value = hashConfig.get(XML_BLOCKSIZE);
if (value != null && (!value.isEmpty())) {
setBLOCKSIZE(value.getInteger());
}
value = hashConfig.get(XML_DELETEONABORT);
if (value != null && (!value.isEmpty())) {
setDeleteOnAbort(value.getBoolean());
}
// We use Apache Commons IO
FilesystemBasedDirJdkAbstract.ueApacheCommonsIo = true;
return true;
}
private boolean loadNetworkServer() {
XmlValue value = hashConfig.get(XML_SERVER_PORT);
int port = 21;
if (value != null && (!value.isEmpty())) {
port = value.getInteger();
} else {
port = 21;
}
setServerPort(port);
value = hashConfig.get(XML_SERVER_ADDRESS);
String address = null;
if (value != null && (!value.isEmpty())) {
address = value.getString();
}
setServerAddress(address);
int min = 100;
int max = 65535;
value = hashConfig.get(XML_RANGE_PORT_MIN);
if (value != null && (!value.isEmpty())) {
min = value.getInteger();
}
value = hashConfig.get(XML_RANGE_PORT_MAX);
if (value != null && (!value.isEmpty())) {
max = value.getInteger();
}
logger.warn("Passive Port range Min: " + min + " Max: " + max);
CircularIntValue rangePort = new CircularIntValue(min, max);
setRangePort(rangePort);
value = hashConfig.get(XML_SERVER_HTTPS_PORT);
int httpsport = 8067;
if (value != null && (!value.isEmpty())) {
httpsport = value.getInteger();
}
SERVER_HTTPSPORT = httpsport;
return true;
}
/**
* Set the Crypto Key from the Document
*
* @param document
* @return True if OK
*/
private boolean setCryptoKey() {
XmlValue value = hashConfig.get(XML_PATH_CRYPTOKEY);
if (value == null || (value.isEmpty())) {
logger.error("Unable to find CryptoKey in Config file");
return false;
}
String filename = value.getString();
File key = new File(filename);
Des des = new Des();
try {
des.setSecretKey(key);
} catch (CryptoException e) {
logger.error("Unable to load CryptoKey from Config file");
return false;
} catch (IOException e) {
logger.error("Unable to load CryptoKey from Config file");
return false;
}
cryptoKey = des;
return true;
}
/**
*
* @return True if the global Exec parameters are correctly loaded
*/
private boolean loadExec() {
// Specific Exec command options
XmlValue value = hashConfig.get(XML_RETRIEVE_COMMAND);
if (value == null || (value.isEmpty())) {
logger.error("Unable to find Retrieve Command in Config file");
return false;
}
String retrieve = value.getString();
value = hashConfig.get(XML_DELAYRETRIEVE_COMMAND);
long retrievedelay = 0;
if (value != null && (!value.isEmpty())) {
retrievedelay = (value.getLong() / 10) * 10;
}
value = hashConfig.get(XML_STORE_COMMAND);
if (value == null || (value.isEmpty())) {
logger.error("Unable to find Store Command in Config file");
return false;
}
String store = value.getString();
value = hashConfig.get(XML_DELAYSTORE_COMMAND);
long storedelay = 0;
if (value != null && (!value.isEmpty())) {
storedelay = (value.getLong() / 10) * 10;
}
AbstractExecutor.initializeExecutor(retrieve, retrievedelay, store, storedelay);
return true;
}
/**
* Load database parameter
*
* @param document
* @return True if OK
*/
private boolean loadDatabase() {
XmlValue value = hashConfig.get(XML_DBDRIVER);
if (value == null || (value.isEmpty())) {
logger.error("Unable to find DBDriver in Config file");
DbConstant.gatewayAdmin = new DbAdmin(); // no database support
} else {
String dbdriver = value.getString();
value = hashConfig.get(XML_DBSERVER);
if (value == null || (value.isEmpty())) {
logger.error("Unable to find DBServer in Config file");
return false;
}
String dbserver = value.getString();
value = hashConfig.get(XML_DBUSER);
if (value == null || (value.isEmpty())) {
logger.error("Unable to find DBUser in Config file");
return false;
}
String dbuser = value.getString();
value = hashConfig.get(XML_DBPASSWD);
if (value == null || (value.isEmpty())) {
logger.error("Unable to find DBPassword in Config file");
return false;
}
String dbpasswd = value.getString();
if (dbdriver == null || dbserver == null || dbuser == null ||
dbpasswd == null || dbdriver.length() == 0 ||
dbserver.length() == 0 || dbuser.length() == 0 ||
dbpasswd.length() == 0) {
logger.error("Unable to find Correct DB data in Config file");
return false;
}
try {
DbConstant.gatewayAdmin =
DbModelFactory.initialize(dbdriver, dbserver, dbuser, dbpasswd,
true);
DbConstant.admin = DbConstant.gatewayAdmin;
} catch (WaarpDatabaseNoConnectionException e2) {
logger.error("Unable to Connect to DB", e2);
return false;
}
}
return true;
}
protected boolean loadSsl() {
// StoreKey for Server
XmlValue value = hashConfig.get(XML_PATH_KEYPATH);
if (value == null || (value.isEmpty())) {
logger.info("Unable to find Key Path");
getFtpInternalConfiguration().setUsingNativeSsl(false);
getFtpInternalConfiguration().setAcceptAuthProt(false);
return true;
} else {
String keypath = value.getString();
if ((keypath == null) || (keypath.length() == 0)) {
logger.error("Bad Key Path");
return false;
}
value = hashConfig.get(XML_PATH_KEYSTOREPASS);
if (value == null || (value.isEmpty())) {
logger.error("Unable to find KeyStore Passwd");
return false;
}
String keystorepass = value.getString();
if ((keystorepass == null) || (keystorepass.length() == 0)) {
logger.error("Bad KeyStore Passwd");
return false;
}
value = hashConfig.get(XML_PATH_KEYPASS);
if (value == null || (value.isEmpty())) {
logger.error("Unable to find Key Passwd");
return false;
}
String keypass = value.getString();
if ((keypass == null) || (keypass.length() == 0)) {
logger.error("Bad Key Passwd");
return false;
}
try {
FtpsInitializer.waarpSecureKeyStore =
new WaarpSecureKeyStore(keypath, keystorepass,
keypass);
} catch (CryptoException e) {
logger.error("Bad SecureKeyStore construction");
return false;
}
}
// TrustedKey for OpenR66 server
value = hashConfig.get(XML_PATH_TRUSTKEYPATH);
if (value == null || (value.isEmpty())) {
logger.info("Unable to find TRUST Key Path");
FtpsInitializer.waarpSecureKeyStore.initEmptyTrustStore();
} else {
String keypath = value.getString();
if ((keypath == null) || (keypath.length() == 0)) {
logger.error("Bad TRUST Key Path");
return false;
}
value = hashConfig.get(XML_PATH_TRUSTKEYSTOREPASS);
if (value == null || (value.isEmpty())) {
logger.error("Unable to find TRUST KeyStore Passwd");
return false;
}
String keystorepass = value.getString();
if ((keystorepass == null) || (keystorepass.length() == 0)) {
logger.error("Bad TRUST KeyStore Passwd");
return false;
}
boolean useClientAuthent = false;
value = hashConfig.get(XML_USECLIENT_AUTHENT);
if (value != null && (!value.isEmpty())) {
useClientAuthent = value.getBoolean();
}
try {
FtpsInitializer.waarpSecureKeyStore.initTrustStore(keypath,
keystorepass, useClientAuthent);
} catch (CryptoException e) {
logger.error("Bad TrustKeyStore construction");
return false;
}
}
FtpsInitializer.waarpSslContextFactory =
new WaarpSslContextFactory(
FtpsInitializer.waarpSecureKeyStore);
boolean useImplicit = false;
value = hashConfig.get(XML_IMPLICIT_FTPS);
if (value != null && (!value.isEmpty())) {
useImplicit = value.getBoolean();
}
boolean useExplicit = false;
value = hashConfig.get(XML_EXPLICIT_FTPS);
if (value != null && (!value.isEmpty())) {
useExplicit = value.getBoolean();
}
if (useImplicit && useExplicit) {
logger.error("Only one of IMPLICIT or EXPLICIT could be True");
return false;
}
if ((!useImplicit) && (!useExplicit)) {
logger.error("Since all SecureStore are specified, one of IMPLICIT or EXPLICIT should be True");
logger.warn("FTPS support will be ignored...");
getFtpInternalConfiguration().setUsingNativeSsl(false);
getFtpInternalConfiguration().setAcceptAuthProt(false);
return true;
}
getFtpInternalConfiguration().setUsingNativeSsl(useImplicit);
getFtpInternalConfiguration().setAcceptAuthProt(useExplicit);
return true;
}
/**
* Initiate the configuration from the xml file for server
*
* @param filename
* @return True if OK
*/
public boolean setConfigurationServerFromXml(String filename) {
Document document = null;
// Open config file
try {
document = new SAXReader().read(filename);
} catch (DocumentException e) {
logger.error("Unable to read the XML Config file: " + filename, e);
return false;
}
if (document == null) {
logger.error("Unable to read the XML Config file: " + filename);
return false;
}
configuration = XmlUtil.read(document, configServer);
hashConfig = new XmlHash(configuration);
// Now read the configuration
if (!loadIdentity()) {
logger.error("Cannot load Identity");
return false;
}
if (!loadDatabase()) {
logger.error("Cannot load Database configuration");
return false;
}
if (!loadServerParam()) {
logger.error("Cannot load Server Parameters");
return false;
}
if (!loadDirectory()) {
logger.error("Cannot load Directory configuration");
return false;
}
if (!loadLimit(false)) {
logger.error("Cannot load Limit configuration");
return false;
}
if (!loadNetworkServer()) {
logger.error("Cannot load Network configuration");
return false;
}
if (!loadExec()) {
logger.error("Cannot load Exec configuration");
return false;
}
// if (!DbConstant.admin.isActive) {
// if no database, must load authentication from file
if (!loadAuthentication()) {
logger.error("Cannot load Authentication configuration");
return false;
}
if (!loadSsl()) {
// ignore and continue => No SSL
getFtpInternalConfiguration().setUsingNativeSsl(false);
getFtpInternalConfiguration().setAcceptAuthProt(false);
return false;
}
// }
hashConfig.clear();
hashConfig = null;
configuration = null;
return true;
}
/**
* Configure HTTPS
*/
public void configureHttps() {
// Now start the HTTPS support
// Configure the server.
httpsBootstrap = new ServerBootstrap();
httpExecutor = new NioEventLoopGroup(getSERVER_THREAD() * 10, new WaarpThreadFactory(
"HttpExecutor"));
bossGroup = new NioEventLoopGroup(getSERVER_THREAD(), new WaarpThreadFactory("HTTP_Boss"));
workerGroup = new NioEventLoopGroup(getSERVER_THREAD() * 10, new WaarpThreadFactory("HTTP_Worker"));
WaarpNettyUtil.setServerBootstrap(httpsBootstrap, bossGroup, workerGroup, (int) getTIMEOUTCON());
// Configure the pipeline factory.
httpsBootstrap.childHandler(new HttpSslInitializer(useHttpCompression));
httpChannelGroup = new DefaultChannelGroup("HttpOpenR66", httpExecutor.next());
// Bind and start to accept incoming connections.
logger.warn("Start Https Support on port: " + SERVER_HTTPSPORT + " with "+ (useHttpCompression ? "" : "no") +" compression support");
ChannelFuture future = httpsBootstrap.bind(new InetSocketAddress(SERVER_HTTPSPORT));
if (future.awaitUninterruptibly().isSuccess()) {
httpChannelGroup.add(future.channel());
}
}
/**
* Configure ConstraintLimitHandler
*/
public void configureConstraint() {
constraintLimitHandler.setHandler(
this.getFtpInternalConfiguration().getGlobalTrafficShapingHandler());
}
/**
* Configure LocalExec
*/
public void configureLExec() {
if (useLocalExec) {
LocalExecClient.initialize(this.getCLIENT_THREAD(), this.getMaxGlobalMemory());
}
}
/**
* Configure the SNMP support if needed
*
* @throws FtpNoConnectionException
*/
public void configureSnmp() throws FtpNoConnectionException {
monitoring = new FtpMonitoring(null);
if (snmpConfig != null) {
int snmpPortShow = getServerPort();
ftpMib =
new FtpPrivateMib(snmpPortShow);
WaarpMOFactory.setFactory(new FtpVariableFactory());
agentSnmp = new WaarpSnmpAgent(new File(snmpConfig), monitoring, ftpMib);
try {
agentSnmp.start();
logger.debug("SNMP configured");
} catch (IOException e) {
monitoring.releaseResources();
monitoring = null;
ftpMib = null;
agentSnmp = null;
throw new FtpNoConnectionException("AgentSnmp Error while starting", e);
}
}
}
/**
* @param serverkey
* the SERVERADMINKEY to set
*/
public void setSERVERKEY(byte[] serverkey) {
SERVERADMINKEY = serverkey;
}
/**
* Check the password for Shutdown
*
* @param password
* @return True if the password is OK
*/
public boolean checkPassword(String password) {
if (password == null) {
return false;
}
return Arrays.equals(SERVERADMINKEY, password.getBytes(WaarpStringUtils.UTF8));
}
/**
* Initialize Authentication from current authenticationFile
*
* @param filename
* the filename from which authentication will be loaded
* @param purge
* if True, the current authentications are totally replaced by the new ones
* @return True if OK
*/
@SuppressWarnings("unchecked")
public boolean initializeAuthent(String filename, boolean purge) {
Document document = null;
try {
document = new SAXReader().read(filename);
} catch (DocumentException e) {
logger.error("Unable to read the XML Authentication file: " +
filename, e);
return false;
}
if (document == null) {
logger.error("Unable to read the XML Authentication file: " +
filename);
return false;
}
XmlValue[] configuration = XmlUtil.read(document, authentElements);
XmlHash hashConfig = new XmlHash(configuration);
XmlValue value = hashConfig.get(XML_AUTHENTIFICATION_ENTRY);
List<XmlValue[]> list = (List<XmlValue[]>) value.getList();
ConcurrentHashMap<String, SimpleAuth> newAuthents =
new ConcurrentHashMap<String, SimpleAuth>();
for (XmlValue[] xmlValues : list) {
hashConfig = new XmlHash(xmlValues);
value = hashConfig.get(XML_AUTHENTICATION_USER);
if (value == null || (value.isEmpty())) {
logger.error("Unable to find a User in Config file");
continue;
}
String user = value.getString();
value = hashConfig.get(XML_AUTHENTICATION_ACCOUNT);
if (value == null || (value.isEmpty())) {
logger.error("Unable to find a Account in Config file: " + user);
continue;
}
String[] account = null;
List<String> listaccount = (List<String>) value.getList();
if (!listaccount.isEmpty()) {
account = new String[listaccount.size()];
int i = 0;
Iterator<String> iteratoraccount = listaccount.iterator();
while (iteratoraccount.hasNext()) {
account[i] = iteratoraccount.next();
// logger.debug("User: {} Acct: {}", user, account[i]);
File directory = new File(getBaseDirectory() + "/" + user + "/" + account[i]);
directory.mkdirs();
i++;
}
} else {
logger.error("Unable to find a Account in Config file: " + user);
continue;
}
value = hashConfig.get(XML_AUTHENTICATION_ADMIN);
boolean isAdmin = false;
if (value != null && (!value.isEmpty())) {
isAdmin = value.getBoolean();
}
String retrcmd = null;
long retrdelay = 0;
String storcmd = null;
long stordelay = 0;
value = hashConfig.get(XML_RETRIEVE_COMMAND);
if (value != null && (!value.isEmpty())) {
retrcmd = value.getString();
}
value = hashConfig.get(XML_DELAYRETRIEVE_COMMAND);
if (value != null && (!value.isEmpty())) {
retrdelay = (value.getLong() / 10) * 10;
}
value = hashConfig.get(XML_STORE_COMMAND);
if (value != null && (!value.isEmpty())) {
storcmd = value.getString();
}
value = hashConfig.get(XML_DELAYSTORE_COMMAND);
if (value != null && (!value.isEmpty())) {
stordelay = (value.getLong() / 10) * 10;
}
String passwd;
value = hashConfig.get(XML_AUTHENTICATION_PASSWDFILE);
if (value != null && (!value.isEmpty())) {
// load key from file
File key = new File(value.getString());
if (!key.canRead()) {
logger.error("Cannot read key for user " + user + ":" + key.getName());
continue;
}
try {
byte[] byteKeys = cryptoKey.decryptHexFile(key);
passwd = new String(byteKeys, WaarpStringUtils.UTF8);
} catch (Exception e2) {
logger.error("Cannot read key for user " + user, e2);
continue;
}
} else {
value = hashConfig.get(XML_AUTHENTICATION_PASSWD);
if (value != null && (!value.isEmpty())) {
String encrypted = value.getString();
byte[] byteKeys = null;
try {
byteKeys =
cryptoKey.decryptHexInBytes(encrypted);
passwd = new String(byteKeys, WaarpStringUtils.UTF8);
} catch (Exception e) {
logger.error(
"Unable to Decrypt Key for user " + user, e);
continue;
}
} else {
logger.error("Unable to find Password in Config file");
// DO NOT Allow empty key
continue;
}
}
SimpleAuth auth = new SimpleAuth(user, passwd, account,
storcmd, stordelay, retrcmd, retrdelay);
auth.setAdmin(isAdmin);
newAuthents.put(user, auth);
hashConfig.clear();
}
hashConfig.clear();
configuration = null;
if (purge) {
ConcurrentHashMap<String, SimpleAuth> previousOne = authentications;
authentications = newAuthents;
previousOne.clear();
} else {
authentications.putAll(newAuthents);
newAuthents.clear();
}
document = null;
return true;
}
/**
* Export the Authentication to the original files
*
* @param filename
* the filename where the authentication will be exported
* @return True if successful
*/
public boolean saveAuthenticationFile(String filename) {
Document document = XmlUtil.createEmptyDocument();
XmlValue[] roots = new XmlValue[1];
XmlValue root = new XmlValue(authentElements[0]);
roots[0] = root;
Enumeration<SimpleAuth> auths = authentications.elements();
while (auths.hasMoreElements()) {
SimpleAuth auth = auths.nextElement();
XmlValue[] values = new XmlValue[configAuthenticationDecls.length];
for (int i = 0; i < configAuthenticationDecls.length; i++) {
values[i] = new XmlValue(configAuthenticationDecls[i]);
}
try {
values[0].setFromString(auth.getUser());
// PasswdFile: none values[1].setFromString();
values[2].setFromString(auth.getPassword());
} catch (InvalidArgumentException e1) {
logger.error("Error during Write Authentication file", e1);
return false;
}
// Accounts
String[] accts = auth.getAccounts();
for (String string : accts) {
try {
values[3].addFromString(string);
} catch (InvalidObjectException e) {
logger.error("Error during Write Authentication file", e);
return false;
} catch (InvalidArgumentException e) {
logger.error("Error during Write Authentication file", e);
return false;
}
}
try {
values[4].setValue(auth.isAdmin());
} catch (InvalidObjectException e) {
logger.error("Error during Write Authentication file", e);
return false;
}
try {
values[5].setFromString(auth.getRetrCmd());
} catch (InvalidArgumentException e1) {
logger.error("Error during Write Authentication file", e1);
return false;
}
try {
values[6].setValue(auth.getRetrDelay());
} catch (InvalidObjectException e) {
logger.error("Error during Write Authentication file", e);
return false;
}
try {
values[7].setFromString(auth.getStorCmd());
} catch (InvalidArgumentException e1) {
logger.error("Error during Write Authentication file", e1);
return false;
}
try {
values[8].setValue(auth.getStorDelay());
} catch (InvalidObjectException e) {
logger.error("Error during Write Authentication file", e);
return false;
}
try {
root.addValue(values);
} catch (InvalidObjectException e) {
logger.error("Error during Write Authentication file", e);
return false;
}
}
XmlUtil.write(document, roots);
try {
XmlUtil.saveDocument(filename, document);
} catch (IOException e1) {
logger.error("Cannot write to file: " + filename + " since {}", e1.getMessage());
return false;
}
return true;
}
/**
* @param user
* @return the SimpleAuth if any for this user
*/
public SimpleAuth getSimpleAuth(String user) {
return authentications.get(user);
}
/**
* @param format
* Format in HTML to use as ouput format
* @return the Html String containing the table of all Authentication entries
*/
public String getHtmlAuth(String format) {
String result;
StringBuilder builder = new StringBuilder();
/*
* XXXUSERXXX XXXPWDXXX XXXACTSXXX XXXADMXXX XXXSTCXXX XXXSTDXXX XXXRTCXXX XXXRTDXXX
*/
Enumeration<SimpleAuth> simpleAuths = authentications.elements();
SimpleAuth auth = null;
while (simpleAuths.hasMoreElements()) {
auth = simpleAuths.nextElement();
String newElt = format.replace("XXXUSERXXX", auth.getUser());
newElt = newElt.replace("XXXPWDXXX", auth.getPassword());
if (auth.getStorCmd() != null)
newElt = newElt.replace("XXXSTCXXX", auth.getStorCmd());
else
newElt = newElt.replace("XXXSTCXXX", "");
if (auth.getRetrCmd() != null)
newElt = newElt.replace("XXXRTCXXX", auth.getRetrCmd());
else
newElt = newElt.replace("XXXRTCXXX", "");
newElt = newElt.replace("XXXSTDXXX", Long.toString(auth.getStorDelay()));
newElt = newElt.replace("XXXRTDXXX", Long.toString(auth.getRetrDelay()));
newElt = newElt.replace("XXXADMXXX", Boolean.toString(auth.isAdmin()));
if (auth.getAccounts() != null) {
StringBuilder accts = new StringBuilder();
for (int i = 0; i < auth.getAccounts().length - 1; i++) {
accts.append(auth.getAccounts()[i]).append(", ");
}
accts.append(auth.getAccounts()[auth.getAccounts().length - 1]);
newElt = newElt.replace("XXXACTSXXX", accts.toString());
} else {
newElt = newElt.replace("XXXACTSXXX", "No Account");
}
builder.append(newElt);
}
result = builder.toString();
return result;
}
/**
* Only available with Database support for Waarp
*
* @param format
* Format in HTML to use as ouput format
* @param limit
* number of TransferLog to populate
* @return the Html String containing the table of all Transfer entries
*/
public String getHtmlTransfer(String format, int limit) {
String result;
StringBuilder builder = new StringBuilder();
/*
* XXXIDXXX XXXUSERXXX XXXACCTXXX XXXFILEXXX XXXMODEXXX XXXSTATUSXXX XXXINFOXXX XXXUPINFXXX
* XXXSTARTXXX XXXSTOPXXX
*/
if (!DbConstant.gatewayAdmin.isActive()) {
return "";
}
DbPreparedStatement preparedStatement = null;
try {
try {
preparedStatement =
DbTransferLog
.getStatusPrepareStament(DbConstant.gatewayAdmin.getSession(), null, limit);
preparedStatement.executeQuery();
} catch (WaarpDatabaseNoConnectionException e) {
return "";
} catch (WaarpDatabaseSqlException e) {
return "";
}
try {
while (preparedStatement.getNext()) {
DbTransferLog log = DbTransferLog.getFromStatement(preparedStatement);
String newElt = format
.replaceAll("XXXIDXXX", Long.toString(log.getSpecialId()));
newElt = newElt.replaceAll("XXXUSERXXX", log.getUser());
newElt = newElt.replaceAll("XXXACCTXXX", log.getAccount());
newElt = newElt.replace("XXXFILEXXX", log.getFilename());
newElt = newElt.replace("XXXMODEXXX", log.getMode());
newElt = newElt.replace("XXXSTATUSXXX", log.getErrorInfo().getMesg());
newElt = newElt.replace("XXXINFOXXX", log.getInfotransf());
newElt = newElt.replace("XXXUPINFXXX", log.getUpdatedInfo().name());
newElt = newElt.replace("XXXSTARTXXX", log.getStart().toString());
newElt = newElt.replace("XXXSTOPXXX", log.getStop().toString());
builder.append(newElt);
}
} catch (WaarpDatabaseNoConnectionException e) {
return "";
} catch (WaarpDatabaseSqlException e) {
return "";
}
result = builder.toString();
return result;
} finally {
if (preparedStatement != null) {
preparedStatement.realClose();
}
}
}
/**
* @see org.waarp.ftp.core.config.FtpConfiguration#getNextRangePort()
*/
@Override
public int getNextRangePort() {
try {
return ((CircularIntValue) getProperty(RANGE_PORT)).getNext();
} catch (FtpUnknownFieldException e) {
return -1;
}
}
/**
*
* @param rangePort
* the range of available ports for Passive connections
*/
private void setRangePort(CircularIntValue rangePort) {
setProperty(RANGE_PORT, rangePort);
}
/**
* @return the httpPipelineExecutor
*/
public EventExecutorGroup getHttpPipelineExecutor() {
return httpExecutor;
}
/**
* @return the httpChannelGroup
*/
public ChannelGroup getHttpChannelGroup() {
return httpChannelGroup;
}
/**
* Finalize resources attached to handlers
*
* @author Frederic Bregier
*/
private static class GgChannelGroupFutureListener implements
ChannelGroupFutureListener {
EventExecutorGroup executorBoss;
EventExecutorGroup executorWorker;
String name;
public GgChannelGroupFutureListener(
String name,
EventExecutorGroup executorBoss, EventExecutorGroup executorWorker) {
this.name = name;
this.executorBoss = executorBoss;
this.executorWorker = executorWorker;
}
public void operationComplete(ChannelGroupFuture future)
throws Exception {
if (executorBoss != null) {
executorBoss.shutdownGracefully();
}
if (executorWorker != null) {
executorWorker.shutdownGracefully();
}
logger.info("Done with shutdown " + name);
}
}
@Override
public void releaseResources() {
super.releaseResources();
if (httpChannelGroup != null) {
final int result = httpChannelGroup.size();
logger.debug("HttpChannelGroup: " + result);
httpChannelGroup.close().addListener(
new GgChannelGroupFutureListener(
"HttpChannelGroup",
bossGroup, workerGroup));
}
if (httpExecutor != null) {
httpExecutor.shutdownGracefully();
}
if (useLocalExec) {
LocalExecClient.releaseResources();
}
if (constraintLimitHandler != null) {
this.constraintLimitHandler.release();
}
if (agentSnmp != null) {
agentSnmp.stop();
}
DbAdmin.closeAllConnection();
}
@Override
public void inShutdownProcess() {
if (ftpMib != null) {
ftpMib.notifyStartStop("Shutdown in progress for " + HOST_ID, "Gives extra seconds: "
+ getTIMEOUTCON());
}
}
/**
* @return the authenticationFile
*/
public String getAuthenticationFile() {
return authenticationFile;
}
/**
* @param authenticationFile the authenticationFile to set
*/
public void setAuthenticationFile(String authenticationFile) {
this.authenticationFile = authenticationFile;
}
}