1 /*
2  * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 package sun.net.ftp;
26 
27 import java.net.*;
28 import java.io.*;
29 import java.util.Date;
30 import java.util.List;
31 import java.util.Iterator;
32 
33 /**
34  * A class that implements the FTP protocol according to
35  * RFCs <A href="http://www.ietf.org/rfc/rfc0959.txt">959</A>,
36  * <A href="http://www.ietf.org/rfc/rfc2228.txt">2228</A>,
37  * <A href="http://www.ietf.org/rfc/rfc2389.txt">2389</A>,
38  * <A href="http://www.ietf.org/rfc/rfc2428.txt">2428</A>,
39  * <A href="http://www.ietf.org/rfc/rfc3659.txt">3659</A>,
40  * <A href="http://www.ietf.org/rfc/rfc4217.txt">4217</A>.
41  * Which includes support for FTP over SSL/TLS (aka ftps).
42  *
43  * {@code FtpClient} provides all the functionalities of a typical FTP
44  * client, like storing or retrieving files, listing or creating directories.
45  * A typical usage would consist of connecting the client to the server,
46  * log in, issue a few commands then logout.
47  * Here is a code example:
48  * <pre>
49  * FtpClient cl = FtpClient.create();
50  * cl.connect("ftp.gnu.org").login("anonymous", "john.doe@mydomain.com".toCharArray())).changeDirectory("pub/gnu");
51  * Iterator&lt;FtpDirEntry&gt; dir = cl.listFiles();
52  *     while (dir.hasNext()) {
53  *         FtpDirEntry f = dir.next();
54  *         System.err.println(f.getName());
55  *     }
56  *     cl.close();
57  * }
58  * </pre>
59  * <p><b>Error reporting:</b> There are, mostly, two families of errors that
60  * can occur during an FTP session. The first kind are the network related issues
61  * like a connection reset, and they are usually fatal to the session, meaning,
62  * in all likelyhood the connection to the server has been lost and the session
63  * should be restarted from scratch. These errors are reported by throwing an
64  * {@link IOException}. The second kind are the errors reported by the FTP server,
65  * like when trying to download a non-existing file for example. These errors
66  * are usually non fatal to the session, meaning more commands can be sent to the
67  * server. In these cases, a {@link FtpProtocolException} is thrown.</p>
68  * <p>
69  * It should be noted that this is not a thread-safe API, as it wouldn't make
70  * too much sense, due to the very sequential nature of FTP, to provide a
71  * client able to be manipulated from multiple threads.
72  *
73  * @since 1.7
74  */
75 public abstract class FtpClient implements java.io.Closeable {
76 
77     private static final int FTP_PORT = 21;
78 
79     public static enum TransferType {
80 
81         ASCII, BINARY, EBCDIC
82     };
83 
84     /**
85      * Returns the default FTP port number.
86      *
87      * @return the port number.
88      */
defaultPort()89     public static final int defaultPort() {
90         return FTP_PORT;
91     }
92 
93     /**
94      * Creates an instance of FtpClient. The client is not connected to any
95      * server yet.
96      *
97      */
FtpClient()98     protected FtpClient() {
99     }
100 
101     /**
102      * Creates an instance of {@code FtpClient}. The client is not connected to any
103      * server yet.
104      *
105      * @return the created {@code FtpClient}
106      */
create()107     public static FtpClient create() {
108         FtpClientProvider provider = FtpClientProvider.provider();
109         return provider.createFtpClient();
110     }
111 
112     /**
113      * Creates an instance of FtpClient and connects it to the specified
114      * address.
115      *
116      * @param dest the {@code InetSocketAddress} to connect to.
117      * @return The created {@code FtpClient}
118      * @throws IOException if the connection fails
119      * @see #connect(java.net.SocketAddress)
120      */
create(InetSocketAddress dest)121     public static FtpClient create(InetSocketAddress dest) throws FtpProtocolException, IOException {
122         FtpClient client = create();
123         if (dest != null) {
124             client.connect(dest);
125         }
126         return client;
127     }
128 
129     /**
130      * Creates an instance of {@code FtpClient} and connects it to the
131      * specified host on the default FTP port.
132      *
133      * @param dest the {@code String} containing the name of the host
134      *        to connect to.
135      * @return The created {@code FtpClient}
136      * @throws IOException if the connection fails.
137      * @throws FtpProtocolException if the server rejected the connection
138      */
create(String dest)139     public static FtpClient create(String dest) throws FtpProtocolException, IOException {
140         return create(new InetSocketAddress(dest, FTP_PORT));
141     }
142 
143     /**
144      * Enables, or disables, the use of the <I>passive</I> mode. In that mode,
145      * data connections are established by having the client connect to the server.
146      * This is the recommended default mode as it will work best through
147      * firewalls and NATs. If set to {@code false} the mode is said to be
148      * <I>active</I> which means the server will connect back to the client
149      * after a PORT command to establish a data connection.
150      *
151      * <p><b>Note:</b> Since the passive mode might not be supported by all
152      * FTP servers, enabling it means the client will try to use it. If the
153      * server rejects it, then the client will attempt to fall back to using
154      * the <I>active</I> mode by issuing a {@code PORT} command instead.</p>
155      *
156      * @param passive {@code true} to force passive mode.
157      * @return This FtpClient
158      * @see #isPassiveModeEnabled()
159      */
enablePassiveMode(boolean passive)160     public abstract FtpClient enablePassiveMode(boolean passive);
161 
162     /**
163      * Tests whether passive mode is enabled.
164      *
165      * @return {@code true} if the passive mode has been enabled.
166      * @see #enablePassiveMode(boolean)
167      */
isPassiveModeEnabled()168     public abstract boolean isPassiveModeEnabled();
169 
170     /**
171      * Sets the default timeout value to use when connecting to the server,
172      *
173      * @param timeout the timeout value, in milliseconds, to use for the connect
174      *        operation. A value of zero or less, means use the default timeout.
175      *
176      * @return This FtpClient
177      */
setConnectTimeout(int timeout)178     public abstract FtpClient setConnectTimeout(int timeout);
179 
180     /**
181      * Returns the current default connection timeout value.
182      *
183      * @return the value, in milliseconds, of the current connect timeout.
184      * @see #setConnectTimeout(int)
185      */
getConnectTimeout()186     public abstract int getConnectTimeout();
187 
188     /**
189      * Sets the timeout value to use when reading from the server,
190      *
191      * @param timeout the timeout value, in milliseconds, to use for the read
192      *        operation. A value of zero or less, means use the default timeout.
193      * @return This FtpClient
194      */
setReadTimeout(int timeout)195     public abstract FtpClient setReadTimeout(int timeout);
196 
197     /**
198      * Returns the current read timeout value.
199      *
200      * @return the value, in milliseconds, of the current read timeout.
201      * @see #setReadTimeout(int)
202      */
getReadTimeout()203     public abstract int getReadTimeout();
204 
205     /**
206      * Set the {@code Proxy} to be used for the next connection.
207      * If the client is already connected, it doesn't affect the current
208      * connection. However it is not recommended to change this during a session.
209      *
210      * @param p the {@code Proxy} to use, or {@code null} for no proxy.
211      * @return This FtpClient
212      */
setProxy(Proxy p)213     public abstract FtpClient setProxy(Proxy p);
214 
215     /**
216      * Get the proxy of this FtpClient
217      *
218      * @return the {@code Proxy}, this client is using, or {@code null}
219      * if none is used.
220      * @see #setProxy(Proxy)
221      */
getProxy()222     public abstract Proxy getProxy();
223 
224     /**
225      * Tests whether this client is connected or not to a server.
226      *
227      * @return {@code true} if the client is connected.
228      */
isConnected()229     public abstract boolean isConnected();
230 
231     /**
232      * Connects the {@code FtpClient} to the specified destination server.
233      *
234      * @param dest the address of the destination server
235      * @return this FtpClient
236      * @throws IOException if connection failed.
237      * @throws SecurityException if there is a SecurityManager installed and it
238      * denied the authorization to connect to the destination.
239      * @throws FtpProtocolException
240      */
connect(SocketAddress dest)241     public abstract FtpClient connect(SocketAddress dest) throws FtpProtocolException, IOException;
242 
243     /**
244      * Connects the FtpClient to the specified destination server.
245      *
246      * @param dest the address of the destination server
247      * @param timeout the value, in milliseconds, to use as a connection timeout
248      * @return this FtpClient
249      * @throws IOException if connection failed.
250      * @throws SecurityException if there is a SecurityManager installed and it
251      * denied the authorization to connect to the destination.
252      * @throws FtpProtocolException
253      */
connect(SocketAddress dest, int timeout)254     public abstract FtpClient connect(SocketAddress dest, int timeout) throws FtpProtocolException, IOException;
255 
256     /**
257      * Retrieves the address of the FTP server this client is connected to.
258      *
259      * @return the {@link SocketAddress} of the server, or {@code null} if this
260      * client is not connected yet.
261      */
getServerAddress()262     public abstract SocketAddress getServerAddress();
263 
264     /**
265      * Attempts to log on the server with the specified user name and password.
266      *
267      * @param user The user name
268      * @param password The password for that user
269      * @return this FtpClient
270      * @throws IOException if an error occurred during the transmission
271      * @throws FtpProtocolException if the login was refused by the server
272      */
login(String user, char[] password)273     public abstract FtpClient login(String user, char[] password) throws FtpProtocolException, IOException;
274 
275     /**
276      * Attempts to log on the server with the specified user name, password and
277      * account name.
278      *
279      * @param user The user name
280      * @param password The password for that user.
281      * @param account The account name for that user.
282      * @return this FtpClient
283      * @throws IOException if an error occurs during the transmission.
284      * @throws FtpProtocolException if the login was refused by the server
285      */
login(String user, char[] password, String account)286     public abstract FtpClient login(String user, char[] password, String account) throws FtpProtocolException, IOException;
287 
288     /**
289      * Closes the current connection. Logs out the current user, if any, by
290      * issuing the QUIT command to the server.
291      * This is in effect terminates the current
292      * session and the connection to the server will be closed.
293      * <p>After a close, the client can then be connected to another server
294      * to start an entirely different session.</P>
295      *
296      * @throws IOException if an error occurs during transmission
297      */
close()298     public abstract void close() throws IOException;
299 
300     /**
301      * Checks whether the client is logged in to the server or not.
302      *
303      * @return {@code true} if the client has already completed a login.
304      */
isLoggedIn()305     public abstract boolean isLoggedIn();
306 
307     /**
308      * Changes to a specific directory on a remote FTP server
309      *
310      * @param  remoteDirectory path of the directory to CD to.
311      * @return this FtpClient
312      * @throws IOException if an error occurs during the transmission.
313      * @throws FtpProtocolException if the command was refused by the server
314      */
changeDirectory(String remoteDirectory)315     public abstract FtpClient changeDirectory(String remoteDirectory) throws FtpProtocolException, IOException;
316 
317     /**
318      * Changes to the parent directory, sending the CDUP command to the server.
319      *
320      * @return this FtpClient
321      * @throws IOException if an error occurs during the transmission.
322      * @throws FtpProtocolException if the command was refused by the server
323      */
changeToParentDirectory()324     public abstract FtpClient changeToParentDirectory() throws FtpProtocolException, IOException;
325 
326     /**
327      * Retrieve the server current working directory using the PWD command.
328      *
329      * @return a {@code String} containing the current working directory
330      * @throws IOException if an error occurs during transmission
331      * @throws FtpProtocolException if the command was refused by the server,
332      */
getWorkingDirectory()333     public abstract String getWorkingDirectory() throws FtpProtocolException, IOException;
334 
335     /**
336      * Sets the restart offset to the specified value.  That value will be
337      * sent through a {@code REST} command to server before the next file
338      * transfer and has the effect of resuming a file transfer from the
339      * specified point. After the transfer the restart offset is set back to
340      * zero.
341      *
342      * @param offset the offset in the remote file at which to start the next
343      *        transfer. This must be a value greater than or equal to zero.
344      * @return this FtpClient
345      * @throws IllegalArgumentException if the offset is negative.
346      */
setRestartOffset(long offset)347     public abstract FtpClient setRestartOffset(long offset);
348 
349     /**
350      * Retrieves a file from the ftp server and writes its content to the specified
351      * {@code OutputStream}.
352      * <p>If the restart offset was set, then a {@code REST} command will be
353      * sent before the {@code RETR} in order to restart the tranfer from the specified
354      * offset.</p>
355      * <p>The {@code OutputStream} is not closed by this method at the end
356      * of the transfer. </p>
357      * <p>This method will block until the transfer is complete or an exception
358      * is thrown.</p>
359      *
360      * @param name a {@code String} containing the name of the file to
361      *        retreive from the server.
362      * @param local the {@code OutputStream} the file should be written to.
363      * @return this FtpClient
364      * @throws IOException if the transfer fails.
365      * @throws FtpProtocolException if the command was refused by the server
366      * @see #setRestartOffset(long)
367      */
getFile(String name, OutputStream local)368     public abstract FtpClient getFile(String name, OutputStream local) throws FtpProtocolException, IOException;
369 
370     /**
371      * Retrieves a file from the ftp server, using the {@code RETR} command, and
372      * returns the InputStream from the established data connection.
373      * {@link #completePending()} <b>has</b> to be called once the application
374      * is done reading from the returned stream.
375      * <p>If the restart offset was set, then a {@code REST} command will be
376      * sent before the {@code RETR} in order to restart the tranfer from the specified
377      * offset.</p>
378      *
379      * @param name the name of the remote file
380      * @return the {@link java.io.InputStream} from the data connection
381      * @throws IOException if an error occurred during the transmission.
382      * @throws FtpProtocolException if the command was refused by the server
383      * @see #setRestartOffset(long)
384      */
getFileStream(String name)385     public abstract InputStream getFileStream(String name) throws FtpProtocolException, IOException;
386 
387     /**
388      * Transfers a file from the client to the server (aka a <I>put</I>)
389      * by sending the STOR command, and returns the {@code OutputStream}
390      * from the established data connection.
391      *
392      * A new file is created at the server site if the file specified does
393      * not already exist.
394      *
395      * {@link #completePending()} <b>has</b> to be called once the application
396      * is finished writing to the returned stream.
397      *
398      * @param name the name of the remote file to write.
399      * @return the {@link java.io.OutputStream} from the data connection or
400      *         {@code null} if the command was unsuccessful.
401      * @throws IOException if an error occurred during the transmission.
402      * @throws FtpProtocolException if the command was rejected by the server
403      */
putFileStream(String name)404     public OutputStream putFileStream(String name) throws FtpProtocolException, IOException {
405         return putFileStream(name, false);
406     }
407 
408     /**
409      * Transfers a file from the client to the server (aka a <I>put</I>)
410      * by sending the STOR or STOU command, depending on the
411      * {@code unique} argument, and returns the {@code OutputStream}
412      * from the established data connection.
413      * {@link #completePending()} <b>has</b> to be called once the application
414      * is finished writing to the stream.
415      *
416      * A new file is created at the server site if the file specified does
417      * not already exist.
418      *
419      * If {@code unique} is set to {@code true}, the resultant file
420      * is to be created under a name unique to that directory, meaning
421      * it will not overwrite an existing file, instead the server will
422      * generate a new, unique, file name.
423      * The name of the remote file can be retrieved, after completion of the
424      * transfer, by calling {@link #getLastFileName()}.
425      *
426      * @param name the name of the remote file to write.
427      * @param unique {@code true} if the remote files should be unique,
428      *        in which case the STOU command will be used.
429      * @return the {@link java.io.OutputStream} from the data connection.
430      * @throws IOException if an error occurred during the transmission.
431      * @throws FtpProtocolException if the command was rejected by the server
432      */
putFileStream(String name, boolean unique)433     public abstract OutputStream putFileStream(String name, boolean unique) throws FtpProtocolException, IOException;
434 
435     /**
436      * Transfers a file from the client to the server (aka a <I>put</I>)
437      * by sending the STOR or STOU command, depending on the
438      * {@code unique} argument. The content of the {@code InputStream}
439      * passed in argument is written into the remote file, overwriting any
440      * existing data.
441      *
442      * A new file is created at the server site if the file specified does
443      * not already exist.
444      *
445      * If {@code unique} is set to {@code true}, the resultant file
446      * is to be created under a name unique to that directory, meaning
447      * it will not overwrite an existing file, instead the server will
448      * generate a new, unique, file name.
449      * The name of the remote file can be retrieved, after completion of the
450      * transfer, by calling {@link #getLastFileName()}.
451      *
452      * <p>This method will block until the transfer is complete or an exception
453      * is thrown.</p>
454      *
455      * @param name the name of the remote file to write.
456      * @param local the {@code InputStream} that points to the data to
457      *        transfer.
458      * @return this FtpClient
459      * @throws IOException if an error occurred during the transmission.
460      * @throws FtpProtocolException if the command was rejected by the server
461      */
putFile(String name, InputStream local)462     public FtpClient putFile(String name, InputStream local) throws FtpProtocolException, IOException {
463         return putFile(name, local, false);
464     }
465 
466     /**
467      * Transfers a file from the client to the server (aka a <I>put</I>)
468      * by sending the STOR command. The content of the {@code InputStream}
469      * passed in argument is written into the remote file, overwriting any
470      * existing data.
471      *
472      * A new file is created at the server site if the file specified does
473      * not already exist.
474      *
475      * <p>This method will block until the transfer is complete or an exception
476      * is thrown.</p>
477      *
478      * @param name the name of the remote file to write.
479      * @param local the {@code InputStream} that points to the data to
480      *        transfer.
481      * @param unique {@code true} if the remote file should be unique
482      *        (i.e. not already existing), {@code false} otherwise.
483      * @return this FtpClient
484      * @throws IOException if an error occurred during the transmission.
485      * @throws FtpProtocolException if the command was rejected by the server
486      * @see #getLastFileName()
487      */
putFile(String name, InputStream local, boolean unique)488     public abstract FtpClient putFile(String name, InputStream local, boolean unique) throws FtpProtocolException, IOException;
489 
490     /**
491      * Sends the APPE command to the server in order to transfer a data stream
492      * passed in argument and append it to the content of the specified remote
493      * file.
494      *
495      * <p>This method will block until the transfer is complete or an exception
496      * is thrown.</p>
497      *
498      * @param name A {@code String} containing the name of the remote file
499      *        to append to.
500      * @param local The {@code InputStream} providing access to the data
501      *        to be appended.
502      * @return this FtpClient
503      * @throws IOException if an error occurred during the transmission.
504      * @throws FtpProtocolException if the command was rejected by the server
505      */
appendFile(String name, InputStream local)506     public abstract FtpClient appendFile(String name, InputStream local) throws FtpProtocolException, IOException;
507 
508     /**
509      * Renames a file on the server.
510      *
511      * @param from the name of the file being renamed
512      * @param to the new name for the file
513      * @return this FtpClient
514      * @throws IOException if an error occurred during the transmission.
515      * @throws FtpProtocolException if the command was rejected by the server
516      */
rename(String from, String to)517     public abstract FtpClient rename(String from, String to) throws FtpProtocolException, IOException;
518 
519     /**
520      * Deletes a file on the server.
521      *
522      * @param name a {@code String} containing the name of the file
523      *        to delete.
524      * @return this FtpClient
525      * @throws IOException if an error occurred during the exchange
526      * @throws FtpProtocolException if the command was rejected by the server
527      */
deleteFile(String name)528     public abstract FtpClient deleteFile(String name) throws FtpProtocolException, IOException;
529 
530     /**
531      * Creates a new directory on the server.
532      *
533      * @param name a {@code String} containing the name of the directory
534      *        to create.
535      * @return this FtpClient
536      * @throws IOException if an error occurred during the exchange
537      * @throws FtpProtocolException if the command was rejected by the server
538      */
makeDirectory(String name)539     public abstract FtpClient makeDirectory(String name) throws FtpProtocolException, IOException;
540 
541     /**
542      * Removes a directory on the server.
543      *
544      * @param name a {@code String} containing the name of the directory
545      *        to remove.
546      *
547      * @return this FtpClient
548      * @throws IOException if an error occurred during the exchange.
549      * @throws FtpProtocolException if the command was rejected by the server
550      */
removeDirectory(String name)551     public abstract FtpClient removeDirectory(String name) throws FtpProtocolException, IOException;
552 
553     /**
554      * Sends a No-operation command. It's useful for testing the connection
555      * status or as a <I>keep alive</I> mechanism.
556      *
557      * @return this FtpClient
558      * @throws IOException if an error occurred during the transmission.
559      * @throws FtpProtocolException if the command was rejected by the server
560      */
noop()561     public abstract FtpClient noop() throws FtpProtocolException, IOException;
562 
563     /**
564      * Sends the {@code STAT} command to the server.
565      * This can be used while a data connection is open to get a status
566      * on the current transfer, in that case the parameter should be
567      * {@code null}.
568      * If used between file transfers, it may have a pathname as argument
569      * in which case it will work as the LIST command except no data
570      * connection will be created.
571      *
572      * @param name an optional {@code String} containing the pathname
573      *        the STAT command should apply to.
574      * @return the response from the server
575      * @throws IOException if an error occurred during the transmission.
576      * @throws FtpProtocolException if the command was rejected by the server
577      */
getStatus(String name)578     public abstract String getStatus(String name) throws FtpProtocolException, IOException;
579 
580     /**
581      * Sends the {@code FEAT} command to the server and returns the list of supported
582      * features in the form of strings.
583      *
584      * The features are the supported commands, like AUTH TLS, PROT or PASV.
585      * See the RFCs for a complete list.
586      *
587      * Note that not all FTP servers support that command, in which case
588      * a {@link FtpProtocolException} will be thrown.
589      *
590      * @return a {@code List} of {@code Strings} describing the
591      *         supported additional features
592      * @throws IOException if an error occurs during the transmission.
593      * @throws FtpProtocolException if the command is rejected by the server
594      */
getFeatures()595     public abstract List<String> getFeatures() throws FtpProtocolException, IOException;
596 
597     /**
598      * Sends the {@code ABOR} command to the server.
599      * <p>It tells the server to stop the previous command or transfer. No action
600      * will be taken if the previous command has already been completed.</p>
601      * <p>This doesn't abort the current session, more commands can be issued
602      * after an abort.</p>
603      *
604      * @return this FtpClient
605      * @throws IOException if an error occurred during the transmission.
606      * @throws FtpProtocolException if the command was rejected by the server
607      */
abort()608     public abstract FtpClient abort() throws FtpProtocolException, IOException;
609 
610     /**
611      * Some methods do not wait until completion before returning, so this
612      * method can be called to wait until completion. This is typically the case
613      * with commands that trigger a transfer like {@link #getFileStream(String)}.
614      * So this method should be called before accessing information related to
615      * such a command.
616      * <p>This method will actually block reading on the command channel for a
617      * notification from the server that the command is finished. Such a
618      * notification often carries extra information concerning the completion
619      * of the pending action (e.g. number of bytes transfered).</p>
620      * <p>Note that this will return immediately if no command or action
621      * is pending</p>
622      * <p>It should be also noted that most methods issuing commands to the ftp
623      * server will call this method if a previous command is pending.
624      * <p>Example of use:
625      * <pre>
626      * InputStream in = cl.getFileStream("file");
627      * ...
628      * cl.completePending();
629      * long size = cl.getLastTransferSize();
630      * </pre>
631      * On the other hand, it's not necessary in a case like:
632      * <pre>
633      * InputStream in = cl.getFileStream("file");
634      * // read content
635      * ...
636      * cl.close();
637      * </pre>
638      * <p>Since {@link #close()} will call completePending() if necessary.</p>
639      * @return this FtpClient
640      * @throws IOException if an error occurred during the transfer
641      * @throws FtpProtocolException if the command didn't complete successfully
642      */
completePending()643     public abstract FtpClient completePending() throws FtpProtocolException, IOException;
644 
645     /**
646      * Reinitializes the USER parameters on the FTP server
647      *
648      * @return this FtpClient
649      * @throws IOException if an error occurs during transmission
650      * @throws FtpProtocolException if the command fails
651      */
reInit()652     public abstract FtpClient reInit() throws FtpProtocolException, IOException;
653 
654     /**
655      * Changes the transfer type (binary, ascii, ebcdic) and issue the
656      * proper command (e.g. TYPE A) to the server.
657      *
658      * @param type the {@code TransferType} to use.
659      * @return This FtpClient
660      * @throws IOException if an error occurs during transmission.
661      * @throws FtpProtocolException if the command was rejected by the server
662      */
setType(TransferType type)663     public abstract FtpClient setType(TransferType type) throws FtpProtocolException, IOException;
664 
665     /**
666      * Changes the current transfer type to binary.
667      * This is a convenience method that is equivalent to
668      * {@code setType(TransferType.BINARY)}
669      *
670      * @return This FtpClient
671      * @throws IOException if an error occurs during the transmission.
672      * @throws FtpProtocolException if the command was rejected by the server
673      * @see #setType(TransferType)
674      */
setBinaryType()675     public FtpClient setBinaryType() throws FtpProtocolException, IOException {
676         setType(TransferType.BINARY);
677         return this;
678     }
679 
680     /**
681      * Changes the current transfer type to ascii.
682      * This is a convenience method that is equivalent to
683      * {@code setType(TransferType.ASCII)}
684      *
685      * @return This FtpClient
686      * @throws IOException if an error occurs during the transmission.
687      * @throws FtpProtocolException if the command was rejected by the server
688      * @see #setType(TransferType)
689      */
setAsciiType()690     public FtpClient setAsciiType() throws FtpProtocolException, IOException {
691         setType(TransferType.ASCII);
692         return this;
693     }
694 
695     /**
696      * Issues a {@code LIST} command to the server to get the current directory
697      * listing, and returns the InputStream from the data connection.
698      *
699      * <p>{@link #completePending()} <b>has</b> to be called once the application
700      * is finished reading from the stream.</p>
701      *
702      * @param path the pathname of the directory to list, or {@code null}
703      *        for the current working directory.
704      * @return the {@code InputStream} from the resulting data connection
705      * @throws IOException if an error occurs during the transmission.
706      * @throws FtpProtocolException if the command was rejected by the server
707      * @see #changeDirectory(String)
708      * @see #listFiles(String)
709      */
list(String path)710     public abstract InputStream list(String path) throws FtpProtocolException, IOException;
711 
712     /**
713      * Issues a {@code NLST path} command to server to get the specified directory
714      * content. It differs from {@link #list(String)} method by the fact that
715      * it will only list the file names which would make the parsing of the
716      * somewhat easier.
717      *
718      * <p>{@link #completePending()} <b>has</b> to be called once the application
719      * is finished reading from the stream.</p>
720      *
721      * @param path a {@code String} containing the pathname of the
722      *        directory to list or {@code null} for the current working directory.
723      * @return the {@code InputStream} from the resulting data connection
724      * @throws IOException if an error occurs during the transmission.
725      * @throws FtpProtocolException if the command was rejected by the server
726      */
nameList(String path)727     public abstract InputStream nameList(String path) throws FtpProtocolException, IOException;
728 
729     /**
730      * Issues the {@code SIZE [path]} command to the server to get the size of a
731      * specific file on the server.
732      * Note that this command may not be supported by the server. In which
733      * case -1 will be returned.
734      *
735      * @param path a {@code String} containing the pathname of the
736      *        file.
737      * @return a {@code long} containing the size of the file or -1 if
738      *         the server returned an error, which can be checked with
739      *         {@link #getLastReplyCode()}.
740      * @throws IOException if an error occurs during the transmission.
741      * @throws FtpProtocolException if the command was rejected by the server
742      */
getSize(String path)743     public abstract long getSize(String path) throws FtpProtocolException, IOException;
744 
745     /**
746      * Issues the {@code MDTM [path]} command to the server to get the modification
747      * time of a specific file on the server.
748      * Note that this command may not be supported by the server, in which
749      * case {@code null} will be returned.
750      *
751      * @param path a {@code String} containing the pathname of the file.
752      * @return a {@code Date} representing the last modification time
753      *         or {@code null} if the server returned an error, which
754      *         can be checked with {@link #getLastReplyCode()}.
755      * @throws IOException if an error occurs during the transmission.
756      * @throws FtpProtocolException if the command was rejected by the server
757      */
getLastModified(String path)758     public abstract Date getLastModified(String path) throws FtpProtocolException, IOException;
759 
760     /**
761      * Sets the parser used to handle the directory output to the specified
762      * one. By default the parser is set to one that can handle most FTP
763      * servers output (Unix base mostly). However it may be necessary for
764      * and application to provide its own parser due to some uncommon
765      * output format.
766      *
767      * @param p The {@code FtpDirParser} to use.
768      * @return this FtpClient
769      * @see #listFiles(String)
770      */
setDirParser(FtpDirParser p)771     public abstract FtpClient setDirParser(FtpDirParser p);
772 
773     /**
774      * Issues a {@code MLSD} command to the server to get the specified directory
775      * listing and applies the internal parser to create an Iterator of
776      * {@link java.net.FtpDirEntry}. Note that the Iterator returned is also a
777      * {@link java.io.Closeable}.
778      * <p>If the server doesn't support the MLSD command, the LIST command is used
779      * instead and the parser set by {@link #setDirParser(java.net.FtpDirParser) }
780      * is used instead.</p>
781      *
782      * {@link #completePending()} <b>has</b> to be called once the application
783      * is finished iterating through the files.
784      *
785      * @param path the pathname of the directory to list or {@code null}
786      *        for the current working directoty.
787      * @return a {@code Iterator} of files or {@code null} if the
788      *         command failed.
789      * @throws IOException if an error occurred during the transmission
790      * @see #setDirParser(FtpDirParser)
791      * @see #changeDirectory(String)
792      * @throws FtpProtocolException if the command was rejected by the server
793      */
listFiles(String path)794     public abstract Iterator<FtpDirEntry> listFiles(String path) throws FtpProtocolException, IOException;
795 
796     /**
797      * Attempts to use Kerberos GSSAPI as an authentication mechanism with the
798      * ftp server. This will issue an {@code AUTH GSSAPI} command, and if
799      * it is accepted by the server, will followup with {@code ADAT}
800      * command to exchange the various tokens until authentication is
801      * successful. This conforms to Appendix I of RFC 2228.
802      *
803      * @return this FtpClient
804      * @throws IOException if an error occurs during the transmission.
805      * @throws FtpProtocolException if the command was rejected by the server
806      */
useKerberos()807     public abstract FtpClient useKerberos() throws FtpProtocolException, IOException;
808 
809     /**
810      * Returns the Welcome string the server sent during initial connection.
811      *
812      * @return a {@code String} containing the message the server
813      *         returned during connection or {@code null}.
814      */
getWelcomeMsg()815     public abstract String getWelcomeMsg();
816 
817     /**
818      * Returns the last reply code sent by the server.
819      *
820      * @return the lastReplyCode or {@code null} if none were received yet.
821      */
getLastReplyCode()822     public abstract FtpReplyCode getLastReplyCode();
823 
824     /**
825      * Returns the last response string sent by the server.
826      *
827      * @return the message string, which can be quite long, last returned
828      *         by the server, or {@code null} if no response were received yet.
829      */
getLastResponseString()830     public abstract String getLastResponseString();
831 
832     /**
833      * Returns, when available, the size of the latest started transfer.
834      * This is retreived by parsing the response string received as an initial
835      * response to a {@code RETR} or similar request.
836      *
837      * @return the size of the latest transfer or -1 if either there was no
838      *         transfer or the information was unavailable.
839      */
getLastTransferSize()840     public abstract long getLastTransferSize();
841 
842     /**
843      * Returns, when available, the remote name of the last transfered file.
844      * This is mainly useful for "put" operation when the unique flag was
845      * set since it allows to recover the unique file name created on the
846      * server which may be different from the one submitted with the command.
847      *
848      * @return the name the latest transfered file remote name, or
849      *         {@code null} if that information is unavailable.
850      */
getLastFileName()851     public abstract String getLastFileName();
852 
853     /**
854      * Attempts to switch to a secure, encrypted connection. This is done by
855      * sending the {@code AUTH TLS} command.
856      * <p>See <a href="http://www.ietf.org/rfc/rfc4217.txt">RFC 4217</a></p>
857      * If successful this will establish a secure command channel with the
858      * server, it will also make it so that all other transfers (e.g. a RETR
859      * command) will be done over an encrypted channel as well unless a
860      * {@link #reInit()} command or a {@link #endSecureSession()} command is issued.
861      * <p>This method should be called after a successful {@link #connect(java.net.InetSocketAddress) }
862      * but before calling {@link #login(java.lang.String, char[]) }.</p>
863      *
864      * @return this FtpCLient
865      * @throws IOException if an error occurred during the transmission.
866      * @throws FtpProtocolException if the command was rejected by the server
867      * @see #endSecureSession()
868      */
startSecureSession()869     public abstract FtpClient startSecureSession() throws FtpProtocolException, IOException;
870 
871     /**
872      * Sends a {@code CCC} command followed by a {@code PROT C}
873      * command to the server terminating an encrypted session and reverting
874      * back to a non encrypted transmission.
875      *
876      * @return this FtpClient
877      * @throws IOException if an error occurred during transmission.
878      * @throws FtpProtocolException if the command was rejected by the server
879      * @see #startSecureSession()
880      */
endSecureSession()881     public abstract FtpClient endSecureSession() throws FtpProtocolException, IOException;
882 
883     /**
884      * Sends the "Allocate" ({@code ALLO}) command to the server telling it to
885      * pre-allocate the specified number of bytes for the next transfer.
886      *
887      * @param size The number of bytes to allocate.
888      * @return this FtpClient
889      * @throws IOException if an error occurred during the transmission.
890      * @throws FtpProtocolException if the command was rejected by the server
891      */
allocate(long size)892     public abstract FtpClient allocate(long size) throws FtpProtocolException, IOException;
893 
894     /**
895      * Sends the "Structure Mount" ({@code SMNT}) command to the server. This let the
896      * user mount a different file system data structure without altering his
897      * login or accounting information.
898      *
899      * @param struct a {@code String} containing the name of the
900      *        structure to mount.
901      * @return this FtpClient
902      * @throws IOException if an error occurred during the transmission.
903      * @throws FtpProtocolException if the command was rejected by the server
904      */
structureMount(String struct)905     public abstract FtpClient structureMount(String struct) throws FtpProtocolException, IOException;
906 
907     /**
908      * Sends a System ({@code SYST}) command to the server and returns the String
909      * sent back by the server describing the operating system at the
910      * server.
911      *
912      * @return a {@code String} describing the OS, or {@code null}
913      *         if the operation was not successful.
914      * @throws IOException if an error occurred during the transmission.
915      * @throws FtpProtocolException if the command was rejected by the server
916      */
getSystem()917     public abstract String getSystem() throws FtpProtocolException, IOException;
918 
919     /**
920      * Sends the {@code HELP} command to the server, with an optional command, like
921      * SITE, and returns the text sent back by the server.
922      *
923      * @param cmd the command for which the help is requested or
924      *        {@code null} for the general help
925      * @return a {@code String} containing the text sent back by the
926      *         server, or {@code null} if the command failed.
927      * @throws IOException if an error occurred during transmission
928      * @throws FtpProtocolException if the command was rejected by the server
929      */
getHelp(String cmd)930     public abstract String getHelp(String cmd) throws FtpProtocolException, IOException;
931 
932     /**
933      * Sends the {@code SITE} command to the server. This is used by the server
934      * to provide services specific to his system that are essential
935      * to file transfer.
936      *
937      * @param cmd the command to be sent.
938      * @return this FtpClient
939      * @throws IOException if an error occurred during transmission
940      * @throws FtpProtocolException if the command was rejected by the server
941      */
siteCmd(String cmd)942     public abstract FtpClient siteCmd(String cmd) throws FtpProtocolException, IOException;
943 }
944