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<FtpDirEntry> 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