View Javadoc

1   /**
2    * This file is part of Waarp Project.
3    * 
4    * Copyright 2009, Frederic Bregier, and individual contributors by the @author tags. See the
5    * COPYRIGHT.txt in the distribution for a full listing of individual contributors.
6    * 
7    * All Waarp Project is free software: you can redistribute it and/or modify it under the terms of
8    * the GNU General Public License as published by the Free Software Foundation, either version 3 of
9    * the License, or (at your option) any later version.
10   * 
11   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
12   * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13   * Public License for more details.
14   * 
15   * You should have received a copy of the GNU General Public License along with Waarp . If not, see
16   * <http://www.gnu.org/licenses/>.
17   */
18  package org.waarp.ftp.core.config;
19  
20  import java.io.File;
21  import java.net.InetAddress;
22  import java.net.InetSocketAddress;
23  import java.util.HashMap;
24  import java.util.concurrent.locks.Lock;
25  import java.util.concurrent.locks.ReentrantLock;
26  
27  import io.netty.channel.Channel;
28  import io.netty.handler.traffic.GlobalChannelTrafficShapingHandler;
29  
30  import org.waarp.common.file.FileParameterInterface;
31  import org.waarp.common.utility.WaarpShutdownHook.ShutdownConfiguration;
32  import org.waarp.ftp.core.control.BusinessHandler;
33  import org.waarp.ftp.core.data.handler.DataBusinessHandler;
34  import org.waarp.ftp.core.exception.FtpNoConnectionException;
35  import org.waarp.ftp.core.exception.FtpUnknownFieldException;
36  import org.waarp.ftp.core.session.FtpSession;
37  
38  /**
39   * Abstract class for configuration
40   * 
41   * @author Frederic Bregier
42   * 
43   */
44  public abstract class FtpConfiguration {
45      // FTP Configuration: Externals
46      /**
47       * Default session limit 64Mbit, so up to 8 full simultaneous clients
48       */
49      static long DEFAULT_SESSION_LIMIT = 0x800000L;
50  
51      /**
52       * Default global limit 512Mbit
53       */
54      static long DEFAULT_GLOBAL_LIMIT = 0x4000000L;
55  
56      /**
57       * Nb of milliseconds after pending data transfer is in timeout
58       */
59      private static long DATATIMEOUTCON = 5000;
60  
61      /**
62       * PASSWORD for SHUTDOWN
63       */
64      private static final String FTP_PASSWORD = "FTP_PASSWORD";
65  
66      // END OF STATIC VALUES
67      /**
68       * Internal configuration
69       */
70      private final FtpInternalConfiguration internalConfiguration;
71  
72      /**
73       * SERVER PORT
74       */
75      private int SERVER_PORT = 21;
76      /**
77       * Default Address if any
78       */
79      private String SERVER_ADDRESS = null;
80  
81      /**
82       * Base Directory
83       */
84      private String BASE_DIRECTORY = null;
85  
86      /**
87       * Associated FileParameterInterface
88       */
89      private final FileParameterInterface fileParameter;
90  
91      /**
92       * True if the service is going to shutdown
93       */
94      private volatile boolean isShutdown = false;
95  
96      /**
97       * Default number of threads in pool for Server. The default value is for client for Executor in
98       * the Pipeline for Business logic. Server will change this value on startup if not set.
99       * Default 0 means in proportion of real core number.
100      */
101     private int SERVER_THREAD = 0;
102 
103     /**
104      * Default number of threads in pool for Client part.
105      */
106     private int CLIENT_THREAD = 80;
107 
108     /**
109      * Which class owns this configuration
110      */
111     Class<?> fromClass = null;
112 
113     /**
114      * Which class will be used for DataBusinessHandler
115      */
116     Class<? extends DataBusinessHandler> dataBusinessHandler = null;
117 
118     /**
119      * Which class will be used for BusinessHandler
120      */
121     Class<? extends BusinessHandler> businessHandler = null;
122 
123     /**
124      * Internal Lock
125      */
126     private ReentrantLock lock = new ReentrantLock();
127 
128     /**
129      * Nb of milliseconds after connection is in timeout
130      */
131     private long TIMEOUTCON = 30000;
132 
133     /**
134      * Size by default of block size for receive/sending files. Should be a multiple of 8192
135      * (maximum = 64K due to block limitation to 2 bytes)
136      */
137     private int BLOCKSIZE = 0x10000; // 64K
138 
139     /**
140      * Limit in Write byte/s to apply globally to the FTP Server
141      */
142     protected long serverGlobalWriteLimit = DEFAULT_GLOBAL_LIMIT;
143 
144     /**
145      * Limit in Read byte/s to apply globally to the FTP Server
146      */
147     protected long serverGlobalReadLimit = DEFAULT_GLOBAL_LIMIT;
148 
149     /**
150      * Limit in Write byte/s to apply by session to the FTP Server
151      */
152     protected long serverChannelWriteLimit = DEFAULT_SESSION_LIMIT;
153 
154     /**
155      * Limit in Read byte/s to apply by session to the FTP Server
156      */
157     protected long serverChannelReadLimit = DEFAULT_SESSION_LIMIT;
158 
159     /**
160      * Delay in ms between two checks
161      */
162     protected long delayLimit = 1000;
163 
164     /**
165      * Should the file be deleted when the transfer is aborted on STOR like commands
166      */
167     private boolean deleteOnAbort = false;
168 
169     /**
170      * Max global memory limit: default is 4GB
171      */
172     private long maxGlobalMemory = 0x100000000L;
173 
174     /**
175      * General Configuration Object
176      */
177     private final HashMap<String, Object> properties = new HashMap<String, Object>();
178 
179     /**
180      * Use by ShutdownHook
181      */
182     private final ShutdownConfiguration shutdownConfiguration = new ShutdownConfiguration();
183 
184     /**
185      * Simple constructor
186      * 
187      * @param classtype
188      *            Owner
189      * @param businessHandler
190      *            class that will be used for BusinessHandler
191      * @param dataBusinessHandler
192      *            class that will be used for DataBusinessHandler
193      * @param fileParameter
194      *            the FileParameterInterface to used
195      */
196     public FtpConfiguration(Class<?> classtype,
197             Class<? extends BusinessHandler> businessHandler,
198             Class<? extends DataBusinessHandler> dataBusinessHandler,
199             FileParameterInterface fileParameter) {
200         fromClass = classtype;
201         this.dataBusinessHandler = dataBusinessHandler;
202         this.businessHandler = businessHandler;
203         internalConfiguration = new FtpInternalConfiguration(this);
204         this.fileParameter = fileParameter;
205     }
206 
207     /**
208      * 
209      * @param key
210      * @return The String property associated to the key
211      * @throws FtpUnknownFieldException
212      */
213     public String getStringProperty(String key) throws FtpUnknownFieldException {
214         String s = (String) properties.get(key);
215         if (s == null) {
216             throw new FtpUnknownFieldException("Property has no value: " + key);
217         }
218         return s;
219     }
220 
221     /**
222      * 
223      * @param key
224      * @return The Integer property associated to the key
225      * @throws FtpUnknownFieldException
226      */
227     public int getIntProperty(String key) throws FtpUnknownFieldException {
228         Integer i = (Integer) properties.get(key);
229         if (i == null) {
230             throw new FtpUnknownFieldException("Property has no value: " + key);
231         }
232         return i;
233     }
234 
235     /**
236      * 
237      * @param key
238      * @return The File associated to the key
239      * @throws FtpUnknownFieldException
240      */
241     public File getFileProperty(String key) throws FtpUnknownFieldException {
242         File f = (File) properties.get(key);
243         if (f == null) {
244             throw new FtpUnknownFieldException("Property has no value: " + key);
245         }
246         return f;
247     }
248 
249     /**
250      * 
251      * @param key
252      * @return The Object property associated to the key
253      * @throws FtpUnknownFieldException
254      */
255     public Object getProperty(String key) throws FtpUnknownFieldException {
256         Object o = properties.get(key);
257         if (o == null) {
258             throw new FtpUnknownFieldException("Property has no value: " + key);
259         }
260         return o;
261     }
262 
263     /**
264      * 
265      * @return the TCP Port to listen in the Ftp Server
266      */
267     public int getServerPort() {
268         return SERVER_PORT;
269     }
270 
271     /**
272      * 
273      * @return the Address of the Ftp Server if any (may be null)
274      */
275     public String getServerAddress() {
276         return SERVER_ADDRESS;
277     }
278 
279     /**
280      * 
281      * @return the limit in Write byte/s to apply globally to the Ftp Server
282      */
283     public long getServerGlobalWriteLimit() {
284         return serverGlobalWriteLimit;
285     }
286 
287     /**
288      * 
289      * @return the limit in Write byte/s to apply for each session to the Ftp Server
290      */
291     public long getServerChannelWriteLimit() {
292         return serverChannelWriteLimit;
293     }
294 
295     /**
296      * 
297      * @return the limit in Read byte/s to apply globally to the Ftp Server
298      */
299     public long getServerGlobalReadLimit() {
300         return serverGlobalReadLimit;
301     }
302 
303     /**
304      * 
305      * @return the limit in Read byte/s to apply for each session to the Ftp Server
306      */
307     public long getServerChannelReadLimit() {
308         return serverChannelReadLimit;
309     }
310 
311     /**
312      * @return the delayLimit to apply between two check
313      */
314     public long getDelayLimit() {
315         return delayLimit;
316     }
317 
318     /**
319      * Check the password for Shutdown
320      * 
321      * @param password
322      * @return True if the password is OK
323      */
324     public boolean checkPassword(String password) {
325         String serverpassword;
326         try {
327             serverpassword = getStringProperty(FTP_PASSWORD);
328         } catch (FtpUnknownFieldException e) {
329             return false;
330         }
331         return serverpassword.equals(password);
332     }
333 
334     /**
335      * Return the next available port for passive connections.
336      * 
337      * @return the next available Port for Passive connections
338      */
339     public abstract int getNextRangePort();
340 
341     /**
342      * 
343      * @return the Base Directory of this Ftp Server
344      */
345     public String getBaseDirectory() {
346         return BASE_DIRECTORY;
347     }
348 
349     /**
350      * 
351      * @param key
352      * @param s
353      */
354     public void setStringProperty(String key, String s) {
355         properties.put(key, s);
356     }
357 
358     /**
359      * 
360      * @param key
361      * @param i
362      */
363     public void setIntProperty(String key, int i) {
364         properties.put(key, Integer.valueOf(i));
365     }
366 
367     /**
368      * 
369      * @param key
370      * @param f
371      */
372     public void setFileProperty(String key, File f) {
373         properties.put(key, f);
374     }
375 
376     /**
377      * 
378      * @param key
379      * @param o
380      */
381     public void setProperty(String key, Object o) {
382         properties.put(key, o);
383     }
384 
385     /**
386      * @param port
387      *            the new port
388      */
389     public void setServerPort(int port) {
390         SERVER_PORT = port;
391     }
392 
393     /**
394      * @param address
395      *            the address to use while answering for address
396      */
397     public void setServerAddress(String address) {
398         SERVER_ADDRESS = address;
399     }
400 
401     /**
402      * @param dir
403      *            the new base directory
404      */
405     public void setBaseDirectory(String dir) {
406         BASE_DIRECTORY = dir;
407     }
408 
409     /**
410      * @param password
411      *            the new password for shutdown
412      */
413     public void setPassword(String password) {
414         setStringProperty(FTP_PASSWORD, password);
415     }
416 
417     /**
418      * @return the dataBusinessHandler
419      */
420     public Class<? extends DataBusinessHandler> getDataBusinessHandler() {
421         return dataBusinessHandler;
422     }
423 
424     /**
425      * Init internal configuration
426      * 
427      * @throws FtpNoConnectionException
428      * 
429      */
430     public void serverStartup() throws FtpNoConnectionException {
431         internalConfiguration.serverStartup();
432     }
433 
434     /**
435      * Reset the global monitor for bandwidth limitation and change future channel monitors with
436      * values divided by 10 (channel = global / 10)
437      * 
438      * @param writeLimit
439      * @param readLimit
440      */
441     public void changeNetworkLimit(long writeLimit, long readLimit) {
442         long newWriteLimit = writeLimit > 1024 ? writeLimit
443                 : serverGlobalWriteLimit;
444         if (writeLimit <= 0) {
445             newWriteLimit = 0;
446         }
447         long newReadLimit = readLimit > 1024 ? readLimit : serverGlobalReadLimit;
448         if (readLimit <= 0) {
449             newReadLimit = 0;
450         }
451         FtpGlobalTrafficShapingHandler fgts = internalConfiguration.getGlobalTrafficShapingHandler();
452         fgts.configure(
453                 newWriteLimit, newReadLimit);
454         serverChannelReadLimit = newReadLimit / 10;
455         serverChannelWriteLimit = newWriteLimit / 10;
456         if (fgts instanceof GlobalChannelTrafficShapingHandler) {
457             ((GlobalChannelTrafficShapingHandler) fgts)
458                 .configureChannel(serverChannelWriteLimit, serverChannelReadLimit);
459         }
460     }
461 
462     /**
463      * Compute number of threads for both client and server from the real number of available
464      * processors (double + 1) if the value is less than 64 threads.
465      * 
466      */
467     public void computeNbThreads() {
468         int nb = Runtime.getRuntime().availableProcessors() * 2 + 1;
469         if (nb > 32) {
470             nb = Runtime.getRuntime().availableProcessors() + 1;
471         }
472         if (getSERVER_THREAD() < nb) {
473             setSERVER_THREAD(nb);
474             setCLIENT_THREAD(getSERVER_THREAD() * 10);
475         } else if (getCLIENT_THREAD() < nb) {
476             setCLIENT_THREAD(nb * 10);
477         }
478     }
479 
480     /**
481      * 
482      * @return the lock on configuration
483      */
484     public Lock getLock() {
485         return lock;
486     }
487 
488     /**
489      * In bind/unbind operation, lock
490      */
491     public void bindLock() {
492         lock.lock();
493     }
494 
495     /**
496      * In bind/unbind operation, unlock
497      */
498     public void bindUnlock() {
499         lock.unlock();
500     }
501 
502     /**
503      * 
504      * @return the FtpInternalConfiguration
505      */
506     public FtpInternalConfiguration getFtpInternalConfiguration() {
507         return internalConfiguration;
508     }
509 
510     /**
511      * Add a session from a couple of addresses
512      * 
513      * @param ipOnly
514      * @param fullIp
515      * @param session
516      */
517     public void setNewFtpSession(InetAddress ipOnly, InetSocketAddress fullIp,
518             FtpSession session) {
519         internalConfiguration.setNewFtpSession(ipOnly, fullIp, session);
520     }
521 
522     /**
523      * Return and remove the FtpSession
524      * 
525      * @param channel
526      * @param active
527      * @return the FtpSession if it exists associated to this channel
528      */
529     public FtpSession getFtpSession(Channel channel, boolean active) {
530         return internalConfiguration.getFtpSession(channel, active, true);
531     }
532 
533     /**
534      * Return the FtpSession
535      * 
536      * @param channel
537      * @param active
538      * @return the FtpSession if it exists associated to this channel
539      */
540     public FtpSession getFtpSessionNoRemove(Channel channel, boolean active) {
541         return internalConfiguration.getFtpSession(channel, active, false);
542     }
543 
544     /**
545      * Remove the FtpSession
546      * 
547      * @param ipOnly
548      * @param fullIp
549      */
550     public void delFtpSession(InetAddress ipOnly, InetSocketAddress fullIp) {
551         internalConfiguration.delFtpSession(ipOnly, fullIp);
552     }
553 
554     /**
555      * Test if the couple of addresses is already in the context
556      * 
557      * @param ipOnly
558      * @param fullIp
559      * @return True if the couple is present
560      */
561     public boolean hasFtpSession(InetAddress ipOnly, InetSocketAddress fullIp) {
562         return internalConfiguration.hasFtpSession(ipOnly, fullIp);
563     }
564 
565     /**
566      * @return the fileParameter
567      */
568     public FileParameterInterface getFileParameter() {
569         return fileParameter;
570     }
571 
572     public String getUniqueExtension() {
573         // Can be overridden if necessary
574         return ".stou";
575     }
576 
577     /**
578      * To use if any external resources are to be released when shutting down
579      */
580     public void releaseResources() {
581         internalConfiguration.releaseResources();
582     }
583 
584     /**
585      * Shutdown process is on going
586      */
587     public abstract void inShutdownProcess();
588 
589     /**
590      * @return the isShutdown
591      */
592     public boolean isShutdown() {
593         return isShutdown;
594     }
595 
596     /**
597      * @param isShutdown the isShutdown to set
598      */
599     public void setShutdown(boolean isShutdown) {
600         this.isShutdown = isShutdown;
601     }
602 
603     /**
604      * @return the sERVER_THREAD
605      */
606     public int getSERVER_THREAD() {
607         return SERVER_THREAD;
608     }
609 
610     /**
611      * @param sERVER_THREAD the sERVER_THREAD to set
612      */
613     public void setSERVER_THREAD(int sERVER_THREAD) {
614         SERVER_THREAD = sERVER_THREAD;
615     }
616 
617     /**
618      * @return the cLIENT_THREAD
619      */
620     public int getCLIENT_THREAD() {
621         return CLIENT_THREAD;
622     }
623 
624     /**
625      * @param cLIENT_THREAD the cLIENT_THREAD to set
626      */
627     public void setCLIENT_THREAD(int cLIENT_THREAD) {
628         CLIENT_THREAD = cLIENT_THREAD;
629     }
630 
631     /**
632      * @return the tIMEOUTCON
633      */
634     public long getTIMEOUTCON() {
635         return TIMEOUTCON;
636     }
637 
638     /**
639      * @param tIMEOUTCON the tIMEOUTCON to set
640      */
641     public void setTIMEOUTCON(long tIMEOUTCON) {
642         TIMEOUTCON = tIMEOUTCON;
643     }
644 
645     /**
646      * @return the bLOCKSIZE
647      */
648     public int getBLOCKSIZE() {
649         return BLOCKSIZE;
650     }
651 
652     /**
653      * @param bLOCKSIZE the bLOCKSIZE to set
654      */
655     public void setBLOCKSIZE(int bLOCKSIZE) {
656         BLOCKSIZE = bLOCKSIZE;
657     }
658 
659     /**
660      * @return the deleteOnAbort
661      */
662     public boolean isDeleteOnAbort() {
663         return deleteOnAbort;
664     }
665 
666     /**
667      * @param deleteOnAbort the deleteOnAbort to set
668      */
669     public void setDeleteOnAbort(boolean deleteOnAbort) {
670         this.deleteOnAbort = deleteOnAbort;
671     }
672 
673     /**
674      * @return the dATATIMEOUTCON
675      */
676     public static long getDATATIMEOUTCON() {
677         return DATATIMEOUTCON;
678     }
679 
680     /**
681      * @param dATATIMEOUTCON the dATATIMEOUTCON to set
682      */
683     public static void setDATATIMEOUTCON(long dATATIMEOUTCON) {
684         DATATIMEOUTCON = dATATIMEOUTCON;
685     }
686 
687     /**
688      * @return the maxGlobalMemory
689      */
690     public long getMaxGlobalMemory() {
691         return maxGlobalMemory;
692     }
693 
694     /**
695      * @param maxGlobalMemory the maxGlobalMemory to set
696      */
697     public void setMaxGlobalMemory(long maxGlobalMemory) {
698         this.maxGlobalMemory = maxGlobalMemory;
699     }
700 
701     /**
702      * @return the shutdownConfiguration
703      */
704     public ShutdownConfiguration getShutdownConfiguration() {
705         return shutdownConfiguration;
706     }
707 }