KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > net > ftp > FTPClient


1 /*
2  * Copyright 2001-2005 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.net.ftp;
17 import java.io.BufferedInputStream JavaDoc;
18 import java.io.BufferedOutputStream JavaDoc;
19 import java.io.BufferedReader JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.InputStream JavaDoc;
22 import java.io.InputStreamReader JavaDoc;
23 import java.io.OutputStream JavaDoc;
24 import java.net.InetAddress JavaDoc;
25 import java.net.ServerSocket JavaDoc;
26 import java.net.Socket JavaDoc;
27 import java.util.Vector JavaDoc;
28
29 import org.apache.commons.net.MalformedServerReplyException;
30 import org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory;
31 import org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory;
32 import org.apache.commons.net.ftp.parser.ParserInitializationException;
33 import org.apache.commons.net.io.CopyStreamEvent;
34 import org.apache.commons.net.io.CopyStreamException;
35 import org.apache.commons.net.io.FromNetASCIIInputStream;
36 import org.apache.commons.net.io.ToNetASCIIOutputStream;
37 import org.apache.commons.net.io.Util;
38
39 /***
40  * FTPClient encapsulates all the functionality necessary to store and
41  * retrieve files from an FTP server. This class takes care of all
42  * low level details of interacting with an FTP server and provides
43  * a convenient higher level interface. As with all classes derived
44  * from {@link org.apache.commons.net.SocketClient},
45  * you must first connect to the server with
46  * {@link org.apache.commons.net.SocketClient#connect connect }
47  * before doing anything, and finally
48  * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
49  * after you're completely finished interacting with the server.
50  * Then you need to check the FTP reply code to see if the connection
51  * was successful. For example:
52  * <pre>
53  * boolean error = false;
54  * try {
55  * int reply;
56  * ftp.connect("ftp.foobar.com");
57  * System.out.println("Connected to " + server + ".");
58  * System.out.print(ftp.getReplyString());
59  *
60  * // After connection attempt, you should check the reply code to verify
61  * // success.
62  * reply = ftp.getReplyCode();
63  *
64  * if(!FTPReply.isPositiveCompletion(reply)) {
65  * ftp.disconnect();
66  * System.err.println("FTP server refused connection.");
67  * System.exit(1);
68  * }
69  * ... // transfer files
70  * ftp.logout();
71  * } catch(IOException e) {
72  * error = true;
73  * e.printStackTrace();
74  * } finally {
75  * if(ftp.isConnected()) {
76  * try {
77  * ftp.disconnect();
78  * } catch(IOException ioe) {
79  * // do nothing
80  * }
81  * }
82  * System.exit(error ? 1 : 0);
83  * }
84  * </pre>
85  * <p>
86  * Immediately after connecting is the only real time you need to check the
87  * reply code (because connect is of type void). The convention for all the
88  * FTP command methods in FTPClient is such that they either return a
89  * boolean value or some other value.
90  * The boolean methods return true on a successful completion reply from
91  * the FTP server and false on a reply resulting in an error condition or
92  * failure. The methods returning a value other than boolean return a value
93  * containing the higher level data produced by the FTP command, or null if a
94  * reply resulted in an error condition or failure. If you want to access
95  * the exact FTP reply code causing a success or failure, you must call
96  * {@link org.apache.commons.net.ftp.FTP#getReplyCode getReplyCode } after
97  * a success or failure.
98  * <p>
99  * The default settings for FTPClient are for it to use
100  * <code> FTP.ASCII_FILE_TYPE </code>,
101  * <code> FTP.NON_PRINT_TEXT_FORMAT </code>,
102  * <code> FTP.STREAM_TRANSFER_MODE </code>, and
103  * <code> FTP.FILE_STRUCTURE </code>. The only file types directly supported
104  * are <code> FTP.ASCII_FILE_TYPE </code> and
105  * <code> FTP.IMAGE_FILE_TYPE </code> (which is the same as
106  * <code> FTP.BINARY_FILE_TYPE </code>). Because there are at lest 4
107  * different EBCDIC encodings, we have opted not to provide direct support
108  * for EBCDIC. To transfer EBCDIC and other unsupported file types you
109  * must create your own filter InputStreams and OutputStreams and wrap
110  * them around the streams returned or required by the FTPClient methods.
111  * FTPClient uses the {@link ToNetASCIIOutputStream NetASCII}
112  * filter streams to provide transparent handling of ASCII files. We will
113  * consider incorporating EBCDIC support if there is enough demand.
114  * <p>
115  * <code> FTP.NON_PRINT_TEXT_FORMAT </code>,
116  * <code> FTP.STREAM_TRANSFER_MODE </code>, and
117  * <code> FTP.FILE_STRUCTURE </code> are the only supported formats,
118  * transfer modes, and file structures.
119  * <p>
120  * Because the handling of sockets on different platforms can differ
121  * significantly, the FTPClient automatically issues a new PORT command
122  * prior to every transfer requiring that the server connect to the client's
123  * data port. This ensures identical problem-free behavior on Windows, Unix,
124  * and Macintosh platforms. Additionally, it relieves programmers from
125  * having to issue the PORT command themselves and dealing with platform
126  * dependent issues.
127  * <p>
128  * Additionally, for security purposes, all data connections to the
129  * client are verified to ensure that they originated from the intended
130  * party (host and port). If a data connection is initiated by an unexpected
131  * party, the command will close the socket and throw an IOException. You
132  * may disable this behavior with
133  * {@link #setRemoteVerificationEnabled setRemoteVerificationEnabled()}.
134  * <p>
135  * You should keep in mind that the FTP server may choose to prematurely
136  * close a connection if the client has been idle for longer than a
137  * given time period (usually 900 seconds). The FTPClient class will detect a
138  * premature FTP server connection closing when it receives a
139  * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE }
140  * response to a command.
141  * When that occurs, the FTP class method encountering that reply will throw
142  * an {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
143  * .
144  * <code>FTPConnectionClosedException</code>
145  * is a subclass of <code> IOException </code> and therefore need not be
146  * caught separately, but if you are going to catch it separately, its
147  * catch block must appear before the more general <code> IOException </code>
148  * catch block. When you encounter an
149  * {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
150  * , you must disconnect the connection with
151  * {@link #disconnect disconnect() } to properly clean up the
152  * system resources used by FTPClient. Before disconnecting, you may check the
153  * last reply code and text with
154  * {@link org.apache.commons.net.ftp.FTP#getReplyCode getReplyCode },
155  * {@link org.apache.commons.net.ftp.FTP#getReplyString getReplyString },
156  * and
157  * {@link org.apache.commons.net.ftp.FTP#getReplyStrings getReplyStrings}.
158  * You may avoid server disconnections while the client is idle by
159  * periodicaly sending NOOP commands to the server.
160  * <p>
161  * Rather than list it separately for each method, we mention here that
162  * every method communicating with the server and throwing an IOException
163  * can also throw a
164  * {@link org.apache.commons.net.MalformedServerReplyException}
165  * , which is a subclass
166  * of IOException. A MalformedServerReplyException will be thrown when
167  * the reply received from the server deviates enough from the protocol
168  * specification that it cannot be interpreted in a useful manner despite
169  * attempts to be as lenient as possible.
170  * <p>
171  * Listing API Examples
172  * Both paged and unpaged examples of directory listings are available,
173  * as follows:
174  * <p>
175  * Unpaged (whole list) access, using a parser accessible by auto-detect:
176  * <pre>
177  * FTPClient f=FTPClient();
178  * f.connect(server);
179  * f.login(username, password);
180  * FTPFile[] files = listFiles(directory);
181  * </pre>
182  * <p>
183  * Paged access, using a parser not accessible by auto-detect. The class
184  * defined in the first parameter of initateListParsing should be derived
185  * from org.apache.commons.net.FTPFileEntryParser:
186  * <pre>
187  * FTPClient f=FTPClient();
188  * f.connect(server);
189  * f.login(username, password);
190  * FTPListParseEngine engine =
191  * f.initiateListParsing("com.whatever.YourOwnParser", directory);
192  *
193  * while (engine.hasNext()) {
194  * FTPFile[] files = engine.getNext(25); // "page size" you want
195  * //do whatever you want with these files, display them, etc.
196  * //expensive FTPFile objects not created until needed.
197  * }
198  * </pre>
199  * <p>
200  * Paged access, using a parser accessible by auto-detect:
201  * <pre>
202  * FTPClient f=FTPClient();
203  * f.connect(server);
204  * f.login(username, password);
205  * FTPListParseEngine engine = f.initiateListParsing(directory);
206  *
207  * while (engine.hasNext()) {
208  * FTPFile[] files = engine.getNext(25); // "page size" you want
209  * //do whatever you want with these files, display them, etc.
210  * //expensive FTPFile objects not created until needed.
211  * }
212  * </pre>
213  * <p>
214  * For examples of using FTPClient on servers whose directory listings
215  * <ul>
216  * <li>use languages other than English</li>
217  * <li>use date formats other than the American English "standard" <code>MM d yyyy</code></li>
218  * <li>are in different timezones and you need accurate timestamps for dependency checking
219  * as in Ant</li>
220  * </ul>see {@link FTPClientConfig FTPClientConfig}.
221  * <p>
222  * NOTE: If you experience problems with unwanted firing of <pre>setSoTimeout()</pre>
223  * during periods of client inactivity, this can be alleviated by calling <pre>setReaderThread(false)</pre>.
224  * For more details, see <a HREF="http://issues.apache.org/bugzilla/show_bug.cgi?id=31122">this thread</a>.
225  * </p>
226  * <p>
227  * @author Daniel F. Savarese
228  * @see FTP
229  * @see FTPConnectionClosedException
230  * @see FTPFileEntryParser
231  * @see FTPFileEntryParserFactory
232  * @see DefaultFTPFileEntryParserFactory
233  * @see FTPClientConfig
234  * @see org.apache.commons.net.MalformedServerReplyException
235  **/

236 public class FTPClient extends FTP
237 implements Configurable
238 {
239     /***
240      * A constant indicating the FTP session is expecting all transfers
241      * to occur between the client (local) and server and that the server
242      * should connect to the client's data port to initiate a data transfer.
243      * This is the default data connection mode when and FTPClient instance
244      * is created.
245      ***/

246     public static final int ACTIVE_LOCAL_DATA_CONNECTION_MODE = 0;
247     /***
248      * A constant indicating the FTP session is expecting all transfers
249      * to occur between two remote servers and that the server
250      * the client is connected to should connect to the other server's
251      * data port to initiate a data transfer.
252      ***/

253     public static final int ACTIVE_REMOTE_DATA_CONNECTION_MODE = 1;
254     /***
255      * A constant indicating the FTP session is expecting all transfers
256      * to occur between the client (local) and server and that the server
257      * is in passive mode, requiring the client to connect to the
258      * server's data port to initiate a transfer.
259      ***/

260     public static final int PASSIVE_LOCAL_DATA_CONNECTION_MODE = 2;
261     /***
262      * A constant indicating the FTP session is expecting all transfers
263      * to occur between two remote servers and that the server
264      * the client is connected to is in passive mode, requiring the other
265      * server to connect to the first server's data port to initiate a data
266      * transfer.
267      ***/

268     public static final int PASSIVE_REMOTE_DATA_CONNECTION_MODE = 3;
269
270     private int __dataConnectionMode, __dataTimeout;
271     private int __passivePort;
272     private String JavaDoc __passiveHost;
273     private int __fileType, __fileFormat, __fileStructure, __fileTransferMode;
274     private boolean __remoteVerificationEnabled;
275     private long __restartOffset;
276     private FTPFileEntryParserFactory __parserFactory;
277     private int __bufferSize;
278
279     // __systemName is a cached value that should not be referenced directly
280
// except when assigned in getSystemName and __initDefaults.
281
private String JavaDoc __systemName;
282
283     // __entryParser is a cached value that should not be referenced directly
284
// except when assigned in listFiles(String, String) and __initDefaults.
285
private FTPFileEntryParser __entryParser;
286     
287     private FTPClientConfig __configuration;
288
289     /***
290      * Default FTPClient constructor. Creates a new FTPClient instance
291      * with the data connection mode set to
292      * <code> ACTIVE_LOCAL_DATA_CONNECTION_MODE </code>, the file type
293      * set to <code> FTP.ASCII_FILE_TYPE </code>, the
294      * file format set to <code> FTP.NON_PRINT_TEXT_FORMAT </code>,
295      * the file structure set to <code> FTP.FILE_STRUCTURE </code>, and
296      * the transfer mode set to <code> FTP.STREAM_TRANSFER_MODE </code>.
297      ***/

298     public FTPClient()
299     {
300         __initDefaults();
301         __dataTimeout = -1;
302         __remoteVerificationEnabled = true;
303         __parserFactory = new DefaultFTPFileEntryParserFactory();
304         __configuration = null;
305     }
306
307
308     private void __initDefaults()
309     {
310         __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE;
311         __passiveHost = null;
312         __passivePort = -1;
313         __fileType = FTP.ASCII_FILE_TYPE;
314         __fileStructure = FTP.FILE_STRUCTURE;
315         __fileFormat = FTP.NON_PRINT_TEXT_FORMAT;
316         __fileTransferMode = FTP.STREAM_TRANSFER_MODE;
317         __restartOffset = 0;
318         __systemName = null;
319         __entryParser = null;
320         __bufferSize = Util.DEFAULT_COPY_BUFFER_SIZE;
321     }
322     
323     private String JavaDoc __parsePathname(String JavaDoc reply)
324     {
325         int begin, end;
326
327         begin = reply.indexOf('"') + 1;
328         end = reply.indexOf('"', begin);
329
330         return reply.substring(begin, end);
331     }
332
333
334     private void __parsePassiveModeReply(String JavaDoc reply)
335     throws MalformedServerReplyException
336     {
337         int i, index, lastIndex;
338         String JavaDoc octet1, octet2;
339         StringBuffer JavaDoc host;
340
341         reply = reply.substring(reply.indexOf('(') + 1,
342                                 reply.indexOf(')')).trim();
343
344         host = new StringBuffer JavaDoc(24);
345         lastIndex = 0;
346         index = reply.indexOf(',');
347         host.append(reply.substring(lastIndex, index));
348
349         for (i = 0; i < 3; i++)
350         {
351             host.append('.');
352             lastIndex = index + 1;
353             index = reply.indexOf(',', lastIndex);
354             host.append(reply.substring(lastIndex, index));
355         }
356
357         lastIndex = index + 1;
358         index = reply.indexOf(',', lastIndex);
359
360         octet1 = reply.substring(lastIndex, index);
361         octet2 = reply.substring(index + 1);
362
363         // index and lastIndex now used as temporaries
364
try
365         {
366             index = Integer.parseInt(octet1);
367             lastIndex = Integer.parseInt(octet2);
368         }
369         catch (NumberFormatException JavaDoc e)
370         {
371             throw new MalformedServerReplyException(
372                 "Could not parse passive host information.\nServer Reply: " + reply);
373         }
374
375         index <<= 8;
376         index |= lastIndex;
377
378         __passiveHost = host.toString();
379         __passivePort = index;
380     }
381
382     private boolean __storeFile(int command, String JavaDoc remote, InputStream JavaDoc local)
383     throws IOException JavaDoc
384     {
385         OutputStream JavaDoc output;
386         Socket JavaDoc socket;
387
388         if ((socket = _openDataConnection_(command, remote)) == null)
389             return false;
390
391         output = new BufferedOutputStream JavaDoc(socket.getOutputStream(),
392                                           getBufferSize()
393                                           );
394         if (__fileType == ASCII_FILE_TYPE)
395             output = new ToNetASCIIOutputStream(output);
396         // Treat everything else as binary for now
397
try
398         {
399             Util.copyStream(local, output, getBufferSize(),
400                             CopyStreamEvent.UNKNOWN_STREAM_SIZE, null,
401                             false);
402         }
403         catch (IOException JavaDoc e)
404         {
405             try
406             {
407                 socket.close();
408             }
409             catch (IOException JavaDoc f)
410             {}
411             throw e;
412         }
413         output.close();
414         socket.close();
415         return completePendingCommand();
416     }
417
418     private OutputStream JavaDoc __storeFileStream(int command, String JavaDoc remote)
419     throws IOException JavaDoc
420     {
421         OutputStream JavaDoc output;
422         Socket JavaDoc socket;
423
424         if ((socket = _openDataConnection_(command, remote)) == null)
425             return null;
426
427         output = socket.getOutputStream();
428         if (__fileType == ASCII_FILE_TYPE) {
429           // We buffer ascii transfers because the buffering has to
430
// be interposed between ToNetASCIIOutputSream and the underlying
431
// socket output stream. We don't buffer binary transfers
432
// because we don't want to impose a buffering policy on the
433
// programmer if possible. Programmers can decide on their
434
// own if they want to wrap the SocketOutputStream we return
435
// for file types other than ASCII.
436
output = new BufferedOutputStream JavaDoc(output,
437                                             getBufferSize());
438           output = new ToNetASCIIOutputStream(output);
439
440         }
441         return new org.apache.commons.net.io.SocketOutputStream(socket, output);
442     }
443
444
445     /**
446      * Establishes a data connection with the FTP server, returning
447      * a Socket for the connection if successful. If a restart
448      * offset has been set with {@link #setRestartOffset(long)},
449      * a REST command is issued to the server with the offset as
450      * an argument before establishing the data connection. Active
451      * mode connections also cause a local PORT command to be issued.
452      * <p>
453      * @param command The text representation of the FTP command to send.
454      * @param arg The arguments to the FTP command. If this parameter is
455      * set to null, then the command is sent with no argument.
456      * @return A Socket corresponding to the established data connection.
457      * Null is returned if an FTP protocol error is reported at
458      * any point during the establishment and initialization of
459      * the connection.
460      * @exception IOException If an I/O error occurs while either sending a
461      * command to the server or receiving a reply from the server.
462      */

463     protected Socket JavaDoc _openDataConnection_(int command, String JavaDoc arg)
464       throws IOException JavaDoc
465     {
466         Socket JavaDoc socket;
467
468         if (__dataConnectionMode != ACTIVE_LOCAL_DATA_CONNECTION_MODE &&
469                 __dataConnectionMode != PASSIVE_LOCAL_DATA_CONNECTION_MODE)
470             return null;
471
472         if (__dataConnectionMode == ACTIVE_LOCAL_DATA_CONNECTION_MODE)
473         {
474             ServerSocket JavaDoc server;
475             server = _socketFactory_.createServerSocket(0, 1, getLocalAddress());
476
477             if (!FTPReply.isPositiveCompletion(port(getLocalAddress(),
478                                                     server.getLocalPort())))
479             {
480                 server.close();
481                 return null;
482             }
483
484             if ((__restartOffset > 0) && !restart(__restartOffset))
485             {
486                 server.close();
487                 return null;
488             }
489
490             if (!FTPReply.isPositivePreliminary(sendCommand(command, arg)))
491             {
492                 server.close();
493                 return null;
494             }
495
496             // For now, let's just use the data timeout value for waiting for
497
// the data connection. It may be desirable to let this be a
498
// separately configurable value. In any case, we really want
499
// to allow preventing the accept from blocking indefinitely.
500
if (__dataTimeout >= 0)
501                 server.setSoTimeout(__dataTimeout);
502             socket = server.accept();
503             server.close();
504         }
505         else
506         { // We must be in PASSIVE_LOCAL_DATA_CONNECTION_MODE
507

508             if (pasv() != FTPReply.ENTERING_PASSIVE_MODE)
509                 return null;
510
511             __parsePassiveModeReply((String JavaDoc)_replyLines.elementAt(0));
512
513             socket = _socketFactory_.createSocket(__passiveHost, __passivePort);
514             if ((__restartOffset > 0) && !restart(__restartOffset))
515             {
516                 socket.close();
517                 return null;
518             }
519
520             if (!FTPReply.isPositivePreliminary(sendCommand(command, arg)))
521             {
522                 socket.close();
523                 return null;
524             }
525         }
526
527         if (__remoteVerificationEnabled && !verifyRemote(socket))
528         {
529             InetAddress JavaDoc host1, host2;
530
531             host1 = socket.getInetAddress();
532             host2 = getRemoteAddress();
533
534             socket.close();
535
536             throw new IOException JavaDoc(
537                 "Host attempting data connection " + host1.getHostAddress() +
538                 " is not same as server " + host2.getHostAddress());
539         }
540
541         if (__dataTimeout >= 0)
542             socket.setSoTimeout(__dataTimeout);
543
544         return socket;
545     }
546
547
548     protected void _connectAction_() throws IOException JavaDoc
549     {
550         super._connectAction_();
551         __initDefaults();
552     }
553
554
555     /***
556      * Sets the timeout in milliseconds to use when reading from the
557      * data connection. This timeout will be set immediately after
558      * opening the data connection.
559      * <p>
560      * @param timeout The default timeout in milliseconds that is used when
561      * opening a data connection socket.
562      ***/

563     public void setDataTimeout(int timeout)
564     {
565         __dataTimeout = timeout;
566     }
567
568     /**
569      * set the factory used for parser creation to the supplied factory object.
570      *
571      * @param parserFactory
572      * factory object used to create FTPFileEntryParsers
573      *
574      * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
575      * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
576      */

577     public void setParserFactory(FTPFileEntryParserFactory parserFactory) {
578         __parserFactory = parserFactory;
579     }
580
581
582     /***
583      * Closes the connection to the FTP server and restores
584      * connection parameters to the default values.
585      * <p>
586      * @exception IOException If an error occurs while disconnecting.
587      ***/

588     public void disconnect() throws IOException JavaDoc
589     {
590         super.disconnect();
591         __initDefaults();
592     }
593
594
595     /***
596      * Enable or disable verification that the remote host taking part
597      * of a data connection is the same as the host to which the control
598      * connection is attached. The default is for verification to be
599      * enabled. You may set this value at any time, whether the
600      * FTPClient is currently connected or not.
601      * <p>
602      * @param enable True to enable verification, false to disable verification.
603      ***/

604     public void setRemoteVerificationEnabled(boolean enable)
605     {
606         __remoteVerificationEnabled = enable;
607     }
608
609     /***
610      * Return whether or not verification of the remote host participating
611      * in data connections is enabled. The default behavior is for
612      * verification to be enabled.
613      * <p>
614      * @return True if verification is enabled, false if not.
615      ***/

616     public boolean isRemoteVerificationEnabled()
617     {
618         return __remoteVerificationEnabled;
619     }
620
621     /***
622      * Login to the FTP server using the provided username and password.
623      * <p>
624      * @param username The username to login under.
625      * @param password The password to use.
626      * @return True if successfully completed, false if not.
627      * @exception FTPConnectionClosedException
628      * If the FTP server prematurely closes the connection as a result
629      * of the client being idle or some other reason causing the server
630      * to send FTP reply code 421. This exception may be caught either
631      * as an IOException or independently as itself.
632      * @exception IOException If an I/O error occurs while either sending a
633      * command to the server or receiving a reply from the server.
634      ***/

635     public boolean login(String JavaDoc username, String JavaDoc password) throws IOException JavaDoc
636     {
637         user(username);
638
639         if (FTPReply.isPositiveCompletion(_replyCode))
640             return true;
641
642         // If we get here, we either have an error code, or an intermmediate
643
// reply requesting password.
644
if (!FTPReply.isPositiveIntermediate(_replyCode))
645             return false;
646
647         return FTPReply.isPositiveCompletion(pass(password));
648     }
649
650
651     /***
652      * Login to the FTP server using the provided username, password,
653      * and account. If no account is required by the server, only
654      * the username and password, the account information is not used.
655      * <p>
656      * @param username The username to login under.
657      * @param password The password to use.
658      * @param account The account to use.
659      * @return True if successfully completed, false if not.
660      * @exception FTPConnectionClosedException
661      * If the FTP server prematurely closes the connection as a result
662      * of the client being idle or some other reason causing the server
663      * to send FTP reply code 421. This exception may be caught either
664      * as an IOException or independently as itself.
665      * @exception IOException If an I/O error occurs while either sending a
666      * command to the server or receiving a reply from the server.
667      ***/

668     public boolean login(String JavaDoc username, String JavaDoc password, String JavaDoc account)
669     throws IOException JavaDoc
670     {
671         user(username);
672
673         if (FTPReply.isPositiveCompletion(_replyCode))
674             return true;
675
676         // If we get here, we either have an error code, or an intermmediate
677
// reply requesting password.
678
if (!FTPReply.isPositiveIntermediate(_replyCode))
679             return false;
680
681         pass(password);
682
683         if (FTPReply.isPositiveCompletion(_replyCode))
684             return true;
685
686         if (!FTPReply.isPositiveIntermediate(_replyCode))
687             return false;
688
689         return FTPReply.isPositiveCompletion(acct(account));
690     }
691
692     /***
693      * Logout of the FTP server by sending the QUIT command.
694      * <p>
695      * @return True if successfully completed, false if not.
696      * @exception FTPConnectionClosedException
697      * If the FTP server prematurely closes the connection as a result
698      * of the client being idle or some other reason causing the server
699      * to send FTP reply code 421. This exception may be caught either
700      * as an IOException or independently as itself.
701      * @exception IOException If an I/O error occurs while either sending a
702      * command to the server or receiving a reply from the server.
703      ***/

704     public boolean logout() throws IOException JavaDoc
705     {
706         return FTPReply.isPositiveCompletion(quit());
707     }
708
709
710     /***
711      * Change the current working directory of the FTP session.
712      * <p>
713      * @param pathname The new current working directory.
714      * @return True if successfully completed, false if not.
715      * @exception FTPConnectionClosedException
716      * If the FTP server prematurely closes the connection as a result
717      * of the client being idle or some other reason causing the server
718      * to send FTP reply code 421. This exception may be caught either
719      * as an IOException or independently as itself.
720      * @exception IOException If an I/O error occurs while either sending a
721      * command to the server or receiving a reply from the server.
722      ***/

723     public boolean changeWorkingDirectory(String JavaDoc pathname) throws IOException JavaDoc
724     {
725         return FTPReply.isPositiveCompletion(cwd(pathname));
726     }
727
728
729     /***
730      * Change to the parent directory of the current working directory.
731      * <p>
732      * @return True if successfully completed, false if not.
733      * @exception FTPConnectionClosedException
734      * If the FTP server prematurely closes the connection as a result
735      * of the client being idle or some other reason causing the server
736      * to send FTP reply code 421. This exception may be caught either
737      * as an IOException or independently as itself.
738      * @exception IOException If an I/O error occurs while either sending a
739      * command to the server or receiving a reply from the server.
740      ***/

741     public boolean changeToParentDirectory() throws IOException JavaDoc
742     {
743         return FTPReply.isPositiveCompletion(cdup());
744     }
745
746
747     /***
748      * Issue the FTP SMNT command.
749      * <p>
750      * @param pathname The pathname to mount.
751      * @return True if successfully completed, false if not.
752      * @exception FTPConnectionClosedException
753      * If the FTP server prematurely closes the connection as a result
754      * of the client being idle or some other reason causing the server
755      * to send FTP reply code 421. This exception may be caught either
756      * as an IOException or independently as itself.
757      * @exception IOException If an I/O error occurs while either sending a
758      * command to the server or receiving a reply from the server.
759      ***/

760     public boolean structureMount(String JavaDoc pathname) throws IOException JavaDoc
761     {
762         return FTPReply.isPositiveCompletion(smnt(pathname));
763     }
764
765     /***
766      * Reinitialize the FTP session. Not all FTP servers support this
767      * command, which issues the FTP REIN command.
768      * <p>
769      * @return True if successfully completed, false if not.
770      * @exception FTPConnectionClosedException
771      * If the FTP server prematurely closes the connection as a result
772      * of the client being idle or some other reason causing the server
773      * to send FTP reply code 421. This exception may be caught either
774      * as an IOException or independently as itself.
775      * @exception IOException If an I/O error occurs while either sending a
776      * command to the server or receiving a reply from the server.
777      ***/

778     boolean reinitialize() throws IOException JavaDoc
779     {
780         rein();
781
782         if (FTPReply.isPositiveCompletion(_replyCode) ||
783                 (FTPReply.isPositivePreliminary(_replyCode) &&
784                  FTPReply.isPositiveCompletion(getReply())))
785         {
786
787             __initDefaults();
788
789             return true;
790         }
791
792         return false;
793     }
794
795
796     /***
797      * Set the current data connection mode to
798      * <code>ACTIVE_LOCAL_DATA_CONNECTION_MODE</code>. No communication
799      * with the FTP server is conducted, but this causes all future data
800      * transfers to require the FTP server to connect to the client's
801      * data port. Additionally, to accommodate differences between socket
802      * implementations on different platforms, this method causes the
803      * client to issue a PORT command before every data transfer.
804      ***/

805     public void enterLocalActiveMode()
806     {
807         __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE;
808         __passiveHost = null;
809         __passivePort = -1;
810     }
811
812
813     /***
814      * Set the current data connection mode to
815      * <code> PASSIVE_LOCAL_DATA_CONNECTION_MODE </code>. Use this
816      * method only for data transfers between the client and server.
817      * This method causes a PASV command to be issued to the server
818      * before the opening of every data connection, telling the server to
819      * open a data port to which the client will connect to conduct
820      * data transfers. The FTPClient will stay in
821      * <code> PASSIVE_LOCAL_DATA_CONNECTION_MODE </code> until the
822      * mode is changed by calling some other method such as
823      * {@link #enterLocalActiveMode enterLocalActiveMode() }
824      ***/

825     public void enterLocalPassiveMode()
826     {
827         __dataConnectionMode = PASSIVE_LOCAL_DATA_CONNECTION_MODE;
828         // These will be set when just before a data connection is opened
829
// in _openDataConnection_()
830
__passiveHost = null;
831         __passivePort = -1;
832     }
833
834
835     /***
836      * Set the current data connection mode to
837      * <code> ACTIVE_REMOTE_DATA_CONNECTION </code>. Use this method only
838      * for server to server data transfers. This method issues a PORT
839      * command to the server, indicating the other server and port to which
840      * it should connect for data transfers. You must call this method
841      * before EVERY server to server transfer attempt. The FTPClient will
842      * NOT automatically continue to issue PORT commands. You also
843      * must remember to call
844      * {@link #enterLocalActiveMode enterLocalActiveMode() } if you
845      * wish to return to the normal data connection mode.
846      * <p>
847      * @param host The passive mode server accepting connections for data
848      * transfers.
849      * @param port The passive mode server's data port.
850      * @return True if successfully completed, false if not.
851      * @exception FTPConnectionClosedException
852      * If the FTP server prematurely closes the connection as a result
853      * of the client being idle or some other reason causing the server
854      * to send FTP reply code 421. This exception may be caught either
855      * as an IOException or independently as itself.
856      * @exception IOException If an I/O error occurs while either sending a
857      * command to the server or receiving a reply from the server.
858      ***/

859     public boolean enterRemoteActiveMode(InetAddress JavaDoc host, int port)
860     throws IOException JavaDoc
861     {
862         if (FTPReply.isPositiveCompletion(port(host, port)))
863         {
864             __dataConnectionMode = ACTIVE_REMOTE_DATA_CONNECTION_MODE;
865             __passiveHost = null;
866             __passivePort = -1;
867             return true;
868         }
869         return false;
870     }
871
872     /***
873      * Set the current data connection mode to
874      * <code> PASSIVE_REMOTE_DATA_CONNECTION_MODE </code>. Use this
875      * method only for server to server data transfers.
876      * This method issues a PASV command to the server, telling it to
877      * open a data port to which the active server will connect to conduct
878      * data transfers. You must call this method
879      * before EVERY server to server transfer attempt. The FTPClient will
880      * NOT automatically continue to issue PASV commands. You also
881      * must remember to call
882      * {@link #enterLocalActiveMode enterLocalActiveMode() } if you
883      * wish to return to the normal data connection mode.
884      * <p>
885      * @return True if successfully completed, false if not.
886      * @exception FTPConnectionClosedException
887      * If the FTP server prematurely closes the connection as a result
888      * of the client being idle or some other reason causing the server
889      * to send FTP reply code 421. This exception may be caught either
890      * as an IOException or independently as itself.
891      * @exception IOException If an I/O error occurs while either sending a
892      * command to the server or receiving a reply from the server.
893      ***/

894     public boolean enterRemotePassiveMode() throws IOException JavaDoc
895     {
896         if (pasv() != FTPReply.ENTERING_PASSIVE_MODE)
897             return false;
898
899         __dataConnectionMode = PASSIVE_REMOTE_DATA_CONNECTION_MODE;
900         __parsePassiveModeReply((String JavaDoc)_replyLines.elementAt(0));
901
902         return true;
903     }
904
905     /***
906      * Returns the hostname or IP address (in the form of a string) returned
907      * by the server when entering passive mode. If not in passive mode,
908      * returns null. This method only returns a valid value AFTER a
909      * data connection has been opened after a call to
910      * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
911      * This is because FTPClient sends a PASV command to the server only
912      * just before opening a data connection, and not when you call
913      * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
914      * <p>
915      * @return The passive host name if in passive mode, otherwise null.
916      ***/

917     public String JavaDoc getPassiveHost()
918     {
919         return __passiveHost;
920     }
921
922     /***
923      * If in passive mode, returns the data port of the passive host.
924      * This method only returns a valid value AFTER a
925      * data connection has been opened after a call to
926      * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
927      * This is because FTPClient sends a PASV command to the server only
928      * just before opening a data connection, and not when you call
929      * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
930      * <p>
931      * @return The data port of the passive server. If not in passive
932      * mode, undefined.
933      ***/

934     public int getPassivePort()
935     {
936         return __passivePort;
937     }
938
939
940     /***
941      * Returns the current data connection mode (one of the
942      * <code> _DATA_CONNECTION_MODE </code> constants.
943      * <p>
944      * @return The current data connection mode (one of the
945      * <code> _DATA_CONNECTION_MODE </code> constants.
946      ***/

947     public int getDataConnectionMode()
948     {
949         return __dataConnectionMode;
950     }
951
952
953     /***
954      * Sets the file type to be transferred. This should be one of
955      * <code> FTP.ASCII_FILE_TYPE </code>, <code> FTP.IMAGE_FILE_TYPE </code>,
956      * etc. The file type only needs to be set when you want to change the
957      * type. After changing it, the new type stays in effect until you change
958      * it again. The default file type is <code> FTP.ASCII_FILE_TYPE </code>
959      * if this method is never called.
960      * <p>
961      * @param fileType The <code> _FILE_TYPE </code> constant indcating the
962      * type of file.
963      * @return True if successfully completed, false if not.
964      * @exception FTPConnectionClosedException
965      * If the FTP server prematurely closes the connection as a result
966      * of the client being idle or some other reason causing the server
967      * to send FTP reply code 421. This exception may be caught either
968      * as an IOException or independently as itself.
969 <