/**
* This file is part of Waarp Project.
*
* 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.
*
* All Waarp Project is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Waarp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Waarp . If not, see
* <http://www.gnu.org/licenses/>.
*/
package org.waarp.ftp.simpleimpl.config;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import io.netty.handler.traffic.AbstractTrafficShapingHandler;
import org.waarp.common.digest.FilesystemBasedDigest;
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.ftp.core.config.FtpConfiguration;
import org.waarp.ftp.core.control.BusinessHandler;
import org.waarp.ftp.core.data.handler.DataBusinessHandler;
import org.waarp.ftp.simpleimpl.file.SimpleAuth;
/**
* 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 PASSWORD (shutdown)
*/
private static final String XML_SERVER_PASSWD = "/config/serverpasswd";
/**
* SERVER PORT
*/
private static final String XML_SERVER_PORT = "/config/serverport";
/**
* SERVER ADDRESS if any
*/
private static final String XML_SERVER_ADDRESS = "/config/serveraddress";
/**
* Base Directory
*/
private static final String XML_SERVER_HOME = "/config/serverhome";
/**
* Default number of threads in pool for Server.
*/
private static final String XML_SERVER_THREAD = "/config/serverthread";
/**
* Default number of threads in pool for Client.
*/
private static final String XML_CLIENT_THREAD = "/config/clientthread";
/**
* Limit per session
*/
private static final String XML_LIMITSESSION = "/config/sessionlimit";
/**
* Limit global
*/
private static final String XML_LIMITGLOBAL = "/config/globallimit";
/**
* Nb of milliseconds after connection is in timeout
*/
private static final String XML_TIMEOUTCON = "/config/timeoutcon";
/**
* Should a file be deleted when a Store like command is aborted
*/
private static final String XML_DELETEONABORT = "/config/deleteonabort";
/**
* Should a file MD5 SHA1 be computed using NIO
*/
private static final String XML_USENIO = "/config/usenio";
/**
* Should a file MD5 be computed using FastMD5
*/
private static final String XML_USEFASTMD5 = "/config/usefastmd5";
/**
* 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 = "/config/blocksize";
/**
* RANGE of PORT for Passive Mode
*/
private static final String XML_RANGE_PORT_MIN = "/config/rangeport/min";
/**
* RANGE of PORT for Passive Mode
*/
private static final String XML_RANGE_PORT_MAX = "/config/rangeport/max";
/**
* Authentication
*/
private static final String XML_AUTHENTIFICATION_FILE = "/config/authentfile";
/**
* Authentication Fields
*/
private static final String XML_AUTHENTIFICATION_BASED = "/authent/entry";
/**
* Authentication Fields
*/
private static final String XML_AUTHENTIFICATION_USER = "user";
/**
* Authentication Fields
*/
private static final String XML_AUTHENTIFICATION_PASSWD = "passwd";
/**
* Authentication Fields
*/
private static final String XML_AUTHENTIFICATION_ACCOUNT = "account";
/**
* Authentication Fields
*/
private static final String XML_AUTHENTIFICATION_ADMIN = "admin";
/**
* RANGE of PORT for Passive Mode
*/
private CircularIntValue RANGE_PORT = null;
/**
* All authentications
*/
private final ConcurrentHashMap<String, SimpleAuth> authentications = new ConcurrentHashMap<String, SimpleAuth>();
/**
* @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();
}
/**
* Initiate the configuration from the xml file
*
* @param filename
* @return True if OK
*/
@SuppressWarnings("unchecked")
public boolean setConfigurationFromXml(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;
}
Node nodebase, node = null;
node = document.selectSingleNode(XML_SERVER_PASSWD);
if (node == null) {
logger.error("Unable to find Password in Config file: " + filename);
return false;
}
String passwd = node.getText();
setPassword(passwd);
node = document.selectSingleNode(XML_SERVER_PORT);
int port = 21;
if (node != null) {
port = Integer.parseInt(node.getText());
}
setServerPort(port);
node = document.selectSingleNode(XML_SERVER_ADDRESS);
String address = null;
if (node != null) {
address = node.getText();
}
setServerAddress(address);
node = document.selectSingleNode(XML_SERVER_HOME);
if (node == null) {
logger.error("Unable to find Home in Config file: " + filename);
return false;
}
String path = node.getText();
File file = new File(path);
try {
setBaseDirectory(FilesystemBasedDirImpl.normalizePath(file
.getCanonicalPath()));
} catch (IOException e1) {
logger.error("Unable to set Home in Config file: " + filename);
return false;
}
if (!file.isDirectory()) {
logger.error("Home is not a directory in Config file: " + filename);
return false;
}
node = document.selectSingleNode(XML_SERVER_THREAD);
if (node != null) {
setSERVER_THREAD(Integer.parseInt(node.getText()));
}
node = document.selectSingleNode(XML_CLIENT_THREAD);
if (node != null) {
setCLIENT_THREAD(Integer.parseInt(node.getText()));
}
if (getSERVER_THREAD() == 0 || getCLIENT_THREAD() == 0) {
computeNbThreads();
}
node = document.selectSingleNode(XML_LIMITGLOBAL);
if (node != null) {
serverGlobalReadLimit = Long.parseLong(node.getText());
if (serverGlobalReadLimit <= 0) {
serverGlobalReadLimit = 0;
}
serverGlobalWriteLimit = serverGlobalReadLimit;
logger.warn("Global Limit: {}", serverGlobalReadLimit);
}
node = document.selectSingleNode(XML_LIMITSESSION);
if (node != null) {
serverChannelReadLimit = Long.parseLong(node.getText());
if (serverChannelReadLimit <= 0) {
serverChannelReadLimit = 0;
}
serverChannelWriteLimit = serverChannelReadLimit;
logger.warn("SessionInterface Limit: {}", serverChannelReadLimit);
}
delayLimit = AbstractTrafficShapingHandler.DEFAULT_CHECK_INTERVAL;
node = document.selectSingleNode(XML_TIMEOUTCON);
if (node != null) {
setTIMEOUTCON(Integer.parseInt(node.getText()));
}
node = document.selectSingleNode(XML_DELETEONABORT);
if (node != null) {
setDeleteOnAbort(Integer.parseInt(node.getText()) == 1 ? true : false);
}
node = document.selectSingleNode(XML_USENIO);
if (node != null) {
FilesystemBasedFileParameterImpl.useNio = Integer.parseInt(node
.getText()) == 1 ? true : false;
}
node = document.selectSingleNode(XML_USEFASTMD5);
if (node != null) {
FilesystemBasedDigest.setUseFastMd5(Integer.parseInt(node.getText()) == 1 ? true
: false);
} else {
FilesystemBasedDigest.setUseFastMd5(false);
}
node = document.selectSingleNode(XML_BLOCKSIZE);
if (node != null) {
setBLOCKSIZE(Integer.parseInt(node.getText()));
}
node = document.selectSingleNode(XML_RANGE_PORT_MIN);
int min = 100;
if (node != null) {
min = Integer.parseInt(node.getText());
}
node = document.selectSingleNode(XML_RANGE_PORT_MAX);
int max = 65535;
if (node != null) {
max = Integer.parseInt(node.getText());
}
CircularIntValue rangePort = new CircularIntValue(min, max);
setRangePort(rangePort);
// We use Apache Commons IO
FilesystemBasedDirJdkAbstract.ueApacheCommonsIo = true;
node = document.selectSingleNode(XML_AUTHENTIFICATION_FILE);
if (node == null) {
logger.error("Unable to find Authentication file in Config file: " +
filename);
return false;
}
String fileauthent = node.getText();
document = null;
try {
document = new SAXReader().read(fileauthent);
} catch (DocumentException e) {
logger.error("Unable to read the XML Authentication file: " +
fileauthent, e);
return false;
}
if (document == null) {
logger.error("Unable to read the XML Authentication file: " +
fileauthent);
return false;
}
List<Node> list = document.selectNodes(XML_AUTHENTIFICATION_BASED);
Iterator<Node> iterator = list.iterator();
while (iterator.hasNext()) {
nodebase = iterator.next();
node = nodebase.selectSingleNode(XML_AUTHENTIFICATION_USER);
if (node == null) {
continue;
}
String user = node.getText();
node = nodebase.selectSingleNode(XML_AUTHENTIFICATION_PASSWD);
if (node == null) {
continue;
}
String userpasswd = node.getText();
node = nodebase.selectSingleNode(XML_AUTHENTIFICATION_ADMIN);
boolean isAdmin = false;
if (node != null) {
isAdmin = node.getText().equals("1") ? true : false;
}
List<Node> listaccount = nodebase
.selectNodes(XML_AUTHENTIFICATION_ACCOUNT);
String[] account = null;
if (!listaccount.isEmpty()) {
account = new String[listaccount.size()];
int i = 0;
Iterator<Node> iteratoraccount = listaccount.iterator();
while (iteratoraccount.hasNext()) {
node = iteratoraccount.next();
account[i] = node.getText();
// logger.debug("User: {} Acct: {}", user, account[i]);
i++;
}
}
SimpleAuth auth = new SimpleAuth(user, userpasswd, account);
auth.setAdmin(isAdmin);
authentications.put(user, auth);
}
document = null;
return true;
}
/**
* @param user
* @return the SimpleAuth if any for this user
*/
public SimpleAuth getSimpleAuth(String user) {
return authentications.get(user);
}
/**
* @see org.waarp.ftp.core.config.FtpConfiguration#getNextRangePort()
*/
@Override
public int getNextRangePort() {
return RANGE_PORT.getNext();
}
/**
*
* @param rangePort
* the range of available ports for Passive connections
*/
private void setRangePort(CircularIntValue rangePort) {
RANGE_PORT = rangePort;
}
@Override
public void inShutdownProcess() {
// nothing to do
}
}