View Javadoc
1   /**
2    * Copyright 2009, Frederic Bregier, and individual contributors by the @author tags. See the
3    * COPYRIGHT.txt in the distribution for a full listing of individual contributors.
4    * 
5    * This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
6    * General Public License as published by the Free Software Foundation; either version 3.0 of the
7    * License, or (at your option) any later version.
8    * 
9    * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10   * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11   * GNU Lesser General Public License for more details.
12   * 
13   * You should have received a copy of the GNU Lesser General Public License along with this
14   * software; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
15   * Boston, MA 02110-1301 USA, or see the FSF site: http://www.fsf.org.
16   */
17  package org.waarp.gateway.ftp.config;
18  
19  import java.io.File;
20  import java.io.IOException;
21  import java.io.InvalidObjectException;
22  import java.net.InetAddress;
23  import java.net.InetSocketAddress;
24  import java.net.UnknownHostException;
25  import java.util.Arrays;
26  import java.util.Enumeration;
27  import java.util.Iterator;
28  import java.util.List;
29  import java.util.concurrent.ConcurrentHashMap;
30  
31  import org.dom4j.Document;
32  import org.dom4j.DocumentException;
33  import org.dom4j.io.SAXReader;
34  
35  import io.netty.bootstrap.ServerBootstrap;
36  import io.netty.channel.ChannelFuture;
37  import io.netty.channel.EventLoopGroup;
38  import io.netty.channel.group.ChannelGroup;
39  import io.netty.channel.group.ChannelGroupFuture;
40  import io.netty.channel.group.ChannelGroupFutureListener;
41  import io.netty.channel.group.DefaultChannelGroup;
42  import io.netty.channel.nio.NioEventLoopGroup;
43  import io.netty.handler.traffic.AbstractTrafficShapingHandler;
44  import io.netty.util.concurrent.EventExecutorGroup;
45  
46  import org.waarp.common.crypto.Des;
47  import org.waarp.common.crypto.ssl.WaarpSecureKeyStore;
48  import org.waarp.common.crypto.ssl.WaarpSslContextFactory;
49  import org.waarp.common.database.DbAdmin;
50  import org.waarp.common.database.DbPreparedStatement;
51  import org.waarp.common.database.exception.WaarpDatabaseNoConnectionException;
52  import org.waarp.common.database.exception.WaarpDatabaseSqlException;
53  import org.waarp.common.digest.FilesystemBasedDigest;
54  import org.waarp.common.exception.CryptoException;
55  import org.waarp.common.exception.InvalidArgumentException;
56  import org.waarp.common.file.DirInterface;
57  import org.waarp.common.file.FileParameterInterface;
58  import org.waarp.common.file.filesystembased.FilesystemBasedDirImpl;
59  import org.waarp.common.file.filesystembased.FilesystemBasedFileParameterImpl;
60  import org.waarp.common.file.filesystembased.specific.FilesystemBasedDirJdkAbstract;
61  import org.waarp.common.logging.WaarpLogger;
62  import org.waarp.common.logging.WaarpLoggerFactory;
63  import org.waarp.common.utility.WaarpNettyUtil;
64  import org.waarp.common.utility.WaarpStringUtils;
65  import org.waarp.common.utility.WaarpThreadFactory;
66  import org.waarp.common.xml.XmlDecl;
67  import org.waarp.common.xml.XmlHash;
68  import org.waarp.common.xml.XmlType;
69  import org.waarp.common.xml.XmlUtil;
70  import org.waarp.common.xml.XmlValue;
71  import org.waarp.ftp.core.config.FtpConfiguration;
72  import org.waarp.ftp.core.control.BusinessHandler;
73  import org.waarp.ftp.core.control.ftps.FtpsInitializer;
74  import org.waarp.ftp.core.data.handler.DataBusinessHandler;
75  import org.waarp.ftp.core.exception.FtpNoConnectionException;
76  import org.waarp.ftp.core.exception.FtpUnknownFieldException;
77  import org.waarp.gateway.ftp.adminssl.HttpSslInitializer;
78  import org.waarp.gateway.ftp.control.FtpConstraintLimitHandler;
79  import org.waarp.gateway.ftp.database.DbConstant;
80  import org.waarp.gateway.ftp.database.data.DbTransferLog;
81  import org.waarp.gateway.ftp.database.model.DbModelFactory;
82  import org.waarp.gateway.ftp.file.SimpleAuth;
83  import org.waarp.gateway.ftp.snmp.FtpMonitoring;
84  import org.waarp.gateway.ftp.snmp.FtpPrivateMib;
85  import org.waarp.gateway.ftp.snmp.FtpVariableFactory;
86  import org.waarp.gateway.kernel.exec.AbstractExecutor;
87  import org.waarp.gateway.kernel.exec.LocalExecClient;
88  import org.waarp.snmp.SnmpConfiguration;
89  import org.waarp.snmp.WaarpMOFactory;
90  import org.waarp.snmp.WaarpSnmpAgent;
91  
92  /**
93   * FtpConfiguration based on a XML file
94   * 
95   * @author Frederic Bregier
96   * 
97   */
98  public class FileBasedConfiguration extends FtpConfiguration {
99      /**
100      * Internal Logger
101      */
102     private static final WaarpLogger logger = WaarpLoggerFactory.getLogger(FileBasedConfiguration.class);
103 
104     /**
105      * SERVER HOSTID
106      */
107     private static final String XML_SERVER_HOSTID = "hostid";
108     /**
109      * Authentication
110      */
111     private static final String XML_AUTHENTIFICATION_FILE = "authentfile";
112     /**
113      * SERVER CRYPTO for Password
114      */
115     private static final String XML_PATH_CRYPTOKEY = "cryptokey";
116 
117     /**
118      * Structure of the Configuration file
119      * 
120      */
121     private static final XmlDecl[] configIdentityDecls = {
122             // identity
123             new XmlDecl(XmlType.STRING, XML_SERVER_HOSTID),
124             new XmlDecl(XmlType.STRING, XML_PATH_CRYPTOKEY),
125             new XmlDecl(XmlType.STRING, XML_AUTHENTIFICATION_FILE)
126     };
127     /**
128      * Use HTTP compression for R66 HTTP connection
129      */
130     private static final String XML_USEHTTPCOMP = "usehttpcomp";
131     /**
132      * Use external Waarp Local Exec for ExecTask and ExecMoveTask
133      */
134     private static final String XML_USELOCALEXEC = "uselocalexec";
135 
136     /**
137      * Address of Waarp Local Exec for ExecTask and ExecMoveTask
138      */
139     private static final String XML_LEXECADDR = "lexecaddr";
140 
141     /**
142      * Port of Waarp Local Exec for ExecTask and ExecMoveTask
143      */
144     private static final String XML_LEXECPORT = "lexecport";
145     /**
146      * ADMINISTRATOR SERVER NAME (shutdown)
147      */
148     private static final String XML_SERVER_ADMIN = "serveradmin";
149     /**
150      * SERVER PASSWORD (shutdown)
151      */
152     private static final String XML_SERVER_PASSWD = "serverpasswd";
153     /**
154      * SERVER SSL STOREKEY PATH ADMIN
155      */
156     private static final String XML_PATH_ADMIN_KEYPATH = "admkeypath";
157 
158     /**
159      * SERVER SSL KEY PASS ADMIN
160      */
161     private static final String XML_PATH_ADMIN_KEYPASS = "admkeypass";
162 
163     /**
164      * SERVER SSL STOREKEY PASS ADMIN
165      */
166     private static final String XML_PATH_ADMIN_KEYSTOREPASS = "admkeystorepass";
167     /**
168      * HTTP Admin Directory
169      */
170     private static final String XML_HTTPADMINPATH = "httpadmin";
171     /**
172      * Monitoring: snmp configuration file (if empty, no snmp support)
173      */
174     private static final String XML_MONITOR_SNMP_CONFIG = "snmpconfig";
175 
176     /**
177      * Structure of the Configuration file
178      * 
179      */
180     private static final XmlDecl[] configServerParamDecls = {
181             // server
182             new XmlDecl(XmlType.BOOLEAN, XML_USELOCALEXEC),
183             new XmlDecl(XmlType.STRING, XML_LEXECADDR),
184             new XmlDecl(XmlType.INTEGER, XML_LEXECPORT),
185             new XmlDecl(XmlType.STRING, XML_SERVER_ADMIN),
186             new XmlDecl(XmlType.STRING, XML_SERVER_PASSWD),
187             new XmlDecl(XmlType.BOOLEAN, XML_USEHTTPCOMP),
188             new XmlDecl(XmlType.STRING, XML_HTTPADMINPATH),
189             new XmlDecl(XmlType.STRING, XML_PATH_ADMIN_KEYPATH),
190             new XmlDecl(XmlType.STRING, XML_PATH_ADMIN_KEYSTOREPASS),
191             new XmlDecl(XmlType.STRING, XML_PATH_ADMIN_KEYPASS),
192             new XmlDecl(XmlType.STRING, XML_MONITOR_SNMP_CONFIG)
193     };
194     /**
195      * SERVER PORT
196      */
197     private static final String XML_SERVER_PORT = "serverport";
198     /**
199      * SERVER ADDRESS if any
200      */
201     private static final String XML_SERVER_ADDRESS = "serveraddress";
202     /**
203      * RANGE of PORT for Passive Mode
204      */
205     private static final String XML_RANGE_PORT_MIN = "portmin";
206 
207     /**
208      * RANGE of PORT for Passive Mode
209      */
210     private static final String XML_RANGE_PORT_MAX = "portmax";
211     /**
212      * SERVER HTTP PORT MONITORING
213      */
214     private static final String XML_SERVER_HTTP_PORT = "serverhttpport";
215     /**
216      * SERVER HTTPS PORT ADMINISTRATION
217      */
218     private static final String XML_SERVER_HTTPS_PORT = "serverhttpsport";
219 
220     /**
221      * Structure of the Configuration file
222      * 
223      */
224     private static final XmlDecl[] configNetworkServerDecls = {
225             // network
226             new XmlDecl(XmlType.INTEGER, XML_SERVER_PORT),
227             new XmlDecl(XmlType.STRING, XML_SERVER_ADDRESS),
228             new XmlDecl(XmlType.INTEGER, XML_RANGE_PORT_MIN),
229             new XmlDecl(XmlType.INTEGER, XML_RANGE_PORT_MAX),
230             new XmlDecl(XmlType.INTEGER, XML_SERVER_HTTP_PORT),
231             new XmlDecl(XmlType.INTEGER, XML_SERVER_HTTPS_PORT)
232     };
233     /**
234      * Database Driver as of oracle, mysql, postgresql, h2
235      */
236     private static final String XML_DBDRIVER = "dbdriver";
237 
238     /**
239      * Database Server connection string as of jdbc:type://[host:port],[failoverhost:port]
240      * .../[database][?propertyName1][ =propertyValue1][&propertyName2][=propertyValue2]...
241      */
242     private static final String XML_DBSERVER = "dbserver";
243 
244     /**
245      * Database User
246      */
247     private static final String XML_DBUSER = "dbuser";
248 
249     /**
250      * Database Password
251      */
252     private static final String XML_DBPASSWD = "dbpasswd";
253     /**
254      * Structure of the Configuration file
255      * 
256      */
257     private static final XmlDecl[] configDbDecls = {
258             // db
259             new XmlDecl(XmlType.STRING, XML_DBDRIVER),
260             new XmlDecl(XmlType.STRING, XML_DBSERVER),
261             new XmlDecl(XmlType.STRING, XML_DBUSER),
262             new XmlDecl(XmlType.STRING, XML_DBPASSWD)
263     };
264     /**
265      * Should a file be deleted when a Store like command is aborted
266      */
267     private static final String XML_DELETEONABORT = "deleteonabort";
268     /**
269      * Default number of threads in pool for Server.
270      */
271     private static final String XML_SERVER_THREAD = "serverthread";
272 
273     /**
274      * Default number of threads in pool for Client.
275      */
276     private static final String XML_CLIENT_THREAD = "clientthread";
277     /**
278      * Memory Limit to use.
279      */
280     private static final String XML_MEMORY_LIMIT = "memorylimit";
281 
282     /**
283      * Limit for Session
284      */
285     private static final String XML_LIMITSESSION = "sessionlimit";
286 
287     /**
288      * Limit for Global
289      */
290     private static final String XML_LIMITGLOBAL = "globallimit";
291     /**
292      * Delay between two checks for Limit
293      */
294     private static final String XML_LIMITDELAY = "delaylimit";
295     /**
296      * Nb of milliseconds after connection is in timeout
297      */
298     private static final String XML_TIMEOUTCON = "timeoutcon";
299     /**
300      * Size by default of block size for receive/sending files. Should be a multiple of 8192
301      * (maximum = 64K due to block limitation to 2 bytes)
302      */
303     private static final String XML_BLOCKSIZE = "blocksize";
304     /**
305      * Should a file MD5 SHA1 be computed using NIO
306      */
307     private static final String XML_USENIO = "usenio";
308 
309     /**
310      * Should a file MD5 be computed using FastMD5
311      */
312     private static final String XML_USEFASTMD5 = "usefastmd5";
313 
314     /**
315      * If using Fast MD5, should we used the binary JNI library, empty meaning no
316      */
317     private static final String XML_FASTMD5 = "fastmd5";
318     /**
319      * Usage of CPU Limit
320      */
321     private static final String XML_CSTRT_USECPULIMIT = "usecpulimit";
322 
323     /**
324      * Usage of JDK CPU Limit (True) or SysMon CPU Limit
325      */
326     private static final String XML_CSTRT_USECPUJDKLIMIT = "usejdkcpulimit";
327 
328     /**
329      * CPU LIMIT between 0 and 1, where 1 stands for no limit
330      */
331     private static final String XML_CSTRT_CPULIMIT = "cpulimit";
332     /**
333      * Connection limit where 0 stands for no limit
334      */
335     private static final String XML_CSTRT_CONNLIMIT = "connlimit";
336     /**
337      * CPU LOW limit to apply increase of throttle
338      */
339     private static final String XML_CSTRT_LOWCPULIMIT = "lowcpulimit";
340     /**
341      * CPU HIGH limit to apply decrease of throttle, 0 meaning no throttle activated
342      */
343     private static final String XML_CSTRT_HIGHCPULIMIT = "highcpulimit";
344     /**
345      * PERCENTAGE DECREASE of Bandwidth
346      */
347     private static final String XML_CSTRT_PERCENTDECREASE = "percentdecrease";
348     /**
349      * Delay between 2 checks of throttle test
350      */
351     private static final String XML_CSTRT_DELAYTHROTTLE = "delaythrottle";
352     /**
353      * Bandwidth low limit to not got below
354      */
355     private static final String XML_CSTRT_LIMITLOWBANDWIDTH = "limitlowbandwidth";
356     /**
357      * Structure of the Configuration file
358      * 
359      */
360     private static final XmlDecl[] configLimitDecls = {
361             // limit
362             new XmlDecl(XmlType.BOOLEAN, XML_DELETEONABORT),
363             new XmlDecl(XmlType.LONG, XML_LIMITSESSION),
364             new XmlDecl(XmlType.LONG, XML_LIMITGLOBAL),
365             new XmlDecl(XmlType.LONG, XML_LIMITDELAY),
366             new XmlDecl(XmlType.INTEGER, XML_SERVER_THREAD),
367             new XmlDecl(XmlType.INTEGER, XML_CLIENT_THREAD),
368             new XmlDecl(XmlType.LONG, XML_MEMORY_LIMIT),
369             new XmlDecl(XmlType.BOOLEAN, XML_CSTRT_USECPULIMIT),
370             new XmlDecl(XmlType.BOOLEAN, XML_CSTRT_USECPUJDKLIMIT),
371             new XmlDecl(XmlType.DOUBLE, XML_CSTRT_CPULIMIT),
372             new XmlDecl(XmlType.INTEGER, XML_CSTRT_CONNLIMIT),
373             new XmlDecl(XmlType.DOUBLE, XML_CSTRT_LOWCPULIMIT),
374             new XmlDecl(XmlType.DOUBLE, XML_CSTRT_HIGHCPULIMIT),
375             new XmlDecl(XmlType.DOUBLE, XML_CSTRT_PERCENTDECREASE),
376             new XmlDecl(XmlType.LONG, XML_CSTRT_LIMITLOWBANDWIDTH),
377             new XmlDecl(XmlType.LONG, XML_CSTRT_DELAYTHROTTLE),
378             new XmlDecl(XmlType.LONG, XML_TIMEOUTCON),
379             new XmlDecl(XmlType.BOOLEAN, XML_USENIO),
380             new XmlDecl(XmlType.BOOLEAN, XML_USEFASTMD5),
381             new XmlDecl(XmlType.STRING, XML_FASTMD5),
382             new XmlDecl(XmlType.INTEGER, XML_BLOCKSIZE)
383     };
384 
385     /**
386      * RETRIEVE COMMAND
387      */
388     public static final String XML_RETRIEVE_COMMAND = "retrievecmd";
389 
390     /**
391      * STORE COMMAND
392      */
393     public static final String XML_STORE_COMMAND = "storecmd";
394 
395     /**
396      * DELAY RETRIEVE COMMAND
397      */
398     public static final String XML_DELAYRETRIEVE_COMMAND = "retrievedelay";
399 
400     /**
401      * DELAY STORE COMMAND
402      */
403     public static final String XML_DELAYSTORE_COMMAND = "storedelay";
404     /**
405      * Structure of the Configuration file
406      * 
407      */
408     private static final XmlDecl[] configExecDecls = {
409             // Exec
410             new XmlDecl(XmlType.STRING, XML_RETRIEVE_COMMAND),
411             new XmlDecl(XmlType.LONG, XML_DELAYRETRIEVE_COMMAND),
412             new XmlDecl(XmlType.STRING, XML_STORE_COMMAND),
413             new XmlDecl(XmlType.LONG, XML_DELAYSTORE_COMMAND)
414     };
415     /**
416      * Base Directory
417      */
418     private static final String XML_SERVER_HOME = "serverhome";
419     /**
420      * Structure of the Configuration file
421      * 
422      */
423     private static final XmlDecl[] configDirectoryDecls = {
424             // directory
425             new XmlDecl(XmlType.STRING, XML_SERVER_HOME)
426     };
427     /**
428      * SERVER SSL STOREKEY PATH
429      */
430     private static final String XML_PATH_KEYPATH = "keypath";
431 
432     /**
433      * SERVER SSL KEY PASS
434      */
435     private static final String XML_PATH_KEYPASS = "keypass";
436 
437     /**
438      * SERVER SSL STOREKEY PASS
439      */
440     private static final String XML_PATH_KEYSTOREPASS = "keystorepass";
441 
442     /**
443      * SERVER SSL TRUSTSTOREKEY PATH
444      */
445     private static final String XML_PATH_TRUSTKEYPATH = "trustkeypath";
446 
447     /**
448      * SERVER SSL TRUSTSTOREKEY PASS
449      */
450     private static final String XML_PATH_TRUSTKEYSTOREPASS = "trustkeystorepass";
451 
452     /**
453      * SERVER SSL Use TrustStore for Client Authentication
454      */
455     private static final String XML_USECLIENT_AUTHENT = "trustuseclientauthenticate";
456     /**
457      * SERVER SSL Use Implicit FTPS
458      */
459     private static final String XML_IMPLICIT_FTPS = "useimplicitftps";
460     /**
461      * SERVER SSL Use Explicit FTPS
462      */
463     private static final String XML_EXPLICIT_FTPS = "useexplicitftps";
464 
465     /**
466      * Structure of the Configuration file
467      * 
468      */
469     private static final XmlDecl[] configSslDecls = {
470             // ssl
471             new XmlDecl(XmlType.STRING, XML_PATH_KEYPATH),
472             new XmlDecl(XmlType.STRING, XML_PATH_KEYSTOREPASS),
473             new XmlDecl(XmlType.STRING, XML_PATH_KEYPASS),
474             new XmlDecl(XmlType.STRING, XML_PATH_TRUSTKEYPATH),
475             new XmlDecl(XmlType.STRING, XML_PATH_TRUSTKEYSTOREPASS),
476             new XmlDecl(XmlType.BOOLEAN, XML_USECLIENT_AUTHENT),
477             new XmlDecl(XmlType.BOOLEAN, XML_IMPLICIT_FTPS),
478             new XmlDecl(XmlType.BOOLEAN, XML_EXPLICIT_FTPS)
479     };
480     /**
481      * Overall structure of the Configuration file
482      */
483     private static final String XML_ROOT = "/config/";
484     private static final String XML_IDENTITY = "identity";
485     private static final String XML_SERVER = "server";
486     private static final String XML_DIRECTORY = "directory";
487     private static final String XML_LIMIT = "limit";
488     private static final String XML_NETWORK = "network";
489     private static final String XML_EXEC = "exec";
490     private static final String XML_DB = "db";
491     private static final String XML_SSL = "ssl";
492     /**
493      * Global Structure for Server Configuration
494      */
495     private static final XmlDecl[] configServer = {
496             new XmlDecl(XML_IDENTITY, XmlType.XVAL, XML_ROOT + XML_IDENTITY, configIdentityDecls,
497                     false),
498             new XmlDecl(XML_SERVER, XmlType.XVAL, XML_ROOT + XML_SERVER, configServerParamDecls,
499                     false),
500             new XmlDecl(XML_NETWORK, XmlType.XVAL, XML_ROOT + XML_NETWORK,
501                     configNetworkServerDecls, false),
502             new XmlDecl(XML_EXEC, XmlType.XVAL, XML_ROOT + XML_EXEC, configExecDecls, false),
503             new XmlDecl(XML_DIRECTORY, XmlType.XVAL, XML_ROOT + XML_DIRECTORY,
504                     configDirectoryDecls, false),
505             new XmlDecl(XML_LIMIT, XmlType.XVAL, XML_ROOT + XML_LIMIT, configLimitDecls, false),
506             new XmlDecl(XML_DB, XmlType.XVAL, XML_ROOT + XML_DB, configDbDecls, false),
507             new XmlDecl(XML_SSL, XmlType.XVAL, XML_ROOT + XML_SSL, configSslDecls, false)
508     };
509 
510     /**
511      * Authentication Fields
512      */
513     private static final String XML_AUTHENTIFICATION_ROOT = "authent";
514     /**
515      * Authentication Fields
516      */
517     private static final String XML_AUTHENTIFICATION_ENTRY = "entry";
518     /**
519      * Authentication Fields
520      */
521     private static final String XML_AUTHENTIFICATION_BASED = "/" +
522             XML_AUTHENTIFICATION_ROOT + "/" + XML_AUTHENTIFICATION_ENTRY;
523 
524     /**
525      * Authentication Fields
526      */
527     private static final String XML_AUTHENTICATION_USER = "user";
528 
529     /**
530      * Authentication Fields
531      */
532     private static final String XML_AUTHENTICATION_PASSWD = "passwd";
533     /**
534      * Authentication Fields
535      */
536     private static final String XML_AUTHENTICATION_PASSWDFILE = "passwdfile";
537 
538     /**
539      * Authentication Fields
540      */
541     private static final String XML_AUTHENTICATION_ACCOUNT = "account";
542 
543     /**
544      * Authentication Fields
545      */
546     private static final String XML_AUTHENTICATION_ADMIN = "admin";
547     /**
548      * Structure of the Configuration file
549      * 
550      */
551     private static final XmlDecl[] configAuthenticationDecls = {
552             // identity
553             new XmlDecl(XmlType.STRING, XML_AUTHENTICATION_USER),
554             new XmlDecl(XmlType.STRING, XML_AUTHENTICATION_PASSWDFILE),
555             new XmlDecl(XmlType.STRING, XML_AUTHENTICATION_PASSWD),
556             new XmlDecl(XML_AUTHENTICATION_ACCOUNT, XmlType.STRING, XML_AUTHENTICATION_ACCOUNT,
557                     true),
558             new XmlDecl(XmlType.BOOLEAN, XML_AUTHENTICATION_ADMIN),
559             // Exec
560             new XmlDecl(XmlType.STRING, XML_RETRIEVE_COMMAND),
561             new XmlDecl(XmlType.LONG, XML_DELAYRETRIEVE_COMMAND),
562             new XmlDecl(XmlType.STRING, XML_STORE_COMMAND),
563             new XmlDecl(XmlType.LONG, XML_DELAYSTORE_COMMAND)
564     };
565     /**
566      * Global Structure for Server Configuration
567      */
568     private static final XmlDecl[] authentElements = {
569             new XmlDecl(XML_AUTHENTIFICATION_ENTRY, XmlType.XVAL, XML_AUTHENTIFICATION_BASED,
570                     configAuthenticationDecls, true)
571     };
572 
573     /**
574      * RANGE of PORT for Passive Mode
575      */
576     private static final String RANGE_PORT = "FTP_RANGE_PORT";
577     /**
578      * Use to access directly the configuration
579      */
580     public static FileBasedConfiguration fileBasedConfiguration;
581     /**
582      * All authentications
583      */
584     private ConcurrentHashMap<String, SimpleAuth> authentications = new ConcurrentHashMap<String, SimpleAuth>();
585 
586     /**
587      * File containing the authentications
588      */
589     private String authenticationFile;
590 
591     /**
592      * Default HTTP server port
593      */
594     private int SERVER_HTTPSPORT = 8067;
595     /**
596      * Http Admin base
597      */
598     public String httpBasePath = "src/main/admin/";
599     /**
600      * Delay in ms between two checks
601      */
602     public long delayLimit = 10000;
603     /**
604      * Does this server will try to compress HTTP connections
605      */
606     public boolean useHttpCompression = false;
607 
608     /**
609      * Does this server will use Waarp LocalExec Daemon for Execute
610      */
611     public boolean useLocalExec = false;
612 
613     /**
614      * Crypto Key
615      */
616     public Des cryptoKey = null;
617     /**
618      * Server Administration Key
619      */
620     private byte[] SERVERADMINKEY = null;
621     /**
622      * FTP server ID
623      */
624     public String HOST_ID = "noId";
625     /**
626      * Admin name Id
627      */
628     public String ADMINNAME = "noAdmin";
629     /**
630      * Limit on CPU and Connection
631      */
632     public FtpConstraintLimitHandler constraintLimitHandler = null;
633 
634     /**
635      * List of all Http Channels to enable the close call on them using Netty ChannelGroup
636      */
637     private ChannelGroup httpChannelGroup = null;
638     /**
639      * Bootstrap for Https server
640      */
641     private ServerBootstrap httpsBootstrap = null;
642     /**
643      * Boss Group for Http
644      */
645     private EventLoopGroup bossGroup = null;
646     /**
647      * Worker Group for Http
648      */
649     private EventLoopGroup workerGroup = null;
650 
651     /**
652      * ThreadPoolExecutor for Http and Https Server
653      */
654     private EventExecutorGroup httpExecutor;
655     /**
656      * Monitoring: snmp configuration file (empty means no snmp support)
657      */
658     public String snmpConfig = null;
659     /**
660      * SNMP Agent (if any)
661      */
662     public WaarpSnmpAgent agentSnmp = null;
663     /**
664      * Associated MIB
665      */
666     public FtpPrivateMib ftpMib = null;
667     /**
668      * Monitoring object
669      */
670     public FtpMonitoring monitoring = null;
671 
672     /**
673      * @param classtype
674      * @param businessHandler
675      *            class that will be used for BusinessHandler
676      * @param dataBusinessHandler
677      *            class that will be used for DataBusinessHandler
678      * @param fileParameter
679      *            the FileParameter to use
680      */
681     public FileBasedConfiguration(Class<?> classtype,
682             Class<? extends BusinessHandler> businessHandler,
683             Class<? extends DataBusinessHandler> dataBusinessHandler,
684             FileParameterInterface fileParameter) {
685         super(classtype, businessHandler, dataBusinessHandler, fileParameter);
686         computeNbThreads();
687     }
688 
689     private static XmlValue[] configuration = null;
690     private static XmlHash hashConfig = null;
691 
692     private boolean loadIdentity() {
693         XmlValue value = hashConfig.get(XML_SERVER_HOSTID);
694         if (value != null && (!value.isEmpty())) {
695             HOST_ID = value.getString();
696         } else {
697             logger.error("Unable to find Host ID in Config file");
698             return false;
699         }
700         return setCryptoKey();
701     }
702 
703     private boolean loadAuthentication() {
704         // if no database, must load authentication from file
705         XmlValue value = hashConfig.get(XML_AUTHENTIFICATION_FILE);
706         if (value != null && (!value.isEmpty())) {
707             setAuthenticationFile(value.getString());
708             if (!initializeAuthent(getAuthenticationFile(), false)) {
709                 return false;
710             }
711         } else {
712             logger.warn("Unable to find Authentication file in Config file");
713             return false;
714         }
715         return true;
716     }
717 
718     private boolean loadServerParam() {
719         XmlValue value = hashConfig.get(XML_USEHTTPCOMP);
720         if (value != null && (!value.isEmpty())) {
721             useHttpCompression = value.getBoolean();
722         }
723         value = hashConfig.get(XML_USELOCALEXEC);
724         if (value != null && (!value.isEmpty())) {
725             useLocalExec = value.getBoolean();
726             if (useLocalExec) {
727                 value = hashConfig.get(XML_LEXECADDR);
728                 String saddr;
729                 InetAddress addr;
730                 if (value != null && (!value.isEmpty())) {
731                     saddr = value.getString();
732                     try {
733                         addr = InetAddress.getByName(saddr);
734                     } catch (UnknownHostException e) {
735                         logger.error("Unable to find LocalExec Address in Config file");
736                         return false;
737                     }
738                 } else {
739                     logger.warn("Unable to find LocalExec Address in Config file");
740                     try {
741                         addr = InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 });
742                     } catch (UnknownHostException e) {
743                         logger.error("Unable to find LocalExec Address in Config file");
744                         return false;
745                     }
746                 }
747                 value = hashConfig.get(XML_LEXECPORT);
748                 int port;
749                 if (value != null && (!value.isEmpty())) {
750                     port = value.getInteger();
751                 } else {
752                     port = 9999;
753                 }
754                 LocalExecClient.setAddress(new InetSocketAddress(addr, port));
755             }
756         }
757         value = hashConfig.get(XML_SERVER_ADMIN);
758         if (value != null && (!value.isEmpty())) {
759             ADMINNAME = value.getString();
760         } else {
761             logger.error("Unable to find Administrator name in Config file");
762             return false;
763         }
764         if (cryptoKey == null) {
765             if (!setCryptoKey()) {
766                 logger.error("Unable to find Crypto Key in Config file");
767                 return false;
768             }
769         }
770         String passwd;
771         value = hashConfig.get(XML_SERVER_PASSWD);
772         if (value != null && (!value.isEmpty())) {
773             passwd = value.getString();
774         } else {
775             logger.error("Unable to find Password in Config file");
776             return false;
777         }
778         byte[] decodedByteKeys = null;
779         try {
780             decodedByteKeys =
781                     cryptoKey.decryptHexInBytes(passwd);
782         } catch (Exception e) {
783             logger.error(
784                     "Unable to Decrypt Server Password in Config file from: " +
785                             passwd, e);
786             return false;
787         }
788         setSERVERKEY(decodedByteKeys);
789         value = hashConfig.get(XML_HTTPADMINPATH);
790         if (value == null || (value.isEmpty())) {
791             logger.error("Unable to find Http Admin Base in Config file");
792             return false;
793         }
794         String path = value.getString();
795         if (path == null || path.length() == 0) {
796             logger.warn("Unable to set correct Http Admin Base in Config file. No HTTPS support will be used.");
797             httpBasePath = null;
798         } else {
799             File file = new File(path);
800             if (!file.isDirectory()) {
801                 logger.error("Http Admin is not a directory in Config file");
802                 return false;
803             }
804             try {
805                 httpBasePath =
806                         FilesystemBasedDirImpl.normalizePath(file.getCanonicalPath()) +
807                                 DirInterface.SEPARATOR;
808             } catch (IOException e1) {
809                 logger.error("Unable to set Http Admin Path in Config file");
810                 return false;
811             }
812         }
813         if (httpBasePath != null) {
814             // Key for HTTPS
815             value = hashConfig.get(XML_PATH_ADMIN_KEYPATH);
816             if (value != null && (!value.isEmpty())) {
817                 String keypath = value.getString();
818                 if ((keypath == null) || (keypath.length() == 0)) {
819                     logger.error("Bad Key Path");
820                     return false;
821                 }
822                 value = hashConfig.get(XML_PATH_ADMIN_KEYSTOREPASS);
823                 if (value == null || (value.isEmpty())) {
824                     logger.error("Unable to find KeyStore Passwd");
825                     return false;
826                 }
827                 String keystorepass = value.getString();
828                 if ((keystorepass == null) || (keystorepass.length() == 0)) {
829                     logger.error("Bad KeyStore Passwd");
830                     return false;
831                 }
832                 value = hashConfig.get(XML_PATH_ADMIN_KEYPASS);
833                 if (value == null || (value.isEmpty())) {
834                     logger.error("Unable to find Key Passwd");
835                     return false;
836                 }
837                 String keypass = value.getString();
838                 if ((keypass == null) || (keypass.length() == 0)) {
839                     logger.error("Bad Key Passwd");
840                     return false;
841                 }
842                 try {
843                     HttpSslInitializer.waarpSecureKeyStore =
844                             new WaarpSecureKeyStore(keypath, keystorepass,
845                                     keypass);
846                 } catch (CryptoException e) {
847                     logger.error("Bad SecureKeyStore construction for AdminSsl");
848                     return false;
849                 }
850                 // No client authentication
851                 HttpSslInitializer.waarpSecureKeyStore.initEmptyTrustStore();
852                 HttpSslInitializer.waarpSslContextFactory =
853                         new WaarpSslContextFactory(
854                                 HttpSslInitializer.waarpSecureKeyStore, true);
855             }
856         }
857         value = hashConfig.get(XML_MONITOR_SNMP_CONFIG);
858         if (value != null && (!value.isEmpty())) {
859             snmpConfig = value.getString();
860             logger.warn("SNMP configuration file: " + snmpConfig);
861             File snmpfile = new File(snmpConfig);
862             if (snmpfile.canRead()) {
863                 if (!SnmpConfiguration.setConfigurationFromXml(snmpfile)) {
864                     logger.warn("Bad SNMP configuration file: " + snmpConfig);
865                     snmpConfig = null;
866                 }
867             } else {
868                 logger.warn("Cannot read SNMP configuration file: " + snmpConfig);
869                 snmpConfig = null;
870             }
871         } else {
872             logger.warn("NO SNMP configuration file");
873         }
874         return true;
875     }
876 
877     private boolean loadDirectory() {
878         XmlValue value = hashConfig.get(XML_SERVER_HOME);
879         if (value == null || (value.isEmpty())) {
880             logger.error("Unable to find Home in Config file");
881             return false;
882         }
883         String path = value.getString();
884         File file = new File(path);
885         if (!file.isDirectory()) {
886             logger.error("Home is not a directory in Config file");
887             return false;
888         }
889         try {
890             setBaseDirectory(FilesystemBasedDirImpl.normalizePath(file
891                     .getCanonicalPath()));
892         } catch (IOException e1) {
893             logger.error("Unable to set Home in Config file: " + path);
894             return false;
895         }
896         return true;
897     }
898 
899     private boolean loadLimit(boolean updateLimit) {
900         XmlValue value = hashConfig.get(XML_LIMITGLOBAL);
901         if (value != null && (!value.isEmpty())) {
902             serverGlobalReadLimit = value.getLong();
903             if (serverGlobalReadLimit <= 0) {
904                 serverGlobalReadLimit = 0;
905             }
906             serverGlobalWriteLimit = serverGlobalReadLimit;
907             logger.info("Global Limit: {}",
908                     serverGlobalReadLimit);
909         }
910         value = hashConfig.get(XML_LIMITSESSION);
911         if (value != null && (!value.isEmpty())) {
912             serverChannelReadLimit = value.getLong();
913             if (serverChannelReadLimit <= 0) {
914                 serverChannelReadLimit = 0;
915             }
916             serverChannelWriteLimit = serverChannelReadLimit;
917             logger.info("SessionInterface Limit: {}",
918                     serverChannelReadLimit);
919         }
920         delayLimit = AbstractTrafficShapingHandler.DEFAULT_CHECK_INTERVAL;
921         value = hashConfig.get(XML_LIMITDELAY);
922         if (value != null && (!value.isEmpty())) {
923             delayLimit = (value.getLong() / 10) * 10;
924             if (delayLimit <= 0) {
925                 delayLimit = 0;
926             }
927             logger.info("Delay Limit: {}",
928                     delayLimit);
929         }
930         boolean useCpuLimit = false;
931         boolean useCpuLimitJDK = false;
932         double cpulimit = 1.0;
933         value = hashConfig.get(XML_CSTRT_USECPULIMIT);
934         if (value != null && (!value.isEmpty())) {
935             useCpuLimit = value.getBoolean();
936             value = hashConfig.get(XML_CSTRT_USECPUJDKLIMIT);
937             if (value != null && (!value.isEmpty())) {
938                 useCpuLimitJDK = value.getBoolean();
939             }
940             value = hashConfig.get(XML_CSTRT_CPULIMIT);
941             if (value != null && (!value.isEmpty())) {
942                 cpulimit = value.getDouble();
943             }
944         }
945         int connlimit = 0;
946         value = hashConfig.get(XML_CSTRT_CONNLIMIT);
947         if (value != null && (!value.isEmpty())) {
948             connlimit = value.getInteger();
949         }
950         double lowcpuLimit = 0;
951         double highcpuLimit = 0;
952         double percentageDecrease = 0;
953         long delay = 1000000;
954         long limitLowBandwidth = 4096;
955         value = hashConfig.get(XML_CSTRT_LOWCPULIMIT);
956         if (value != null && (!value.isEmpty())) {
957             lowcpuLimit = value.getDouble();
958         }
959         value = hashConfig.get(XML_CSTRT_HIGHCPULIMIT);
960         if (value != null && (!value.isEmpty())) {
961             highcpuLimit = value.getDouble();
962         }
963         value = hashConfig.get(XML_CSTRT_PERCENTDECREASE);
964         if (value != null && (!value.isEmpty())) {
965             percentageDecrease = value.getDouble();
966         }
967         value = hashConfig.get(XML_CSTRT_DELAYTHROTTLE);
968         if (value != null && (!value.isEmpty())) {
969             delay = (value.getLong() / 10) * 10;
970         }
971         value = hashConfig.get(XML_CSTRT_LIMITLOWBANDWIDTH);
972         if (value != null && (!value.isEmpty())) {
973             limitLowBandwidth = value.getLong();
974         }
975         value = hashConfig.get(XML_TIMEOUTCON);
976         if (value != null && (!value.isEmpty())) {
977             setTIMEOUTCON((value.getLong() / 10) * 10);
978         }
979         if (highcpuLimit > 0) {
980             constraintLimitHandler =
981                     new FtpConstraintLimitHandler(getTIMEOUTCON(), useCpuLimit, useCpuLimitJDK,
982                             cpulimit, connlimit,
983                             lowcpuLimit, highcpuLimit, percentageDecrease, null, delay,
984                             limitLowBandwidth);
985         } else {
986             constraintLimitHandler =
987                     new FtpConstraintLimitHandler(getTIMEOUTCON(), useCpuLimit, useCpuLimitJDK,
988                             cpulimit, connlimit);
989         }
990         value = hashConfig.get(XML_SERVER_THREAD);
991         if (value != null && (!value.isEmpty())) {
992             setSERVER_THREAD(value.getInteger());
993         }
994         value = hashConfig.get(XML_CLIENT_THREAD);
995         if (value != null && (!value.isEmpty())) {
996             setCLIENT_THREAD(value.getInteger());
997         }
998         if (getSERVER_THREAD() == 0 || getCLIENT_THREAD() == 0) {
999             computeNbThreads();
1000         }
1001         value = hashConfig.get(XML_MEMORY_LIMIT);
1002         if (value != null && (!value.isEmpty())) {
1003             setMaxGlobalMemory(value.getLong());
1004         }
1005         ((FilesystemBasedFileParameterImpl) getFileParameter()).deleteOnAbort = false;
1006         value = hashConfig.get(XML_USENIO);
1007         if (value != null && (!value.isEmpty())) {
1008             FilesystemBasedFileParameterImpl.useNio = value.getBoolean();
1009         }
1010         value = hashConfig.get(XML_USEFASTMD5);
1011         if (value != null && (!value.isEmpty())) {
1012             FilesystemBasedDigest.setUseFastMd5(value.getBoolean());
1013         }
1014         value = hashConfig.get(XML_BLOCKSIZE);
1015         if (value != null && (!value.isEmpty())) {
1016             setBLOCKSIZE(value.getInteger());
1017         }
1018         value = hashConfig.get(XML_DELETEONABORT);
1019         if (value != null && (!value.isEmpty())) {
1020             setDeleteOnAbort(value.getBoolean());
1021         }
1022         // We use Apache Commons IO
1023         FilesystemBasedDirJdkAbstract.ueApacheCommonsIo = true;
1024         return true;
1025     }
1026 
1027     private boolean loadNetworkServer() {
1028         XmlValue value = hashConfig.get(XML_SERVER_PORT);
1029         int port = 21;
1030         if (value != null && (!value.isEmpty())) {
1031             port = value.getInteger();
1032         } else {
1033             port = 21;
1034         }
1035         setServerPort(port);
1036         value = hashConfig.get(XML_SERVER_ADDRESS);
1037         String address = null;
1038         if (value != null && (!value.isEmpty())) {
1039             address = value.getString();
1040         }
1041         setServerAddress(address);
1042         int min = 100;
1043         int max = 65535;
1044         value = hashConfig.get(XML_RANGE_PORT_MIN);
1045         if (value != null && (!value.isEmpty())) {
1046             min = value.getInteger();
1047         }
1048         value = hashConfig.get(XML_RANGE_PORT_MAX);
1049         if (value != null && (!value.isEmpty())) {
1050             max = value.getInteger();
1051         }
1052         logger.warn("Passive Port range Min: " + min + " Max: " + max);
1053         CircularIntValue rangePort = new CircularIntValue(min, max);
1054         setRangePort(rangePort);
1055         value = hashConfig.get(XML_SERVER_HTTPS_PORT);
1056         int httpsport = 8067;
1057         if (value != null && (!value.isEmpty())) {
1058             httpsport = value.getInteger();
1059         }
1060         SERVER_HTTPSPORT = httpsport;
1061         return true;
1062     }
1063 
1064     /**
1065      * Set the Crypto Key from the Document
1066      * 
1067      * @param document
1068      * @return True if OK
1069      */
1070     private boolean setCryptoKey() {
1071         XmlValue value = hashConfig.get(XML_PATH_CRYPTOKEY);
1072         if (value == null || (value.isEmpty())) {
1073             logger.error("Unable to find CryptoKey in Config file");
1074             return false;
1075         }
1076         String filename = value.getString();
1077         File key = new File(filename);
1078         Des des = new Des();
1079         try {
1080             des.setSecretKey(key);
1081         } catch (CryptoException e) {
1082             logger.error("Unable to load CryptoKey from Config file");
1083             return false;
1084         } catch (IOException e) {
1085             logger.error("Unable to load CryptoKey from Config file");
1086             return false;
1087         }
1088         cryptoKey = des;
1089         return true;
1090     }
1091 
1092     /**
1093      * 
1094      * @return True if the global Exec parameters are correctly loaded
1095      */
1096     private boolean loadExec() {
1097         // Specific Exec command options
1098         XmlValue value = hashConfig.get(XML_RETRIEVE_COMMAND);
1099         if (value == null || (value.isEmpty())) {
1100             logger.error("Unable to find Retrieve Command in Config file");
1101             return false;
1102         }
1103         String retrieve = value.getString();
1104         value = hashConfig.get(XML_DELAYRETRIEVE_COMMAND);
1105         long retrievedelay = 0;
1106         if (value != null && (!value.isEmpty())) {
1107             retrievedelay = (value.getLong() / 10) * 10;
1108         }
1109         value = hashConfig.get(XML_STORE_COMMAND);
1110         if (value == null || (value.isEmpty())) {
1111             logger.error("Unable to find Store Command in Config file");
1112             return false;
1113         }
1114         String store = value.getString();
1115         value = hashConfig.get(XML_DELAYSTORE_COMMAND);
1116         long storedelay = 0;
1117         if (value != null && (!value.isEmpty())) {
1118             storedelay = (value.getLong() / 10) * 10;
1119         }
1120         AbstractExecutor.initializeExecutor(retrieve, retrievedelay, store, storedelay);
1121         return true;
1122     }
1123 
1124     /**
1125      * Load database parameter
1126      * 
1127      * @param document
1128      * @return True if OK
1129      */
1130     private boolean loadDatabase() {
1131         XmlValue value = hashConfig.get(XML_DBDRIVER);
1132         if (value == null || (value.isEmpty())) {
1133             logger.error("Unable to find DBDriver in Config file");
1134             DbConstant.gatewayAdmin = new DbAdmin(); // no database support
1135         } else {
1136             String dbdriver = value.getString();
1137             value = hashConfig.get(XML_DBSERVER);
1138             if (value == null || (value.isEmpty())) {
1139                 logger.error("Unable to find DBServer in Config file");
1140                 return false;
1141             }
1142             String dbserver = value.getString();
1143             value = hashConfig.get(XML_DBUSER);
1144             if (value == null || (value.isEmpty())) {
1145                 logger.error("Unable to find DBUser in Config file");
1146                 return false;
1147             }
1148             String dbuser = value.getString();
1149             value = hashConfig.get(XML_DBPASSWD);
1150             if (value == null || (value.isEmpty())) {
1151                 logger.error("Unable to find DBPassword in Config file");
1152                 return false;
1153             }
1154             String dbpasswd = value.getString();
1155             if (dbdriver == null || dbserver == null || dbuser == null ||
1156                     dbpasswd == null || dbdriver.length() == 0 ||
1157                     dbserver.length() == 0 || dbuser.length() == 0 ||
1158                     dbpasswd.length() == 0) {
1159                 logger.error("Unable to find Correct DB data in Config file");
1160                 return false;
1161             }
1162             try {
1163                 DbConstant.gatewayAdmin =
1164                         DbModelFactory.initialize(dbdriver, dbserver, dbuser, dbpasswd,
1165                                 true);
1166                 DbConstant.admin = DbConstant.gatewayAdmin;
1167             } catch (WaarpDatabaseNoConnectionException e2) {
1168                 logger.error("Unable to Connect to DB", e2);
1169                 return false;
1170             }
1171         }
1172         return true;
1173     }
1174 
1175     protected boolean loadSsl() {
1176         // StoreKey for Server
1177         XmlValue value = hashConfig.get(XML_PATH_KEYPATH);
1178         if (value == null || (value.isEmpty())) {
1179             logger.info("Unable to find Key Path");
1180             getFtpInternalConfiguration().setUsingNativeSsl(false);
1181             getFtpInternalConfiguration().setAcceptAuthProt(false);
1182             return true;
1183         } else {
1184             String keypath = value.getString();
1185             if ((keypath == null) || (keypath.length() == 0)) {
1186                 logger.error("Bad Key Path");
1187                 return false;
1188             }
1189             value = hashConfig.get(XML_PATH_KEYSTOREPASS);
1190             if (value == null || (value.isEmpty())) {
1191                 logger.error("Unable to find KeyStore Passwd");
1192                 return false;
1193             }
1194             String keystorepass = value.getString();
1195             if ((keystorepass == null) || (keystorepass.length() == 0)) {
1196                 logger.error("Bad KeyStore Passwd");
1197                 return false;
1198             }
1199             value = hashConfig.get(XML_PATH_KEYPASS);
1200             if (value == null || (value.isEmpty())) {
1201                 logger.error("Unable to find Key Passwd");
1202                 return false;
1203             }
1204             String keypass = value.getString();
1205             if ((keypass == null) || (keypass.length() == 0)) {
1206                 logger.error("Bad Key Passwd");
1207                 return false;
1208             }
1209             try {
1210                 FtpsInitializer.waarpSecureKeyStore =
1211                         new WaarpSecureKeyStore(keypath, keystorepass,
1212                                 keypass);
1213             } catch (CryptoException e) {
1214                 logger.error("Bad SecureKeyStore construction");
1215                 return false;
1216             }
1217 
1218         }
1219         // TrustedKey for OpenR66 server
1220         value = hashConfig.get(XML_PATH_TRUSTKEYPATH);
1221         if (value == null || (value.isEmpty())) {
1222             logger.info("Unable to find TRUST Key Path");
1223             FtpsInitializer.waarpSecureKeyStore.initEmptyTrustStore();
1224         } else {
1225             String keypath = value.getString();
1226             if ((keypath == null) || (keypath.length() == 0)) {
1227                 logger.error("Bad TRUST Key Path");
1228                 return false;
1229             }
1230             value = hashConfig.get(XML_PATH_TRUSTKEYSTOREPASS);
1231             if (value == null || (value.isEmpty())) {
1232                 logger.error("Unable to find TRUST KeyStore Passwd");
1233                 return false;
1234             }
1235             String keystorepass = value.getString();
1236             if ((keystorepass == null) || (keystorepass.length() == 0)) {
1237                 logger.error("Bad TRUST KeyStore Passwd");
1238                 return false;
1239             }
1240             boolean useClientAuthent = false;
1241             value = hashConfig.get(XML_USECLIENT_AUTHENT);
1242             if (value != null && (!value.isEmpty())) {
1243                 useClientAuthent = value.getBoolean();
1244             }
1245             try {
1246                 FtpsInitializer.waarpSecureKeyStore.initTrustStore(keypath,
1247                         keystorepass, useClientAuthent);
1248             } catch (CryptoException e) {
1249                 logger.error("Bad TrustKeyStore construction");
1250                 return false;
1251             }
1252         }
1253         FtpsInitializer.waarpSslContextFactory =
1254                 new WaarpSslContextFactory(
1255                         FtpsInitializer.waarpSecureKeyStore);
1256         boolean useImplicit = false;
1257         value = hashConfig.get(XML_IMPLICIT_FTPS);
1258         if (value != null && (!value.isEmpty())) {
1259             useImplicit = value.getBoolean();
1260         }
1261         boolean useExplicit = false;
1262         value = hashConfig.get(XML_EXPLICIT_FTPS);
1263         if (value != null && (!value.isEmpty())) {
1264             useExplicit = value.getBoolean();
1265         }
1266         if (useImplicit && useExplicit) {
1267             logger.error("Only one of IMPLICIT or EXPLICIT could be True");
1268             return false;
1269         }
1270         if ((!useImplicit) && (!useExplicit)) {
1271             logger.error("Since all SecureStore are specified, one of IMPLICIT or EXPLICIT should be True");
1272             logger.warn("FTPS support will be ignored...");
1273             getFtpInternalConfiguration().setUsingNativeSsl(false);
1274             getFtpInternalConfiguration().setAcceptAuthProt(false);
1275             return true;
1276         }
1277         getFtpInternalConfiguration().setUsingNativeSsl(useImplicit);
1278         getFtpInternalConfiguration().setAcceptAuthProt(useExplicit);
1279         return true;
1280     }
1281 
1282     /**
1283      * Initiate the configuration from the xml file for server
1284      * 
1285      * @param filename
1286      * @return True if OK
1287      */
1288     public boolean setConfigurationServerFromXml(String filename) {
1289         Document document = null;
1290         // Open config file
1291         try {
1292             document = new SAXReader().read(filename);
1293         } catch (DocumentException e) {
1294             logger.error("Unable to read the XML Config file: " + filename, e);
1295             return false;
1296         }
1297         if (document == null) {
1298             logger.error("Unable to read the XML Config file: " + filename);
1299             return false;
1300         }
1301         configuration = XmlUtil.read(document, configServer);
1302         hashConfig = new XmlHash(configuration);
1303         // Now read the configuration
1304         if (!loadIdentity()) {
1305             logger.error("Cannot load Identity");
1306             return false;
1307         }
1308         if (!loadDatabase()) {
1309             logger.error("Cannot load Database configuration");
1310             return false;
1311         }
1312         if (!loadServerParam()) {
1313             logger.error("Cannot load Server Parameters");
1314             return false;
1315         }
1316         if (!loadDirectory()) {
1317             logger.error("Cannot load Directory configuration");
1318             return false;
1319         }
1320         if (!loadLimit(false)) {
1321             logger.error("Cannot load Limit configuration");
1322             return false;
1323         }
1324         if (!loadNetworkServer()) {
1325             logger.error("Cannot load Network configuration");
1326             return false;
1327         }
1328         if (!loadExec()) {
1329             logger.error("Cannot load Exec configuration");
1330             return false;
1331         }
1332         // if (!DbConstant.admin.isActive) {
1333         // if no database, must load authentication from file
1334         if (!loadAuthentication()) {
1335             logger.error("Cannot load Authentication configuration");
1336             return false;
1337         }
1338         if (!loadSsl()) {
1339             // ignore and continue => No SSL
1340             getFtpInternalConfiguration().setUsingNativeSsl(false);
1341             getFtpInternalConfiguration().setAcceptAuthProt(false);
1342             return false;
1343         }
1344         // }
1345         hashConfig.clear();
1346         hashConfig = null;
1347         configuration = null;
1348         return true;
1349     }
1350 
1351     /**
1352      * Configure HTTPS
1353      */
1354     public void configureHttps() {
1355         // Now start the HTTPS support
1356         // Configure the server.
1357         httpsBootstrap = new ServerBootstrap();
1358         httpExecutor = new NioEventLoopGroup(getSERVER_THREAD() * 10, new WaarpThreadFactory(
1359                 "HttpExecutor"));
1360         bossGroup = new NioEventLoopGroup(getSERVER_THREAD(), new WaarpThreadFactory("HTTP_Boss"));
1361         workerGroup = new NioEventLoopGroup(getSERVER_THREAD() * 10, new WaarpThreadFactory("HTTP_Worker"));
1362         WaarpNettyUtil.setServerBootstrap(httpsBootstrap, bossGroup, workerGroup, (int) getTIMEOUTCON());
1363 
1364         // Configure the pipeline factory.
1365         httpsBootstrap.childHandler(new HttpSslInitializer(useHttpCompression));
1366         httpChannelGroup = new DefaultChannelGroup("HttpOpenR66", httpExecutor.next());
1367 
1368         // Bind and start to accept incoming connections.
1369         logger.warn("Start Https Support on port: " + SERVER_HTTPSPORT + " with "+ (useHttpCompression ? "" : "no") +" compression support");
1370         ChannelFuture future = httpsBootstrap.bind(new InetSocketAddress(SERVER_HTTPSPORT));
1371         if (future.awaitUninterruptibly().isSuccess()) {
1372             httpChannelGroup.add(future.channel());
1373         }
1374     }
1375 
1376     /**
1377      * Configure ConstraintLimitHandler
1378      */
1379     public void configureConstraint() {
1380         constraintLimitHandler.setHandler(
1381                 this.getFtpInternalConfiguration().getGlobalTrafficShapingHandler());
1382     }
1383 
1384     /**
1385      * Configure LocalExec
1386      */
1387     public void configureLExec() {
1388         if (useLocalExec) {
1389             LocalExecClient.initialize(this.getCLIENT_THREAD(), this.getMaxGlobalMemory());
1390         }
1391     }
1392 
1393     /**
1394      * Configure the SNMP support if needed
1395      * 
1396      * @throws FtpNoConnectionException
1397      */
1398     public void configureSnmp() throws FtpNoConnectionException {
1399         monitoring = new FtpMonitoring(null);
1400         if (snmpConfig != null) {
1401             int snmpPortShow = getServerPort();
1402             ftpMib =
1403                     new FtpPrivateMib(snmpPortShow);
1404             WaarpMOFactory.setFactory(new FtpVariableFactory());
1405             agentSnmp = new WaarpSnmpAgent(new File(snmpConfig), monitoring, ftpMib);
1406             try {
1407                 agentSnmp.start();
1408                 logger.debug("SNMP configured");
1409             } catch (IOException e) {
1410                 monitoring.releaseResources();
1411                 monitoring = null;
1412                 ftpMib = null;
1413                 agentSnmp = null;
1414                 throw new FtpNoConnectionException("AgentSnmp Error while starting", e);
1415             }
1416         }
1417     }
1418 
1419     /**
1420      * @param serverkey
1421      *            the SERVERADMINKEY to set
1422      */
1423     public void setSERVERKEY(byte[] serverkey) {
1424         SERVERADMINKEY = serverkey;
1425     }
1426 
1427     /**
1428      * Check the password for Shutdown
1429      * 
1430      * @param password
1431      * @return True if the password is OK
1432      */
1433     public boolean checkPassword(String password) {
1434         if (password == null) {
1435             return false;
1436         }
1437         return Arrays.equals(SERVERADMINKEY, password.getBytes(WaarpStringUtils.UTF8));
1438     }
1439 
1440     /**
1441      * Initialize Authentication from current authenticationFile
1442      * 
1443      * @param filename
1444      *            the filename from which authentication will be loaded
1445      * @param purge
1446      *            if True, the current authentications are totally replaced by the new ones
1447      * @return True if OK
1448      */
1449     @SuppressWarnings("unchecked")
1450     public boolean initializeAuthent(String filename, boolean purge) {
1451         Document document = null;
1452         try {
1453             document = new SAXReader().read(filename);
1454         } catch (DocumentException e) {
1455             logger.error("Unable to read the XML Authentication file: " +
1456                     filename, e);
1457             return false;
1458         }
1459         if (document == null) {
1460             logger.error("Unable to read the XML Authentication file: " +
1461                     filename);
1462             return false;
1463         }
1464         XmlValue[] configuration = XmlUtil.read(document, authentElements);
1465         XmlHash hashConfig = new XmlHash(configuration);
1466 
1467         XmlValue value = hashConfig.get(XML_AUTHENTIFICATION_ENTRY);
1468         List<XmlValue[]> list = (List<XmlValue[]>) value.getList();
1469         ConcurrentHashMap<String, SimpleAuth> newAuthents =
1470                 new ConcurrentHashMap<String, SimpleAuth>();
1471         for (XmlValue[] xmlValues : list) {
1472             hashConfig = new XmlHash(xmlValues);
1473             value = hashConfig.get(XML_AUTHENTICATION_USER);
1474             if (value == null || (value.isEmpty())) {
1475                 logger.error("Unable to find a User in Config file");
1476                 continue;
1477             }
1478             String user = value.getString();
1479             value = hashConfig.get(XML_AUTHENTICATION_ACCOUNT);
1480             if (value == null || (value.isEmpty())) {
1481                 logger.error("Unable to find a Account in Config file: " + user);
1482                 continue;
1483             }
1484             String[] account = null;
1485             List<String> listaccount = (List<String>) value.getList();
1486             if (!listaccount.isEmpty()) {
1487                 account = new String[listaccount.size()];
1488                 int i = 0;
1489                 Iterator<String> iteratoraccount = listaccount.iterator();
1490                 while (iteratoraccount.hasNext()) {
1491                     account[i] = iteratoraccount.next();
1492                     // logger.debug("User: {} Acct: {}", user, account[i]);
1493                     File directory = new File(getBaseDirectory() + "/" + user + "/" + account[i]);
1494                     directory.mkdirs();
1495                     i++;
1496                 }
1497             } else {
1498                 logger.error("Unable to find a Account in Config file: " + user);
1499                 continue;
1500             }
1501             value = hashConfig.get(XML_AUTHENTICATION_ADMIN);
1502             boolean isAdmin = false;
1503             if (value != null && (!value.isEmpty())) {
1504                 isAdmin = value.getBoolean();
1505             }
1506             String retrcmd = null;
1507             long retrdelay = 0;
1508             String storcmd = null;
1509             long stordelay = 0;
1510             value = hashConfig.get(XML_RETRIEVE_COMMAND);
1511             if (value != null && (!value.isEmpty())) {
1512                 retrcmd = value.getString();
1513             }
1514             value = hashConfig.get(XML_DELAYRETRIEVE_COMMAND);
1515             if (value != null && (!value.isEmpty())) {
1516                 retrdelay = (value.getLong() / 10) * 10;
1517             }
1518             value = hashConfig.get(XML_STORE_COMMAND);
1519             if (value != null && (!value.isEmpty())) {
1520                 storcmd = value.getString();
1521             }
1522             value = hashConfig.get(XML_DELAYSTORE_COMMAND);
1523             if (value != null && (!value.isEmpty())) {
1524                 stordelay = (value.getLong() / 10) * 10;
1525             }
1526             String passwd;
1527             value = hashConfig.get(XML_AUTHENTICATION_PASSWDFILE);
1528             if (value != null && (!value.isEmpty())) {
1529                 // load key from file
1530                 File key = new File(value.getString());
1531                 if (!key.canRead()) {
1532                     logger.error("Cannot read key for user " + user + ":" + key.getName());
1533                     continue;
1534                 }
1535                 try {
1536                     byte[] byteKeys = cryptoKey.decryptHexFile(key);
1537                     passwd = new String(byteKeys, WaarpStringUtils.UTF8);
1538                 } catch (Exception e2) {
1539                     logger.error("Cannot read key for user " + user, e2);
1540                     continue;
1541                 }
1542             } else {
1543                 value = hashConfig.get(XML_AUTHENTICATION_PASSWD);
1544                 if (value != null && (!value.isEmpty())) {
1545                     String encrypted = value.getString();
1546                     byte[] byteKeys = null;
1547                     try {
1548                         byteKeys =
1549                                 cryptoKey.decryptHexInBytes(encrypted);
1550                         passwd = new String(byteKeys, WaarpStringUtils.UTF8);
1551                     } catch (Exception e) {
1552                         logger.error(
1553                                 "Unable to Decrypt Key for user " + user, e);
1554                         continue;
1555                     }
1556                 } else {
1557                     logger.error("Unable to find Password in Config file");
1558                     // DO NOT Allow empty key
1559                     continue;
1560                 }
1561             }
1562             SimpleAuth auth = new SimpleAuth(user, passwd, account,
1563                     storcmd, stordelay, retrcmd, retrdelay);
1564             auth.setAdmin(isAdmin);
1565             newAuthents.put(user, auth);
1566             hashConfig.clear();
1567         }
1568         hashConfig.clear();
1569         configuration = null;
1570         if (purge) {
1571             ConcurrentHashMap<String, SimpleAuth> previousOne = authentications;
1572             authentications = newAuthents;
1573             previousOne.clear();
1574         } else {
1575             authentications.putAll(newAuthents);
1576             newAuthents.clear();
1577         }
1578         document = null;
1579         return true;
1580     }
1581 
1582     /**
1583      * Export the Authentication to the original files
1584      * 
1585      * @param filename
1586      *            the filename where the authentication will be exported
1587      * @return True if successful
1588      */
1589     public boolean saveAuthenticationFile(String filename) {
1590         Document document = XmlUtil.createEmptyDocument();
1591         XmlValue[] roots = new XmlValue[1];
1592         XmlValue root = new XmlValue(authentElements[0]);
1593         roots[0] = root;
1594         Enumeration<SimpleAuth> auths = authentications.elements();
1595         while (auths.hasMoreElements()) {
1596             SimpleAuth auth = auths.nextElement();
1597             XmlValue[] values = new XmlValue[configAuthenticationDecls.length];
1598             for (int i = 0; i < configAuthenticationDecls.length; i++) {
1599                 values[i] = new XmlValue(configAuthenticationDecls[i]);
1600             }
1601             try {
1602                 values[0].setFromString(auth.getUser());
1603                 // PasswdFile: none values[1].setFromString();
1604                 values[2].setFromString(auth.getPassword());
1605             } catch (InvalidArgumentException e1) {
1606                 logger.error("Error during Write Authentication file", e1);
1607                 return false;
1608             }
1609             // Accounts
1610             String[] accts = auth.getAccounts();
1611             for (String string : accts) {
1612                 try {
1613                     values[3].addFromString(string);
1614                 } catch (InvalidObjectException e) {
1615                     logger.error("Error during Write Authentication file", e);
1616                     return false;
1617                 } catch (InvalidArgumentException e) {
1618                     logger.error("Error during Write Authentication file", e);
1619                     return false;
1620                 }
1621             }
1622             try {
1623                 values[4].setValue(auth.isAdmin());
1624             } catch (InvalidObjectException e) {
1625                 logger.error("Error during Write Authentication file", e);
1626                 return false;
1627             }
1628             try {
1629                 values[5].setFromString(auth.getRetrCmd());
1630             } catch (InvalidArgumentException e1) {
1631                 logger.error("Error during Write Authentication file", e1);
1632                 return false;
1633             }
1634             try {
1635                 values[6].setValue(auth.getRetrDelay());
1636             } catch (InvalidObjectException e) {
1637                 logger.error("Error during Write Authentication file", e);
1638                 return false;
1639             }
1640             try {
1641                 values[7].setFromString(auth.getStorCmd());
1642             } catch (InvalidArgumentException e1) {
1643                 logger.error("Error during Write Authentication file", e1);
1644                 return false;
1645             }
1646             try {
1647                 values[8].setValue(auth.getStorDelay());
1648             } catch (InvalidObjectException e) {
1649                 logger.error("Error during Write Authentication file", e);
1650                 return false;
1651             }
1652             try {
1653                 root.addValue(values);
1654             } catch (InvalidObjectException e) {
1655                 logger.error("Error during Write Authentication file", e);
1656                 return false;
1657             }
1658         }
1659         XmlUtil.write(document, roots);
1660         try {
1661             XmlUtil.saveDocument(filename, document);
1662         } catch (IOException e1) {
1663             logger.error("Cannot write to file: " + filename + " since {}", e1.getMessage());
1664             return false;
1665         }
1666         return true;
1667     }
1668 
1669     /**
1670      * @param user
1671      * @return the SimpleAuth if any for this user
1672      */
1673     public SimpleAuth getSimpleAuth(String user) {
1674         return authentications.get(user);
1675     }
1676 
1677     /**
1678      * @param format
1679      *            Format in HTML to use as ouput format
1680      * @return the Html String containing the table of all Authentication entries
1681      */
1682     public String getHtmlAuth(String format) {
1683         String result;
1684         StringBuilder builder = new StringBuilder();
1685         /*
1686          * XXXUSERXXX XXXPWDXXX XXXACTSXXX XXXADMXXX XXXSTCXXX XXXSTDXXX XXXRTCXXX XXXRTDXXX
1687          */
1688         Enumeration<SimpleAuth> simpleAuths = authentications.elements();
1689         SimpleAuth auth = null;
1690         while (simpleAuths.hasMoreElements()) {
1691             auth = simpleAuths.nextElement();
1692             String newElt = format.replace("XXXUSERXXX", auth.getUser());
1693             newElt = newElt.replace("XXXPWDXXX", auth.getPassword());
1694             if (auth.getStorCmd() != null)
1695                 newElt = newElt.replace("XXXSTCXXX", auth.getStorCmd());
1696             else
1697                 newElt = newElt.replace("XXXSTCXXX", "");
1698             if (auth.getRetrCmd() != null)
1699                 newElt = newElt.replace("XXXRTCXXX", auth.getRetrCmd());
1700             else
1701                 newElt = newElt.replace("XXXRTCXXX", "");
1702             newElt = newElt.replace("XXXSTDXXX", Long.toString(auth.getStorDelay()));
1703             newElt = newElt.replace("XXXRTDXXX", Long.toString(auth.getRetrDelay()));
1704             newElt = newElt.replace("XXXADMXXX", Boolean.toString(auth.isAdmin()));
1705             if (auth.getAccounts() != null) {
1706                 StringBuilder accts = new StringBuilder();
1707                 for (int i = 0; i < auth.getAccounts().length - 1; i++) {
1708                     accts.append(auth.getAccounts()[i]).append(", ");
1709                 }
1710                 accts.append(auth.getAccounts()[auth.getAccounts().length - 1]);
1711                 newElt = newElt.replace("XXXACTSXXX", accts.toString());
1712             } else {
1713                 newElt = newElt.replace("XXXACTSXXX", "No Account");
1714             }
1715             builder.append(newElt);
1716         }
1717         result = builder.toString();
1718         return result;
1719     }
1720 
1721     /**
1722      * Only available with Database support for Waarp
1723      * 
1724      * @param format
1725      *            Format in HTML to use as ouput format
1726      * @param limit
1727      *            number of TransferLog to populate
1728      * @return the Html String containing the table of all Transfer entries
1729      */
1730     public String getHtmlTransfer(String format, int limit) {
1731         String result;
1732         StringBuilder builder = new StringBuilder();
1733         /*
1734          * XXXIDXXX XXXUSERXXX XXXACCTXXX XXXFILEXXX XXXMODEXXX XXXSTATUSXXX XXXINFOXXX XXXUPINFXXX
1735          * XXXSTARTXXX XXXSTOPXXX
1736          */
1737         if (!DbConstant.gatewayAdmin.isActive()) {
1738             return "";
1739         }
1740         DbPreparedStatement preparedStatement = null;
1741         try {
1742             try {
1743                 preparedStatement =
1744                         DbTransferLog
1745                                 .getStatusPrepareStament(DbConstant.gatewayAdmin.getSession(), null, limit);
1746                 preparedStatement.executeQuery();
1747             } catch (WaarpDatabaseNoConnectionException e) {
1748                 return "";
1749             } catch (WaarpDatabaseSqlException e) {
1750                 return "";
1751             }
1752             try {
1753                 while (preparedStatement.getNext()) {
1754                     DbTransferLog log = DbTransferLog.getFromStatement(preparedStatement);
1755                     String newElt = format
1756                             .replaceAll("XXXIDXXX", Long.toString(log.getSpecialId()));
1757                     newElt = newElt.replaceAll("XXXUSERXXX", log.getUser());
1758                     newElt = newElt.replaceAll("XXXACCTXXX", log.getAccount());
1759                     newElt = newElt.replace("XXXFILEXXX", log.getFilename());
1760                     newElt = newElt.replace("XXXMODEXXX", log.getMode());
1761                     newElt = newElt.replace("XXXSTATUSXXX", log.getErrorInfo().getMesg());
1762                     newElt = newElt.replace("XXXINFOXXX", log.getInfotransf());
1763                     newElt = newElt.replace("XXXUPINFXXX", log.getUpdatedInfo().name());
1764                     newElt = newElt.replace("XXXSTARTXXX", log.getStart().toString());
1765                     newElt = newElt.replace("XXXSTOPXXX", log.getStop().toString());
1766                     builder.append(newElt);
1767                 }
1768             } catch (WaarpDatabaseNoConnectionException e) {
1769                 return "";
1770             } catch (WaarpDatabaseSqlException e) {
1771                 return "";
1772             }
1773             result = builder.toString();
1774             return result;
1775         } finally {
1776             if (preparedStatement != null) {
1777                 preparedStatement.realClose();
1778             }
1779         }
1780     }
1781 
1782     /**
1783      * @see org.waarp.ftp.core.config.FtpConfiguration#getNextRangePort()
1784      */
1785     @Override
1786     public int getNextRangePort() {
1787         try {
1788             return ((CircularIntValue) getProperty(RANGE_PORT)).getNext();
1789         } catch (FtpUnknownFieldException e) {
1790             return -1;
1791         }
1792     }
1793 
1794     /**
1795      * 
1796      * @param rangePort
1797      *            the range of available ports for Passive connections
1798      */
1799     private void setRangePort(CircularIntValue rangePort) {
1800         setProperty(RANGE_PORT, rangePort);
1801     }
1802 
1803     /**
1804      * @return the httpPipelineExecutor
1805      */
1806     public EventExecutorGroup getHttpPipelineExecutor() {
1807         return httpExecutor;
1808     }
1809 
1810     /**
1811      * @return the httpChannelGroup
1812      */
1813     public ChannelGroup getHttpChannelGroup() {
1814         return httpChannelGroup;
1815     }
1816 
1817     /**
1818      * Finalize resources attached to handlers
1819      * 
1820      * @author Frederic Bregier
1821      */
1822     private static class GgChannelGroupFutureListener implements
1823             ChannelGroupFutureListener {
1824         EventExecutorGroup executorBoss;
1825         EventExecutorGroup executorWorker;
1826         String name;
1827 
1828         public GgChannelGroupFutureListener(
1829                 String name,
1830                 EventExecutorGroup executorBoss, EventExecutorGroup executorWorker) {
1831             this.name = name;
1832             this.executorBoss = executorBoss;
1833             this.executorWorker = executorWorker;
1834         }
1835 
1836         public void operationComplete(ChannelGroupFuture future)
1837                 throws Exception {
1838             if (executorBoss != null) {
1839                 executorBoss.shutdownGracefully();
1840             }
1841             if (executorWorker != null) {
1842                 executorWorker.shutdownGracefully();
1843             }
1844             logger.info("Done with shutdown " + name);
1845         }
1846     }
1847 
1848     @Override
1849     public void releaseResources() {
1850         super.releaseResources();
1851         if (httpChannelGroup != null) {
1852             final int result = httpChannelGroup.size();
1853             logger.debug("HttpChannelGroup: " + result);
1854             httpChannelGroup.close().addListener(
1855                     new GgChannelGroupFutureListener(
1856                             "HttpChannelGroup",
1857                             bossGroup, workerGroup));
1858         }
1859         if (httpExecutor != null) {
1860             httpExecutor.shutdownGracefully();
1861         }
1862         if (useLocalExec) {
1863             LocalExecClient.releaseResources();
1864         }
1865         if (constraintLimitHandler != null) {
1866             this.constraintLimitHandler.release();
1867         }
1868         if (agentSnmp != null) {
1869             agentSnmp.stop();
1870         }
1871         DbAdmin.closeAllConnection();
1872     }
1873 
1874     @Override
1875     public void inShutdownProcess() {
1876         if (ftpMib != null) {
1877             ftpMib.notifyStartStop("Shutdown in progress for " + HOST_ID, "Gives extra seconds: "
1878                     + getTIMEOUTCON());
1879         }
1880     }
1881 
1882     /**
1883      * @return the authenticationFile
1884      */
1885     public String getAuthenticationFile() {
1886         return authenticationFile;
1887     }
1888 
1889     /**
1890      * @param authenticationFile the authenticationFile to set
1891      */
1892     public void setAuthenticationFile(String authenticationFile) {
1893         this.authenticationFile = authenticationFile;
1894     }
1895 }