Home | History | Annotate | Download | only in ftp
      1 /*
      2  * Copyright (c) 2009, 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 (at) 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      */
     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      */
     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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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 occured during the transmission
    271      * @throws FtpProtocolException if the login was refused by the server
    272      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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 occured during the transmission.
    382      * @throws FtpProtocolException if the command was refused by the server
    383      * @see #setRestartOffset(long)
    384      */
    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 occured during the transmission.
    402      * @throws FtpProtocolException if the command was rejected by the server
    403      */
    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 occured during the transmission.
    431      * @throws FtpProtocolException if the command was rejected by the server
    432      */
    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 occured during the transmission.
    460      * @throws FtpProtocolException if the command was rejected by the server
    461      */
    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 occured during the transmission.
    485      * @throws FtpProtocolException if the command was rejected by the server
    486      * @see #getLastFileName()
    487      */
    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 occured during the transmission.
    504      * @throws FtpProtocolException if the command was rejected by the server
    505      */
    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 occured during the transmission.
    515      * @throws FtpProtocolException if the command was rejected by the server
    516      */
    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 occured during the exchange
    526      * @throws FtpProtocolException if the command was rejected by the server
    527      */
    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 occured during the exchange
    537      * @throws FtpProtocolException if the command was rejected by the server
    538      */
    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 occured during the exchange.
    549      * @throws FtpProtocolException if the command was rejected by the server
    550      */
    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 occured during the transmission.
    559      * @throws FtpProtocolException if the command was rejected by the server
    560      */
    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 occured during the transmission.
    576      * @throws FtpProtocolException if the command was rejected by the server
    577      */
    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      */
    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 occured during the transmission.
    606      * @throws FtpProtocolException if the command was rejected by the server
    607      */
    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 occured during the transfer
    641      * @throws FtpProtocolException if the command didn't complete successfully
    642      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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 occured during the transmission
    790      * @see #setDirParser(FtpDirParser)
    791      * @see #changeDirectory(String)
    792      * @throws FtpProtocolException if the command was rejected by the server
    793      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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 occured during the transmission.
    866      * @throws FtpProtocolException if the command was rejected by the server
    867      * @see #endSecureSession()
    868      */
    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 occured during transmission.
    878      * @throws FtpProtocolException if the command was rejected by the server
    879      * @see #startSecureSession()
    880      */
    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 occured during the transmission.
    890      * @throws FtpProtocolException if the command was rejected by the server
    891      */
    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 occured during the transmission.
    903      * @throws FtpProtocolException if the command was rejected by the server
    904      */
    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 occured during the transmission.
    915      * @throws FtpProtocolException if the command was rejected by the server
    916      */
    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 occured during transmission
    928      * @throws FtpProtocolException if the command was rejected by the server
    929      */
    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 occured during transmission
    940      * @throws FtpProtocolException if the command was rejected by the server
    941      */
    942     public abstract FtpClient siteCmd(String cmd) throws FtpProtocolException, IOException;
    943 }
    944