1   /* ClientFTP.java
2    *
3    * $Id: ClientFTP.java 4573 2006-08-31 22:31:23Z paul_jack $
4    *
5    * Created on Jun 5, 2003
6    *
7    * Copyright (C) 2003 Internet Archive.
8    *
9    * This file is part of the Heritrix web crawler (crawler.archive.org).
10   *
11   * Heritrix is free software; you can redistribute it and/or modify
12   * it under the terms of the GNU Lesser Public License as published by
13   * the Free Software Foundation; either version 2.1 of the License, or
14   * any later version.
15   *
16   * Heritrix is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU Lesser Public License for more details.
20   *
21   * You should have received a copy of the GNU Lesser Public License
22   * along with Heritrix; if not, write to the Free Software
23   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24   */
25  package org.archive.net;
26  
27  
28  import java.io.IOException;
29  import java.net.Socket;
30  
31  import org.apache.commons.net.ftp.FTPClient;
32  import org.apache.commons.net.ftp.FTPReply;
33  
34  
35  /***
36   * Client for FTP operations.  This class is necessary only because the
37   * {@link #_openDataConnection_(int, String)} method is protected in 
38   * the superclass, and we need to call it directly to handle directory
39   * listings.  (The code that provides directory listings in the 
40   * superclass doesn't scale:  It reads the entire directory into
41   * an in-memory list).
42   * 
43   * <p>Additionally, "strict" methods are provided for the other operations
44   * we use.  Maddeningly, the superclass never raises exceptions.  If an 
45   * FTP operation fails, then the superclass methods generally return false.
46   * A developer then needs to check the {@link FTP#getReplyCode()}
47   * method to see what actually went wrong.  The "strict" methods provided
48   * by this class invoke the superclass method, check if the success flag
49   * is false, and then raise an {@link FTPException} with the value of
50   * {@link FTP#getReplyCode()}.
51   *
52   * @author pjack
53   */
54  public class ClientFTP extends FTPClient {
55      
56      
57      /***
58       * Constructs a new <code>ClientFTP</code>.
59       */
60      public ClientFTP() {
61      }
62      
63  
64      /***
65       * Connects to the FTP server at the given host and port.
66       * 
67       * @param host    the host of the FTP server to connect to
68       * @param port    the port the FTP server listens on
69       * @throws IOException  if the connection cannot be made due to IO error
70       * @throws FTPException  if the server refuses the connection
71       */
72      public void connectStrict(String host, int port) throws IOException {
73          this.connect(host, port);
74          int reply = this.getReplyCode();
75          if (!FTPReply.isPositiveCompletion(reply)) {
76              throw new FTPException(reply);
77          }
78      }
79  
80      
81      /***
82       * Login to the FTP server with the given username and password.
83       * 
84       * @param user   the username to login under
85       * @param pass   the password to use
86       * @throws IOException   if a network error occurs
87       * @throws FTPException  if the login is rejected by the server
88       * @throws org.apache.commons.net.ftp.FTPConnectionClosedException   
89       *   if the FTP server prematurely closes the connection (for 
90       *   instance, if the client was idle for too long)
91       */
92      public void loginStrict(String user, String pass) throws IOException {
93          boolean r = this.login(user, pass);
94          if (!r) {
95              throw new FTPException(this.getReplyCode());
96          }
97      }
98  
99      
100     /***
101      * Tells the FTP server to send binary files.
102      *
103      * @throws IOException   if a network error occurs
104      * @throws FTPException  if the server rejects the command
105      * @throws org.apache.commons.net.ftp.FTPConnectionClosedException   
106      *   if the FTP server prematurely closes the connection (for 
107      *   instance, if the client was idle for too long)
108      */
109     public void setBinary() throws IOException {
110         boolean r = super.setFileType(BINARY_FILE_TYPE);
111         if (!r) {
112             throw new FTPException(getReplyCode());
113         }
114     }
115 
116 
117     /***
118      * Opens a data connection. 
119      * 
120      * @param command  the data command (eg, RETR or LIST)
121      * @param path     the path of the file to retrieve
122      * @return  the socket to read data from
123      * @throws  IOException  if a network error occurs
124      * @throws  FTPException  if a protocol error occurs
125      */
126     public Socket openDataConnection(int command, String path)
127     throws IOException {
128         Socket socket = _openDataConnection_(command, path);
129         if (socket == null) {
130             throw new FTPException(this.getReplyCode());
131         }
132         return socket;
133     }
134 
135     
136 }