Source Code Cross Referenced for FTPClient.java in  » Net » edtftpj » com » enterprisedt » net » ftp » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Net » edtftpj » com.enterprisedt.net.ftp 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         *
0003:         *  edtFTPj
0004:         *
0005:         *  Copyright (C) 2000-2003  Enterprise Distributed Technologies Ltd
0006:         *
0007:         *  www.enterprisedt.com
0008:         *
0009:         *  This library is free software; you can redistribute it and/or
0010:         *  modify it under the terms of the GNU Lesser General Public
0011:         *  License as published by the Free Software Foundation; either
0012:         *  version 2.1 of the License, or (at your option) any later version.
0013:         *
0014:         *  This library is distributed in the hope that it will be useful,
0015:         *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0016:         *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0017:         *  Lesser General Public License for more details.
0018:         *
0019:         *  You should have received a copy of the GNU Lesser General Public
0020:         *  License along with this library; if not, write to the Free Software
0021:         *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0022:         *
0023:         *  Bug fixes, suggestions and comments should be should posted on 
0024:         *  http://www.enterprisedt.com/forums/index.php
0025:         *
0026:         *  Change Log:
0027:         *
0028:         *        $Log: FTPClient.java,v $
0029:         *        Revision 1.93  2008-01-09 03:54:21  bruceb
0030:         *        executeCommand() now returns reply code
0031:         *
0032:         *        Revision 1.92  2007-12-18 07:54:58  bruceb
0033:         *        many small changes to prepare for FileTransferClient
0034:         *
0035:         *        Revision 1.91  2007-11-29 02:32:09  hans
0036:         *        Added DEFAULT_LISTING_LOCALES and made related changes to initializers.
0037:         *
0038:         *        Revision 1.90  2007-11-13 07:14:04  bruceb
0039:         *        ListenOnAllInterfaces
0040:         *
0041:         *        Revision 1.89  2007-11-07 23:53:50  bruceb
0042:         *        refactoring for FXP
0043:         *
0044:         *        Revision 1.88  2007-10-12 05:21:13  bruceb
0045:         *        can set multiple locales (and 2 set by default)
0046:         *
0047:         *        Revision 1.87  2007-08-15 03:47:39  bruceb
0048:         *        fix separator
0049:         *
0050:         *        Revision 1.86  2007-08-09 00:50:20  bruceb
0051:         *        added 250 reply to some commands
0052:         *
0053:         *        Revision 1.85  2007-08-07 04:46:25  bruceb
0054:         *        added counts for transfers and deletes plus getLastReply()
0055:         *
0056:         *        Revision 1.84  2007-07-18 02:16:33  bruceb
0057:         *        ignore size() exception in resume
0058:         *
0059:         *        Revision 1.83  2007-07-05 05:28:27  bruceb
0060:         *        add getters for message collections
0061:         *
0062:         *        Revision 1.82  2007-06-14 04:12:48  bruceb
0063:         *        added setForceUniqueNames()
0064:         *
0065:         *        Revision 1.81  2007-06-06 22:20:11  bruceb
0066:         *        FTP_LINE_SEPARATOR now public
0067:         *
0068:         *        Revision 1.80  2007-05-29 04:17:24  bruceb
0069:         *        modify connected() method, and null out control when quitting
0070:         *
0071:         *        Revision 1.79  2007-05-15 01:02:58  bruceb
0072:         *        file factory change if syst doesn't work
0073:         *
0074:         *        Revision 1.78  2007/04/24 01:58:03  bruceb
0075:         *        more debug for validateTransferOnError
0076:         *
0077:         *        Revision 1.77  2007/04/23 23:43:20  bruceb
0078:         *        check on dirname in dirDetails()
0079:         *
0080:         *        Revision 1.76  2007/04/21 04:24:46  bruceb
0081:         *        fix to cope with any ascii file
0082:         *
0083:         *        Revision 1.75  2007/03/22 04:03:47  bruceb
0084:         *        added getOutputStream()
0085:         *
0086:         *        Revision 1.74  2007/03/19 22:07:36  bruceb
0087:         *        set control to null
0088:         *
0089:         *        Revision 1.73  2007/03/13 02:45:08  bruceb
0090:         *        deleteOnFailure flag added
0091:         *
0092:         *        Revision 1.72  2007/03/09 05:04:01  bruceb
0093:         *        fixed bugs in ASCII put & get
0094:         *
0095:         *        Revision 1.71  2007/02/26 07:17:54  bruceb
0096:         *        make various method package or protected visibility so they can be accessed by subclasses etc
0097:         *
0098:         *        Revision 1.70  2007/02/07 23:02:26  bruceb
0099:         *        fixed failure to throw cancellation exception
0100:         *
0101:         *        Revision 1.69  2007/02/06 07:19:24  bruceb
0102:         *        fixed autodetect bug re actual mode not being changed on the server
0103:         *
0104:         *        Revision 1.68  2007/02/04 23:02:40  bruceb
0105:         *        more error logging and extra codes, set strict validation off
0106:         *
0107:         *        Revision 1.67  2007/02/01 06:05:18  bruceb
0108:         *        enable cancelling of large directory listings
0109:         *
0110:         *        Revision 1.66  2007/01/15 23:05:14  bruceb
0111:         *        added fileDetails()
0112:         *
0113:         *        Revision 1.65  2007/01/12 02:04:56  bruceb
0114:         *        extracted string matchers & fixed exists()
0115:         *
0116:         *        Revision 1.64  2007/01/10 02:37:39  bruceb
0117:         *        modify exists to use RETR if necessary
0118:         *
0119:         *        Revision 1.63  2006/12/12 01:04:54  hans
0120:         *        Fixed bug in exists method and added logging of raw directory listing.
0121:         *
0122:         *        Revision 1.62  2006/10/27 15:44:06  bruceb
0123:         *        added sendServerWakeup()
0124:         *
0125:         *        Revision 1.61  2006/10/17 11:03:41  bruceb
0126:         *        fix setActivePortRange comment, include using single port info
0127:         *
0128:         *        Revision 1.60  2006/10/17 10:28:43  bruceb
0129:         *        refactored to get setupDataSocket()
0130:         *
0131:         *        Revision 1.59  2006/10/11 08:38:00  bruceb
0132:         *        controlEncoding applied to directory listings
0133:         *
0134:         *        Revision 1.58  2006/09/11 12:34:00  bruceb
0135:         *        added exists() method
0136:         *
0137:         *        Revision 1.57  2006/08/23 08:48:51  bruceb
0138:         *        don't null out FileFactory when quit() is called
0139:         *
0140:         *        Revision 1.56  2006/07/27 14:12:01  bruceb
0141:         *        IPV6 changes and fixed bug re control channel messages after unexpected close on data connection
0142:         *
0143:         *        Revision 1.55  2006/05/22 01:54:42  hans
0144:         *        Made remoteHost protected.
0145:         *
0146:         *        Revision 1.54  2006/02/16 19:47:09  hans
0147:         *        Added comment
0148:         *
0149:         *        Revision 1.53  2005/11/15 21:02:32  bruceb
0150:         *        more debug
0151:         *
0152:         *        Revision 1.52  2005/11/10 19:46:13  bruceb
0153:         *        delegate resume comments to FTPClientInterface
0154:         *
0155:         *        Revision 1.51  2005/11/10 13:40:28  bruceb
0156:         *        more elaborate versioning info to debug
0157:         *
0158:         *        Revision 1.50  2005/11/09 21:15:38  bruceb
0159:         *        autodetect file types
0160:         *
0161:         *        Revision 1.49  2005/10/10 20:42:56  bruceb
0162:         *        append now in FTPClientInterface
0163:         *
0164:         *        Revision 1.48  2005/09/29 16:03:06  bruceb
0165:         *        permit 350 return from STOR
0166:         *
0167:         *        Revision 1.47  2005/09/21 10:38:06  bruceb
0168:         *        fix for LIST error re empty dir (proFTPD/TLS)
0169:         *
0170:         *        Revision 1.46  2005/09/20 09:44:36  bruceb
0171:         *        extra no files found string, SYST accepts 213
0172:         *
0173:         *        Revision 1.45  2005/09/02 21:03:04  bruceb
0174:         *        no abort() with cancel
0175:         *
0176:         *        Revision 1.44  2005/08/26 17:48:16  bruceb
0177:         *        passive ip address setting + ASCII optimisation
0178:         *
0179:         *        Revision 1.43  2005/06/17 18:25:56  bruceb
0180:         *        fix javadoc
0181:         *
0182:         *        Revision 1.42  2005/06/16 21:39:49  hans
0183:         *        deprecated ControlPort accessors and removed comments for FTPClientInterface methods
0184:         *
0185:         *        Revision 1.41  2005/06/10 15:44:38  bruceb
0186:         *        added noOperation() and connected()
0187:         *
0188:         *        Revision 1.40  2005/06/03 11:25:17  bruceb
0189:         *        ascii fixes, setActivePortRange
0190:         *
0191:         *        Revision 1.41  2005/05/24 11:32:28  bruceb
0192:         *        version + timestamp info in static block
0193:         *
0194:         *        Revision 1.40  2005/05/15 19:46:28  bruceb
0195:         *        changes for testing setActivePortRange + STOR accepting 350 nonstrict
0196:         *
0197:         *        Revision 1.39  2005/04/01 13:58:15  bruceb
0198:         *        restructured dir() exception handling + quote() change
0199:         *
0200:         *        Revision 1.38  2005/03/18 11:04:32  bruceb
0201:         *        deprecated constructors
0202:         *
0203:         *        Revision 1.37  2005/03/11 14:40:11  bruceb
0204:         *        added cdup() and changed buffer defaults
0205:         *
0206:         *        Revision 1.36  2005/03/03 21:07:14  bruceb
0207:         *        implement interface & augment login doco
0208:         *
0209:         *        Revision 1.35  2005/02/04 12:40:35  bruceb
0210:         *        tidied javadoc
0211:         *
0212:         *        Revision 1.34  2005/02/04 12:28:51  bruceb
0213:         *        when getting, if file exists and is readonly, exception is thrown
0214:         *
0215:         *        Revision 1.33  2005/01/28 13:55:39  bruceb
0216:         *        added ACCT handling
0217:         *
0218:         *        Revision 1.32  2005/01/14 20:27:02  bruceb
0219:         *        exception restructuring + ABOR
0220:         *
0221:         *        Revision 1.31  2004/11/19 08:28:10  bruceb
0222:         *        added setPORTIP()
0223:         *
0224:         *        Revision 1.30  2004/10/18 15:54:48  bruceb
0225:         *        clearSOCKS added, set encoding for control sock, locale for parser
0226:         *
0227:         *        Revision 1.29  2004/09/21 21:28:28  bruceb
0228:         *        fixed javadoc comment
0229:         *
0230:         *        Revision 1.28  2004/09/18 14:27:57  bruceb
0231:         *        features() throw exception if not supported
0232:         *
0233:         *        Revision 1.27  2004/09/18 09:33:47  bruceb
0234:         *        1.1.8 tweaks
0235:         *
0236:         *        Revision 1.26  2004/09/17 14:12:38  bruceb
0237:         *        fixed javadoc re filemasks
0238:         *
0239:         *        Revision 1.25  2004/09/14 06:24:03  bruceb
0240:         *        fixed javadoc comment
0241:         *
0242:         *        Revision 1.24  2004/08/31 13:48:29  bruceb
0243:         *        resume,features,restructure
0244:         *
0245:         *        Revision 1.23  2004/07/23 08:34:32  bruceb
0246:         *        strict replies or not, better tfr monitor reporting
0247:         *
0248:         *        Revision 1.22  2004/06/25 11:47:46  bruceb
0249:         *        made 1.1.x compatible
0250:         *
0251:         *        Revision 1.21  2004/06/11 10:20:35  bruceb
0252:         *        permit 200 to be returned from various cmds
0253:         *
0254:         *        Revision 1.20  2004/05/22 16:52:57  bruceb
0255:         *        message listener
0256:         *
0257:         *        Revision 1.19  2004/05/15 22:37:22  bruceb
0258:         *        put debugResponses back in
0259:         *
0260:         *        Revision 1.18  2004/05/13 23:00:34  hans
0261:         *        changed comment
0262:         *
0263:         *        Revision 1.17  2004/05/08 21:14:41  bruceb
0264:         *        checkConnection stuff
0265:         *
0266:         *        Revision 1.14  2004/04/19 21:54:06  bruceb
0267:         *        final tweaks to dirDetails() re caching
0268:         *
0269:         *        Revision 1.13  2004/04/18 11:16:44  bruceb
0270:         *        made validateTransfer() public
0271:         *
0272:         *        Revision 1.12  2004/04/17 18:37:38  bruceb
0273:         *        new parse functionality
0274:         *
0275:         *        Revision 1.11  2004/03/23 20:26:49  bruceb
0276:         *        tweak to size(), catch exceptions on puts()
0277:         *
0278:         *        Revision 1.10  2003/11/15 11:23:55  bruceb
0279:         *        changes required for ssl subclasses
0280:         *
0281:         *        Revision 1.6  2003/05/31 14:53:44  bruceb
0282:         *        1.2.2 changes
0283:         *
0284:         *        Revision 1.5  2003/01/29 22:46:08  bruceb
0285:         *        minor changes
0286:         *
0287:         *        Revision 1.4  2002/11/19 22:01:25  bruceb
0288:         *        changes for 1.2
0289:         *
0290:         *        Revision 1.3  2001/10/09 20:53:46  bruceb
0291:         *        Active mode changes
0292:         *
0293:         *        Revision 1.1  2001/10/05 14:42:03  bruceb
0294:         *        moved from old project
0295:         *
0296:         */package com.enterprisedt.net.ftp;
0297:
0298:        import java.io.BufferedInputStream;
0299:        import java.io.BufferedOutputStream;
0300:        import java.io.ByteArrayInputStream;
0301:        import java.io.ByteArrayOutputStream;
0302:        import java.io.DataInputStream;
0303:        import java.io.DataOutputStream;
0304:        import java.io.File;
0305:        import java.io.FileInputStream;
0306:        import java.io.FileOutputStream;
0307:        import java.io.IOException;
0308:        import java.io.InputStream;
0309:        import java.io.InputStreamReader;
0310:        import java.io.LineNumberReader;
0311:        import java.io.OutputStream;
0312:        import java.net.InetAddress;
0313:        import java.net.ServerSocket;
0314:        import java.text.ParseException;
0315:        import java.text.ParsePosition;
0316:        import java.text.SimpleDateFormat;
0317:        import java.util.Date;
0318:        import java.util.Locale;
0319:        import java.util.Properties;
0320:        import java.util.TimeZone;
0321:        import java.util.Vector;
0322:
0323:        import com.enterprisedt.util.debug.Level;
0324:        import com.enterprisedt.util.debug.Logger;
0325:
0326:        /**
0327:         *  Supports client-side FTP. Most common
0328:         *  FTP operations are present in this class.
0329:         *
0330:         *  @author      Bruce Blackshaw
0331:         *  @version     $Revision: 1.93 $
0332:         */
0333:        public class FTPClient implements  FTPClientInterface {
0334:
0335:            /**
0336:             *  Revision control id
0337:             */
0338:            public static String cvsId = "@(#)$Id: FTPClient.java,v 1.93 2008-01-09 03:54:21 bruceb Exp $";
0339:
0340:            /**
0341:             * Default byte interval for transfer monitor
0342:             */
0343:            final public static int DEFAULT_MONITOR_INTERVAL = 65535;
0344:
0345:            /**
0346:             * Default transfer buffer size
0347:             */
0348:            final public static int DEFAULT_BUFFER_SIZE = 16384;
0349:
0350:            /**
0351:             * Maximum port number
0352:             */
0353:            final private static int MAX_PORT = 65535;
0354:
0355:            /**
0356:             * Default timeout
0357:             */
0358:            final public static int DEFAULT_TIMEOUT = 60 * 1000;
0359:
0360:            /**
0361:             * Short value for a timeout
0362:             */
0363:            final private static int SHORT_TIMEOUT = 500;
0364:
0365:            /**
0366:             * Default encoding used for control data
0367:             */
0368:            final public static String DEFAULT_ENCODING = "US-ASCII";
0369:
0370:            /**
0371:             * SOCKS port property name
0372:             */
0373:            final private static String SOCKS_PORT = "socksProxyPort";
0374:
0375:            /**
0376:             * SOCKS host property name
0377:             */
0378:            final private static String SOCKS_HOST = "socksProxyHost";
0379:
0380:            /**
0381:             * Line separator
0382:             */
0383:            final private static byte[] LINE_SEPARATOR = System.getProperty(
0384:                    "line.separator").getBytes();
0385:
0386:            /**
0387:             * Used for ASCII translation
0388:             */
0389:            final public static byte CARRIAGE_RETURN = 13;
0390:
0391:            /**
0392:             * Used for ASCII translation
0393:             */
0394:            final public static byte LINE_FEED = 10;
0395:
0396:            /**
0397:             * Used for ASCII translation
0398:             */
0399:            final public static byte[] FTP_LINE_SEPARATOR = { CARRIAGE_RETURN,
0400:                    LINE_FEED };
0401:
0402:            /**
0403:             * Marker in reply for STOU reply with filename
0404:             */
0405:            final private static String STOU_FILENAME_MARKER = "FILE:";
0406:
0407:            /**
0408:             * Store command
0409:             */
0410:            final private static String STORE_CMD = "STOR ";
0411:
0412:            /**
0413:             * Store unique command
0414:             */
0415:            final private static String STORE_UNIQ_CMD = "STOU ";
0416:
0417:            /**
0418:             * Default locales
0419:             */
0420:            public static Locale[] DEFAULT_LISTING_LOCALES;
0421:
0422:            /**
0423:             * Logging object
0424:             */
0425:            private static Logger log = Logger.getLogger("FTPClient");
0426:
0427:            /**
0428:             *  Format to interpret MTDM timestamp
0429:             */
0430:            private SimpleDateFormat tsFormat = new SimpleDateFormat(
0431:                    "yyyyMMddHHmmss");
0432:
0433:            /**
0434:             *  Socket responsible for controlling
0435:             *  the connection
0436:             */
0437:            protected FTPControlSocket control = null;
0438:
0439:            /**
0440:             *  Socket responsible for transferring
0441:             *  the data
0442:             */
0443:            protected FTPDataSocket data = null;
0444:
0445:            /**
0446:             *  Socket timeout for both data and control. In
0447:             *  milliseconds
0448:             */
0449:            protected int timeout = DEFAULT_TIMEOUT;
0450:
0451:            /**
0452:             * Interval in seconds in between server wakeups. O is
0453:             * not enabled
0454:             */
0455:            protected int serverWakeupInterval = 0;
0456:
0457:            /**
0458:             * Address of the remote server.
0459:             */
0460:            protected InetAddress remoteAddr;
0461:
0462:            /**
0463:             * Name/IP of remote host
0464:             */
0465:            protected String remoteHost;
0466:
0467:            /**
0468:             * Id of instance
0469:             */
0470:            protected String id;
0471:
0472:            /**
0473:             * Control port number.
0474:             */
0475:            protected int controlPort = FTPControlSocket.CONTROL_PORT;
0476:
0477:            /**
0478:             * If true, uses the original host IP if an internal IP address
0479:             * is returned by the server in PASV mode
0480:             */
0481:            private boolean autoPassiveIPSubstitution = false;
0482:
0483:            /**
0484:             * IP address to force to use in active mode
0485:             */
0486:            private String activeIP = null;
0487:
0488:            /**
0489:             * Encoding used on control socket
0490:             */
0491:            protected String controlEncoding = DEFAULT_ENCODING;
0492:
0493:            /**
0494:             * Use strict return codes if true
0495:             */
0496:            private boolean strictReturnCodes = false;
0497:
0498:            /**
0499:             * Matcher for directory empty
0500:             */
0501:            protected DirectoryEmptyStrings dirEmptyStrings = new DirectoryEmptyStrings();
0502:
0503:            /**
0504:             * Matcher for transfer complete
0505:             */
0506:            protected TransferCompleteStrings transferCompleteStrings = new TransferCompleteStrings();
0507:
0508:            /**
0509:             * Matcher for permission denied
0510:             */
0511:            protected FileNotFoundStrings fileNotFoundStrings = new FileNotFoundStrings();
0512:            /**
0513:             *  Can be used to cancel a transfer
0514:             */
0515:            private boolean cancelTransfer = false;
0516:
0517:            /**
0518:             * If true, a file transfer is being resumed
0519:             */
0520:            private boolean resume = false;
0521:
0522:            /**
0523:             * MDTM supported flag
0524:             */
0525:            private boolean mdtmSupported = true;
0526:
0527:            /**
0528:             * SIZE supported flag
0529:             */
0530:            private boolean sizeSupported = true;
0531:
0532:            /**
0533:             * Resume byte marker point
0534:             */
0535:            private long resumeMarker = 0;
0536:
0537:            /**
0538:             * Delete partial files on transfer failure?
0539:             */
0540:            private boolean deleteOnFailure = true;
0541:
0542:            /**
0543:             * If true, filetypes are autodetected and transfer mode changed to binary/ASCII as 
0544:             * required
0545:             */
0546:            protected boolean detectTransferMode = false;
0547:
0548:            /**
0549:             * Lowest port in active mode port range
0550:             */
0551:            private int lowPort = -1;
0552:
0553:            /**
0554:             * Highest port in active mode port range
0555:             */
0556:            private int highPort = -1;
0557:
0558:            /**
0559:             * Command sent to server for storing a file
0560:             */
0561:            private String storeCommand = STORE_CMD;
0562:
0563:            /**
0564:             * Bytes transferred in between monitor callbacks
0565:             */
0566:            protected long monitorInterval = DEFAULT_MONITOR_INTERVAL;
0567:
0568:            /**
0569:             * Size of transfer buffers
0570:             */
0571:            protected int transferBufferSize = DEFAULT_BUFFER_SIZE;
0572:
0573:            /**
0574:             * Count of downloaded files
0575:             */
0576:            private int downloadCount = 0;
0577:
0578:            /**
0579:             * Count of uploaded files
0580:             */
0581:            private int uploadCount = 0;
0582:
0583:            /**
0584:             * Count of deleted files
0585:             */
0586:            private int deleteCount = 0;
0587:
0588:            /**
0589:             * Listen to all interfaces in active mode
0590:             */
0591:            private boolean listenOnAllInterfaces = true;
0592:
0593:            /**
0594:             * Parses LIST output
0595:             */
0596:            private FTPFileFactory fileFactory = null;
0597:
0598:            /**
0599:             * Locales for date parsing
0600:             */
0601:            private Locale[] listingLocales;
0602:
0603:            /**
0604:             * Parses the MLSD and MLST formats
0605:             */
0606:            private MLSXEntryParser mlsxParser = new MLSXEntryParser();
0607:
0608:            /**
0609:             *  Progress monitor
0610:             */
0611:            protected FTPProgressMonitor monitor = null;
0612:
0613:            /**
0614:             * Message listener
0615:             */
0616:            protected FTPMessageListener messageListener = null;
0617:
0618:            /**
0619:             * File transfer listener
0620:             */
0621:            protected FTPProgressMonitorEx monitorEx = null;
0622:
0623:            /**
0624:             *  Record of the transfer type - make the default ASCII
0625:             */
0626:            protected FTPTransferType transferType = FTPTransferType.ASCII;
0627:
0628:            /**
0629:             *  Record of the connect mode - make the default PASV (as this was
0630:             *  the original mode supported)
0631:             */
0632:            private FTPConnectMode connectMode = FTPConnectMode.PASV;
0633:
0634:            /**
0635:             *  Holds the last valid reply from the server on the control socket
0636:             */
0637:            protected FTPReply lastValidReply;
0638:
0639:            /**
0640:             *  Holds the last reply from the server on the control socket
0641:             */
0642:            protected FTPReply lastReply;
0643:
0644:            /**
0645:             * set default listing locales.
0646:             */
0647:            static {
0648:                DEFAULT_LISTING_LOCALES = new Locale[2];
0649:                DEFAULT_LISTING_LOCALES[0] = Locale.ENGLISH;
0650:                DEFAULT_LISTING_LOCALES[1] = Locale.getDefault();
0651:            }
0652:
0653:            /**
0654:             *  Instance initializer. Sets formatter to GMT.
0655:             */
0656:            {
0657:                tsFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
0658:                listingLocales = DEFAULT_LISTING_LOCALES;
0659:            }
0660:
0661:            /**
0662:             * Get the version of edtFTPj
0663:             * 
0664:             * @return int array of {major,middle,minor} version numbers 
0665:             */
0666:            public static int[] getVersion() {
0667:                return VersionDetails.getVersion();
0668:            }
0669:
0670:            /**
0671:             * Get the build timestamp
0672:             * 
0673:             * @return d-MMM-yyyy HH:mm:ss z build timestamp 
0674:             */
0675:            public static String getBuildTimestamp() {
0676:                return VersionDetails.getBuildTimestamp();
0677:            }
0678:
0679:            /**
0680:             *  Constructor. Creates the control
0681:             *  socket
0682:             *
0683:             *  @param   remoteHost  the remote hostname
0684:             *  @deprecated  use setter methods to set properties
0685:             */
0686:            public FTPClient(String remoteHost) throws IOException,
0687:                    FTPException {
0688:
0689:                this (remoteHost, FTPControlSocket.CONTROL_PORT, 0);
0690:            }
0691:
0692:            /**
0693:             *  Constructor. Creates the control
0694:             *  socket
0695:             *
0696:             *  @param   remoteHost  the remote hostname
0697:             *  @param   controlPort  port for control stream (-1 for default port)
0698:             *  @deprecated  use setter methods to set properties
0699:             */
0700:            public FTPClient(String remoteHost, int controlPort)
0701:                    throws IOException, FTPException {
0702:
0703:                this (remoteHost, controlPort, 0);
0704:            }
0705:
0706:            /**
0707:             *  Constructor. Creates the control
0708:             *  socket
0709:             *
0710:             *  @param   remoteHost  the remote hostname
0711:             *  @param   controlPort  port for control stream (use -1 for the default port)
0712:             *  @param  timeout       the length of the timeout, in milliseconds
0713:             *                        (pass in 0 for no timeout)
0714:             *  @deprecated  use setter methods to set properties
0715:             */
0716:            public FTPClient(String remoteHost, int controlPort, int timeout)
0717:                    throws IOException, FTPException {
0718:
0719:                this (InetAddress.getByName(remoteHost), controlPort, timeout);
0720:            }
0721:
0722:            /**
0723:             *  Constructor. Creates the control
0724:             *  socket
0725:             *
0726:             *  @param   remoteHost  the remote hostname
0727:             *  @param   controlPort  port for control stream (use -1 for the default port)
0728:             *  @param  timeout       the length of the timeout, in milliseconds
0729:             *                        (pass in 0 for no timeout)
0730:             *  @param   encoding         character encoding used for data
0731:             *  @deprecated  use setter methods to set properties
0732:             */
0733:            public FTPClient(String remoteHost, int controlPort, int timeout,
0734:                    String encoding) throws IOException, FTPException {
0735:
0736:                this (InetAddress.getByName(remoteHost), controlPort, timeout,
0737:                        encoding);
0738:            }
0739:
0740:            /**
0741:             *  Constructor. Creates the control
0742:             *  socket
0743:             *
0744:             *  @param   remoteAddr  the address of the
0745:             *                       remote host
0746:             *  @deprecated  use setter methods to set properties
0747:             */
0748:            public FTPClient(InetAddress remoteAddr) throws IOException,
0749:                    FTPException {
0750:
0751:                this (remoteAddr, FTPControlSocket.CONTROL_PORT, 0);
0752:            }
0753:
0754:            /**
0755:             *  Constructor. Creates the control
0756:             *  socket. Allows setting of control port (normally
0757:             *  set by default to 21).
0758:             *
0759:             *  @param   remoteAddr  the address of the
0760:             *                       remote host
0761:             *  @param   controlPort  port for control stream
0762:             *  @deprecated  use setter methods to set properties
0763:             */
0764:            public FTPClient(InetAddress remoteAddr, int controlPort)
0765:                    throws IOException, FTPException {
0766:
0767:                this (remoteAddr, controlPort, 0);
0768:            }
0769:
0770:            /**
0771:             *  Constructor. Creates the control
0772:             *  socket. Allows setting of control port (normally
0773:             *  set by default to 21).
0774:             *
0775:             *  @param   remoteAddr    the address of the
0776:             *                          remote host
0777:             *  @param   controlPort   port for control stream (-1 for default port)
0778:             *  @param  timeout        the length of the timeout, in milliseconds 
0779:             *                         (pass in 0 for no timeout)
0780:             *  @deprecated  use setter methods to set properties
0781:             */
0782:            public FTPClient(InetAddress remoteAddr, int controlPort,
0783:                    int timeout) throws IOException, FTPException {
0784:                if (controlPort < 0)
0785:                    controlPort = FTPControlSocket.CONTROL_PORT;
0786:                initialize(new FTPControlSocket(remoteAddr, controlPort,
0787:                        timeout, DEFAULT_ENCODING, null));
0788:            }
0789:
0790:            /**
0791:             *  Constructor. Creates the control
0792:             *  socket. Allows setting of control port (normally
0793:             *  set by default to 21).
0794:             *
0795:             *  @param   remoteAddr    the address of the
0796:             *                          remote host
0797:             *  @param   controlPort   port for control stream (-1 for default port)
0798:             *  @param   timeout        the length of the timeout, in milliseconds 
0799:             *                         (pass in 0 for no timeout)
0800:             *  @param   encoding         character encoding used for data
0801:             *  @deprecated  use setter methods to set properties
0802:             */
0803:            public FTPClient(InetAddress remoteAddr, int controlPort,
0804:                    int timeout, String encoding) throws IOException,
0805:                    FTPException {
0806:                if (controlPort < 0)
0807:                    controlPort = FTPControlSocket.CONTROL_PORT;
0808:                initialize(new FTPControlSocket(remoteAddr, controlPort,
0809:                        timeout, encoding, null));
0810:            }
0811:
0812:            /**
0813:             *  Default constructor should now always be used together with setter methods
0814:             *  in preference to other constructors (now deprecated). The {@link #connect()}
0815:             *  method is used to perform the actual connection to the remote host - but only
0816:             *  for this constructor. Deprecated constructors connect in the constructor and
0817:             *  connect() is not required (and cannot be called).
0818:             */
0819:            public FTPClient() {
0820:                log.debug(VersionDetails.report(this ));
0821:            }
0822:
0823:            /**
0824:             * Connects to the server at the address and port number defined
0825:             * in the constructor. Must be performed <b>before</b> login() or user() is
0826:             * called.
0827:             * 
0828:             * @throws IOException Thrown if there is a TCP/IP-related error.
0829:             * @throws FTPException Thrown if there is an error related to the FTP protocol. 
0830:             */
0831:            public void connect() throws IOException, FTPException {
0832:
0833:                checkConnection(false);
0834:
0835:                log.debug("Connecting to " + remoteAddr + ":" + controlPort);
0836:
0837:                initialize(new FTPControlSocket(remoteAddr, controlPort,
0838:                        timeout, controlEncoding, messageListener));
0839:            }
0840:
0841:            /**
0842:             * Is this client connected? 
0843:             * 
0844:             * @return true if connected, false otherwise
0845:             */
0846:            public boolean connected() {
0847:                if (control == null)
0848:                    return false;
0849:                else {
0850:                    try {
0851:                        if (!SocketUtils.isConnected(control.controlSock)) {
0852:                            control = null;
0853:                            return false;
0854:                        } else {
0855:                            return true;
0856:                        }
0857:                    } catch (IOException e) {
0858:                        return false;
0859:                    }
0860:                }
0861:            }
0862:
0863:            /**
0864:             * Checks if the client has connected to the server and throws an exception if it hasn't.
0865:             * This is only intended to be used by subclasses
0866:             * 
0867:             * @throws FTPException Thrown if the client has not connected to the server.
0868:             */
0869:            protected void checkConnection(boolean shouldBeConnected)
0870:                    throws FTPException {
0871:                if (shouldBeConnected && !connected())
0872:                    throw new FTPException(
0873:                            "The FTP client has not yet connected to the server.  "
0874:                                    + "The requested action cannot be performed until after a connection has been established.");
0875:                else if (!shouldBeConnected && connected())
0876:                    throw new FTPException(
0877:                            "The FTP client has already been connected to the server.  "
0878:                                    + "The requested action must be performed before a connection is established.");
0879:            }
0880:
0881:            /**
0882:             * Set the control socket explicitly
0883:             * 
0884:             * @param control   control socket reference
0885:             */
0886:            protected void initialize(FTPControlSocket control)
0887:                    throws IOException {
0888:                this .control = control;
0889:                control.setMessageListener(messageListener);
0890:                control.setStrictReturnCodes(strictReturnCodes);
0891:                control.setListenOnAllInterfaces(listenOnAllInterfaces);
0892:                control.setTimeout(timeout);
0893:                control.setAutoPassiveIPSubstitution(autoPassiveIPSubstitution);
0894:                if (activeIP != null)
0895:                    control.setActivePortIPAddress(activeIP);
0896:                if (lowPort > 0 && highPort > 0)
0897:                    control.setActivePortRange(lowPort, highPort);
0898:            }
0899:
0900:            /**
0901:             *  Switch debug of responses on or off
0902:             *
0903:             *  @param  on  true if you wish to have responses to
0904:             *              the log stream, false otherwise
0905:             *  @deprecated  use the Logger class to switch debugging on and off
0906:             */
0907:            public void debugResponses(boolean on) {
0908:                if (on)
0909:                    Logger.setLevel(Level.DEBUG);
0910:                else
0911:                    Logger.setLevel(Level.OFF);
0912:            }
0913:
0914:            /**
0915:             * Get the identifying string for this instance
0916:             */
0917:            public String getId() {
0918:                return id;
0919:            }
0920:
0921:            /**
0922:             * Set the identifying string for this instance
0923:             * 
0924:             * @param id    identifying string
0925:             */
0926:            public void setId(String id) {
0927:                this .id = id;
0928:            }
0929:
0930:            /**
0931:             * Get the number of files downloaded since the count was
0932:             * reset
0933:             * 
0934:             * @return  download file count
0935:             */
0936:            public int getDownloadCount() {
0937:                return downloadCount;
0938:            }
0939:
0940:            /**
0941:             * Reset the count of downloaded files to zero.
0942:             *
0943:             */
0944:            public void resetDownloadCount() {
0945:                downloadCount = 0;
0946:            }
0947:
0948:            /**
0949:             * Get the number of files uploaded since the count was
0950:             * reset
0951:             * 
0952:             * @return  upload file count
0953:             */
0954:            public int getUploadCount() {
0955:                return uploadCount;
0956:            }
0957:
0958:            /**
0959:             * Reset the count of uploaded files to zero.
0960:             *
0961:             */
0962:            public void resetUploadCount() {
0963:                uploadCount = 0;
0964:            }
0965:
0966:            /**
0967:             * Get the number of files deleted since the count was
0968:             * reset
0969:             * 
0970:             * @return  deleted file count
0971:             */
0972:            public int getDeleteCount() {
0973:                return deleteCount;
0974:            }
0975:
0976:            /**
0977:             * Reset the count of deleted files to zero.
0978:             *
0979:             */
0980:            public void resetDeleteCount() {
0981:                deleteCount = 0;
0982:            }
0983:
0984:            /**
0985:             * Set strict checking of FTP return codes. If strict 
0986:             * checking is on (the default) code must exactly match the expected 
0987:             * code. If strict checking is off, only the first digit must match.
0988:             * 
0989:             * @param strict    true for strict checking, false for loose checking
0990:             */
0991:            public void setStrictReturnCodes(boolean strict) {
0992:                this .strictReturnCodes = strict;
0993:                if (control != null)
0994:                    control.setStrictReturnCodes(strict);
0995:            }
0996:
0997:            /**
0998:             * Determine if strict checking of return codes is switched on. If it is 
0999:             * (the default), all return codes must exactly match the expected code.  
1000:             * If strict checking is off, only the first digit must match.
1001:             * 
1002:             * @return  true if strict return code checking, false if non-strict.
1003:             */
1004:            public boolean isStrictReturnCodes() {
1005:                return strictReturnCodes;
1006:            }
1007:
1008:            /**
1009:             * Listen on all interfaces for active mode transfers (the default).
1010:             * 
1011:             * @param listenOnAll   true if listen on all interfaces, false to listen on the control interface
1012:             */
1013:            public void setListenOnAllInterfaces(boolean listenOnAll) {
1014:                this .listenOnAllInterfaces = listenOnAll;
1015:                if (control != null)
1016:                    control.setListenOnAllInterfaces(listenOnAll);
1017:            }
1018:
1019:            /**
1020:             * Are we listening on all interfaces in active mode, which is the default?
1021:             * 
1022:             * @return true if listening on all interfaces, false if listening just on the control interface
1023:             */
1024:            public boolean getListenOnAllInterfaces() {
1025:                return listenOnAllInterfaces;
1026:            }
1027:
1028:            /**
1029:             * Get class that holds fragments of server messages that indicate a file was 
1030:             * not found. New messages can be added.
1031:             * <p>
1032:             * The fragments are used when it is necessary to examine the message
1033:             * returned by a server to see if it is saying a file was not found. 
1034:             * If an FTP server is returning a different message that still clearly 
1035:             * indicates a file was not found, use this property to add a new server 
1036:             * fragment to the repository via the add method. It would be helpful to
1037:             * email support at enterprisedt dot com to inform us of the message so
1038:             * it can be added to the next build.
1039:             * 
1040:             * @return  messages class
1041:             */
1042:            public FileNotFoundStrings getFileNotFoundMessages() {
1043:                return fileNotFoundStrings;
1044:            }
1045:
1046:            /**
1047:             * Set a new instance of the strings class
1048:             * 
1049:             * @param fileNotFoundStrings  new instance
1050:             */
1051:            public void setFileNotFoundMessages(
1052:                    FileNotFoundStrings fileNotFoundStrings) {
1053:                this .fileNotFoundStrings = fileNotFoundStrings;
1054:            }
1055:
1056:            /**
1057:             * Get class that holds fragments of server messages that indicate a transfer completed. 
1058:             * New messages can be added.
1059:             * <p>
1060:             * The fragments are used when it is necessary to examine the message
1061:             * returned by a server to see if it is saying a transfer completed. 
1062:             * If an FTP server is returning a different message that still clearly 
1063:             * indicates a transfer failed, use this property to add a new server 
1064:             * fragment to the repository via the add method. It would be helpful to
1065:             * email support at enterprisedt dot com to inform us of the message so
1066:             * it can be added to the next build.
1067:             * 
1068:             * @return  messages class
1069:             */
1070:            public TransferCompleteStrings getTransferCompleteMessages() {
1071:                return transferCompleteStrings;
1072:            }
1073:
1074:            /**
1075:             * Set a new instance of the strings class
1076:             * 
1077:             * @param transferCompleteStrings  new instance
1078:             */
1079:            public void setTransferCompleteMessages(
1080:                    TransferCompleteStrings transferCompleteStrings) {
1081:                this .transferCompleteStrings = transferCompleteStrings;
1082:            }
1083:
1084:            /**
1085:             * Get class that holds fragments of server messages that indicate a  
1086:             * directory is empty. New messages can be added.
1087:             * <p>
1088:             * The fragments are used when it is necessary to examine the message
1089:             * returned by a server to see if it is saying a directory is empty. 
1090:             * If an FTP server is returning a different message that still clearly 
1091:             * indicates a directory is empty, use this property to add a new server 
1092:             * fragment to the repository via the add method. It would be helpful to
1093:             * email support at enterprisedt dot com to inform us of the message so
1094:             * it can be added to the next build.
1095:             * 
1096:             * @return  messages class
1097:             */
1098:            public DirectoryEmptyStrings getDirectoryEmptyMessages() {
1099:                return dirEmptyStrings;
1100:            }
1101:
1102:            /**
1103:             * Set a new instance of the strings class
1104:             * 
1105:             * @param dirEmptyStrings  new instance
1106:             */
1107:            public void setDirectoryEmptyMessages(
1108:                    DirectoryEmptyStrings dirEmptyStrings) {
1109:                this .dirEmptyStrings = dirEmptyStrings;
1110:            }
1111:
1112:            /* (non-Javadoc)
1113:             * @see com.enterprisedt.net.ftp.FTPClientInterface#setDetectTransferMode(boolean)
1114:             */
1115:            public void setDetectTransferMode(boolean detectTransferMode) {
1116:                this .detectTransferMode = detectTransferMode;
1117:            }
1118:
1119:            /* (non-Javadoc)
1120:             * @see com.enterprisedt.net.ftp.FTPClientInterface#getDetectTransferMode()
1121:             */
1122:            public boolean getDetectTransferMode() {
1123:                return detectTransferMode;
1124:            }
1125:
1126:            /**
1127:             * Set to true if the STOU command is always to be used when
1128:             * uploading files, even if a filename is supplied. Normally
1129:             * STOU is only used if the supplied remote filename is null or
1130:             * the empty string.
1131:             * 
1132:             * @param forceUnique   true if STOU is always to be used
1133:             */
1134:            public void setForceUniqueNames(boolean forceUnique) {
1135:                if (forceUnique)
1136:                    storeCommand = STORE_UNIQ_CMD;
1137:                else
1138:                    storeCommand = STORE_CMD;
1139:            }
1140:
1141:            /**
1142:             * Switch the transfer mode if requested and if necessary
1143:             * 
1144:             * @param filename      filename of file to be transferred
1145:             * @throws FTPException 
1146:             * @throws IOException 
1147:             */
1148:            protected void chooseTransferMode(String filename)
1149:                    throws IOException, FTPException {
1150:                if (detectTransferMode) {
1151:                    if (filename == null) {
1152:                        log
1153:                                .warn("Cannot choose transfer mode as filename not supplied");
1154:                        return;
1155:                    }
1156:                    if (FileTypes.ASCII.matches(filename)
1157:                            && transferType.equals(FTPTransferType.BINARY)) {
1158:                        setType(FTPTransferType.ASCII);
1159:                        log
1160:                                .debug("Autodetect on - changed transfer type to ASCII");
1161:                    } else if (FileTypes.BINARY.matches(filename)
1162:                            && transferType.equals(FTPTransferType.ASCII)) {
1163:                        setType(FTPTransferType.BINARY);
1164:                        log
1165:                                .debug("Autodetect on - changed transfer type to binary");
1166:                    }
1167:                }
1168:            }
1169:
1170:            /**
1171:             *   Set the SO_TIMEOUT in milliseconds on the underlying socket.
1172:             *   If set this means the socket will block in a read operation
1173:             *   only for this length of time - useful if the FTP sever has 
1174:             *   hung, for example. The default is 0, which is an infinite timeout. 
1175:             *
1176:             *   Note that for JREs 1.4+, the timeout is also used when first 
1177:             *   connecting to the remote host. 
1178:             *
1179:             *   @param millis The length of the timeout, in milliseconds
1180:             */
1181:            public void setTimeout(int millis) throws IOException {
1182:
1183:                this .timeout = millis;
1184:                if (control != null)
1185:                    control.setTimeout(millis);
1186:            }
1187:
1188:            /**
1189:             *  Get the TCP timeout 
1190:             *  
1191:             *  @return timeout that is used, in milliseconds
1192:             */
1193:            public int getTimeout() {
1194:                return timeout;
1195:            }
1196:
1197:            /**
1198:             * Returns the control-port being connected to on the remote server. 
1199:             * 
1200:             * Note that this method replaces {@link #getControlPort()}.
1201:             * 
1202:             * @return Returns the port being connected to on the remote server. 
1203:             */
1204:            public int getRemotePort() {
1205:                return controlPort;
1206:            }
1207:
1208:            /** 
1209:             * Set the control to connect to on the remote server. Can only do this if
1210:             * not already connected.
1211:             * 
1212:             * Note that this method replaces {@link #setControlPort(int)}.
1213:             * 
1214:             * @param remotePort The port to use. 
1215:             * @throws FTPException Thrown if the client is already connected to the server.
1216:             */
1217:            public void setRemotePort(int remotePort) throws FTPException {
1218:                checkConnection(false);
1219:                this .controlPort = remotePort;
1220:            }
1221:
1222:            /**
1223:             * Returns the control-port being connected to on the remote server. 
1224:             * @return Returns the port being connected to on the remote server. 
1225:             * @deprecated Use {@link com.enterprisedt.net.ftp.FTPClientInterface#getRemotePort()} instead.
1226:             */
1227:            public int getControlPort() {
1228:                return controlPort;
1229:            }
1230:
1231:            /** 
1232:             * Set the control to connect to on the remote server. Can only do this if
1233:             * not already connected.
1234:             * 
1235:             * @param controlPort The port to use. 
1236:             * @throws FTPException Thrown if the client is already connected to the server.
1237:             * @deprecated Use {@link com.enterprisedt.net.ftp.FTPClientInterface#setRemotePort(int)} instead.
1238:             */
1239:            public void setControlPort(int controlPort) throws FTPException {
1240:                checkConnection(false);
1241:                this .controlPort = controlPort;
1242:            }
1243:
1244:            /**
1245:             * @return Returns the remoteAddr.
1246:             */
1247:            public InetAddress getRemoteAddr() {
1248:                return remoteAddr;
1249:            }
1250:
1251:            /**
1252:             * Set the remote address
1253:             * 
1254:             * @param remoteAddr The remoteAddr to set.
1255:             * @throws FTPException
1256:             */
1257:            public void setRemoteAddr(InetAddress remoteAddr)
1258:                    throws FTPException {
1259:                checkConnection(false);
1260:                this .remoteAddr = remoteAddr;
1261:                this .remoteHost = remoteAddr.getHostName();
1262:            }
1263:
1264:            /*
1265:             *  (non-Javadoc)
1266:             * @see com.enterprisedt.net.ftp.FTPClientInterface#getRemoteHost()
1267:             */
1268:            public String getRemoteHost() {
1269:                return remoteHost;
1270:            }
1271:
1272:            /*
1273:             *  (non-Javadoc)
1274:             * @see com.enterprisedt.net.ftp.FTPClientInterface#setRemoteHost(java.lang.String)
1275:             */
1276:            public void setRemoteHost(String remoteHost) throws IOException,
1277:                    FTPException {
1278:                checkConnection(false);
1279:                this .remoteHost = remoteHost;
1280:                this .remoteAddr = InetAddress.getByName(remoteHost);
1281:            }
1282:
1283:            /**
1284:             * Is automatic substitution of the remote host IP set to
1285:             * be on for passive mode connections?
1286:             * 
1287:             * @return true if set on, false otherwise
1288:             */
1289:            public boolean isAutoPassiveIPSubstitution() {
1290:                return autoPassiveIPSubstitution;
1291:            }
1292:
1293:            /**
1294:             * Set automatic substitution of the remote host IP on if
1295:             * in passive mode
1296:             * 
1297:             * @param autoPassiveIPSubstitution true if set to on, false otherwise
1298:             */
1299:            public void setAutoPassiveIPSubstitution(
1300:                    boolean autoPassiveIPSubstitution) {
1301:                this .autoPassiveIPSubstitution = autoPassiveIPSubstitution;
1302:                if (control != null)
1303:                    control
1304:                            .setAutoPassiveIPSubstitution(autoPassiveIPSubstitution);
1305:            }
1306:
1307:            /**
1308:             * Get server wakeup interval in seconds. A value of 0
1309:             * means it is disabled (the default).
1310:             * 
1311:             * @return interval in seconds
1312:             */
1313:            public int getServerWakeupInterval() {
1314:                return serverWakeupInterval;
1315:            }
1316:
1317:            /**
1318:             * Set server wakeup interval in seconds. A value of 0 
1319:             * means it is disabled (the default). This may hang or confuse 
1320:             * the FTP server - use with caution.
1321:             * 
1322:             * @param interval  interval in seconds
1323:             */
1324:            public void setServerWakeupInterval(int interval) {
1325:                this .serverWakeupInterval = interval;
1326:            }
1327:
1328:            /**
1329:             * Get the encoding used for the control connection
1330:             * 
1331:             * @return Returns the current controlEncoding.
1332:             */
1333:            public String getControlEncoding() {
1334:                return controlEncoding;
1335:            }
1336:
1337:            /**
1338:             * Set the control socket's encoding. Can only do this if
1339:             * not connected
1340:             * 
1341:             * @param controlEncoding The controlEncoding to set, which is the name of a Charset
1342:             * @see java.nio.charset.Charset
1343:             * @throws FTPException
1344:             */
1345:            public void setControlEncoding(String controlEncoding)
1346:                    throws FTPException {
1347:                checkConnection(false);
1348:                this .controlEncoding = controlEncoding;
1349:            }
1350:
1351:            /**
1352:             * @return Returns the messageListener.
1353:             */
1354:            public FTPMessageListener getMessageListener() {
1355:                return messageListener;
1356:            }
1357:
1358:            /**
1359:             * Set a listener that handles all FTP messages
1360:             * 
1361:             * @param listener  message listener
1362:             */
1363:            public void setMessageListener(FTPMessageListener listener) {
1364:                this .messageListener = listener;
1365:                if (control != null)
1366:                    control.setMessageListener(listener);
1367:            }
1368:
1369:            /**
1370:             * Get reference to the transfer listener
1371:             * 
1372:             * @return FTPProgressMonitorEx
1373:             */
1374:            public FTPProgressMonitorEx getProgressMonitorEx() {
1375:                return monitorEx;
1376:            }
1377:
1378:            /**
1379:             * Set reference to the transfer listener
1380:             * 
1381:             * @param monitorEx  transfer listener
1382:             */
1383:            public void setProgressMonitorEx(FTPProgressMonitorEx monitorEx) {
1384:                this .monitorEx = monitorEx;
1385:            }
1386:
1387:            /**
1388:             *  Set the connect mode
1389:             *
1390:             *  @param  mode  ACTIVE or PASV mode
1391:             */
1392:            public void setConnectMode(FTPConnectMode mode) {
1393:                connectMode = mode;
1394:            }
1395:
1396:            /**
1397:             * @return Returns the connectMode.
1398:             */
1399:            public FTPConnectMode getConnectMode() {
1400:                return connectMode;
1401:            }
1402:
1403:            /*
1404:             *  (non-Javadoc)
1405:             * @see com.enterprisedt.net.ftp.FTPClientInterface#setProgressMonitor(com.enterprisedt.net.ftp.FTPProgressMonitor, long)
1406:             */
1407:            public void setProgressMonitor(FTPProgressMonitor monitor,
1408:                    long interval) {
1409:                this .monitor = monitor;
1410:                this .monitorInterval = interval;
1411:            }
1412:
1413:            /*
1414:             *  (non-Javadoc)
1415:             * @see com.enterprisedt.net.ftp.FTPClientInterface#setProgressMonitor(com.enterprisedt.net.ftp.FTPProgressMonitor)
1416:             */
1417:            public void setProgressMonitor(FTPProgressMonitor monitor) {
1418:                this .monitor = monitor;
1419:            }
1420:
1421:            /**
1422:             * Get the reference to the progress monitor
1423:             * 
1424:             * @return  progress monitor
1425:             */
1426:            public FTPProgressMonitor getProgressMonitor() {
1427:                return monitor;
1428:            }
1429:
1430:            /*
1431:             *  (non-Javadoc)
1432:             * @see com.enterprisedt.net.ftp.FTPClientInterface#getMonitorInterval()
1433:             */
1434:            public long getMonitorInterval() {
1435:                return monitorInterval;
1436:            }
1437:
1438:            /**
1439:             *  Set the number of bytes transferred between each callback on the
1440:             *  progress monitor
1441:             * 
1442:             * param interval     bytes to be transferred before a callback
1443:             */
1444:            public void setMonitorInterval(long interval) {
1445:                this .monitorInterval = interval;
1446:            }
1447:
1448:            /**
1449:             * Set the size of the buffers used in writing to and reading from
1450:             * the data sockets
1451:             * 
1452:             * @param size  new size of buffer in bytes
1453:             */
1454:            public void setTransferBufferSize(int size) {
1455:                transferBufferSize = size;
1456:            }
1457:
1458:            /**
1459:             * Get the size of the buffers used in writing to and reading from
1460:             * the data sockets
1461:             * 
1462:             * @return  transfer buffer size
1463:             */
1464:            public int getTransferBufferSize() {
1465:                return transferBufferSize;
1466:            }
1467:
1468:            /*
1469:             *  (non-Javadoc)
1470:             * @see com.enterprisedt.net.ftp.FTPClientInterface#cancelTransfer()
1471:             */
1472:            public void cancelTransfer() {
1473:                cancelTransfer = true;
1474:                log.warn("cancelTransfer() called");
1475:            }
1476:
1477:            /**
1478:             * Has the current transfer been cancelled?
1479:             * 
1480:             * @return true if cancel, false otherwise
1481:             */
1482:            public boolean isTransferCancelled() {
1483:                return cancelTransfer;
1484:            }
1485:
1486:            /**
1487:             * If true, delete partially written files when exceptions are thrown
1488:             * during a download
1489:             * 
1490:             * @return true if delete local file on error
1491:             */
1492:            public boolean isDeleteOnFailure() {
1493:                return deleteOnFailure;
1494:            }
1495:
1496:            /**
1497:             * Switch on or off the automatic deletion of partially written files 
1498:             * that are left when an exception is thrown during a download
1499:             * 
1500:             * @param deleteOnFailure  true if delete when a failure occurs
1501:             */
1502:            public void setDeleteOnFailure(boolean deleteOnFailure) {
1503:                this .deleteOnFailure = deleteOnFailure;
1504:            }
1505:
1506:            /**
1507:             * We can force PORT to send a fixed IP address, which can be useful with certain
1508:             * NAT configurations. Must be connected to the remote host to call this method.
1509:             * 
1510:             * @param IPAddress     IP address to force, in 192.168.1.0 form
1511:             * @deprecated
1512:             */
1513:            public void setPORTIP(String IPAddress) throws FTPException {
1514:                setActiveIPAddress(IPAddress);
1515:            }
1516:
1517:            /**
1518:             * We can force PORT to send a fixed IP address, which can be useful with certain
1519:             * NAT configurations. Must be connected to the remote host to call this method.
1520:             * 
1521:             * @param activeIP     IP address to force, in 192.168.1.0 form or in IPV6 form, e.g.
1522:             *                            1080::8:800:200C:417A
1523:             */
1524:            public void setActiveIPAddress(String activeIP) throws FTPException {
1525:
1526:                this .activeIP = activeIP;
1527:                if (control != null)
1528:                    control.setActivePortIPAddress(activeIP);
1529:            }
1530:
1531:            /**
1532:             * Get the active IP address that is set.
1533:             * 
1534:             * @return  active IP address or null if not set
1535:             */
1536:            public String getActiveIPAddress() {
1537:                return activeIP;
1538:            }
1539:
1540:            /**
1541:             * Force a certain range of ports to be used in active mode. This is
1542:             * generally so that a port range can be configured in a firewall. Note
1543:             * that if lowest == highest, a single port will be used. This works well
1544:             * for uploads, but downloads generally require multiple ports, as most
1545:             * servers fail to create a connection repeatedly for the same port.
1546:             * 
1547:             * @param lowest     Lower limit of range.
1548:             * @param highest    Upper limit of range.
1549:             */
1550:            public void setActivePortRange(int lowest, int highest)
1551:                    throws FTPException {
1552:
1553:                this .lowPort = lowest;
1554:                this .highPort = highest;
1555:
1556:                if (lowest < 0 || lowest > highest || highest > MAX_PORT)
1557:                    throw new FTPException("Invalid port range specified");
1558:
1559:                if (control != null)
1560:                    control.setActivePortRange(lowest, highest);
1561:
1562:                log.debug("setActivePortRange(" + lowest + "," + highest + ")");
1563:            }
1564:
1565:            /**
1566:             * Get the lower limit of the port range for active mode.
1567:             * 
1568:             * @return lower limit, or -1 if not set
1569:             */
1570:            public int getActiveLowPort() {
1571:                return lowPort;
1572:            }
1573:
1574:            /**
1575:             * Get the upper limit of the port range for active mode.
1576:             * 
1577:             * @return upper limit, or -1 if not set
1578:             */
1579:            public int getActiveHighPort() {
1580:                return highPort;
1581:            }
1582:
1583:            /**
1584:             *  Login into an account on the FTP server. This
1585:             *  call completes the entire login process. Note that
1586:             *  connect() must be called first.
1587:             *
1588:             *  @param   user       user name
1589:             *  @param   password   user's password
1590:             */
1591:            public void login(String user, String password) throws IOException,
1592:                    FTPException {
1593:
1594:                checkConnection(true);
1595:
1596:                user(user);
1597:
1598:                if (lastValidReply.getReplyCode().equals("230"))
1599:                    return;
1600:                else {
1601:                    password(password);
1602:                }
1603:            }
1604:
1605:            /**
1606:             *  Login into an account on the FTP server. This call completes the 
1607:             *  entire login process. This method permits additional account information 
1608:             *  to be supplied. FTP servers can use combinations of these parameters in 
1609:             *  many different ways, e.g. to pass in proxy details via this method, some 
1610:             *  servers use the "user" as 'ftpUser + "@" + ftpHost + " " + ftpProxyUser', 
1611:             *  the "password" as the FTP user's password, and the accountInfo as the proxy 
1612:             *  password. Note that connect() must be called first.
1613:             *
1614:             *  @param   user           user name
1615:             *  @param   password       user's password
1616:             *  @param   accountInfo    account info string
1617:             */
1618:            public void login(String user, String password, String accountInfo)
1619:                    throws IOException, FTPException {
1620:
1621:                checkConnection(true);
1622:
1623:                user(user);
1624:
1625:                if (lastValidReply.getReplyCode().equals("230")) // no pwd
1626:                    return;
1627:                else {
1628:                    password(password);
1629:                    if (lastValidReply.getReplyCode().equals("332")) // requires acct info
1630:                        account(accountInfo);
1631:                }
1632:            }
1633:
1634:            /**
1635:             *  Supply the user name to log into an account
1636:             *  on the FTP server. Must be followed by the
1637:             *  password() method - but we allow for no password.
1638:             *  Note that connect() must be called first.
1639:             *
1640:             *  @param   user       user name
1641:             */
1642:            public void user(String user) throws IOException, FTPException {
1643:
1644:                checkConnection(true);
1645:
1646:                lastReply = control.sendCommand("USER " + user);
1647:
1648:                // we allow for a site with no password - 230 response
1649:                String[] validCodes = { "230", "331" };
1650:                lastValidReply = control.validateReply(lastReply, validCodes);
1651:            }
1652:
1653:            /**
1654:             *  Supplies the password for a previously supplied
1655:             *  username to log into the FTP server. Must be
1656:             *  preceeded by the user() method
1657:             *
1658:             *  @param   password       The password.
1659:             */
1660:            public void password(String password) throws IOException,
1661:                    FTPException {
1662:
1663:                checkConnection(true);
1664:
1665:                lastReply = control.sendCommand("PASS " + password);
1666:
1667:                // we allow for a site with no passwords (202) or requiring
1668:                // ACCT info (332)
1669:                String[] validCodes = { "230", "202", "332" };
1670:                lastValidReply = control.validateReply(lastReply, validCodes);
1671:            }
1672:
1673:            /**
1674:             *  Supply account information string to the server. This can be
1675:             *  used for a variety of purposes - for example, the server could
1676:             *  indicate that a password has expired (by sending 332 in reply to
1677:             *  PASS) and a new password automatically supplied via ACCT. It
1678:             *  is up to the server how it uses this string.
1679:             *
1680:             *  @param   accountInfo    account information string
1681:             */
1682:            public void account(String accountInfo) throws IOException,
1683:                    FTPException {
1684:
1685:                checkConnection(true);
1686:
1687:                lastReply = control.sendCommand("ACCT " + accountInfo);
1688:
1689:                // ok or not implemented
1690:                String[] validCodes = { "230", "202" };
1691:                lastValidReply = control.validateReply(lastReply, validCodes);
1692:            }
1693:
1694:            /**
1695:             *  Set up SOCKS v4/v5 proxy settings. This can be used if there
1696:             *  is a SOCKS proxy server in place that must be connected thru.
1697:             *  Note that setting these properties directs <b>all</b> TCP
1698:             *  sockets in this JVM to the SOCKS proxy
1699:             *
1700:             *  @param  port  SOCKS proxy port
1701:             *  @param  host  SOCKS proxy hostname
1702:             */
1703:            public static void initSOCKS(String port, String host) {
1704:                Properties props = System.getProperties();
1705:                props.put(SOCKS_PORT, port);
1706:                props.put(SOCKS_HOST, host);
1707:                System.setProperties(props);
1708:            }
1709:
1710:            /**
1711:             *  Set up SOCKS username and password for SOCKS username/password
1712:             *  authentication. Often, no authentication will be required
1713:             *  but the SOCKS server may be configured to request these.
1714:             *
1715:             *  @param  username   the SOCKS username
1716:             *  @param  password   the SOCKS password
1717:             */
1718:            public static void initSOCKSAuthentication(String username,
1719:                    String password) {
1720:                Properties props = System.getProperties();
1721:                props.put("java.net.socks.username", username);
1722:                props.put("java.net.socks.password", password);
1723:                System.setProperties(props);
1724:            }
1725:
1726:            /**
1727:             * Clear SOCKS settings. Note that setting these properties affects 
1728:             * <b>all</b> TCP sockets in this JVM
1729:             */
1730:            public static void clearSOCKS() {
1731:
1732:                Properties prop = System.getProperties();
1733:                prop.remove(SOCKS_HOST);
1734:                prop.remove(SOCKS_PORT);
1735:                System.setProperties(prop);
1736:            }
1737:
1738:            /**
1739:             *  Get the name of the remote host
1740:             *
1741:             *  @return  remote host name
1742:             */
1743:            String getRemoteHostName() {
1744:                return control.getRemoteHostName();
1745:            }
1746:
1747:            /**
1748:             *  Issue arbitrary ftp commands to the FTP server.
1749:             *
1750:             *  @param command     ftp command to be sent to server
1751:             *  @param validCodes  valid return codes for this command. If null
1752:             *                      is supplied no validation is performed
1753:             * 
1754:             *  @return  the text returned by the FTP server
1755:             */
1756:            public String quote(String command, String[] validCodes)
1757:                    throws IOException, FTPException {
1758:
1759:                checkConnection(true);
1760:
1761:                lastReply = control.sendCommand(command);
1762:
1763:                // allow for no validation to be supplied
1764:                if (validCodes != null) {
1765:                    lastValidReply = control.validateReply(lastReply,
1766:                            validCodes);
1767:                } else { // no validation
1768:                    lastValidReply = lastReply; // assume valid
1769:                }
1770:                return lastValidReply.getReplyText();
1771:            }
1772:
1773:            /**
1774:             *  Issue arbitrary ftp commands to the FTP server.
1775:             *
1776:             *  @param command     ftp command to be sent to server
1777:             *  @return  the raw text returned by the FTP server including reply code
1778:             */
1779:            public String quote(String command) throws IOException,
1780:                    FTPException {
1781:
1782:                checkConnection(true);
1783:
1784:                lastValidReply = control.sendCommand(command);
1785:                return lastValidReply.getRawReply();
1786:            }
1787:
1788:            /*
1789:             *  (non-Javadoc)
1790:             * @see com.enterprisedt.net.ftp.FTPClientInterface#exists(java.lang.String)
1791:             */
1792:            public boolean exists(String remoteFile) throws IOException,
1793:                    FTPException {
1794:                checkConnection(true);
1795:
1796:                // first try the SIZE command
1797:                if (sizeSupported) {
1798:                    lastReply = control.sendCommand("SIZE " + remoteFile);
1799:                    char ch = lastReply.getReplyCode().charAt(0);
1800:                    if (ch == '2')
1801:                        return true;
1802:                    if (ch == '5'
1803:                            && fileNotFoundStrings.matches(lastReply
1804:                                    .getReplyText()))
1805:                        return false;
1806:
1807:                    sizeSupported = false;
1808:                    log.debug("SIZE not supported - trying MDTM");
1809:                }
1810:
1811:                // then try the MDTM command
1812:                if (mdtmSupported) {
1813:                    lastReply = control.sendCommand("MDTM " + remoteFile);
1814:                    char ch = lastReply.getReplyCode().charAt(0);
1815:                    if (ch == '2')
1816:                        return true;
1817:                    if (ch == '5'
1818:                            && fileNotFoundStrings.matches(lastReply
1819:                                    .getReplyText()))
1820:                        return false;
1821:
1822:                    mdtmSupported = false;
1823:                    log.debug("MDTM not supported - trying RETR");
1824:                }
1825:
1826:                // ok, now try RETR since nothing else is supported
1827:                ServerSocket sock = new ServerSocket(0);
1828:                short port = (short) sock.getLocalPort();
1829:                sock.close();
1830:                control.sendPORTCommand(port);
1831:
1832:                // send the retrieve command
1833:                lastReply = control.sendCommand("RETR " + remoteFile);
1834:                char ch = lastReply.getReplyCode().charAt(0);
1835:
1836:                // normally return 125 etc. But could return 425 unable to create data
1837:                // connection, which means the file exists but can't connect to our (non-
1838:                // existent) server socket
1839:                if (ch == '1' || ch == '2' || ch == '4')
1840:                    return true;
1841:                if (ch == '5'
1842:                        && fileNotFoundStrings
1843:                                .matches(lastReply.getReplyText()))
1844:                    return false;
1845:
1846:                String msg = "Unable to determine if file '" + remoteFile
1847:                        + "' exists.";
1848:                log.warn(msg);
1849:                throw new FTPException(msg);
1850:            }
1851:
1852:            /**
1853:             * Read reply from control socket
1854:             * 
1855:             * @return
1856:             * @throws IOException
1857:             */
1858:            FTPReply readReply() throws IOException {
1859:                return control.readReply();
1860:            }
1861:
1862:            /**
1863:             * Get the PASV address string (including port numbers)
1864:             * @param pasvReply
1865:             * @return
1866:             */
1867:            String getPASVAddress(String pasvReply) {
1868:                int start = -1;
1869:                int i = 0;
1870:                while (i < pasvReply.length()) {
1871:                    if (Character.isDigit(pasvReply.charAt(i))) {
1872:                        start = i;
1873:                        break;
1874:                    }
1875:                    i++;
1876:                }
1877:                int end = -1;
1878:                i = pasvReply.length() - 1;
1879:                while (i >= 0) {
1880:                    if (Character.isDigit(pasvReply.charAt(i))) {
1881:                        end = i;
1882:                        break;
1883:                    }
1884:                    i--;
1885:                }
1886:                if (start < 0 || end < 0)
1887:                    return null;
1888:
1889:                return pasvReply.substring(start, end + 1);
1890:            }
1891:
1892:            /**
1893:             * Send a command to the server and get the reply
1894:             * @param command   command
1895:             * @return FTPReply
1896:             * @throws IOException
1897:             */
1898:            public FTPReply sendCommand(String command) throws IOException {
1899:                return control.sendCommand(command);
1900:            }
1901:
1902:            /**
1903:             * Validate an FTPReply 
1904:             * 
1905:             * @param reply         reply object
1906:             * @param expectedReplyCode  expected code
1907:             * @throws FTPException
1908:             */
1909:            public void validateReply(FTPReply reply, String expectedReplyCode)
1910:                    throws FTPException {
1911:                control.validateReply(reply, expectedReplyCode);
1912:            }
1913:
1914:            /**
1915:             * Validate an FTPReply 
1916:             * 
1917:             * @param reply         reply object
1918:             * @param expectedReplyCodes  expected codes
1919:             * @throws FTPException
1920:             */
1921:            public void validateReply(FTPReply reply,
1922:                    String[] expectedReplyCodes) throws FTPException {
1923:                control.validateReply(reply, expectedReplyCodes);
1924:            }
1925:
1926:            /*
1927:             *  (non-Javadoc)
1928:             * @see com.enterprisedt.net.ftp.FTPClientInterface#size(java.lang.String)
1929:             */
1930:            public long size(String remoteFile) throws IOException,
1931:                    FTPException {
1932:
1933:                checkConnection(true);
1934:
1935:                lastReply = control.sendCommand("SIZE " + remoteFile);
1936:                lastValidReply = control.validateReply(lastReply, "213");
1937:
1938:                // parse the reply string .
1939:                String replyText = lastValidReply.getReplyText();
1940:
1941:                // trim off any trailing characters after a space, e.g. webstar
1942:                // responds to SIZE with 213 55564 bytes
1943:                int spacePos = replyText.indexOf(' ');
1944:                if (spacePos >= 0)
1945:                    replyText = replyText.substring(0, spacePos);
1946:
1947:                // parse the reply
1948:                try {
1949:                    return Long.parseLong(replyText);
1950:                } catch (NumberFormatException ex) {
1951:                    throw new FTPException("Failed to parse reply: "
1952:                            + replyText);
1953:                }
1954:            }
1955:
1956:            /*
1957:             *  (non-Javadoc)
1958:             * @see com.enterprisedt.net.ftp.FTPClientInterface#resume()
1959:             */
1960:            public void resume() throws FTPException {
1961:                if (transferType.equals(FTPTransferType.ASCII))
1962:                    throw new FTPException(
1963:                            "Resume only supported for BINARY transfers");
1964:                resume = true;
1965:                log.info("Resume=true");
1966:            }
1967:
1968:            /*
1969:             *  (non-Javadoc)
1970:             * @see com.enterprisedt.net.ftp.FTPClientInterface#cancelResume()
1971:             */
1972:            public void cancelResume() throws IOException, FTPException {
1973:                restart(0);
1974:                resume = false;
1975:            }
1976:
1977:            /**
1978:             * Force the resume flag off. Internal use only.
1979:             */
1980:            protected void forceResumeOff() {
1981:                resume = false;
1982:            }
1983:
1984:            /**
1985:             * Issue the RESTart command to the remote server. This indicates the byte
1986:             * position that REST is performed at. For put, bytes start at this point, while
1987:             * for get, bytes are fetched from this point.
1988:             * 
1989:             * @param size     the REST param, the mark at which the restart is 
1990:             *                  performed on the remote file. For STOR, this is retrieved
1991:             *                  by SIZE
1992:             * @throws IOException
1993:             * @throws FTPException
1994:             */
1995:            public void restart(long size) throws IOException, FTPException {
1996:                lastReply = control.sendCommand("REST " + size);
1997:                lastValidReply = control.validateReply(lastReply, "350");
1998:            }
1999:
2000:            /*
2001:             *  (non-Javadoc)
2002:             * @see com.enterprisedt.net.ftp.FTPClientInterface#put(java.lang.String, java.lang.String)
2003:             */
2004:            public String put(String localPath, String remoteFile)
2005:                    throws IOException, FTPException {
2006:
2007:                return put(localPath, remoteFile, false);
2008:            }
2009:
2010:            /*
2011:             *  (non-Javadoc)
2012:             * @see com.enterprisedt.net.ftp.FTPClientInterface#put(java.io.InputStream, java.lang.String)
2013:             */
2014:            public String put(InputStream srcStream, String remoteFile)
2015:                    throws IOException, FTPException {
2016:
2017:                return put(srcStream, remoteFile, false);
2018:            }
2019:
2020:            /*
2021:             *  (non-Javadoc)
2022:             * @see com.enterprisedt.net.ftp.FTPClientInterface#put(java.lang.String, java.lang.String, boolean)
2023:             */
2024:            public String put(String localPath, String remoteFile,
2025:                    boolean append) throws IOException, FTPException {
2026:
2027:                InputStream srcStream = new FileInputStream(localPath);
2028:                return put(srcStream, remoteFile, append);
2029:            }
2030:
2031:            /*
2032:             *  (non-Javadoc)
2033:             * @see com.enterprisedt.net.ftp.FTPClientInterface#put(java.io.InputStream, 
2034:             *  java.lang.String, boolean)
2035:             */
2036:            public String put(InputStream srcStream, String remoteFile,
2037:                    boolean append) throws IOException, FTPException {
2038:
2039:                FTPTransferType previousType = transferType;
2040:                chooseTransferMode(remoteFile);
2041:                boolean resetMode = true;
2042:                Exception e = null;
2043:                try {
2044:                    if (monitorEx != null)
2045:                        monitorEx.transferStarted(TransferDirection.UPLOAD,
2046:                                remoteFile);
2047:                    remoteFile = putData(srcStream, remoteFile, append);
2048:                    validateTransfer();
2049:                    uploadCount++;
2050:                } catch (FTPException ex) {
2051:                    e = ex;
2052:                    throw ex;
2053:                } catch (IOException ex) {
2054:                    e = ex;
2055:                    resetMode = false;
2056:                    validateTransferOnError(ex);
2057:                    throw ex;
2058:                } finally {
2059:                    if (monitorEx != null)
2060:                        monitorEx.transferComplete(TransferDirection.UPLOAD,
2061:                                remoteFile);
2062:                    if (resetMode)
2063:                        resetTransferMode(previousType);
2064:                }
2065:                return remoteFile;
2066:            }
2067:
2068:            /**
2069:             * Validate that the put() or get() was successful.  This method is not
2070:             * for general use.
2071:             */
2072:            public void validateTransfer() throws IOException, FTPException {
2073:
2074:                checkConnection(true);
2075:
2076:                // check the control response
2077:                String[] validCodes = { "225", "226", "250", "426", "450" };
2078:                lastReply = control.readReply();
2079:
2080:                // permit 426/450 error if we cancelled the transfer, otherwise
2081:                // throw an exception
2082:                String code = lastReply.getReplyCode();
2083:                if ((code.equals("426") || code.equals("450"))
2084:                        && !cancelTransfer)
2085:                    throw new FTPException(lastReply);
2086:
2087:                lastValidReply = control.validateReply(lastReply, validCodes);
2088:
2089:                if (cancelTransfer) {
2090:                    log.warn("Transfer has been cancelled!");
2091:                    throw new FTPTransferCancelledException();
2092:                }
2093:            }
2094:
2095:            /**
2096:             * Validate a transfer when an error has occurred on the data channel.
2097:             * Set a very short transfer in case things have hung. Set it back
2098:             * at the end.
2099:             * 
2100:             * @throws IOException
2101:             * @throws FTPException
2102:             */
2103:            protected void validateTransferOnError(IOException ex)
2104:                    throws IOException, FTPException {
2105:
2106:                log.debug("Validate transfer on error after exception", ex);
2107:                checkConnection(true);
2108:
2109:                control.setTimeout(SHORT_TIMEOUT);
2110:                try {
2111:                    validateTransfer();
2112:                } catch (Exception e) {
2113:                    log.warn("Validate transfer on error failed", e);
2114:                } finally {
2115:                    control.setTimeout(timeout);
2116:                }
2117:            }
2118:
2119:            /**
2120:             * Close the data socket
2121:             */
2122:            private void closeDataSocket() {
2123:                if (data != null) {
2124:                    try {
2125:                        data.close();
2126:                        data = null;
2127:                    } catch (IOException ex) {
2128:                        log.warn("Caught exception closing data socket", ex);
2129:                    }
2130:                }
2131:            }
2132:
2133:            /**
2134:             * Close stream for data socket. Not for 
2135:             * general use!
2136:             * 
2137:             * @param stream    stream reference
2138:             */
2139:            protected void closeDataSocket(InputStream stream) {
2140:                if (stream != null) {
2141:                    try {
2142:                        stream.close();
2143:                    } catch (IOException ex) {
2144:                        log.warn("Caught exception closing data socket", ex);
2145:                    }
2146:                }
2147:
2148:                closeDataSocket();
2149:            }
2150:
2151:            /**
2152:             * Close stream for data socket
2153:             * 
2154:             * @param stream    stream reference
2155:             */
2156:            protected void closeDataSocket(OutputStream stream) {
2157:                if (stream != null) {
2158:                    try {
2159:                        stream.close();
2160:                    } catch (IOException ex) {
2161:                        log.warn("Caught exception closing data socket", ex);
2162:                    }
2163:                }
2164:
2165:                closeDataSocket();
2166:            }
2167:
2168:            /**
2169:             * Set up the data socket
2170:             * 
2171:             * @throws FTPException 
2172:             * @throws IOException 
2173:             */
2174:            protected void setupDataSocket() throws IOException, FTPException {
2175:
2176:                data = control.createDataSocket(connectMode);
2177:                data.setTimeout(timeout);
2178:            }
2179:
2180:            /**
2181:             * Request the server to set up the put
2182:             * 
2183:             * @param remoteFile
2184:             *            name of remote file in current directory
2185:             * @param append
2186:             *            true if appending, false otherwise
2187:             */
2188:            protected String initPut(String remoteFile, boolean append)
2189:                    throws IOException, FTPException {
2190:
2191:                checkConnection(true);
2192:
2193:                // if a remote filename isn't supplied, assume STOU is to be used
2194:                boolean storeUnique = (remoteFile == null || remoteFile
2195:                        .length() == 0);
2196:                if (storeUnique) {
2197:                    remoteFile = "";
2198:                    // check STOU isn't used with append
2199:                    if (append) {
2200:                        String msg = "A remote filename must be supplied when appending";
2201:                        log.error(msg);
2202:                        throw new FTPException(msg);
2203:                    }
2204:                }
2205:
2206:                // reset the cancel flag
2207:                cancelTransfer = false;
2208:
2209:                boolean close = false;
2210:                try {
2211:                    // set up data channel
2212:                    setupDataSocket();
2213:
2214:                    // if resume is requested, we must obtain the size of the
2215:                    // remote file and issue REST
2216:                    if (resume) {
2217:                        if (transferType.equals(FTPTransferType.ASCII))
2218:                            throw new FTPException(
2219:                                    "Resume only supported for BINARY transfers");
2220:                        try {
2221:                            resumeMarker = 0;
2222:                            resumeMarker = size(remoteFile);
2223:                        } catch (FTPException ex) {
2224:                            log.warn("Failed to find size of file '"
2225:                                    + remoteFile + "' for resuming ("
2226:                                    + ex.getMessage() + ")");
2227:                        }
2228:                        restart(resumeMarker);
2229:                    }
2230:
2231:                    // send the command to store
2232:                    String cmd = append ? "APPE " : (storeUnique ? "STOU"
2233:                            : storeCommand);
2234:                    lastReply = control.sendCommand(cmd + remoteFile);
2235:
2236:                    // Can get a 125 or a 150, also allow 350 (for Global eXchange Services server)
2237:                    // JScape returns 151
2238:                    String[] validCodes = { "125", "150", "151", "350" };
2239:                    lastValidReply = control.validateReply(lastReply,
2240:                            validCodes);
2241:
2242:                    String replyText = lastValidReply.getReplyText();
2243:                    if (storeUnique) {
2244:                        int pos = replyText.indexOf(STOU_FILENAME_MARKER);
2245:                        if (pos >= 0) {
2246:                            pos += STOU_FILENAME_MARKER.length();
2247:                            remoteFile = replyText.substring(pos).trim();
2248:                        } else { // couldn't find marker, just return last word of reply
2249:                            // e.g. 150 Opening BINARY mode data connection for FTP0000004.
2250:                            log.debug("Could not find " + STOU_FILENAME_MARKER
2251:                                    + " in reply - using last word instead.");
2252:                            pos = replyText.lastIndexOf(' ');
2253:                            remoteFile = replyText.substring(++pos);
2254:                            int len = remoteFile.length();
2255:                            if (len > 0 && remoteFile.charAt(len - 1) == '.') {
2256:                                remoteFile = remoteFile.substring(0, len - 1);
2257:                            }
2258:                        }
2259:                    }
2260:                    return remoteFile;
2261:                } catch (IOException ex) {
2262:                    close = true;
2263:                    log.error("Caught and rethrowing exception in initPut()",
2264:                            ex);
2265:                    throw ex;
2266:                } catch (FTPException ex) {
2267:                    close = true;
2268:                    log.error("Caught and rethrowing exception in initPut()",
2269:                            ex);
2270:                    throw ex;
2271:                } finally {
2272:                    if (close) {
2273:                        resume = false;
2274:                        closeDataSocket();
2275:                    }
2276:                }
2277:            }
2278:
2279:            /**
2280:             *  Put data. For ASCII, translate line terminators, coping 
2281:             *  with \r\n, \r or \n in the local file
2282:             *
2283:             *  @param  srcStream   input stream of data to put
2284:             *  @param  remoteFile  name of remote file we are writing to
2285:             *  @param  append      true if appending, false otherwise
2286:             */
2287:            private String putData(InputStream srcStream, String remoteFile,
2288:                    boolean append) throws IOException, FTPException {
2289:
2290:                IOException storedEx = null;
2291:                BufferedInputStream in = null;
2292:                BufferedOutputStream out = null;
2293:                long size = 0;
2294:                try {
2295:                    in = new BufferedInputStream(srcStream);
2296:
2297:                    remoteFile = initPut(remoteFile, append);
2298:
2299:                    // get an output stream
2300:                    out = new BufferedOutputStream(new DataOutputStream(
2301:                            getOutputStream()), transferBufferSize * 2);
2302:
2303:                    // if resuming, we skip over the unwanted bytes
2304:                    if (resume) {
2305:                        in.skip(resumeMarker);
2306:                    }
2307:
2308:                    byte[] buf = new byte[transferBufferSize];
2309:                    byte[] prevBuf = new byte[FTP_LINE_SEPARATOR.length];
2310:                    int matchpos = 0;
2311:
2312:                    // read a chunk at a time and write to the data socket            
2313:                    long monitorCount = 0;
2314:                    int count = 0;
2315:                    boolean isASCII = getType() == FTPTransferType.ASCII;
2316:                    long start = System.currentTimeMillis();
2317:
2318:                    while ((count = in.read(buf)) > 0 && !cancelTransfer) {
2319:                        if (isASCII) { // we want to allow \r\n, \r and \n
2320:                            for (int i = 0; i < count; i++) {
2321:                                // LF without preceding CR (i.e. Unix text file)
2322:                                if (buf[i] == LINE_FEED && matchpos == 0) {
2323:                                    out.write(CARRIAGE_RETURN);
2324:                                    out.write(LINE_FEED);
2325:                                    size += 2;
2326:                                    monitorCount += 2;
2327:                                } else if (buf[i] == FTP_LINE_SEPARATOR[matchpos]) {
2328:                                    prevBuf[matchpos] = buf[i];
2329:                                    matchpos++;
2330:                                    if (matchpos == FTP_LINE_SEPARATOR.length) {
2331:                                        out.write(CARRIAGE_RETURN);
2332:                                        out.write(LINE_FEED);
2333:                                        size += 2;
2334:                                        monitorCount += 2;
2335:                                        matchpos = 0;
2336:                                    }
2337:                                } else { // no match current char 
2338:                                    // this must be a matching \r if we matched first char
2339:                                    if (matchpos > 0) {
2340:                                        out.write(CARRIAGE_RETURN);
2341:                                        out.write(LINE_FEED);
2342:                                        size += 2;
2343:                                        monitorCount += 2;
2344:                                    }
2345:                                    out.write(buf[i]);
2346:                                    size++;
2347:                                    monitorCount++;
2348:                                    matchpos = 0;
2349:                                }
2350:                            }
2351:                        } else { // binary
2352:                            out.write(buf, 0, count);
2353:                            size += count;
2354:                            monitorCount += count;
2355:                        }
2356:
2357:                        if (monitor != null && monitorCount > monitorInterval) {
2358:                            monitor.bytesTransferred(size);
2359:                            monitorCount = 0;
2360:                        }
2361:                        if (serverWakeupInterval > 0
2362:                                && System.currentTimeMillis() - start > serverWakeupInterval * 1000) {
2363:                            start = System.currentTimeMillis();
2364:                            sendServerWakeup();
2365:                        }
2366:                    }
2367:                    // write out anything left at the end that has been saved
2368:                    // - must be a \r which we convert into a line terminator
2369:                    if (isASCII && matchpos > 0) {
2370:                        out.write(CARRIAGE_RETURN);
2371:                        out.write(LINE_FEED);
2372:                        size += 2;
2373:                        monitorCount += 2;
2374:                    }
2375:                } catch (IOException ex) {
2376:                    storedEx = ex;
2377:                    log
2378:                            .error(
2379:                                    "Caught and rethrowing exception in getDataAfterInitGet()",
2380:                                    ex);
2381:                } finally {
2382:                    resume = false;
2383:                    try {
2384:                        if (in != null)
2385:                            in.close();
2386:                    } catch (IOException ex) {
2387:                        log.warn("Caught exception closing input stream", ex);
2388:                    }
2389:
2390:                    closeDataSocket(out);
2391:
2392:                    // if we failed to write the file, rethrow the exception
2393:                    if (storedEx != null)
2394:                        throw storedEx;
2395:
2396:                    // notify the final transfer size
2397:                    if (monitor != null)
2398:                        monitor.bytesTransferred(size);
2399:                    // log bytes transferred
2400:                    log.debug("Transferred " + size + " bytes to remote host");
2401:                }
2402:                return remoteFile;
2403:            }
2404:
2405:            /*
2406:             *  (non-Javadoc)
2407:             * @see com.enterprisedt.net.ftp.FTPClientInterface#put(byte[], java.lang.String)
2408:             */
2409:            public String put(byte[] bytes, String remoteFile)
2410:                    throws IOException, FTPException {
2411:
2412:                return put(bytes, remoteFile, false);
2413:            }
2414:
2415:            /*
2416:             *  (non-Javadoc)
2417:             * @see com.enterprisedt.net.ftp.FTPClientInterface#put(byte[], java.lang.String, boolean)
2418:             */
2419:            public String put(byte[] bytes, String remoteFile, boolean append)
2420:                    throws IOException, FTPException {
2421:
2422:                ByteArrayInputStream input = new ByteArrayInputStream(bytes);
2423:                return put(input, remoteFile, append);
2424:
2425:            }
2426:
2427:            /*
2428:             *  (non-Javadoc)
2429:             * @see com.enterprisedt.net.ftp.FTPClientInterface#get(java.lang.String, java.lang.String)
2430:             */
2431:            public void get(String localPath, String remoteFile)
2432:                    throws IOException, FTPException {
2433:
2434:                File localFile = new File(localPath);
2435:                if (localFile.isDirectory()) {
2436:                    localPath = localPath + File.separator + remoteFile;
2437:                    log.debug("Setting local path to " + localPath);
2438:                }
2439:
2440:                FTPTransferType previousType = transferType;
2441:                chooseTransferMode(remoteFile);
2442:                boolean resetMode = true;
2443:                Exception e = null;
2444:                try {
2445:                    if (monitorEx != null)
2446:                        monitorEx.transferStarted(TransferDirection.DOWNLOAD,
2447:                                remoteFile);
2448:                    getData(localPath, remoteFile);
2449:                    validateTransfer();
2450:                    downloadCount++;
2451:                } catch (FTPException ex) {
2452:                    e = ex;
2453:                    throw ex;
2454:                } catch (IOException ex) {
2455:                    e = ex;
2456:                    resetMode = false;
2457:                    validateTransferOnError(ex);
2458:                    throw ex;
2459:                } finally {
2460:                    if (monitorEx != null)
2461:                        monitorEx.transferComplete(TransferDirection.DOWNLOAD,
2462:                                remoteFile);
2463:                    if (resetMode)
2464:                        resetTransferMode(previousType);
2465:                }
2466:            }
2467:
2468:            /*
2469:             *  (non-Javadoc)
2470:             * @see com.enterprisedt.net.ftp.FTPClientInterface#get(java.io.OutputStream, java.lang.String)
2471:             */
2472:            public void get(OutputStream destStream, String remoteFile)
2473:                    throws IOException, FTPException {
2474:
2475:                FTPTransferType previousType = transferType;
2476:                chooseTransferMode(remoteFile);
2477:                boolean resetMode = true;
2478:                Exception e = null;
2479:                try {
2480:                    if (monitorEx != null)
2481:                        monitorEx.transferStarted(TransferDirection.DOWNLOAD,
2482:                                remoteFile);
2483:                    getData(destStream, remoteFile);
2484:                    validateTransfer();
2485:                    downloadCount++;
2486:                } catch (FTPException ex) {
2487:                    e = ex;
2488:                    throw ex;
2489:                } catch (IOException ex) {
2490:                    e = ex;
2491:                    resetMode = false;
2492:                    validateTransferOnError(ex);
2493:                    throw ex;
2494:                } finally {
2495:                    if (monitorEx != null)
2496:                        monitorEx.transferComplete(TransferDirection.DOWNLOAD,
2497:                                remoteFile);
2498:                    if (resetMode)
2499:                        resetTransferMode(previousType);
2500:                }
2501:            }
2502:
2503:            /**
2504:             * Reset the transfer mode back to what it should be, if 
2505:             * it has changed.
2506:             * 
2507:             * @param previousType      previous transfer type
2508:             * @throws IOException
2509:             * @throws FTPException
2510:             */
2511:            public void resetTransferMode(FTPTransferType previousType)
2512:                    throws IOException, FTPException {
2513:
2514:                if (!transferType.equals(previousType)) {
2515:                    setType(previousType);
2516:                }
2517:            }
2518:
2519:            /**
2520:             *  Request to the server that the get is set up
2521:             *
2522:             *  @param  remoteFile  name of remote file
2523:             */
2524:            protected void initGet(String remoteFile) throws IOException,
2525:                    FTPException {
2526:
2527:                checkConnection(true);
2528:
2529:                // reset the cancel flag
2530:                cancelTransfer = false;
2531:
2532:                boolean close = false;
2533:                try {
2534:                    // set up data channel
2535:                    setupDataSocket();
2536:
2537:                    // if resume is requested, we must issue REST
2538:                    if (resume) {
2539:                        if (transferType.equals(FTPTransferType.ASCII))
2540:                            throw new FTPException(
2541:                                    "Resume only supported for BINARY transfers");
2542:                        restart(resumeMarker);
2543:                    }
2544:
2545:                    // send the retrieve command
2546:                    lastReply = control.sendCommand("RETR " + remoteFile);
2547:
2548:                    // Can get a 125 or a 150
2549:                    String[] validCodes1 = { "125", "150" };
2550:                    lastValidReply = control.validateReply(lastReply,
2551:                            validCodes1);
2552:                } catch (IOException ex) {
2553:                    close = true;
2554:                    log.error("Caught and rethrowing exception in initGet()",
2555:                            ex);
2556:                    throw ex;
2557:                } catch (FTPException ex) {
2558:                    close = true;
2559:                    log.error("Caught and rethrowing exception in initGet()",
2560:                            ex);
2561:                    throw ex;
2562:                } finally {
2563:                    if (close) {
2564:                        resume = false;
2565:                        closeDataSocket();
2566:                    }
2567:                }
2568:            }
2569:
2570:            /**
2571:             *  Get as binary file, i.e. straight transfer of data
2572:             *
2573:             *  @param localPath   full path of local file to write to
2574:             *  @param remoteFile  name of remote file
2575:             */
2576:            private void getData(String localPath, String remoteFile)
2577:                    throws IOException, FTPException {
2578:
2579:                // B. McKeown: Need to store the local file name so the file can be
2580:                // deleted if necessary.
2581:                File localFile = new File(localPath);
2582:                if (localFile.exists()) {
2583:                    // if resuming, we must find the marker
2584:                    if (!localFile.canWrite())
2585:                        throw new FTPException(localPath
2586:                                + " is readonly - cannot write");
2587:                    if (resume)
2588:                        resumeMarker = localFile.length();
2589:                }
2590:
2591:                // B.McKeown:
2592:                // Call initGet() before creating the FileOutputStream.
2593:                // This will prevent being left with an empty file if a FTPException
2594:                // is thrown by initGet().
2595:                initGet(remoteFile);
2596:
2597:                // create the buffered output stream for writing the file
2598:                FileOutputStream out = new FileOutputStream(localPath, resume);
2599:
2600:                try {
2601:                    getDataAfterInitGet(out);
2602:                } catch (IOException ex) {
2603:                    if (deleteOnFailure) {
2604:                        localFile.delete();
2605:                        log.debug("Deleting local file '"
2606:                                + localFile.getAbsolutePath() + "'");
2607:                    } else {
2608:                        log.debug("Possibly partial local file not deleted");
2609:                    }
2610:                    throw ex;
2611:                }
2612:            }
2613:
2614:            /**
2615:             *  Get as binary file, i.e. straight transfer of data
2616:             *
2617:             *  @param destStream  stream to write to
2618:             *  @param remoteFile  name of remote file
2619:             */
2620:            private void getData(OutputStream destStream, String remoteFile)
2621:                    throws IOException, FTPException {
2622:
2623:                initGet(remoteFile);
2624:
2625:                getDataAfterInitGet(destStream);
2626:            }
2627:
2628:            /**
2629:             * Get the data input stream. Not for general use!
2630:             * 
2631:             * @return
2632:             * @throws IOException
2633:             */
2634:            InputStream getInputStream() throws IOException {
2635:                return data.getInputStream();
2636:            }
2637:
2638:            /**
2639:             * Get the data input stream. Not for general use!
2640:             * 
2641:             * @return
2642:             * @throws IOException
2643:             */
2644:            OutputStream getOutputStream() throws IOException {
2645:                return data.getOutputStream();
2646:            }
2647:
2648:            /**
2649:             *  Get as binary file, i.e. straight transfer of data
2650:             *
2651:             *  @param destStream  stream to write to
2652:             */
2653:            private void getDataAfterInitGet(OutputStream destStream)
2654:                    throws IOException, FTPException {
2655:
2656:                // create the buffered output stream for writing the file
2657:                BufferedOutputStream out = new BufferedOutputStream(destStream);
2658:
2659:                BufferedInputStream in = null;
2660:                long size = 0;
2661:                IOException storedEx = null;
2662:                try {
2663:                    // get an input stream to read data from ... AFTER we have
2664:                    // the ok to go ahead AND AFTER we've successfully opened a
2665:                    // stream for the local file
2666:                    in = new BufferedInputStream(new DataInputStream(data
2667:                            .getInputStream()));
2668:
2669:                    // do the retrieving
2670:                    long monitorCount = 0;
2671:                    byte[] chunk = new byte[transferBufferSize];
2672:                    int count;
2673:                    boolean isASCII = getType() == FTPTransferType.ASCII;
2674:                    long start = System.currentTimeMillis();
2675:
2676:                    byte[] prevBuf = new byte[FTP_LINE_SEPARATOR.length];
2677:                    int matchpos = 0;
2678:
2679:                    // read from socket & write to file in chunks        
2680:                    while ((count = readChunk(in, chunk, transferBufferSize)) >= 0
2681:                            && !cancelTransfer) {
2682:                        if (isASCII) {
2683:                            for (int i = 0; i < count; i++) {
2684:                                if (chunk[i] == FTP_LINE_SEPARATOR[matchpos]) {
2685:                                    prevBuf[matchpos] = chunk[i];
2686:                                    matchpos++;
2687:                                    if (matchpos == FTP_LINE_SEPARATOR.length) {
2688:                                        out.write(LINE_SEPARATOR);
2689:                                        size += LINE_SEPARATOR.length;
2690:                                        monitorCount += LINE_SEPARATOR.length;
2691:                                        matchpos = 0;
2692:                                    }
2693:                                } else { // no match
2694:                                    // write out existing matches
2695:                                    if (matchpos > 0) {
2696:                                        out.write(prevBuf, 0, matchpos);
2697:                                        size += matchpos;
2698:                                        monitorCount += matchpos;
2699:                                    }
2700:                                    out.write(chunk[i]);
2701:                                    size++;
2702:                                    monitorCount++;
2703:                                    matchpos = 0;
2704:                                }
2705:                            }
2706:                        } else { // binary
2707:                            out.write(chunk, 0, count);
2708:                            size += count;
2709:                            monitorCount += count;
2710:                        }
2711:
2712:                        if (monitor != null && monitorCount > monitorInterval) {
2713:                            monitor.bytesTransferred(size);
2714:                            monitorCount = 0;
2715:                        }
2716:
2717:                        if (serverWakeupInterval > 0
2718:                                && System.currentTimeMillis() - start > serverWakeupInterval * 1000) {
2719:                            start = System.currentTimeMillis();
2720:                            sendServerWakeup();
2721:                        }
2722:                    }
2723:
2724:                    // write out anything left at the end that has been saved
2725:                    if (isASCII && matchpos > 0) {
2726:                        out.write(prevBuf, 0, matchpos);
2727:                        size += matchpos;
2728:                        monitorCount += matchpos;
2729:                    }
2730:                } catch (IOException ex) {
2731:                    storedEx = ex;
2732:                    log
2733:                            .error(
2734:                                    "Caught and rethrowing exception in getDataAfterInitGet()",
2735:                                    ex);
2736:                } finally {
2737:                    try {
2738:                        if (out != null)
2739:                            out.close();
2740:                    } catch (IOException ex) {
2741:                        log.warn("Caught exception closing output stream", ex);
2742:                    }
2743:
2744:                    resume = false;
2745:
2746:                    // close streams
2747:                    closeDataSocket(in);
2748:
2749:                    // if we failed to write the file, rethrow the exception
2750:                    if (storedEx != null)
2751:                        throw storedEx;
2752:                    else if (monitor != null)
2753:                        monitor.bytesTransferred(size);
2754:
2755:                    // log bytes transferred
2756:                    log
2757:                            .debug("Transferred " + size
2758:                                    + " bytes from remote host");
2759:                }
2760:            }
2761:
2762:            /*
2763:             *  (non-Javadoc)
2764:             * @see com.enterprisedt.net.ftp.FTPClientInterface#get(java.lang.String)
2765:             */
2766:            public byte[] get(String remoteFile) throws IOException,
2767:                    FTPException {
2768:
2769:                FTPTransferType previousType = transferType;
2770:                chooseTransferMode(remoteFile);
2771:                boolean resetMode = true;
2772:                Exception e = null;
2773:                try {
2774:                    if (monitorEx != null)
2775:                        monitorEx.transferStarted(TransferDirection.DOWNLOAD,
2776:                                remoteFile);
2777:                    ByteArrayOutputStream result = new ByteArrayOutputStream(
2778:                            transferBufferSize);
2779:                    getData(result, remoteFile);
2780:                    validateTransfer();
2781:                    downloadCount++;
2782:                    return result == null ? null : result.toByteArray();
2783:                } catch (FTPException ex) {
2784:                    e = ex;
2785:                    throw ex;
2786:                } catch (IOException ex) {
2787:                    e = ex;
2788:                    resetMode = false;
2789:                    validateTransferOnError(ex);
2790:                    throw ex;
2791:                } finally {
2792:                    if (monitorEx != null)
2793:                        monitorEx.transferComplete(TransferDirection.DOWNLOAD,
2794:                                remoteFile);
2795:                    if (resetMode)
2796:                        resetTransferMode(previousType);
2797:                }
2798:            }
2799:
2800:            /**
2801:             *  Run a site-specific command on the
2802:             *  server. Support for commands is dependent
2803:             *  on the server
2804:             *
2805:             *  @param  command   the site command to run
2806:             *  @return true if command ok, false if
2807:             *          command not implemented
2808:             */
2809:            public boolean site(String command) throws IOException,
2810:                    FTPException {
2811:
2812:                checkConnection(true);
2813:
2814:                // send the retrieve command
2815:                lastReply = control.sendCommand("SITE " + command);
2816:
2817:                // Can get a 200 (ok) or 202 (not impl). Some
2818:                // FTP servers return 502 (not impl). Added 250 for leitch
2819:                String[] validCodes = { "200", "202", "250", "502" };
2820:                lastValidReply = control.validateReply(lastReply, validCodes);
2821:
2822:                // return true or false? 200 is ok, 202/502 not
2823:                // implemented
2824:                if (lastReply.getReplyCode().equals("200"))
2825:                    return true;
2826:                else
2827:                    return false;
2828:            }
2829:
2830:            /**
2831:             *  List a directory's contents
2832:             *
2833:             *  @param  dirname  the name of the directory (<b>not</b> a file mask)
2834:             *  @return a string containing the line separated
2835:             *          directory listing
2836:             *  @deprecated  As of FTP 1.1, replaced by {@link #dir(String)}
2837:             */
2838:            public String list(String dirname) throws IOException, FTPException {
2839:
2840:                return list(dirname, false);
2841:            }
2842:
2843:            /**
2844:             *  List a directory's contents as one string. A detailed
2845:             *  listing is available, otherwise just filenames are provided.
2846:             *  The detailed listing varies in details depending on OS and
2847:             *  FTP server.
2848:             *
2849:             *  @param  dirname  the name of the directory(<b>not</b> a file mask)
2850:             *  @param  full     true if detailed listing required
2851:             *                   false otherwise
2852:             *  @return a string containing the line separated
2853:             *          directory listing
2854:             *  @deprecated  As of FTP 1.1, replaced by {@link #dir(String,boolean)}
2855:             */
2856:            public String list(String dirname, boolean full)
2857:                    throws IOException, FTPException {
2858:
2859:                String[] list = dir(dirname, full);
2860:
2861:                StringBuffer result = new StringBuffer();
2862:                String sep = System.getProperty("line.separator");
2863:
2864:                // loop thru results and make into one string
2865:                for (int i = 0; i < list.length; i++) {
2866:                    result.append(list[i]);
2867:                    result.append(sep);
2868:                }
2869:
2870:                return result.toString();
2871:            }
2872:
2873:            /**
2874:             * Override the chosen file factory with a user created one - meaning
2875:             * that a specific parser has been selected
2876:             * 
2877:             * @param fileFactory
2878:             */
2879:            public void setFTPFileFactory(FTPFileFactory fileFactory) {
2880:                this .fileFactory = fileFactory;
2881:            }
2882:
2883:            /**
2884:             * Set the locale for date parsing of dir listings
2885:             * 
2886:             * @param locale    new locale to use
2887:             * @deprecated @see FTPClient#setParserLocales(Locale[])
2888:             */
2889:            public void setParserLocale(Locale locale) {
2890:                listingLocales = new Locale[1];
2891:                listingLocales[0] = locale;
2892:            }
2893:
2894:            /**
2895:             * Set the list of locales to be tried for date parsing of dir listings
2896:             * 
2897:             * @param locales    locales to use
2898:             */
2899:            public void setParserLocales(Locale[] locales) {
2900:                listingLocales = locales;
2901:            }
2902:
2903:            /**
2904:             * Uses the MLST command to find out details about the
2905:             * named file. A single filename should be supplied. Note
2906:             * that the MLST command is not supported by many servers.
2907:             * 
2908:             * @param name   name of a file
2909:             * @return  if it exists, an FTPFile object
2910:             */
2911:            public FTPFile fileDetails(String name) throws IOException,
2912:                    FTPException, ParseException {
2913:
2914:                checkConnection(true);
2915:
2916:                lastReply = control.sendCommand("MLST " + name);
2917:                lastValidReply = control.validateReply(lastReply, "250");
2918:
2919:                if (lastReply.getReplyData() != null)
2920:                    return mlsxParser.parse(lastReply.getReplyData()[0]);
2921:
2922:                log.warn("No file data returned from MLST");
2923:                return null;
2924:            }
2925:
2926:            /*
2927:             *  (non-Javadoc)
2928:             * @see com.enterprisedt.net.ftp.FTPClientInterface#dirDetails(java.lang.String)
2929:             */
2930:            public FTPFile[] dirDetails(String dirname) throws IOException,
2931:                    FTPException, ParseException {
2932:
2933:                // create the factory
2934:                if (fileFactory == null) {
2935:                    try {
2936:                        fileFactory = new FTPFileFactory(system());
2937:                    } catch (FTPException ex) {
2938:                        log
2939:                                .warn(
2940:                                        "SYST command failed - setting Unix as default parser",
2941:                                        ex);
2942:                        fileFactory = new FTPFileFactory(
2943:                                FTPFileFactory.UNIX_STR);
2944:                    }
2945:                }
2946:                fileFactory.setLocales(listingLocales);
2947:
2948:                String path = pwd();
2949:
2950:                // add dirname to path if it looks like a directory name
2951:                // and has no obvious wildcards
2952:                if (dirname != null && dirname.length() > 0
2953:                        && dirname.indexOf('*') < 0 && dirname.indexOf('?') < 0) {
2954:
2955:                    path += "/" + dirname;
2956:                }
2957:
2958:                // get the details and parse. Set the directory for each file
2959:                FTPFile[] result = fileFactory.parse(dir(dirname, true));
2960:                for (int i = 0; i < result.length; i++) {
2961:                    result[i].setPath(path);
2962:                }
2963:
2964:                return result;
2965:            }
2966:
2967:            /*
2968:             *  (non-Javadoc)
2969:             * @see com.enterprisedt.net.ftp.FTPClientInterface#dir()
2970:             */
2971:            public String[] dir() throws IOException, FTPException {
2972:
2973:                return dir(null, false);
2974:            }
2975:
2976:            /*
2977:             *  (non-Javadoc)
2978:             * @see com.enterprisedt.net.ftp.FTPClientInterface#dir(java.lang.String)
2979:             */
2980:            public String[] dir(String dirname) throws IOException,
2981:                    FTPException {
2982:
2983:                return dir(dirname, false);
2984:            }
2985:
2986:            /*
2987:             *  (non-Javadoc)
2988:             * @see com.enterprisedt.net.ftp.FTPClientInterface#dir(java.lang.String, boolean)
2989:             */
2990:            public String[] dir(String dirname, boolean full)
2991:                    throws IOException, FTPException {
2992:
2993:                checkConnection(true);
2994:
2995:                // reset the cancel flag
2996:                cancelTransfer = false;
2997:
2998:                try {
2999:                    // set up data channel
3000:                    setupDataSocket();
3001:
3002:                    // send the retrieve command
3003:                    String command = full ? "LIST " : "NLST ";
3004:                    if (dirname != null)
3005:                        command += dirname;
3006:
3007:                    // some FTP servers bomb out if NLST has whitespace appended
3008:                    command = command.trim();
3009:                    lastReply = control.sendCommand(command);
3010:
3011:                    // check the control response. wu-ftp returns 550 if the
3012:                    // directory is empty, so we handle 550 appropriately. Similarly
3013:                    // proFTPD returns 450 or 226 (depending on NLST or LIST)
3014:                    String[] validCodes1 = { "125", "150", "226", "450", "550" };
3015:                    lastValidReply = control.validateReply(lastReply,
3016:                            validCodes1);
3017:
3018:                    // an empty array of files for 450/550
3019:                    String[] result = new String[0];
3020:
3021:                    // a normal reply ... extract the file list
3022:                    String replyCode = lastValidReply.getReplyCode();
3023:                    if (!replyCode.equals("450") && !replyCode.equals("550")
3024:                            && !replyCode.equals("226")) {
3025:                        // get a character input stream to read data from .
3026:                        LineNumberReader in = null;
3027:                        Vector lines = new Vector();
3028:                        try {
3029:                            in = new LineNumberReader(new InputStreamReader(
3030:                                    data.getInputStream(), controlEncoding));
3031:
3032:                            // read a line at a time
3033:                            String line = null;
3034:                            while ((line = readLine(in)) != null
3035:                                    && !cancelTransfer) {
3036:                                lines.addElement(line);
3037:                                log.log(Level.ALL, line, null);
3038:                            }
3039:                        } catch (IOException ex) {
3040:                            validateTransferOnError(ex);
3041:                            throw ex;
3042:                        } finally {
3043:                            try {
3044:                                if (in != null)
3045:                                    in.close();
3046:                            } catch (IOException ex) {
3047:                                log
3048:                                        .error(
3049:                                                "Failed to close socket in dir()",
3050:                                                ex);
3051:                            }
3052:                            closeDataSocket();
3053:                        }
3054:
3055:                        // check the control response
3056:                        String[] validCodes2 = { "226", "250" };
3057:                        lastReply = control.readReply();
3058:                        lastValidReply = control.validateReply(lastReply,
3059:                                validCodes2);
3060:
3061:                        // empty array is default
3062:                        if (!lines.isEmpty()) {
3063:                            result = new String[lines.size()];
3064:                            lines.copyInto(result);
3065:                        }
3066:                    } else { // throw exception if not "No files" or other message
3067:                        String replyText = lastValidReply.getReplyText()
3068:                                .toUpperCase();
3069:                        if (!dirEmptyStrings.matches(replyText)
3070:                                && !transferCompleteStrings.matches(replyText))
3071:                            throw new FTPException(lastReply);
3072:                    }
3073:                    return result;
3074:                } finally {
3075:                    closeDataSocket();
3076:                }
3077:            }
3078:
3079:            /**
3080:             * Attempts to read a specified number of bytes from the given
3081:             * <code>InputStream</code> and place it in the given byte-array. The
3082:             * purpose of this method is to permit subclasses to execute any additional
3083:             * code necessary when performing this operation.
3084:             * 
3085:             * @param in
3086:             *            The <code>InputStream</code> to read from.
3087:             * @param chunk
3088:             *            The byte-array to place read bytes in.
3089:             * @param chunksize
3090:             *            Number of bytes to read.
3091:             * @return Number of bytes actually read.
3092:             * @throws IOException
3093:             *             Thrown if there was an error while reading.
3094:             */
3095:            public int readChunk(BufferedInputStream in, byte[] chunk,
3096:                    int chunksize) throws IOException {
3097:
3098:                return in.read(chunk, 0, chunksize);
3099:            }
3100:
3101:            /**
3102:             * Attempts to read a single character from the given <code>InputStream</code>. 
3103:             * The purpose of this method is to permit subclasses to execute
3104:             * any additional code necessary when performing this operation. 
3105:             * @param in The <code>LineNumberReader</code> to read from.
3106:             * @return The character read.
3107:             * @throws IOException Thrown if there was an error while reading.
3108:             */
3109:            protected int readChar(LineNumberReader in) throws IOException {
3110:
3111:                return in.read();
3112:            }
3113:
3114:            /**
3115:             * Attempts to read a single line from the given <code>InputStream</code>. 
3116:             * The purpose of this method is to permit subclasses to execute
3117:             * any additional code necessary when performing this operation. 
3118:             * @param in The <code>LineNumberReader</code> to read from.
3119:             * @return The string read.
3120:             * @throws IOException Thrown if there was an error while reading.
3121:             */
3122:            protected String readLine(LineNumberReader in) throws IOException {
3123:
3124:                return in.readLine();
3125:            }
3126:
3127:            /**
3128:             *  Gets the latest valid reply from the server
3129:             *
3130:             *  @return  reply object encapsulating last valid server response
3131:             */
3132:            public FTPReply getLastValidReply() {
3133:                return lastValidReply;
3134:            }
3135:
3136:            /**
3137:             *  Gets the last reply from the server, whether valid or not
3138:             *
3139:             *  @return  reply object encapsulating last server response
3140:             */
3141:            public FTPReply getLastReply() {
3142:                return lastReply;
3143:            }
3144:
3145:            /**
3146:             *  Get the current transfer type
3147:             *
3148:             *  @return  the current type of the transfer,
3149:             *           i.e. BINARY or ASCII
3150:             */
3151:            public FTPTransferType getType() {
3152:                return transferType;
3153:            }
3154:
3155:            /**
3156:             *  Set the transfer type
3157:             *
3158:             *  @param  type  the transfer type to
3159:             *                set the server to
3160:             */
3161:            public void setType(FTPTransferType type) throws IOException,
3162:                    FTPException {
3163:
3164:                checkConnection(true);
3165:
3166:                // determine the character to send
3167:                String typeStr = FTPTransferType.ASCII_CHAR;
3168:                if (type.equals(FTPTransferType.BINARY))
3169:                    typeStr = FTPTransferType.BINARY_CHAR;
3170:
3171:                // send the command
3172:                String[] validCodes = { "200", "250" };
3173:                lastReply = control.sendCommand("TYPE " + typeStr);
3174:                lastValidReply = control.validateReply(lastReply, validCodes);
3175:
3176:                // record the type
3177:                transferType = type;
3178:            }
3179:
3180:            /*
3181:             *  (non-Javadoc)
3182:             * @see com.enterprisedt.net.ftp.FTPClientInterface#delete(java.lang.String)
3183:             */
3184:            public void delete(String remoteFile) throws IOException,
3185:                    FTPException {
3186:
3187:                checkConnection(true);
3188:                String[] validCodes = { "200", "250" };
3189:                lastReply = control.sendCommand("DELE " + remoteFile);
3190:                lastValidReply = control.validateReply(lastReply, validCodes);
3191:                deleteCount++;
3192:            }
3193:
3194:            /*
3195:             *  (non-Javadoc)
3196:             * @see com.enterprisedt.net.ftp.FTPClientInterface#rename(java.lang.String, java.lang.String)
3197:             */
3198:            public void rename(String from, String to) throws IOException,
3199:                    FTPException {
3200:
3201:                checkConnection(true);
3202:
3203:                lastReply = control.sendCommand("RNFR " + from);
3204:                lastValidReply = control.validateReply(lastReply, "350");
3205:
3206:                lastReply = control.sendCommand("RNTO " + to);
3207:                lastValidReply = control.validateReply(lastReply, "250");
3208:            }
3209:
3210:            /*
3211:             *  (non-Javadoc)
3212:             * @see com.enterprisedt.net.ftp.FTPClientInterface#rmdir(java.lang.String)
3213:             */
3214:            public void rmdir(String dir) throws IOException, FTPException {
3215:
3216:                checkConnection(true);
3217:
3218:                lastReply = control.sendCommand("RMD " + dir);
3219:
3220:                // some servers return 200,257, technically incorrect but
3221:                // we cater for it ...
3222:                String[] validCodes = { "200", "250", "257" };
3223:                lastValidReply = control.validateReply(lastReply, validCodes);
3224:            }
3225:
3226:            /*
3227:             *  (non-Javadoc)
3228:             * @see com.enterprisedt.net.ftp.FTPClientInterface#mkdir(java.lang.String)
3229:             */
3230:            public void mkdir(String dir) throws IOException, FTPException {
3231:
3232:                checkConnection(true);
3233:
3234:                lastReply = control.sendCommand("MKD " + dir);
3235:
3236:                // some servers return 200,257, technically incorrect but
3237:                // we cater for it ...
3238:                String[] validCodes = { "200", "250", "257" };
3239:                lastValidReply = control.validateReply(lastReply, validCodes);
3240:            }
3241:
3242:            /*
3243:             *  (non-Javadoc)
3244:             * @see com.enterprisedt.net.ftp.FTPClientInterface#chdir(java.lang.String)
3245:             */
3246:            public void chdir(String dir) throws IOException, FTPException {
3247:
3248:                checkConnection(true);
3249:
3250:                lastReply = control.sendCommand("CWD " + dir);
3251:                lastValidReply = control.validateReply(lastReply, "250");
3252:            }
3253:
3254:            /*
3255:             *  (non-Javadoc)
3256:             * @see com.enterprisedt.net.ftp.FTPClientInterface#cdup()
3257:             */
3258:            public void cdup() throws IOException, FTPException {
3259:
3260:                checkConnection(true);
3261:
3262:                lastReply = control.sendCommand("CDUP");
3263:                String[] validCodes = { "200", "250" };
3264:                lastValidReply = control.validateReply(lastReply, validCodes);
3265:            }
3266:
3267:            /*
3268:             *  (non-Javadoc)
3269:             * @see com.enterprisedt.net.ftp.FTPClientInterface#modtime(java.lang.String)
3270:             */
3271:            public Date modtime(String remoteFile) throws IOException,
3272:                    FTPException {
3273:
3274:                checkConnection(true);
3275:
3276:                lastReply = control.sendCommand("MDTM " + remoteFile);
3277:                lastValidReply = control.validateReply(lastReply, "213");
3278:
3279:                // parse the reply string ...
3280:                Date ts = tsFormat.parse(lastValidReply.getReplyText(),
3281:                        new ParsePosition(0));
3282:                return ts;
3283:            }
3284:
3285:            /*
3286:             *  (non-Javadoc)
3287:             * @see com.enterprisedt.net.ftp.FTPClientInterface#pwd()
3288:             */
3289:            public String pwd() throws IOException, FTPException {
3290:
3291:                checkConnection(true);
3292:
3293:                lastReply = control.sendCommand("PWD");
3294:                lastValidReply = control.validateReply(lastReply, "257");
3295:
3296:                // get the reply text and extract the dir
3297:                // listed in quotes, if we can find it. Otherwise
3298:                // just return the whole reply string
3299:                String text = lastValidReply.getReplyText();
3300:                int start = text.indexOf('"');
3301:                int end = text.lastIndexOf('"');
3302:                if (start >= 0 && end > start)
3303:                    return text.substring(start + 1, end);
3304:                else
3305:                    return text;
3306:            }
3307:
3308:            /**
3309:             *  Get the server supplied features
3310:             *
3311:             *  @return   string containing server features, or null if no features or not
3312:             *             supported
3313:             */
3314:            public String[] features() throws IOException, FTPException {
3315:
3316:                checkConnection(true);
3317:
3318:                lastReply = control.sendCommand("FEAT");
3319:                String[] validCodes = { "211", "500", "502" };
3320:                lastValidReply = control.validateReply(lastReply, validCodes);
3321:                if (lastValidReply.getReplyCode().equals("211"))
3322:                    return lastValidReply.getReplyData();
3323:                else
3324:                    throw new FTPException(lastReply);
3325:            }
3326:
3327:            /**
3328:             *  Get the type of the OS at the server
3329:             *
3330:             *  @return   the type of server OS
3331:             */
3332:            public String system() throws IOException, FTPException {
3333:
3334:                checkConnection(true);
3335:
3336:                lastReply = control.sendCommand("SYST");
3337:                String[] validCodes = { "200", "213", "215", "250" }; // added 250 for leitch
3338:                lastValidReply = control.validateReply(lastReply, validCodes);
3339:                return lastValidReply.getReplyText();
3340:            }
3341:
3342:            /**
3343:             *  Send a "no operation" message that does nothing. Can be
3344:             *  called periodically to prevent the connection timing out
3345:             */
3346:            public void noOperation() throws IOException, FTPException {
3347:
3348:                checkConnection(true);
3349:
3350:                lastReply = control.sendCommand("NOOP");
3351:                String[] validCodes = { "200", "250" }; // added 250 for leitch
3352:                lastValidReply = control.validateReply(lastReply, validCodes);
3353:            }
3354:
3355:            /**
3356:             *  Sends stat message to enquire about the status of a
3357:             *  transfer. 
3358:             */
3359:            public String stat() throws IOException, FTPException {
3360:
3361:                checkConnection(true);
3362:
3363:                lastReply = control.sendCommand("STAT");
3364:                String[] validCodes = { "211", "212", "213" };
3365:                lastValidReply = control.validateReply(lastReply, validCodes);
3366:                return lastValidReply.getReplyText();
3367:            }
3368:
3369:            /**
3370:             * Wake up the server during a transfer to prevent a
3371:             * timeout from occuring. This may hang or confuse the server -
3372:             * use with caution.
3373:             * 
3374:             * @throws IOException 
3375:             * @throws FTPException 
3376:             *
3377:             */
3378:            public void sendServerWakeup() throws IOException, FTPException {
3379:                noOperation();
3380:            }
3381:
3382:            /**
3383:             *  Tries to keep the current connection alive by 
3384:             *  sending an innocuous commmand to signal that the 
3385:             *  client is still active
3386:             */
3387:            public void keepAlive() throws IOException, FTPException {
3388:                log.debug("keepAlive() called");
3389:                int op = (int) Math.ceil(Math.random() * 2);
3390:                switch (op) {
3391:                case 1:
3392:                    noOperation();
3393:                    break;
3394:                case 2:
3395:                    pwd();
3396:                    break;
3397:                default:
3398:                    pwd();
3399:                }
3400:            }
3401:
3402:            /**
3403:             *  Get the help text for the specified command
3404:             *
3405:             *  @param  command  name of the command to get help on
3406:             *  @return help text from the server for the supplied command
3407:             */
3408:            public String help(String command) throws IOException, FTPException {
3409:
3410:                checkConnection(true);
3411:
3412:                lastReply = control.sendCommand("HELP " + command);
3413:                String[] validCodes = { "211", "214" };
3414:                lastValidReply = control.validateReply(lastReply, validCodes);
3415:                return lastValidReply.getReplyText();
3416:            }
3417:
3418:            /**
3419:             *  Abort the current action
3420:             */
3421:            protected void abort() throws IOException, FTPException {
3422:
3423:                checkConnection(true);
3424:
3425:                lastReply = control.sendCommand("ABOR");
3426:                String[] validCodes = { "426", "226" };
3427:                lastValidReply = control.validateReply(lastReply, validCodes);
3428:            }
3429:
3430:            /*
3431:             *  (non-Javadoc)
3432:             * @see com.enterprisedt.net.ftp.FTPClientInterface#quit()
3433:             */
3434:            public void quit() throws IOException, FTPException {
3435:
3436:                checkConnection(true);
3437:
3438:                try {
3439:                    lastReply = control.sendCommand("QUIT");
3440:                    String[] validCodes = { "221", "226" };
3441:                    lastValidReply = control.validateReply(lastReply,
3442:                            validCodes);
3443:                } finally { // ensure we clean up the connection
3444:                    try {
3445:                        control.logout();
3446:                    } finally {
3447:                        control = null;
3448:                    }
3449:                }
3450:            }
3451:
3452:            /*
3453:             *  (non-Javadoc)
3454:             * @see com.enterprisedt.net.ftp.FTPClientInterface#quitImmediately()
3455:             */
3456:            public void quitImmediately() throws IOException, FTPException {
3457:
3458:                checkConnection(true);
3459:
3460:                cancelTransfer();
3461:                try {
3462:                    control.controlSock.close();
3463:                } finally {
3464:                    control = null;
3465:                }
3466:            }
3467:
3468:            /**
3469:             * String representation
3470:             */
3471:            public String toString() {
3472:                StringBuffer result = new StringBuffer("[");
3473:                result.append("FTP").append(",").append(remoteHost).append(",")
3474:                        .append(controlPort).append(",").append(getId())
3475:                        .append("]");
3476:                return result.toString();
3477:            }
3478:
3479:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.