You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by br...@apache.org on 2002/04/03 06:38:40 UTC

cvs commit: jakarta-commons-sandbox/net/src/java/org/apache/commons/net/ftp DefaultFTPFileListParser.java FTP.java FTPClient.java FTPCommand.java FTPConnectionClosedException.java FTPFile.java FTPFileListParser.java FTPReply.java

brekke      02/04/02 20:38:40

  Added:       net/src/java/org/apache/commons/net/ftp
                        DefaultFTPFileListParser.java FTP.java
                        FTPClient.java FTPCommand.java
                        FTPConnectionClosedException.java FTPFile.java
                        FTPFileListParser.java FTPReply.java
  Log:
  Moving com.oroinc.net.ftp to org.apache.commons.net.ftp
  
  Revision  Changes    Path
  1.1                  jakarta-commons-sandbox/net/src/java/org/apache/commons/net/ftp/DefaultFTPFileListParser.java
  
  Index: DefaultFTPFileListParser.java
  ===================================================================
  package org.apache.commons.net.ftp;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Commons" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  import java.io.*;
  import java.util.*;
  
  /***
   * DefaultFTPFileListParser is the default implementation of
   * <a href="org.apache.commons.net.ftp.FTPFileListParser.html"> FTPFileListParser </a>
   * used by <a href="org.apache.commons.net.ftp.FTPClient.html"> FTPClient </a>
   * to parse file listings.
   * Sometimes you will want to parse unusual listing formats, in which
   * case you would create your own implementation of FTPFileListParser and
   * if necessary, subclass FTPFile.
   * <p>
   * <p>
   * @author Daniel F. Savarese
   * @see FTPFileListParser
   * @see FTPFile
   * @see FTPClient#listFiles
   ***/
  
  public final class DefaultFTPFileListParser implements FTPFileListParser {
  
  
    // end is one beyond end
    private int __charArrayToInt(char[] arr, int start, int end) {
      int value = 0, decimal;
      decimal = 1;
      while(end-- > start) {
        value+=(decimal*(arr[end] - '0'));
        decimal*=10;
      }
      return value;
    }
  
    private long __charArrayToLong(char[] arr, int start, int end) {
      long value = 0, decimal;
      decimal = 1;
      while(end-- > start) {
        value+=(decimal*(arr[end] - '0'));
        decimal*=10;
      }
      return value;
    }
  
    private int __skipWhitespace(char[] cToken, int start) {
      while(start < cToken.length && Character.isWhitespace(cToken[start]))
        ++start;
      return start;
    }
  
    private int __skipDigits(char[] cToken, int start) {
      while(start < cToken.length && Character.isDigit(cToken[start]))
        ++start;
      return start;
    }
  
    private int __skipNonWhitespace(char[] cToken, int start) {
      while(start < cToken.length && !Character.isWhitespace(cToken[start]))
        ++start;
      return start;
    }
  
    private int __skipNonWhitespaceToLower(char[] cToken, int start) {
      while(start < cToken.length && !Character.isWhitespace(cToken[start])){
        cToken[start] = Character.toLowerCase(cToken[start]);
        ++start;
      }
      return start;
    }
  
  
    /***
     * Parses an FTP server listing entry (a single line) and returns an
     * FTPFile instance with the resulting information.  If the entry could
     * not be parsed, returns null.
     * <p>
     * @param entry  A single line of an FTP server listing with the
     *                 end of line truncated.
     * @return An FTPFile instance representing the file information.  null if
     *         the entry could be parsed, returns null.
     ***/
    public FTPFile parseFTPEntry(String entry) {
      int access, start, end, type, month, year, hour, minutes;
      boolean isDevice;
      Calendar date;
      StringTokenizer tokenizer;
      String sToken;
      char cToken[];
      FTPFile file;
  
      try {
        cToken = entry.toCharArray();
  
        file   = new FTPFile();
        file.setRawListing(entry);
  
        isDevice = (cToken[0] == 'b' || cToken[0] == 'c');
  
        switch(cToken[0]) {
        case 'd': type = FTPFile.DIRECTORY_TYPE; break;
        case 'l': type = FTPFile.SYMBOLIC_LINK_TYPE; break;
        default:  type = FTPFile.FILE_TYPE; break;
        }
  
        file.setType(type);
  
        for(access = 0, start=1; access < 3; access++) {
  	// We use != '-' so we avoid having to check for suid and sticky bits
  	file.setPermission(access, FTPFile.READ_PERMISSION,
  			   (cToken[start++] != '-'));
  	file.setPermission(access, FTPFile.WRITE_PERMISSION,
  			   (cToken[start++] != '-'));
  	file.setPermission(access, FTPFile.EXECUTE_PERMISSION,
  			   (cToken[start++] != '-'));
        }
  
        start = __skipWhitespace(cToken, start);
        end = __skipDigits(cToken, start);
        file.setHardLinkCount(__charArrayToInt(cToken, start, end));
  
        start = __skipWhitespace(cToken, end);
        end   = __skipNonWhitespace(cToken, start);
        // Get user and group
        file.setUser(new String(cToken, start, end - start));
  
        start = __skipWhitespace(cToken, end);
        end   = __skipNonWhitespace(cToken, start);
        file.setGroup(new String(cToken, start, end - start));
      
        // Get size, if block or character device, set size to zero and skip
        // next two tokens.
        if(isDevice) {
  	start = __skipWhitespace(cToken, end);
  	end   = __skipNonWhitespace(cToken, start);
  	start = __skipWhitespace(cToken, end);
  	end   = __skipNonWhitespace(cToken, start);
  	// Don't explicitly set size because it is zero by default
        } else {
  	start = __skipWhitespace(cToken, end);
  	end   = __skipDigits(cToken, start);
  	file.setSize(__charArrayToLong(cToken, start, end));
        }
  
        start = __skipWhitespace(cToken, end);
        end   = __skipNonWhitespaceToLower(cToken, start);
  
        // Get month
        switch(cToken[start]) {
        case 'a':
  	if(cToken[end - 1] == 'r')
  	  month = 3;
  	else
  	  month = 7;
  	break;
        case 'd':	month = 11; break;
        case 'f': month = 1; break;
        case 'j':
  	if(cToken[end - 1] == 'l')
  	  month = 6;
  	else if(cToken[start + 1] == 'a')
  	  month = 0;
  	else
  	  month = 5;
  	break;
        case 'm':
  	if(cToken[end - 1] == 'y')
  	  month = 4;
  	else
  	  month = 2;
  	break;
        case 'n': month = 10; break;
        case 'o': month = 9; break;
        case 's': month = 8; break;
        default:	month = 0; break;
        }
  
        // Get day, and store in access
        start = __skipWhitespace(cToken, end);
        end   = __skipDigits(cToken, start);
        access = __charArrayToInt(cToken, start, end);
  
        start = __skipWhitespace(cToken, end);
        end   = __skipDigits(cToken, start);
  
        date = Calendar.getInstance();
  
        try {
  	// If token contains a :, it must be a time, otherwise a year
  	if(cToken[end] == ':') {
  	  year  = date.get(Calendar.YEAR);
  	  hour  = date.get(Calendar.MONTH);
  	  if(hour < month)
  	    --year;
  	  hour = __charArrayToInt(cToken, start, end);
  	  start = end + 1;
  	  end   = __skipDigits(cToken, start);
  	  minutes = __charArrayToInt(cToken, start, end);
  	} else {
  	  // Have to set minutes or compiler will complain not initialized
  	  hour = minutes = -1;
  	  year = __charArrayToInt(cToken, start, end);
  	}
  
  	date.clear();
  	date.set(Calendar.YEAR, year);
  	date.set(Calendar.MONTH, month);
  	date.set(Calendar.DATE, access);
  
  	if(hour != -1) {
  	  date.set(Calendar.HOUR, hour);
  	  date.set(Calendar.MINUTE, minutes);
  	}
  
        } catch(IllegalArgumentException e) {
  	// Do nothing
        }
  
        file.setTimestamp(date);
  
        // This is dangerous, but we're going to assume there is only one
        // space after the date.  Most servers seem to use that format and
        // we need to be able to preserve leading spacesin filenames.
        //start = __skipWhitespace(cToken, end);
        start = end + 1;
        end   = __skipNonWhitespace(cToken, start);
  
        if(end >= cToken.length) {
  	file.setName(new String(cToken, start, end - start));
  	return file;
        }
  
        // Now we have to deal with the possibilities of symbolic links and
        // filenames with spaces.  The filename and/or link may contain
        // spaces, numbers, or appear like the date entry, group, etc.,
  
        sToken = new String(cToken, start, cToken.length - start);
  
        if(type == FTPFile.SYMBOLIC_LINK_TYPE) {
  	end = sToken.indexOf(" -> ");
  	// Give up if no link indicator is present
  	if(end == -1) {
  	  file.setName(sToken);
  	  return file;
  	}
  
  	file.setName(sToken.substring(0, end));
  	file.setLink(sToken.substring(end + 4));
  	return file;
        }
  
        // For other cases, just take the entire token
  
        file.setName(sToken);
      } catch(ArrayIndexOutOfBoundsException e) {
        return null;
      } catch(StringIndexOutOfBoundsException e) {
        return null;
      }
  
      return file;
    }
  
  
    /***
     * Parses an FTP server file listing and converts it into a usable format
     * in the form of an array of <code> FTPFile </code> instances.  If the
     * file list contains no files, <code> null </code> is returned, otherwise
     * an array of <code> FTPFile </code> instances representing the files in 
     * the directory is returned.
     * <p>
     * @param listStream The InputStream from which the file list should be
     *        read.
     * @return The list of file information contained in the given path.  null
     *     if the list could not be obtained or if there are no files in
     *     the directory.
     * @exception IOException  If an I/O error occurs reading the listStream.
     ***/
    public FTPFile[] parseFileList(InputStream listStream) throws IOException {
      String line;
      Vector results;
      BufferedReader reader;
      FTPFile entry;
  
      reader = new BufferedReader(new InputStreamReader(listStream));
  
      if((line = reader.readLine()) == null) {
        results = null;
      } else {
        results = new Vector();
  
        // This is to handle a line at the beginning of the listing
        // that says "total xx" or "Gemstat xx" or something else.
        if(line.toLowerCase().startsWith("total"))
  	line = reader.readLine();
        else {
  	if((entry = parseFTPEntry(line)) != null)
  	  results.addElement(entry);
  	line = reader.readLine();
        }
  
        while(line != null) {
  	if(line.length() == 0 || (entry = parseFTPEntry(line)) == null) {
  	  results = null;
  	  break;
  	}
  	results.addElement(entry);
  	line = reader.readLine();
        }
      }
  
      // Finish reading from stream just in case
      if(line != null)
        while((line = reader.readLine()) != null);
  
      reader.close();
  
      if(results != null) {
        FTPFile[] result;
  
        result = new FTPFile[results.size()];
        if(result.length > 0)
  	results.copyInto(result);
        return result;
      }
  
      return null;
    }
  
  } 
  
  
  
  1.1                  jakarta-commons-sandbox/net/src/java/org/apache/commons/net/ftp/FTP.java
  
  Index: FTP.java
  ===================================================================
  package org.apache.commons.net.ftp;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Commons" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  import java.net.*;
  import java.io.*;
  import java.util.*;
  
  import org.apache.commons.net.*;
  import org.apache.commons.net.telnet.*;
  
  /***
   * FTP provides the basic the functionality necessary to implement your
   * own FTP client.  It extends org.apache.commons.net.TelnetClient
   * simply because it saves the writing of extra code to handle the FTP
   * control connection which always remains open during an FTP session and
   * uses the Telnet protocol.  Aggregation would require writing new
   * wrapper methods and wouldn't leverage the functionality already
   * present in org.apache.commons.net.SocketClient.
   * <p>
   * To derive the full benefits of the FTP class requires some knowledge
   * of the FTP protocol defined in RFC 959.  However, there is no reason
   * why you should have to use the FTP class.  The
   * <a href="org.apache.commons.net.ftp.FTPClient.html"> FTPClient </a> class,
   * derived from FTP,
   * implements all the functionality required of an FTP client.  The
   * FTP class is made public to provide access to various FTP constants
   * and to make it easier for adventurous programmers (or those with
   * special needs) to interact with the FTP protocol and implement their
   * own clients.  A set of methods with names corresponding to the FTP
   * command names are provided to facilitate this interaction.
   * <p>
   * You should keep in mind that the FTP server may choose to prematurely
   * close a connection if the client has been idle for longer than a
   * given time period (usually 900 seconds).  The FTP class will detect a
   * premature FTP server connection closing when it receives a
   * <a href="org.apache.commons.net.ftp.FTPReply.html#SERVICE_NOT_AVAILABLE">
   * FTPReply.SERVICE_NOT_AVAILABLE </a> response to a command.
   * When that occurs, the FTP class method encountering that reply will throw
   * an <a href="org.apache.commons.net.ftp.FTPConnectionClosedException.html">
   * FTPConnectionClosedException </a>.  <code>FTPConectionClosedException</code>
   * is a subclass of <code> IOException </code> and therefore need not be
   * caught separately, but if you are going to catch it separately, its
   * catch block must appear before the more general <code> IOException </code>
   * catch block.  When you encounter an
   * <a href="org.apache.commons.net.ftp.FTPConnectionClosedException.html">
   * FTPConnectionClosedException </a>, you must disconnect the connection with
   * <a href="#disconnect"> disconnect() </a> to properly clean up the
   * system resources used by FTP.  Before disconnecting, you may check the
   * last reply code and text with
   * <a href="#getReplyCode"> getReplyCode </a>,
   * <a href="#getReplyString"> getReplyString </a>,
   * and <a href="#getReplyStrings"> getReplyStrings</a>.
   * You may avoid server disconnections while the client is idle by
   * periodicaly sending NOOP commands to the server.
   * <p>
   * Rather than list it separately for each method, we mention here that
   * every method communicating with the server and throwing an IOException
   * can also throw a 
   * <a href="org.apache.commons.net.MalformedServerReplyException.html">
   * MalformedServerReplyException </a>, which is a subclass
   * of IOException.  A MalformedServerReplyException will be thrown when
   * the reply received from the server deviates enough from the protocol 
   * specification that it cannot be interpreted in a useful manner despite
   * attempts to be as lenient as possible.
   * <p>
   * <p>
   * @author Daniel F. Savarese
   * @see FTPClient
   * @see FTPConnectionClosedException
   * @see org.apache.commons.net.MalformedServerReplyException
   ***/
  
  public class FTP extends TelnetClient {
    /*** The default FTP data port (20). ***/
    public static final int DEFAULT_DATA_PORT = 20;
    /*** The default FTP control port (21). ***/
    public static final int DEFAULT_PORT      = 21;
  
    /***
     * A constant used to indicate the file(s) being transfered should
     * be treated as ASCII.  This is the default file type.  All constants
     * ending in <code>FILE_TYPE</code> are used to indicate file types.
     ***/
    public static final int ASCII_FILE_TYPE  = 0;
  
    /***
     * A constant used to indicate the file(s) being transfered should
     * be treated as EBCDIC.  Note however that there are several different
     * EBCDIC formats.  All constants ending in <code>FILE_TYPE</code>
     * are used to indicate file types.
     ***/
    public static final int EBCDIC_FILE_TYPE = 1;
  
    /***
     * A constant used to indicate the file(s) being transfered should
     * be treated as a binary image, i.e., no translations should be
     * performed.  All constants ending in <code>FILE_TYPE</code> are used to
     * indicate file types.
     ***/
    public static final int IMAGE_FILE_TYPE  = 2;
  
    /***
     * A constant used to indicate the file(s) being transfered should
     * be treated as a binary image, i.e., no translations should be
     * performed.  All constants ending in <code>FILE_TYPE</code> are used to
     * indicate file types.
     ***/
    public static final int BINARY_FILE_TYPE = 2;
  
    /***
     * A constant used to indicate the file(s) being transfered should
     * be treated as a local type.  All constants ending in
     * <code>FILE_TYPE</code> are used to indicate file types.
     ***/
    public static final int LOCAL_FILE_TYPE  = 3;
  
    /***
     * A constant used for text files to indicate a non-print text format.
     * This is the default format.
     * All constants ending in <code>TEXT_FORMAT</code> are used to indicate
     * text formatting for text transfers (both ASCII and EBCDIC).
     ***/
    public static final int NON_PRINT_TEXT_FORMAT        = 4;
  
    /***
     * A constant used to indicate a text file contains format vertical format
     * control characters.
     * All constants ending in <code>TEXT_FORMAT</code> are used to indicate
     * text formatting for text transfers (both ASCII and EBCDIC).
     ***/
    public static final int TELNET_TEXT_FORMAT           = 5;
  
    /***
     * A constant used to indicate a text file contains ASA vertical format
     * control characters.
     * All constants ending in <code>TEXT_FORMAT</code> are used to indicate
     * text formatting for text transfers (both ASCII and EBCDIC).
     ***/
    public static final int CARRIAGE_CONTROL_TEXT_FORMAT = 6;
  
    /***
     * A constant used to indicate a file is to be treated as a continuous
     * sequence of bytes.  This is the default structure.  All constants ending
     * in <code>_STRUCTURE</code> are used to indicate file structure for
     * file transfers.
     ***/
    public static final int FILE_STRUCTURE            = 7;
  
    /***
     * A constant used to indicate a file is to be treated as a sequence
     * of records.  All constants ending in <code>_STRUCTURE</code>
     * are used to indicate file structure for file transfers.
     ***/
    public static final int RECORD_STRUCTURE          = 8;
  
    /***
     * A constant used to indicate a file is to be treated as a set of
     * independent indexed pages.  All constants ending in
     * <code>_STRUCTURE</code> are used to indicate file structure for file
     * transfers.
     ***/
    public static final int PAGE_STRUCTURE            = 9;
  
    /***
     * A constant used to indicate a file is to be transfered as a stream
     * of bytes.  This is the default transfer mode.  All constants ending
     * in <code>TRANSFER_MODE</code> are used to indicate file transfer
     * modes.
     ***/
    public static final int STREAM_TRANSFER_MODE      = 10;
  
    /***
     * A constant used to indicate a file is to be transfered as a series
     * of blocks.  All constants ending in <code>TRANSFER_MODE</code> are used
     * to indicate file transfer modes.
     ***/
    public static final int BLOCK_TRANSFER_MODE       = 11;
  
    /***
     * A constant used to indicate a file is to be transfered as FTP
     * compressed data.  All constants ending in <code>TRANSFER_MODE</code>
     * are used to indicate file transfer modes.
     ***/
    public static final int COMPRESSED_TRANSFER_MODE  = 12;
  
    private static final String __modes = "ABILNTCFRPSBC";
  
    private StringBuffer __commandBuffer;
  
    BufferedReader _controlInput;
    BufferedWriter _controlOutput;
    int _replyCode;
    Vector  _replyLines;
    boolean _newReplyString;
    String  _replyString;
  
    /***
     * A ProtocolCommandSupport object used to manage the registering of
     * ProtocolCommandListeners and te firing of ProtocolCommandEvents.
     ***/
    protected ProtocolCommandSupport _commandSupport_;
  
    /***
     * The default FTP constructor.  Sets the default port to
     * <code>DEFAULT_PORT</code> and initializes internal data structures
     * for saving FTP reply information.
     ***/
    public FTP() {
      setDefaultPort(DEFAULT_PORT);
      __commandBuffer = new StringBuffer();
      _replyLines     = new Vector();
      _newReplyString = false;
      _replyString    = null;
      _commandSupport_ = new ProtocolCommandSupport(this);
    }
  
    private void __getReply() throws IOException {
      int length;
      String line, code;
  
      _newReplyString = true;
      _replyLines.setSize(0);
  
      line = _controlInput.readLine();
  
      if(line == null)
        throw new FTPConnectionClosedException(
  		     "Connection closed without indication.");
  
      // In case we run into an anomaly we don't want fatal index exceptions
      // to be thrown.
      length = line.length();
      if(length < 3)
        throw new MalformedServerReplyException(
  				      "Truncated server reply: " + line);
  
      try {
        _replyCode = Integer.parseInt(code = line.substring(0, 3));
      } catch(NumberFormatException e) {
        throw new MalformedServerReplyException(
        "Could not parse response code.\nServer Reply: " + line);
      }
  
      _replyLines.addElement(line);
  
      // Get extra lines if message continues.
      if(length > 3 && line.charAt(3) == '-') {
        do {
  	line = _controlInput.readLine();
  
  	if(line == null)
  	  throw new FTPConnectionClosedException(
  				 "Connection closed without indication.");
  
  	_replyLines.addElement(line);
  
  	// The length() check handles problems that could arise from readLine()
  	// returning too soon after encountering a naked CR or some other
  	// anomaly.
        } while(!(line.length() >= 4 && line.charAt(3) != '-' &&
  		Character.isDigit(line.charAt(0))));
        // This is too strong a condition because of non-conforming ftp
        // servers like ftp.funet.fi which sent 226 as the last line of a
        // 426 multi-line reply in response to ls /.  We relax the condition to
        // test that the line starts with a digit rather than starting with
        // the code.
        // line.startsWith(code)));
      }
  
      if(_commandSupport_.getListenerCount() > 0)
        _commandSupport_.fireReplyReceived(_replyCode, getReplyString());
  
      if(_replyCode == FTPReply.SERVICE_NOT_AVAILABLE)
        throw new FTPConnectionClosedException(
  		     "FTP response 421 received.  Server closed connection.");
    }
  
    // initiates control connections and gets initial reply
    protected void _connectAction_() throws IOException {
      super._connectAction_();
      _controlInput = 
        new BufferedReader(new InputStreamReader(getInputStream()));
      _controlOutput =
        new BufferedWriter(new OutputStreamWriter(getOutputStream()));
      __getReply();
      // If we received code 120, we have to fetch completion reply.
      if(FTPReply.isPositivePreliminary(_replyCode))
        __getReply();
    }
  
  
    /***
     * Adds a ProtocolCommandListener.  Delegates this task to
     * <a href="#_commandSupport_"> _commandSupport_ </a>.
     * <p>
     * @param listener  The ProtocolCommandListener to add.
     ***/
    public void addProtocolCommandListener(ProtocolCommandListener listener){
      _commandSupport_.addProtocolCommandListener(listener);
    }
  
    /***
     * Removes a ProtocolCommandListener.  Delegates this task to
     * <a href="#_commandSupport_"> _commandSupport_ </a>.
     * <p>
     * @param listener  The ProtocolCommandListener to remove.
     ***/
    public void removeProtocolCommandistener(ProtocolCommandListener listener){
      _commandSupport_.removeProtocolCommandListener(listener);
    }
  
  
    /***
     * Closes the control connection to the FTP server and sets to null
     * some internal data so that the memory may be reclaimed by the
     * garbage collector.  The reply text and code information from the
     * last command is voided so that the memory it used may be reclaimed.
     * <p>
     * @exception IOException If an error occurs while disconnecting.
     ***/
    public void disconnect() throws IOException {
      super.disconnect();
      _controlInput  = null;
      _controlOutput = null;
      _replyLines.setSize(0);
      _newReplyString = false;
      _replyString    = null;
    }
  
  
    /***
     * Sends an FTP command to the server, waits for a reply and returns the
     * numerical response code.  After invocation, for more detailed
     * information, the actual reply text can be accessed by calling
     * <a href="#getReplyString"> getReplyString </a> or 
     * <a href="#getReplyStrings"> getReplyStrings </a>.
     * <p>
     * @param command  The text representation of the  FTP command to send.
     * @param args The arguments to the FTP command.  If this parameter is
     *             set to null, then the command is sent with no argument.
     * @return The integer value of the FTP reply code returned by the server
     *         in response to the command.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int sendCommand(String command, String args) throws IOException {
      String message;
  
      __commandBuffer.setLength(0);
      __commandBuffer.append(command);
  
      if(args != null) {
        __commandBuffer.append(' ');
        __commandBuffer.append(args);
      }
      __commandBuffer.append(SocketClient.NETASCII_EOL);
  
      _controlOutput.write(message = __commandBuffer.toString());
      _controlOutput.flush();
  
      if(_commandSupport_.getListenerCount() > 0)
        _commandSupport_.fireCommandSent(command, message);
  
      __getReply();
      return _replyCode;
    }
  
  
    /***
     * Sends an FTP command to the server, waits for a reply and returns the
     * numerical response code.  After invocation, for more detailed
     * information, the actual reply text can be accessed by calling
     * <a href="#getReplyString"> getReplyString </a> or 
     * <a href="#getReplyStrings"> getReplyStrings </a>.
     * <p>
     * @param command  The FTPCommand constant corresponding to the FTP command
     *                 to send.
     * @param args The arguments to the FTP command.  If this parameter is
     *             set to null, then the command is sent with no argument.
     * @return The integer value of the FTP reply code returned by the server
     *         in response to the command.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int sendCommand(int command, String args) throws IOException {
      return sendCommand(FTPCommand._commands[command], args);
    }
  
  
    /***
     * Sends an FTP command with no arguments to the server, waits for a
     * reply and returns the numerical response code.  After invocation, for
     * more detailed information, the actual reply text can be accessed by
     * calling <a href="#getReplyString"> getReplyString </a> or 
     * <a href="#getReplyStrings"> getReplyStrings </a>.
     * <p>
     * @param command  The text representation of the  FTP command to send.
     * @return The integer value of the FTP reply code returned by the server
     *         in response to the command.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int sendCommand(String command) throws IOException {
      return sendCommand(command, null);
    }
  
  
    /***
     * Sends an FTP command with no arguments to the server, waits for a
     * reply and returns the numerical response code.  After invocation, for
     * more detailed information, the actual reply text can be accessed by
     * calling <a href="#getReplyString"> getReplyString </a> or 
     * <a href="#getReplyStrings"> getReplyStrings </a>.
     * <p>
     * @param command  The FTPCommand constant corresponding to the FTP command
     *                 to send.
     * @return The integer value of the FTP reply code returned by the server
     *         in response to the command.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int sendCommand(int command) throws IOException {
      return sendCommand(command, null);
    }
  
  
    /***
     * Returns the integer value of the reply code of the last FTP reply.
     * You will usually only use this method after you connect to the
     * FTP server to check that the connection was successful since
     * <code> connect </code> is of type void.
     * <p>
     * @return The integer value of the reply code of the last FTP reply.
     ***/
    public int getReplyCode() {
      return _replyCode;
    }
  
    /***
     * Fetches a reply from the FTP server and returns the integer reply
     * code.  After calling this method, the actual reply text can be accessed
     * from either  calling <a href="#getReplyString"> getReplyString </a> or 
     * <a href="#getReplyStrings"> getReplyStrings </a>.  Only use this
     * method if you are implementing your own FTP client or if you need to
     * fetch a secondary response from the FTP server.
     * <p>
     * @return The integer value of the reply code of the fetched FTP reply.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while receiving the
     *                         server reply.
     ***/
    public int getReply() throws IOException {
      __getReply();
      return _replyCode;
    }
  
  
    /***
     * Returns the lines of text from the last FTP server response as an array
     * of strings, one entry per line.  The end of line markers of each are
     * stripped from each line.
     * <p>
     * @return The lines of text from the last FTP response as an array.
     ***/
    public String[] getReplyStrings() {
      String[] lines;
      lines = new String[_replyLines.size()];
      _replyLines.copyInto(lines);
      return lines;
    }
  
    /***
     * Returns the entire text of the last FTP server response exactly
     * as it was received, including all end of line markers in NETASCII
     * format.
     * <p>
     * @return The entire text from the last FTP response as a String.
     ***/
    public String getReplyString() {
      Enumeration enum;
      StringBuffer buffer;
  
      if(!_newReplyString)
        return _replyString;
  
      buffer = new StringBuffer(256);
      enum = _replyLines.elements();
      while(enum.hasMoreElements()) {
        buffer.append((String)enum.nextElement());
        buffer.append(SocketClient.NETASCII_EOL);
      }
  
      _newReplyString = false;
  
      return (_replyString = buffer.toString());
    }
  
  
    /***
     * A convenience method to send the FTP USER command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param username  The username to login under.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int user(String username) throws IOException {
      return sendCommand(FTPCommand.USER, username);
    }
  
    /***
     * A convenience method to send the FTP PASS command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param pass  The plain text password of the username being logged into.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int pass(String password) throws IOException {
      return sendCommand(FTPCommand.PASS, password);
    }
  
    /***
     * A convenience method to send the FTP ACCT command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param account  The account name to access.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int acct(String account) throws IOException {
      return sendCommand(FTPCommand.ACCT, account);
    }
  
  
    /***
     * A convenience method to send the FTP ABOR command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int abor() throws IOException {
      return sendCommand(FTPCommand.ABOR);
    }
  
    /***
     * A convenience method to send the FTP CWD command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param directory The new working directory.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int cwd(String directory) throws IOException {
      return sendCommand(FTPCommand.CWD, directory);
    }
  
    /***
     * A convenience method to send the FTP CDUP command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int cdup() throws IOException {
      return sendCommand(FTPCommand.CDUP);
    }
  
    /***
     * A convenience method to send the FTP QUIT command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int quit() throws IOException {
      return sendCommand(FTPCommand.QUIT);
    }
  
    /***
     * A convenience method to send the FTP REIN command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int rein() throws IOException {
      return sendCommand(FTPCommand.REIN);
    }
  
    /***
     * A convenience method to send the FTP SMNT command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param dir  The directory name.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int smnt(String dir) throws IOException {
      return sendCommand(FTPCommand.SMNT);
    }
  
    /***
     * A convenience method to send the FTP PORT command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param host  The host owning the port.
     * @param port  The new port.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int port(InetAddress host, int port) throws IOException {
      int num;
      StringBuffer info = new StringBuffer(24);
  
      info.append(host.getHostAddress().replace('.', ','));
      num = port >>> 8;
      info.append(','); info.append(num); info.append(','); 
      num = port & 0xff;
      info.append(num);
  
      return sendCommand(FTPCommand.PORT, info.toString());
    }
  
    /***
     * A convenience method to send the FTP PASV command to the server,
     * receive the reply, and return the reply code.  Remember, it's up
     * to you to interpret the reply string containing the host/port
     * information.
     * <p>
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int pasv() throws IOException {
      return sendCommand(FTPCommand.PASV);
    }
  
    /***
     * A convenience method to send the FTP TYPE command for text files
     * to the server, receive the reply, and return the reply code.
     * <p>
     * @param type  The type of the file (one of the <code>FILE_TYPE</code>
     *              constants).
     * @param formatOrByteSize  The format of the file (one of the
     *              <code>_FORMAT</code> constants.  In the case of
     *              <code>LOCAL_FILE_TYPE</code>, the byte size.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int type(int fileType, int formatOrByteSize) throws IOException {
      StringBuffer arg = new StringBuffer();
  
      arg.append(__modes.charAt(fileType));
      arg.append(' ');
      if(fileType == LOCAL_FILE_TYPE)
        arg.append(formatOrByteSize);
      else
        arg.append(__modes.charAt(formatOrByteSize));
  
      return sendCommand(FTPCommand.TYPE, arg.toString());
    }
  
  
    /***
     * A convenience method to send the FTP TYPE command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param type  The type of the file (one of the <code>FILE_TYPE</code>
     *              constants).
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int type(int fileType) throws IOException {
      return sendCommand(FTPCommand.TYPE,
  		       __modes.substring(fileType, fileType+1));
    }
  
    /***
     * A convenience method to send the FTP STRU command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param structure  The structure of the file (one of the
     *         <code>_STRUCTURE</code> constants).
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int stru(int structure) throws IOException {
      return sendCommand(FTPCommand.STRU,
  		       __modes.substring(structure, structure+1));
    }
  
    /***
     * A convenience method to send the FTP MODE command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param mode  The transfer mode to use (one of the
     *         <code>TRANSFER_MODE</code> constants).
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int mode(int mode) throws IOException {
      return sendCommand(FTPCommand.MODE,
  		       __modes.substring(mode, mode+1));
    }
  
    /***
     * A convenience method to send the FTP RETR command to the server,
     * receive the reply, and return the reply code.  Remember, it is up
     * to you to manage the data connection.  If you don't need this low
     * level of access, use <a href="org.apache.commons.net.ftp.FTPClient.html">
     * FTPClient</a>, which will handle all low level details for you.
     * <p>
     * @param pathname  The pathname of the file to retrieve.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int retr(String pathname) throws IOException {
      return sendCommand(FTPCommand.RETR, pathname);
    }
  
    /***
     * A convenience method to send the FTP STOR command to the server,
     * receive the reply, and return the reply code.  Remember, it is up
     * to you to manage the data connection.  If you don't need this low
     * level of access, use <a href="org.apache.commons.net.ftp.FTPClient.html">
     * FTPClient</a>, which will handle all low level details for you.
     * <p>
     * @param pathname  The pathname to use for the file when stored at
     *                  the remote end of the transfer.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int stor(String pathname) throws IOException {
      return sendCommand(FTPCommand.STOR, pathname);
    }
  
    /***
     * A convenience method to send the FTP STOU command to the server,
     * receive the reply, and return the reply code.  Remember, it is up
     * to you to manage the data connection.  If you don't need this low
     * level of access, use <a href="org.apache.commons.net.ftp.FTPClient.html">
     * FTPClient</a>, which will handle all low level details for you.
     * <p>
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int stou() throws IOException {
      return sendCommand(FTPCommand.STOU);
    }
  
    /***
     * A convenience method to send the FTP STOU command to the server,
     * receive the reply, and return the reply code.  Remember, it is up
     * to you to manage the data connection.  If you don't need this low
     * level of access, use <a href="org.apache.commons.net.ftp.FTPClient.html">
     * FTPClient</a>, which will handle all low level details for you.
     * <p>
     * @param pathname  The base pathname to use for the file when stored at
     *                  the remote end of the transfer.  Some FTP servers
     *                  require this.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int stou(String filename) throws IOException {
      return sendCommand(FTPCommand.STOU, filename);
    }
  
    /***
     * A convenience method to send the FTP APPE command to the server,
     * receive the reply, and return the reply code.  Remember, it is up
     * to you to manage the data connection.  If you don't need this low
     * level of access, use <a href="org.apache.commons.net.ftp.FTPClient.html">
     * FTPClient</a>, which will handle all low level details for you.
     * <p>
     * @param pathname  The pathname to use for the file when stored at
     *                  the remote end of the transfer.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int appe(String pathname) throws IOException {
      return sendCommand(FTPCommand.APPE, pathname);
    }
  
    /***
     * A convenience method to send the FTP ALLO command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param bytes The number of bytes to allocate.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int allo(int bytes) throws IOException {
      return sendCommand(FTPCommand.ALLO, Integer.toString(bytes));
    }
  
    /***
     * A convenience method to send the FTP ALLO command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param bytes The number of bytes to allocate.
     * @param recordSize  The size of a record.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int allo(int bytes, int recordSize) throws IOException {
      return sendCommand(FTPCommand.ALLO, Integer.toString(bytes) + " R " +
  		       Integer.toString(recordSize));
    }
  
    /***
     * A convenience method to send the FTP REST command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param marker The marker at which to restart a transfer.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int rest(String marker) throws IOException {
      return sendCommand(FTPCommand.REST, marker);
    }
  
    /***
     * A convenience method to send the FTP RNFR command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param pathname The pathname to rename from.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int rnfr(String pathname) throws IOException {
      return sendCommand(FTPCommand.RNFR, pathname);
    }
  
    /***
     * A convenience method to send the FTP RNTO command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param pathname The pathname to rename to
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int rnto(String pathname) throws IOException {
      return sendCommand(FTPCommand.RNTO, pathname);
    }
  
    /***
     * A convenience method to send the FTP DELE command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param pathname The pathname to delete.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int dele(String pathname) throws IOException {
      return sendCommand(FTPCommand.DELE, pathname);
    }
  
    /***
     * A convenience method to send the FTP RMD command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param pathname The pathname of the directory to remove.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int rmd(String pathname) throws IOException {
      return sendCommand(FTPCommand.RMD, pathname);
    }
  
    /***
     * A convenience method to send the FTP MKD command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param pathname The pathname of the new directory to create.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int mkd(String pathname) throws IOException {
      return sendCommand(FTPCommand.MKD, pathname);
    }
  
    /***
     * A convenience method to send the FTP PWD command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int pwd() throws IOException {
      return sendCommand(FTPCommand.PWD);
    }
  
    /***
     * A convenience method to send the FTP LIST command to the server,
     * receive the reply, and return the reply code.  Remember, it is up
     * to you to manage the data connection.  If you don't need this low
     * level of access, use <a href="org.apache.commons.net.ftp.FTPClient.html">
     * FTPClient</a>, which will handle all low level details for you.
     * <p>
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int list() throws IOException {
      return sendCommand(FTPCommand.LIST);
    }
  
    /***
     * A convenience method to send the FTP LIST command to the server,
     * receive the reply, and return the reply code.  Remember, it is up
     * to you to manage the data connection.  If you don't need this low
     * level of access, use <a href="org.apache.commons.net.ftp.FTPClient.html">
     * FTPClient</a>, which will handle all low level details for you.
     * <p>
     * @param pathname  The pathname to list.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int list(String pathname) throws IOException {
      return sendCommand(FTPCommand.LIST, pathname);
    }
  
    /***
     * A convenience method to send the FTP NLST command to the server,
     * receive the reply, and return the reply code.  Remember, it is up
     * to you to manage the data connection.  If you don't need this low
     * level of access, use <a href="org.apache.commons.net.ftp.FTPClient.html">
     * FTPClient</a>, which will handle all low level details for you.
     * <p>
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int nlst() throws IOException {
      return sendCommand(FTPCommand.NLST);
    }
  
    /***
     * A convenience method to send the FTP NLST command to the server,
     * receive the reply, and return the reply code.  Remember, it is up
     * to you to manage the data connection.  If you don't need this low
     * level of access, use <a href="org.apache.commons.net.ftp.FTPClient.html">
     * FTPClient</a>, which will handle all low level details for you.
     * <p>
     * @param pathname  The pathname to list.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int nlst(String pathname) throws IOException {
      return sendCommand(FTPCommand.NLST, pathname);
    }
  
    /***
     * A convenience method to send the FTP SITE command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param parameters  The site parameters to send.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int site(String parameters) throws IOException {
      return sendCommand(FTPCommand.SITE, parameters);
    }
  
    /***
     * A convenience method to send the FTP SYST command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int syst() throws IOException {
      return sendCommand(FTPCommand.SYST);
    }
  
    /***
     * A convenience method to send the FTP STAT command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int stat() throws IOException {
      return sendCommand(FTPCommand.STAT);
    }
  
    /***
     * A convenience method to send the FTP STAT command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param pathname  A pathname to list.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int stat(String pathname) throws IOException {
      return sendCommand(FTPCommand.STAT, pathname);
    }
  
    /***
     * A convenience method to send the FTP HELP command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int help() throws IOException {
      return sendCommand(FTPCommand.HELP);
    }
  
    /***
     * A convenience method to send the FTP HELP command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @param command  The command name on which to request help.
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int help(String command) throws IOException {
      return sendCommand(FTPCommand.HELP, command);
    }
  
    /***
     * A convenience method to send the FTP NOOP command to the server,
     * receive the reply, and return the reply code.
     * <p>
     * @return The reply code received from the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending the
     *      command or receiving the server reply.
     ***/
    public int noop() throws IOException {
      return sendCommand(FTPCommand.NOOP);
    }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/net/src/java/org/apache/commons/net/ftp/FTPClient.java
  
  Index: FTPClient.java
  ===================================================================
  package org.apache.commons.net.ftp;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Commons" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  import java.net.*;
  import java.io.*;
  import java.util.*;
  
  import org.apache.commons.io.*;
  import org.apache.commons.net.MalformedServerReplyException;
  
  /***
   * FTPClient encapsulates all the functionality necessary to store and
   * retrieve files from an FTP server.  This class takes care of all
   * low level details of interacting with an FTP server and provides
   * a convenient higher level interface.  As with all classes derived
   * from <a href="org.apache.commons.net.SocketClient.html"> SocketClient </a>,
   * you must first connect to the server with 
   * <a href="org.apache.commons.net.SocketClient.html#connect"> connect </a>
   * before doing anything, and finally
   * <a href="org.apache.commons.net.SocketClient.html#disconnect"> disconnect </a>
   * after you're completely finished interacting with the server.
   * Then you need to check the FTP reply code to see if the connection
   * was successful.  For example:
   * <pre>
   *    try {
   *      int reply;
   *      ftp.connect("ftp.foobar.com");
   *      System.out.println("Connected to " + server + ".");
   *      System.out.print(ftp.getReplyString());
   *
   *      // After connection attempt, you should check the reply code to verify
   *      // success.
   *      reply = ftp.getReplyCode();
   *
   *      if(!FTPReply.isPositiveCompletion(reply)) {
   *        ftp.disconnect();
   *        System.err.println("FTP server refused connection.");
   *        System.exit(1);
   *      }
   *    } catch(IOException e) {
   *      if(ftp.isConnected()) {
   *        try {
   *          ftp.disconnect();
   *        } catch(IOException f) {
   *          // do nothing
   *        }
   *      }
   *      System.err.println("Could not connect to server.");
   *      e.printStackTrace();
   *      System.exit(1);
   *    }
   * </pre>
   * <p>
   * Immediately after connecting is the only real time you need to check the
   * reply code (because connect is of type void).  The convention for all the
   * FTP command methods in FTPClient is such that they either return a
   * boolean value or some other value.
   * The boolean methods return true on a successful completion reply from
   * the FTP server and false on a reply resulting in an error condition or
   * failure.  The methods returning a value other than boolean return a value
   * containing the higher level data produced by the FTP command, or null if a
   * reply resulted in an error condition or failure.  If you want to access
   * the exact FTP reply code causing a success or failure, you must call
   * <a href="org.apache.commons.net.ftp.FTP.html#getReplyCode"> getReplyCode </a> after
   * a success or failure.
   * <p>
   * The default settings for FTPClient are for it to use
   * <code> FTP.ASCII_FILE_TYPE </code>,
   * <code> FTP.NON_PRINT_TEXT_FORMAT </code>,
   * <code> FTP.STREAM_TRANSFER_MODE </code>, and
   * <code> FTP.FILE_STRUCTURE </code>.  The only file types directly supported
   * are <code> FTP.ASCII_FILE_TYPE </code> and
   * <code> FTP.IMAGE_FILE_TYPE </code> (which is the same as 
   * <code> FTP.BINARY_FILE_TYPE </code>).  Because there are at lest 4
   * different EBCDIC encodings, we have opted not to provide direct support
   * for EBCDIC.  To transfer EBCDIC and other unsupported file types you
   * must create your own filter InputStreams and OutputStreams and wrap
   * them around the streams returned or required by the FTPClient methods.
   * FTPClient uses the NetASCII filter streams in
   * <a href="Package-org.apache.commons.io.html"> org.apache.commons.io </a> to provide
   * transparent handling of ASCII files.  We will consider incorporating
   * EBCDIC support if there is enough demand.
   * <p>
   * <code> FTP.NON_PRINT_TEXT_FORMAT </code>,
   * <code> FTP.STREAM_TRANSFER_MODE </code>, and
   * <code> FTP.FILE_STRUCTURE </code> are the only supported formats,
   * transfer modes, and file structures.
   * <p>
   * Because the handling of sockets on different platforms can differ
   * significantly, the FTPClient automatically issues a new PORT command
   * prior to every transfer requiring that the server connect to the client's
   * data port.  This ensures identical problem-free behavior on Windows, Unix,
   * and Macintosh platforms.  Additionally, it relieves programmers from
   * having to issue the PORT command themselves and dealing with platform
   * dependent issues.
   * <p>
   * Additionally, for security purposes, all data connections to the
   * client are verified to ensure that they originated from the intended
   * party (host and port).  If a data connection is initiated by an unexpected
   * party, the command will close the socket and throw an IOException.  You
   * may disable this behavior with
   * <a href="#setRemoteVerificationEnabled">setRemoteVerificationEnabled()</a>.
   * <p>
   * You should keep in mind that the FTP server may choose to prematurely
   * close a connection if the client has been idle for longer than a
   * given time period (usually 900 seconds).  The FTPClient class will detect a
   * premature FTP server connection closing when it receives a
   * <a href="org.apache.commons.net.ftp.FTPReply.html#SERVICE_NOT_AVAILABLE">
   * FTPReply.SERVICE_NOT_AVAILABLE </a> response to a command.
   * When that occurs, the FTP class method encountering that reply will throw
   * an <a href="org.apache.commons.net.ftp.FTPConnectionClosedException.html">
   * FTPConnectionClosedException </a>.
   * <code>FTPConnectionClosedException</code>
   * is a subclass of <code> IOException </code> and therefore need not be
   * caught separately, but if you are going to catch it separately, its
   * catch block must appear before the more general <code> IOException </code>
   * catch block.  When you encounter an
   * <a href="org.apache.commons.net.ftp.FTPConnectionClosedException.html">
   * FTPConnectionClosedException </a>, you must disconnect the connection with
   * <a href="#disconnect"> disconnect() </a> to properly clean up the
   * system resources used by FTPClient.  Before disconnecting, you may check the
   * last reply code and text with
   * <a href="org.apache.commons.net.ftp.FTP.html#getReplyCode"> getReplyCode </a>,
   * <a href="org.apache.commons.net.ftp.FTP.html#getReplyString"> getReplyString </a>,
   * and
   * <a href="org.apache.commons.net.ftp.FTP.html#getReplyStrings"> getReplyStrings</a>.
   * You may avoid server disconnections while the client is idle by
   * periodicaly sending NOOP commands to the server.
   * <p>
   * Rather than list it separately for each method, we mention here that
   * every method communicating with the server and throwing an IOException
   * can also throw a 
   * <a href="org.apache.commons.net.MalformedServerReplyException.html">
   * MalformedServerReplyException </a>, which is a subclass
   * of IOException.  A MalformedServerReplyException will be thrown when
   * the reply received from the server deviates enough from the protocol 
   * specification that it cannot be interpreted in a useful manner despite
   * attempts to be as lenient as possible.
   * <p>
   * <p>
   * @author Daniel F. Savarese
   * @see FTP
   * @see FTPConnectionClosedException
   * @see DefaultFTPFileListParser
   * @see org.apache.commons.net.MalformedServerReplyException
   ***/
  
  public class FTPClient extends FTP {
    /***
     * A constant indicating the FTP session is expecting all transfers
     * to occur between the client (local) and server and that the server
     * should connect to the client's data port to initiate a data transfer.
     * This is the default data connection mode when and FTPClient instance
     * is created.
     ***/
    public static final int ACTIVE_LOCAL_DATA_CONNECTION_MODE   = 0;
    /***
     * A constant indicating the FTP session is expecting all transfers
     * to occur between two remote servers and that the server
     * the client is connected to should connect to the other server's
     * data port to initiate a data transfer.
     ***/
    public static final int ACTIVE_REMOTE_DATA_CONNECTION_MODE  = 1;
    /***
     * A constant indicating the FTP session is expecting all transfers
     * to occur between the client (local) and server and that the server
     * is in passive mode, requiring the client to connect to the 
     * server's data port to initiate a transfer.
     ***/
    public static final int PASSIVE_LOCAL_DATA_CONNECTION_MODE  = 2;
    /***
     * A constant indicating the FTP session is expecting all transfers
     * to occur between two remote servers and that the server
     * the client is connected to is in passive mode, requiring the other
     * server to connect to the first server's data port to initiate a data
     * transfer.
     ***/
    public static final int PASSIVE_REMOTE_DATA_CONNECTION_MODE = 3;
  
    private int __dataConnectionMode, __dataTimeout;
    private int __passivePort;
    private String __passiveHost;
    private int __fileType, __fileFormat, __fileStructure, __fileTransferMode;
    private boolean __remoteVerificationEnabled;
    private FTPFileListParser __fileListParser;
  
    /***
     * Default FTPClient constructor.  Creates a new FTPClient instance
     * with the data connection mode set to 
     * <code> ACTIVE_LOCAL_DATA_CONNECTION_MODE </code>, the file type
     * set to <code> FTP.ASCII_FILE_TYPE </code>, the
     * file format set to <code> FTP.NON_PRINT_TEXT_FORMAT </code>, 
     * the file structure set to <code> FTP.FILE_STRUCTURE </code>, and
     * the transfer mode set to <code> FTP.STREAM_TRANSFER_MODE </code>.
     ***/
    public FTPClient() {
      __initDefaults();
      __fileListParser = new DefaultFTPFileListParser();
      __dataTimeout    = -1;
      __remoteVerificationEnabled = true;
    }
  
  
    private void __initDefaults() {
      __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE;
      __passiveHost    = null;
      __passivePort    = -1;
      __fileType       = FTP.ASCII_FILE_TYPE;
      __fileStructure  = FTP.FILE_STRUCTURE;
      __fileFormat     = FTP.NON_PRINT_TEXT_FORMAT;
      __fileTransferMode = FTP.STREAM_TRANSFER_MODE;
    }
  
    private String __parsePathname(String reply) {
      int begin, end;
  
      begin = reply.indexOf('"') + 1;
      end   = reply.indexOf('"', begin);
  
      return reply.substring(begin, end);
    }
  
  
    private void __parsePassiveModeReply(String reply)
         throws MalformedServerReplyException
    {
      int i, index, lastIndex;
      String octet1, octet2;
      StringBuffer host;
  
      reply = reply.substring(reply.indexOf('(') + 1,
  			      reply.indexOf(')')).trim();
  
      host = new StringBuffer(24);
      lastIndex = 0;
      index     = reply.indexOf(',');
      host.append(reply.substring(lastIndex, index));
      
      for(i = 0; i < 3; i++) {
        host.append('.');
        lastIndex = index + 1;
        index     = reply.indexOf(',', lastIndex);
        host.append(reply.substring(lastIndex, index));
      }
  
      lastIndex = index + 1;
      index     = reply.indexOf(',', lastIndex);
  
      octet1 = reply.substring(lastIndex, index);
      octet2 = reply.substring(index + 1);
  
      // index and lastIndex now used as temporaries
      try {
        index     = Integer.parseInt(octet1);
        lastIndex = Integer.parseInt(octet2);
      } catch(NumberFormatException e) {
        throw new MalformedServerReplyException(
        "Could not parse passive host information.\nServer Reply: " + reply);
      }
  
      index <<= 8;
      index |= lastIndex;
  
      __passiveHost = host.toString();
      __passivePort = index;
    }
  
  
    // null arg if no arg
    private Socket __openDataConnection(int command, String arg)
         throws IOException
    {
      Socket socket;
  
      if(__dataConnectionMode != ACTIVE_LOCAL_DATA_CONNECTION_MODE &&
         __dataConnectionMode != PASSIVE_LOCAL_DATA_CONNECTION_MODE)
        return null;
  
      if(__dataConnectionMode == ACTIVE_LOCAL_DATA_CONNECTION_MODE) {
        ServerSocket server;
        server = _socketFactory_.createServerSocket(0, 1, getLocalAddress());
  
        if(!FTPReply.isPositiveCompletion(port(getLocalAddress(),
  					     server.getLocalPort()))){
  	server.close();
  	return null;
        }
  
        if(!FTPReply.isPositivePreliminary(sendCommand(command, arg))) {
  	server.close();
  	return null;
        }
  
        // For now, let's just use the data timeout value for waiting for
        // the data connection.  It may be desirable to let this be a
        // separately configurable value.  In any case, we really want
        // to allow preventing the accept from blocking indefinitely.
        if(__dataTimeout >= 0)
  	server.setSoTimeout(__dataTimeout);
        socket = server.accept();
        server.close();
      } else  { // We must be in PASSIVE_LOCAL_DATA_CONNECTION_MODE
  
        if(pasv() != FTPReply.ENTERING_PASSIVE_MODE)
  	return null;
  
        __parsePassiveModeReply((String)_replyLines.elementAt(0));
  
        socket = _socketFactory_.createSocket(__passiveHost, __passivePort);
  
        if(!FTPReply.isPositivePreliminary(sendCommand(command, arg))) {
  	socket.close();
  	return null;
        }
      }
  
      if(__remoteVerificationEnabled && !verifyRemote(socket)) {
        InetAddress host1, host2;
  
        host1 = socket.getInetAddress();
        host2 = getRemoteAddress();
  
        socket.close();
  
        throw new IOException(
  	    "Host attempting data connection " + host1.getHostAddress() +
  	    " is not same as server " + host2.getHostAddress());
      }
  
      if(__dataTimeout >= 0)
        socket.setSoTimeout(__dataTimeout);
  
      return socket;
    }
  
  
    private boolean __storeFile(int command, String remote, InputStream local)
         throws IOException
    {
      OutputStream output;
      Socket socket;
  
      if((socket = __openDataConnection(command, remote)) == null)
        return false;
  
      output = new BufferedOutputStream(socket.getOutputStream());
      if(__fileType == ASCII_FILE_TYPE)
        output = new ToNetASCIIOutputStream(output);
      // Treat everything else as binary for now
      try {
        Util.copyStream(local, output);
      } catch(IOException e) {
        try {
  	socket.close();
        } catch(IOException f) {
        }
        throw e;
      }
      output.close();
      socket.close();
      return completePendingCommand();
    }
  
    private OutputStream __storeFileStream(int command, String remote)
         throws IOException
    {
      OutputStream output;
      Socket socket;
  
      if((socket = __openDataConnection(command, remote)) == null)
        return null;
  
      output = socket.getOutputStream();
      if(__fileType == ASCII_FILE_TYPE)
        output = new ToNetASCIIOutputStream(output);
      return new org.apache.commons.io.SocketOutputStream(socket, output);
    }
  
  
    protected void _connectAction_() throws IOException {
      super._connectAction_();
      __initDefaults();
    }
  
  
    /***
     * Sets the timeout in milliseconds to use when reading from the
     * data connection.  This timeout will be set immediately after
     * opening the data connection.
     * <p>
     * @param  timeout The default timeout in milliseconds that is used when
     *        opening a data connection socket.
     ***/
    public void setDataTimeout(int timeout) {
      __dataTimeout = timeout;
    }
  
  
    /***
     * Closes the connection to the FTP server and restores
     * connection parameters to the default values.
     * <p>
     * @exception IOException If an error occurs while disconnecting.
     ***/
    public void disconnect() throws IOException {
      super.disconnect();
      __initDefaults();
    }
  
  
    /***
     * Enable or disable verification that the remote host taking part
     * of a data connection is the same as the host to which the control
     * connection is attached.  The default is for verification to be
     * enabled.  You may set this value at any time, whether the
     * FTPClient is currently connected or not.
     * <p>
     * @param enable True to enable verification, false to disable verification.
     ***/
    public void setRemoteVerificationEnabled(boolean enable) {
      __remoteVerificationEnabled = enable;
    }
  
    /***
     * Return whether or not verification of the remote host participating
     * in data connections is enabled.  The default behavior is for
     * verification to be enabled.
     * <p>
     * @return True if verification is enabled, false if not.
     ***/
    public boolean isRemoteVerificationEnabled() {
      return __remoteVerificationEnabled;
    }
  
    /***
     * Login to the FTP server using the provided username and password.
     * <p>
     * @param username The username to login under.
     * @param password The password to use.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean login(String username, String password) throws IOException {
      user(username);
  
      if(FTPReply.isPositiveCompletion(_replyCode))
        return true;
  
      // If we get here, we either have an error code, or an intermmediate
      // reply requesting password.
      if(!FTPReply.isPositiveIntermediate(_replyCode))
        return false;
  
      return FTPReply.isPositiveCompletion(pass(password));
    }
  
    
    /***
     * Login to the FTP server using the provided username, password,
     * and account.  If no account is required by the server, only
     * the username and password, the account information is not used.
     * <p>
     * @param username The username to login under.
     * @param password The password to use.
     * @param account  The account to use.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean login(String username, String password, String account)
         throws IOException
    {
      user(username);
  
      if(FTPReply.isPositiveCompletion(_replyCode))
        return true;
  
      // If we get here, we either have an error code, or an intermmediate
      // reply requesting password.
      if(!FTPReply.isPositiveIntermediate(_replyCode))
        return false;
  
      pass(password);
  
      if(FTPReply.isPositiveCompletion(_replyCode))
        return true;
  
      if(!FTPReply.isPositiveIntermediate(_replyCode))
        return false;
  
      return FTPReply.isPositiveCompletion(acct(account));
    }
  
    /***
     * Logout of the FTP server by sending the QUIT command.
     * <p>
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean logout() throws IOException {
      return FTPReply.isPositiveCompletion(quit());
    }
  
  
    /***
     * Change the current working directory of the FTP session.
     * <p>
     * @param pathname  The new current working directory.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean changeWorkingDirectory(String pathname) throws IOException {
      return FTPReply.isPositiveCompletion(cwd(pathname));
    }
  
  
    /***
     * Change to the parent directory of the current working directory.
     * <p>
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean changeToParentDirectory() throws IOException {
      return FTPReply.isPositiveCompletion(cdup());
    }
  
  
    /***
     * Issue the FTP SMNT command.
     * <p>
     * @param pathname The pathname to mount.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean structureMount(String pathname) throws IOException {
      return FTPReply.isPositiveCompletion(smnt(pathname));
    }
  
    /***
     * Reinitialize the FTP session.  Not all FTP servers support this
     * command, which issues the FTP REIN command.
     * <p>
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    boolean reinitialize() throws IOException {
      rein();
  
      if(FTPReply.isPositiveCompletion(_replyCode) ||
         (FTPReply.isPositivePreliminary(_replyCode) &&
  	FTPReply.isPositiveCompletion(getReply()))) {
  
        __initDefaults();
  
        return true;
      }
  
      return false;
    }
  
  
    /***
     * Set the current data connection mode to
     * <code>ACTIVE_LOCAL_DATA_CONNECTION_MODE</code>.  No communication
     * with the FTP server is conducted, but this causes all future data
     * transfers to require the FTP server to connect to the client's
     * data port.  Additionally, to accommodate differences between socket
     * implementations on different platforms, this method causes the
     * client to issue a PORT command before every data transfer.
     ***/
    public void enterLocalActiveMode() {
      __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE;
      __passiveHost        = null;
      __passivePort        = -1;
    }
  
  
    /***
     * Set the current data connection mode to 
     * <code> PASSIVE_LOCAL_DATA_CONNECTION_MODE </code>.  Use this
     * method only for data transfers between the client and server.
     * This method causes a PASV command to be issued to the server
     * before the opening of every data connection, telling the server to
     * open a data port to which the client will connect to conduct
     * data transfers.  The FTPClient will stay in
     * <code> PASSIVE_LOCAL_DATA_CONNECTION_MODE </code> until the
     * mode is changed by calling some other method such as
     * <a href="#enterLocalActiveMode"> enterLocalActiveMode() </a>
     ***/
    public void enterLocalPassiveMode() {
      __dataConnectionMode = PASSIVE_LOCAL_DATA_CONNECTION_MODE;
      // These will be set when just before a data connection is opened
      // in __openDataConnection()
      __passiveHost        = null;
      __passivePort        = -1;
    }
  
  
    /***
     * Set the current data connection mode to
     * <code> ACTIVE_REMOTE_DATA_CONNECTION </code>.  Use this method only
     * for server to server data transfers.  This method issues a PORT
     * command to the server, indicating the other server and port to which
     * it should connect for data transfers.  You must call this method
     * before EVERY server to server transfer attempt.  The FTPClient will
     * NOT automatically continue to issue PORT commands.  You also
     * must remember to call
     * <a href="#enterLocalActiveMode"> enterLocalActiveMode() </a> if you
     * wish to return to the normal data connection mode.
     * <p>
     * @param host The passive mode server accepting connections for data
     *             transfers.
     * @param port The passive mode server's data port.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean enterRemoteActiveMode(InetAddress host, int port)
         throws IOException
    {
      if(FTPReply.isPositiveCompletion(port(host, port))) {
        __dataConnectionMode = ACTIVE_REMOTE_DATA_CONNECTION_MODE;
        __passiveHost        = null;
        __passivePort        = -1;
        return true;
      }
      return false;
    }
  
    /***
     * Set the current data connection mode to 
     * <code> PASSIVE_REMOTE_DATA_CONNECTION_MODE </code>.  Use this
     * method only for server to server data transfers.
     * This method issues a PASV command to the server, telling it to
     * open a data port to which the active server will connect to conduct
     * data transfers.  You must call this method
     * before EVERY server to server transfer attempt.  The FTPClient will
     * NOT automatically continue to issue PASV commands.  You also
     * must remember to call
     * <a href="#enterLocalActiveMode"> enterLocalActiveMode() </a> if you
     * wish to return to the normal data connection mode.
     * <p>
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean enterRemotePassiveMode() throws IOException {
      if(pasv() != FTPReply.ENTERING_PASSIVE_MODE)
        return false;
  
      __dataConnectionMode = PASSIVE_REMOTE_DATA_CONNECTION_MODE;
      __parsePassiveModeReply((String)_replyLines.elementAt(0));
  
      return true;
    }
  
    /***
     * Returns the hostname or IP address (in the form of a string) returned
     * by the server when entering passive mode.  If not in passive mode,
     * returns null.  This method only returns a valid value AFTER a
     * data connection has been opened after a call to
     * <a href="#enterLocalPassiveMode">enterLocalPassiveMode()</a>.
     * This is because FTPClient sends a PASV command to the server only
     * just before opening a data connection, and not when you call
     * <a href="#enterLocalPassiveMode">enterLocalPassiveMode()</a>.
     * <p>
     * @return The passive host name if in passive mode, otherwise null.
     ***/
    public String getPassiveHost() { return __passiveHost; }
  
    /***
     * If in passive mode, returns the data port of the passive host.
     * This method only returns a valid value AFTER a
     * data connection has been opened after a call to
     * <a href="#enterLocalPassiveMode">enterLocalPassiveMode()</a>.
     * This is because FTPClient sends a PASV command to the server only
     * just before opening a data connection, and not when you call
     * <a href="#enterLocalPassiveMode">enterLocalPassiveMode()</a>.
     * <p>
     * @return The data port of the passive server.  If not in passive
     *         mode, undefined.
     ***/
    public int getPassivePort() { return __passivePort; }
  
  
    /***
     * Returns the current data connection mode (one of the
     * <code> _DATA_CONNECTION_MODE </code> constants.
     * <p>
     * @return The current data connection mode (one of the
     * <code> _DATA_CONNECTION_MODE </code> constants.
     ***/
    public int getDataConnectionMode() { return __dataConnectionMode; }
  
  
    /***
     * Sets the file type to be transferred.  This should be one of 
     * <code> FTP.ASCII_FILE_TYPE </code>, <code> FTP.IMAGE_FILE_TYPE </code>,
     * etc.  The file type only needs to be set when you want to change the
     * type.  After changing it, the new type stays in effect until you change
     * it again.  The default file type is <code> FTP.ASCII_FILE_TYPE </code>
     * if this method is never called.
     * <p>
     * @param fileType The <code> _FILE_TYPE </code> constant indcating the
     *                 type of file.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean setFileType(int fileType) throws IOException {
      if(FTPReply.isPositiveCompletion(type(fileType))) {
        __fileType   = fileType;
        __fileFormat = FTP.NON_PRINT_TEXT_FORMAT;
        return true; 
      }
      return false;
    }
  
  
    /***
     * Sets the file type to be transferred and the format.  The type should be
     * one of  <code> FTP.ASCII_FILE_TYPE </code>,
     * <code> FTP.IMAGE_FILE_TYPE </code>, etc.  The file type only needs to
     * be set when you want to change the type.  After changing it, the new
     * type stays in effect until you change it again.  The default file type
     * is <code> FTP.ASCII_FILE_TYPE </code> if this method is never called.
     * The format should be one of the FTP class <code> TEXT_FORMAT </code>
     * constants, or if the type is <code> FTP.LOCAL_FILE_TYPE </code>, the
     * format should be the byte size for that type.  The default format
     * is <code> FTP.NON_PRINT_TEXT_FORMAT </code> if this method is never
     * called.
     * <p>
     * @param fileType The <code> _FILE_TYPE </code> constant indcating the
     *                 type of file.
     * @param formatOrByteSize  The format of the file (one of the
     *              <code>_FORMAT</code> constants.  In the case of
     *              <code>LOCAL_FILE_TYPE</code>, the byte size.
     * <p>
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean setFileType(int fileType, int formatOrByteSize)
         throws IOException
    {
      if(FTPReply.isPositiveCompletion(type(fileType, formatOrByteSize))) {
        __fileType   = fileType;
        __fileFormat = formatOrByteSize;
        return true; 
      }
      return false;
    }
  
  
    /***
     * Sets the file structure.  The default structure is
     * <code> FTP.FILE_STRUCTURE </code> if this method is never called.
     * <p>
     * @param structure  The structure of the file (one of the FTP class
     *         <code>_STRUCTURE</code> constants).
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean setFileStructure(int structure) throws IOException {
      if(FTPReply.isPositiveCompletion(stru(structure))) {
        __fileStructure = structure;
        return true; 
      }
      return false;
    }
  
  
    /***
     * Sets the transfer mode.  The default transfer mode
     * <code> FTP.STREAM_TRANSFER_MODE </code> if this method is never called.
     * <p>
     * @param mode  The new transfer mode to use (one of the FTP class
     *         <code>_TRANSFER_MODE</code> constants).
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean setFileTransferMode(int mode) throws IOException {
      if(FTPReply.isPositiveCompletion(mode(mode))) {
        __fileTransferMode = mode;
        return true; 
      }
      return false;
    }
  
  
    /***
     * Initiate a server to server file transfer.  This method tells the
     * server to which the client is connected to retrieve a given file from
     * the other server.
     * <p>
     * @param filename  The name of the file to retrieve.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean remoteRetrieve(String filename) throws IOException {
      if(__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
         __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
        return FTPReply.isPositivePreliminary(retr(filename));
      return false;
    }
  
  
    /***
     * Initiate a server to server file transfer.  This method tells the
     * server to which the client is connected to store a file on
     * the other server using the given filename.  The other server must
     * have had a <code> remoteRetrieve </code> issued to it by another
     * FTPClient.
     * <p>
     * @param filename  The name to call the file that is to be stored.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean remoteStore(String filename) throws IOException {
      if(__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
         __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
        return FTPReply.isPositivePreliminary(stor(filename));
      return false;
    }
  
  
    /***
     * Initiate a server to server file transfer.  This method tells the
     * server to which the client is connected to store a file on
     * the other server using a unique filename based on the given filename.
     * The other server must have had a <code> remoteRetrieve </code> issued
     * to it by another FTPClient.
     * <p>
     * @param filename  The name on which to base the filename of the file
     *                  that is to be stored.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean remoteStoreUnique(String filename) throws IOException {
      if(__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
         __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
        return FTPReply.isPositivePreliminary(stou(filename));
      return false;
    }
  
  
    /***
     * Initiate a server to server file transfer.  This method tells the
     * server to which the client is connected to store a file on
     * the other server using a unique filename.
     * The other server must have had a <code> remoteRetrieve </code> issued
     * to it by another FTPClient.  Many FTP servers require that a base
     * filename be given from which the unique filename can be derived.  For
     * those servers use the other version of <code> remoteStoreUnique</code>
     * <p>
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean remoteStoreUnique() throws IOException {
      if(__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
         __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
        return FTPReply.isPositivePreliminary(stou());
      return false;
    }
  
    // For server to server transfers
    /***
     * Initiate a server to server file transfer.  This method tells the
     * server to which the client is connected to append to a given file on
     * the other server.  The other server must have had a
     * <code> remoteRetrieve </code> issued to it by another FTPClient.
     * <p>
     * @param filename  The name of the file to be appended to, or if the
     *        file does not exist, the name to call the file being stored.
     * <p>
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean remoteAppend(String filename) throws IOException {
      if(__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
         __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
        return FTPReply.isPositivePreliminary(stor(filename));
      return false;
    }
  
    /***
     * There are a few FTPClient methods that do not complete the
     * entire sequence of FTP commands to complete a transaction.  These
     * commands require some action by the programmer after the reception
     * of a positive intermediate command.  After the programmer's code
     * completes its actions, it must call this method to receive
     * the completion reply from the server and verify the success of the
     * entire transaction.
     * <p>
     * For example, 
     * <pre>
     * InputStream input;
     * OutputStream output;
     * input  = new FileInputStream("foobaz.txt");
     * output = ftp.storeFileStream("foobar.txt")
     * if(!FTPReply.isPositiveIntermediate(ftp.getReplyCode())) {
     *     input.close();
     *     output.close();
     *     ftp.logout();
     *     ftp.disconnect();
     *     System.err.println("File transfer failed.");
     *     System.exit(1);
     * }
     * Util.copyStream(input, output);
     * input.close();
     * output.close();
     * // Must call completePendingCommand() to finish command.
     * if(!ftp.completePendingCommand()) {
     *     ftp.logout();
     *     ftp.disconnect();
     *     System.err.println("File transfer failed.");
     *     System.exit(1);
     * }
     * </pre>
     * <p>
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean completePendingCommand() throws IOException {
      return FTPReply.isPositiveCompletion(getReply());
    }
  
  
    /***
     * Retrieves a named file from the server and writes it to the given
     * OutputStream.  This method does NOT close the given OutputStream.
     * If the current file type is ASCII, line separators in the file are
     * converted to the local representation.
     * <p>
     * @param remote  The name of the remote file.
     * @param local   The local OutputStream to which to write the file.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception CopyStreamException  If an I/O error occurs while actually
     *      transferring the file.  The CopyStreamException allows you to
     *      determine the number of bytes transferred and the IOException
     *      causing the error.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean retrieveFile(String remote, OutputStream local)
         throws IOException
    {
      InputStream input;
      Socket socket;
  
      if((socket = __openDataConnection(FTPCommand.RETR, remote)) == null)
        return false;
  
      input = new BufferedInputStream(socket.getInputStream());
      if(__fileType == ASCII_FILE_TYPE)
        input = new FromNetASCIIInputStream(input);
      // Treat everything else as binary for now
      try {
        Util.copyStream(input, local);
      } catch(IOException e) {
        try {
  	socket.close();
        } catch(IOException f) {
        }
        throw e;
      }
      socket.close();
      return completePendingCommand();
    }
  
    /***
     * Returns an InputStream from which a named file from the server
     * can be read.  If the current file type is ASCII, the returned
     * InputStream will convert line separators in the file to
     * the local representation.  You must close the InputStream when you
     * finish reading from it.  The InputStream itself will take care of
     * closing the parent data connection socket upon being closed.  To
     * finalize the file transfer you must call
     * <a href="#completePendingCommand"> completePendingCommand </a> and
     * check its return value to verify success.
     * <p>
     * @param remote  The name of the remote file.
     * @return An InputStream from which the remote file can be read.  If
     *      the data connection cannot be opened (e.g., the file does not
     *      exist), null is returned (in which case you may check the reply
     *      code to determine the exact reason for failure).
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public InputStream retrieveFileStream(String remote) throws IOException {
      InputStream input;
      Socket socket;
  
      if((socket = __openDataConnection(FTPCommand.RETR, remote)) == null)
        return null;
  
      input = socket.getInputStream();
      if(__fileType == ASCII_FILE_TYPE)
        input = new FromNetASCIIInputStream(input);
      return new org.apache.commons.io.SocketInputStream(socket, input);
    }
  
  
    /***
     * Stores a file on the server using the given name and taking input
     * from the given InputStream.  This method does NOT close the given
     * InputStream.  If the current file type is ASCII, line separators in
     * the file are transparently converted to the NETASCII format (i.e.,
     * you should not attempt to create a special InputStream to do this).
     * <p>
     * @param remote  The name to give the remote file.
     * @param local   The local InputStream from which to read the file.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception CopyStreamException  If an I/O error occurs while actually
     *      transferring the file.  The CopyStreamException allows you to
     *      determine the number of bytes transferred and the IOException
     *      causing the error.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean storeFile(String remote, InputStream local)
         throws IOException
    { return __storeFile(FTPCommand.STOR, remote, local); }
  
  
    /***
     * Returns an OutputStream through which data can be written to store
     * a file on the server using the given name.  If the current file type
     * is ASCII, the returned OutputStream will convert line separators in
     * the file to the NETASCII format  (i.e., you should not attempt to
     * create a special OutputStream to do this).  You must close the
     * OutputStream when you finish writing to it.  The OutputStream itself
     * will take care of closing the parent data connection socket upon being
     * closed.  To finalize the file transfer you must call
     * <a href="#completePendingCommand"> completePendingCommand </a> and
     * check its return value to verify success.
     * <p>
     * @param remote  The name to give the remote file.
     * @return An OutputStream through which the remote file can be written.  If
     *      the data connection cannot be opened (e.g., the file does not
     *      exist), null is returned (in which case you may check the reply
     *      code to determine the exact reason for failure).
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public OutputStream storeFileStream(String remote) throws IOException {
      return __storeFileStream(FTPCommand.STOR, remote);
    }
  
    /***
     * Appends to a file on the server with the given name, taking input
     * from the given InputStream.  This method does NOT close the given
     * InputStream.  If the current file type is ASCII, line separators in
     * the file are transparently converted to the NETASCII format (i.e.,
     * you should not attempt to create a special InputStream to do this).
     * <p>
     * @param remote  The name of the remote file.
     * @param local   The local InputStream from which to read the data to
     *                be appended to the remote file.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception CopyStreamException  If an I/O error occurs while actually
     *      transferring the file.  The CopyStreamException allows you to
     *      determine the number of bytes transferred and the IOException
     *      causing the error.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean appendFile(String remote, InputStream local)
         throws IOException
    { return __storeFile(FTPCommand.APPE, remote, local); }
  
    /***
     * Returns an OutputStream through which data can be written to append
     * to a file on the server with the given name.  If the current file type
     * is ASCII, the returned OutputStream will convert line separators in
     * the file to the NETASCII format  (i.e., you should not attempt to
     * create a special OutputStream to do this).  You must close the
     * OutputStream when you finish writing to it.  The OutputStream itself
     * will take care of closing the parent data connection socket upon being
     * closed.  To finalize the file transfer you must call
     * <a href="#completePendingCommand"> completePendingCommand </a> and
     * check its return value to verify success.
     * <p>
     * @param remote  The name of the remote file.
     * @return An OutputStream through which the remote file can be appended.
     *      If the data connection cannot be opened (e.g., the file does not
     *      exist), null is returned (in which case you may check the reply
     *      code to determine the exact reason for failure).
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public OutputStream appendFileStream(String remote) throws IOException {
      return __storeFileStream(FTPCommand.APPE, remote);
    }
  
    /***
     * Stores a file on the server using a unique name derived from the
     * given name and taking input
     * from the given InputStream.  This method does NOT close the given
     * InputStream.  If the current file type is ASCII, line separators in
     * the file are transparently converted to the NETASCII format (i.e.,
     * you should not attempt to create a special InputStream to do this).
     * <p>
     * @param remote  The name on which to base the unique name given to
     *                the remote file.
     * @param local   The local InputStream from which to read the file.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception CopyStreamException  If an I/O error occurs while actually
     *      transferring the file.  The CopyStreamException allows you to
     *      determine the number of bytes transferred and the IOException
     *      causing the error.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean storeUniqueFile(String remote, InputStream local)
         throws IOException
    { return __storeFile(FTPCommand.STOU, remote, local); }
  
  
    /***
     * Returns an OutputStream through which data can be written to store
     * a file on the server using a unique name derived from the given name.
     * If the current file type
     * is ASCII, the returned OutputStream will convert line separators in
     * the file to the NETASCII format  (i.e., you should not attempt to
     * create a special OutputStream to do this).  You must close the
     * OutputStream when you finish writing to it.  The OutputStream itself
     * will take care of closing the parent data connection socket upon being
     * closed.  To finalize the file transfer you must call
     * <a href="#completePendingCommand"> completePendingCommand </a> and
     * check its return value to verify success.
     * <p>
     * @param remote  The name on which to base the unique name given to
     *                the remote file.
     * @return An OutputStream through which the remote file can be written.  If
     *      the data connection cannot be opened (e.g., the file does not
     *      exist), null is returned (in which case you may check the reply
     *      code to determine the exact reason for failure).
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public OutputStream storeUniqueFileStream(String remote) throws IOException {
      return __storeFileStream(FTPCommand.STOU, remote);
    }
  
    /***
     * Stores a file on the server using a unique name assigned by the
     * server and taking input from the given InputStream.  This method does
     * NOT close the given
     * InputStream.  If the current file type is ASCII, line separators in
     * the file are transparently converted to the NETASCII format (i.e.,
     * you should not attempt to create a special InputStream to do this).
     * <p>
     * @param remote  The name to give the remote file.
     * @param local   The local InputStream from which to read the file.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception CopyStreamException  If an I/O error occurs while actually
     *      transferring the file.  The CopyStreamException allows you to
     *      determine the number of bytes transferred and the IOException
     *      causing the error.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean storeUniqueFile(InputStream local) throws IOException {
      return __storeFile(FTPCommand.STOU, null, local);
    }
  
    /***
     * Returns an OutputStream through which data can be written to store
     * a file on the server using a unique name assigned by the server.
     * If the current file type
     * is ASCII, the returned OutputStream will convert line separators in
     * the file to the NETASCII format  (i.e., you should not attempt to
     * create a special OutputStream to do this).  You must close the
     * OutputStream when you finish writing to it.  The OutputStream itself
     * will take care of closing the parent data connection socket upon being
     * closed.  To finalize the file transfer you must call
     * <a href="#completePendingCommand"> completePendingCommand </a> and
     * check its return value to verify success.
     * <p>
     * @param remote  The name to give the remote file.
     * @return An OutputStream through which the remote file can be written.  If
     *      the data connection cannot be opened (e.g., the file does not
     *      exist), null is returned (in which case you may check the reply
     *      code to determine the exact reason for failure).
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public OutputStream storeUniqueFileStream() throws IOException {
      return __storeFileStream(FTPCommand.STOU, null);
    }
  
    /***
     * Reserve a number of bytes on the server for the next file transfer.
     * <p>
     * @param bytes  The number of bytes which the server should allocate.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean allocate(int bytes) throws IOException {
      return FTPReply.isPositiveCompletion(allo(bytes));
    }
  
  
    /***
     * Reserve space on the server for the next file transfer.
     * <p>
     * @param bytes  The number of bytes which the server should allocate.
     * @param bytes  The size of a file record.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean allocate(int bytes, int recordSize) throws IOException {
      return FTPReply.isPositiveCompletion(allo(bytes, recordSize));
    }
  
  
    /***
     * Restart a <code>STREAM_TRANSFER_MODE</code> file transfer starting
     * from the given offset.  This will only work on FTP servers supporting
     * the REST comand for the stream transfer mode.  However, most FTP
     * servers support this.  Any subsequent file transfer will start
     * reading or writing the remote file from the indicated offset.
     * <p>
     * @param offset  The offset into the remote file at which to start the
     *           next file transfer.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean restart(long offset) throws IOException {
      return FTPReply.isPositiveIntermediate(rest(Long.toString(offset)));
    }
  
  
    /***
     * Renames a remote file.
     * <p>
     * @param from  The name of the remote file to rename.
     * @param to    The new name of the remote file.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean rename(String from, String to) throws IOException {
      if(!FTPReply.isPositiveIntermediate(rnfr(from)))
        return false;
  
      return FTPReply.isPositiveCompletion(rnto(to));
    }
  
  
    /***
     * Abort a transfer in progress.
     * <p>
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean abort() throws IOException {
      return FTPReply.isPositiveCompletion(abor());
    }
  
    /***
     * Deletes a file on the FTP server.
     * <p>
     * @param pathname   The pathname of the file to be deleted.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean deleteFile(String pathname) throws IOException {
      return FTPReply.isPositiveCompletion(dele(pathname));
    }
  
  
    /***
     * Removes a directory on the FTP server (if empty).
     * <p>
     * @param pathname  The pathname of the directory to remove.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean removeDirectory(String pathname) throws IOException {
      return FTPReply.isPositiveCompletion(rmd(pathname));
    }
  
  
    /***
     * Creates a new subdirectory on the FTP server in the current directory
     * (if a relative pathname is given) or where specified (if an absolute
     * pathname is given).
     * <p>
     * @param pathname The pathname of the directory to create.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean makeDirectory(String pathname) throws IOException {
      return FTPReply.isPositiveCompletion(mkd(pathname));
    }
  
  
    /***
     * Returns the pathname of the current working directory.
     * <p>
     * @return The pathname of the current working directory.  If it cannot
     *         be obtained, returns null.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public String printWorkingDirectory() throws IOException {
      if(pwd() != FTPReply.PATHNAME_CREATED)
        return null;
  
      return __parsePathname((String)_replyLines.elementAt(0));
    }
  
  
    /***
     * Send a site specific command.
     * <p>
     * @param argument  The site specific command and arguments.
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean sendSiteCommand(String arguments) throws IOException {
      return FTPReply.isPositiveCompletion(site(arguments));
    }
  
  
    /***
     * Fetches the system type name from the server and returns the string.
     * <p>
     * @return The system type name obtained from the server.  null if the
     *       information could not be obtained.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *  command to the server or receiving a reply from the server.
     ***/
    public String getSystemName() throws IOException {
      if(syst() == FTPReply.NAME_SYSTEM_TYPE)
        return ((String)_replyLines.elementAt(0)).substring(4);
  
      return null;
    }
  
  
    /***
     * Fetches the system help information from the server and returns the
     * full string.
     * <p>
     * @return The system help string obtained from the server.  null if the
     *       information could not be obtained.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *  command to the server or receiving a reply from the server.
     ***/
    public String listHelp() throws IOException {
      if(FTPReply.isPositiveCompletion(help()))
        return getReplyString();
      return null;
    }
  
  
    /***
     * Fetches the help information for a given command from the server and
     * returns the full string.
     * <p>
     * @param  The command on which to ask for help.
     * @return The command help string obtained from the server.  null if the
     *       information could not be obtained.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *  command to the server or receiving a reply from the server.
     ***/
    public String listHelp(String command) throws IOException {
      if(FTPReply.isPositiveCompletion(help(command)))
        return getReplyString();
      return null;
    }
  
  
    /***
     * Sends a NOOP command to the FTP server.  This is useful for preventing
     * server timeouts.
     * <p>
     * @return True if successfully completed, false if not.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public boolean sendNoOp() throws IOException {
      return FTPReply.isPositiveCompletion(noop());
    }
  
  
    /***
     * Obtain a list of filenames in a directory (or just the name of a given
     * file, which is not particularly useful).  This information is obtained
     * through the NLST command.  If the given pathname is a directory and
     * contains no files,  a zero length array is returned only
     * if the FTP server returned a positive completion code, otherwise
     * null is returned (the FTP server returned a 550 error No files found.).
     * If the directory is not empty, an array of filenames in the directory is
     * returned. If the pathname corresponds
     * to a file, only that file will be listed.  The server may or may not
     * expand glob expressions.
     * <p>
     * @param pathname  The file or directory to list.
     * @return The list of filenames contained in the given path.  null if
     *     the list could not be obtained.  If there are no filenames in
     *     the directory, a zero-length array is returned.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public String[] listNames(String pathname) throws IOException {
      String line;
      Socket socket;
      BufferedReader reader;
      Vector results;
  
      if((socket = __openDataConnection(FTPCommand.NLST, pathname)) == null)
        return null;
  
      reader =
        new BufferedReader(new InputStreamReader(socket.getInputStream()));
  
      results = new Vector();
      while((line = reader.readLine()) != null)
        results.addElement(line);
      reader.close();
      socket.close();
  
      if(completePendingCommand()) {
        String[] result;
        result = new String[results.size()];
        results.copyInto(result);
        return result;
      }
  
      return null;
    }
  
  
    /***
     * Obtain a list of filenames in the current working directory
     * This information is obtained through the NLST command.  If the current
     * directory contains no files, a zero length array is returned only
     * if the FTP server returned a positive completion code, otherwise,
     * null is returned (the FTP server returned a 550 error No files found.).
     * If the directory is not empty, an array of filenames in the directory is
     * returned.
     * <p>
     * @return The list of filenames contained in the current working
     *     directory.  null if the list could not be obtained.
     *     If there are no filenames in the directory, a zero-length array
     *     is returned.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public String[] listNames() throws IOException { return listNames(null); }
  
  
  
    /***
     * Using a programmer specified <code> FTPFileListParser </code>, obtain a 
     * list of file information for a directory or information for
     * just a single file.  This information is obtained through the LIST
     * command.  The contents of the returned array is determined by the
     * <code> FTPFileListParser </code> used.
     * The server may or may not expand glob expressions.  You should avoid
     * using glob expressions because the return format for glob listings
     * differs from server to server and will likely cause this method to fail.
     * <p>
     * @param parser The <code> FTPFileListParser </code> that should be
     *         used to parse the server file listing.   
     * @param pathname  The file or directory to list.
     * @return The list of file information contained in the given path in
     *         the format determined by the <code> parser </code> parameter.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public FTPFile[] listFiles(FTPFileListParser parser, String pathname) 
         throws IOException
    {
      Socket socket;
      FTPFile[] results;
  
      if((socket = __openDataConnection(FTPCommand.LIST, pathname)) == null)
        return null;
  
      results = parser.parseFileList(socket.getInputStream());
  
      socket.close();
  
      completePendingCommand();
  
      return results;
    }
  
  
    /***
     * Using a programmer specified <code> FTPFileListParser </code>,
     * obtain a list of file information for the current working directory.
     * This information is obtained through the LIST command.
     * The contents of the array returned is determined by the
     * <code> FTPFileListParser </code> used.
     * <p>
     * @param parser The <code> FTPFileListParser </code> that should be
     *         used to parse the server file listing.   
     * @return The list of file information contained in the given path in
     *         the format determined by the <code> parser </code> parameter.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public FTPFile[] listFiles(FTPFileListParser parser) throws IOException {
      return listFiles(parser, null);
    }
  
  
    /***
     * Using the <code> DefaultFTPFileListParser </code>, obtain a list of
     * file information
     * for a directory or information for just a single file.  This information
     * is obtained through the LIST command.  If the given
     * pathname is a directory and contains no files, <code> null </code> is
     * returned, otherwise an array of <code> FTPFile </code> instances
     * representing the files in the directory is returned.
     * If the pathname corresponds to a file, only the information for that
     * file will be contained in the array (which will be of length 1).  The
     * server may or may not expand glob expressions.  You should avoid using
     * glob expressions because the return format for glob listings differs
     * from server to server and will likely cause this method to fail.
     * <p>
     * @param pathname  The file or directory to list.
     * @return The list of file information contained in the given path.  null
     *     if the list could not be obtained or if there are no files in
     *     the directory.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public FTPFile[] listFiles(String pathname) throws IOException {
      return listFiles(__fileListParser, pathname);
    }
  
    /***
     * Using the <code> DefaultFTPFileListParser </code>, obtain a list of 
     * file information for the current working directory.  This information
     * is obtained through the LIST command.  If the given
     * current directory contains no files null is returned, otherwise an 
     * array of <code> FTPFile </code> instances representing the files in the
     * directory is returned.
     * <p>
     * @return The list of file information contained in the current working
     *     directory.  null if the list could not be obtained or if there are
     *     no files in the directory.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public FTPFile[] listFiles() throws IOException {
      return listFiles(__fileListParser);
    }
  
  
    /***
     * Issue the FTP STAT command to the server.
     * <p>
     * @return The status information returned by the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public String getStatus() throws IOException {
      if(FTPReply.isPositiveCompletion(stat()))
        return getReplyString();
      return null;
    }
  
  
    /***
     * Issue the FTP STAT command to the server for a given pathname.  This
     * should produce a listing of the file or directory.
     * <p>
     * @return The status information returned by the server.
     * @exception FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @exception IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     ***/
    public String getStatus(String pathname) throws IOException {
      if(FTPReply.isPositiveCompletion(stat(pathname)))
        return getReplyString();
      return null;
    }
  
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/net/src/java/org/apache/commons/net/ftp/FTPCommand.java
  
  Index: FTPCommand.java
  ===================================================================
  package org.apache.commons.net.ftp;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Commons" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  import java.net.*;
  import java.io.*;
  
  /***
   * FTPCommand stores a set of constants for FTP command codes.  To interpret
   * the meaning of the codes, familiarity with RFC 959 is assumed.
   * The mnemonic constant names are transcriptions from the code descriptions
   * of RFC 959.  For those who think in terms of the actual FTP commands,
   * a set of constants such as <a href="#USER"> USER </a> are provided
   * where the constant name is the same as the FTP command.
   * <p>
   * <p>
   * @author Daniel F. Savarese
   ***/
  
  public final class FTPCommand {
  
  
    public static final int USER = 0;
    public static final int PASS = 1;
    public static final int ACCT = 2;
    public static final int CWD  = 3;
    public static final int CDUP = 4;
    public static final int SMNT = 5;
    public static final int REIN = 6;
    public static final int QUIT = 7;
    public static final int PORT = 8;
    public static final int PASV = 9;
    public static final int TYPE = 10;
    public static final int STRU = 11;
    public static final int MODE = 12;
    public static final int RETR = 13;
    public static final int STOR = 14;
    public static final int STOU = 15;
    public static final int APPE = 16;
    public static final int ALLO = 17;
    public static final int REST = 18;
    public static final int RNFR = 19;
    public static final int RNTO = 20;
    public static final int ABOR = 21;
    public static final int DELE = 22;
    public static final int RMD  = 23;
    public static final int MKD  = 24;
    public static final int PWD  = 25;
    public static final int LIST = 26;
    public static final int NLST = 27;
    public static final int SITE = 28;
    public static final int SYST = 29;
    public static final int STAT = 30;
    public static final int HELP = 31;
    public static final int NOOP = 32;
  
    public static final int USERNAME                   = USER;
    public static final int PASSWORD                   = PASS;
    public static final int ACCOUNT                    = ACCT;
    public static final int CHANGE_WORKING_DIRECTORY   = CWD;
    public static final int CHANGE_TO_PARENT_DIRECTORY = CDUP;
    public static final int STRUCTURE_MOUNT            = SMNT;
    public static final int REINITIALIZE               = REIN;
    public static final int LOGOUT                     = QUIT;
    public static final int DATA_PORT                  = PORT;
    public static final int PASSIVE                    = PASV;
    public static final int REPRESENTATION_TYPE        = TYPE;
    public static final int FILE_STRUCTURE             = STRU;
    public static final int TRANSFER_MODE              = MODE;
    public static final int RETRIEVE                   = RETR;
    public static final int STORE                      = STOR;
    public static final int STORE_UNIQUE               = STOU;
    public static final int APPEND                     = APPE;
    public static final int ALLOCATE                   = ALLO;
    public static final int RESTART                    = REST;
    public static final int RENAME_FROM                = RNFR;
    public static final int RENAME_TO                  = RNTO;
    public static final int ABORT                      = ABOR;
    public static final int DELETE                     = DELE;
    public static final int REMOVE_DIRECTORY           = RMD;
    public static final int MAKE_DIRECTORY             = MKD;
    public static final int PRINT_WORKING_DIRECTORY    = PWD;
    //  public static final int LIST = LIST;
    public static final int NAME_LIST                  = NLST;
    public static final int SITE_PARAMETERS            = SITE;
    public static final int SYSTEM                     = SYST;
    public static final int STATUS                     = STAT;
    //public static final int HELP = HELP;
    //public static final int NOOP = NOOP;
  
    // Cannot be instantiated
    private FTPCommand() {}
  
    static final String[] _commands =  {
      "USER", "PASS", "ACCT", "CWD",  "CDUP", "SMNT", "REIN", "QUIT", "PORT",
      "PASV", "TYPE", "STRU", "MODE", "RETR", "STOR", "STOU", "APPE", "ALLO",
      "REST", "RNFR", "RNTO", "ABOR", "DELE", "RMD",  "MKD",  "PWD",  "LIST",
      "NLST", "SITE", "SYST", "STAT", "HELP", "NOOP"
    };
  
  
    /***
     * Retrieve the FTP protocol command string corresponding to a specified
     * command code.
     * <p>
     * @param The command code.
     * @return The FTP protcol command string corresponding to a specified
     *         command code.
     ***/
    public static final String getCommand(int command) {
      return _commands[command];
    }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/net/src/java/org/apache/commons/net/ftp/FTPConnectionClosedException.java
  
  Index: FTPConnectionClosedException.java
  ===================================================================
  package org.apache.commons.net.ftp;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Commons" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  import java.io.*;
  
  /***
   * FTPConnectionClosedException is used to indicate the premature or
   * unexpected closing of an FTP connection resulting from a 
   * <a href="org.apache.commons.net.ftp.FTPReply.html#SERVICE_NOT_AVAILABLE">
   * FTPReply.SERVICE_NOT_AVAILABLE </a> response (FTP reply code 421) to a
   * failed FTP command.  This exception is derived from IOException and
   * therefore may be caught either as an IOException or specifically as an
   * FTPConnectionClosedException.
   * <p>
   * <p>
   * @author Daniel F. Savarese
   * @see FTP
   * @see FTPClient
   ***/
  
  public class FTPConnectionClosedException extends IOException {
  
    /*** Constructs a FTPConnectionClosedException with no message ***/
    public FTPConnectionClosedException() {
      super();
    }
  
    /*** 
     * Constructs a FTPConnectionClosedException with a specified message.
     * <p>
     * @param message  The message explaining the reason for the exception.
     ***/
    public FTPConnectionClosedException(String message) {
      super(message);
    }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/net/src/java/org/apache/commons/net/ftp/FTPFile.java
  
  Index: FTPFile.java
  ===================================================================
  package org.apache.commons.net.ftp;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Commons" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  import java.util.*;
  
  /***
   * The FTPFile class is used to represent information about files stored
   * on an FTP server.  Because there is no standard representation for
   * file information on FTP servers, it may not always be possible to
   * extract all the information that can be represented by FTPFile, or
   * it may even be possible to extract more information.  In cases where
   * more information can be extracted, you will want to subclass FTPFile
   * and implement your own <a href="org.apache.commons.net.ftp.FTPFileListParser.html">
   * FTPFileListParser </a> to extract the information.
   * However, most FTP servers return file information in a format that
   * can be completely parsed by
   * <a href="org.apache.commons.net.ftp.DefaultFTPFileListParser.html">
   * DefaultFTPFileListParser </a> and stored in FTPFile.
   * <p>
   * <p>
   * @author Daniel F. Savarese
   * @see FTPFileListParser
   * @see DefaultFTPFileListParser
   * @see FTPClient#listFiles
   ***/
  
  public class FTPFile implements java.io.Serializable {
    /** A constant indicating an FTPFile is a file. ***/
    public static final int FILE_TYPE          = 0;
    /** A constant indicating an FTPFile is a directory. ***/
    public static final int DIRECTORY_TYPE     = 1;
    /** A constant indicating an FTPFile is a symbolic link. ***/
    public static final int SYMBOLIC_LINK_TYPE = 2;
    /** A constant indicating an FTPFile is of unknown type. ***/
    public static final int UNKNOWN_TYPE       = 3;
  
    /** A constant indicating user access permissions. ***/
    public static final int USER_ACCESS  = 0;
    /** A constant indicating group access permissions. ***/
    public static final int GROUP_ACCESS = 1;
    /** A constant indicating world access permissions. ***/
    public static final int WORLD_ACCESS = 2;
  
    /** A constant indicating file/directory read permission. ***/
    public static final int READ_PERMISSION    = 0;
    /** A constant indicating file/directory write permission. ***/
    public static final int WRITE_PERMISSION   = 1;
    /**
     * A constant indicating file execute permission or directory listing
     * permission.
     ***/
    public static final int EXECUTE_PERMISSION = 2;
  
    int _type, _hardLinkCount;
    long _size;
    String _rawListing, _user, _group, _name, _link;
    Calendar _date;
    boolean[] _permissions[];
  
    /*** Creates an empty FTPFile. ***/
    public FTPFile() {
      _permissions = new boolean[3][3];
      _rawListing  = null;
      _type = UNKNOWN_TYPE;
      _hardLinkCount = 0;
      _size = 0;
      _user  = null;
      _group = null;
      _date  = null;
      _name  = null;
    }
  
  
    /***
     * Set the original FTP server raw listing from which the FTPFile was
     * created.
     * <p>
     * @param rawListing  The raw FTP server listing.
     ***/
    public void setRawListing(String rawListing) {
       _rawListing = rawListing;
    }
  
    /***
     * Get the original FTP server raw listing used to initialize the FTPFile.
     * <p>
     * @return The original FTP server raw listing used to initialize the
     *         FTPFile.
     ***/
    public String getRawListing() {
      return _rawListing;
    }
  
  
    /***
     * Determine if the file is a directory.
     * <p>
     * @return True if the file is of type <code>DIRECTORY_TYPE</code>, false if
     *         not.
     ***/
    public boolean isDirectory()    { return (_type == DIRECTORY_TYPE); }
  
    /***
     * Determine if the file is a regular file.
     * <p>
     * @return True if the file is of type <code>FILE_TYPE</code>, false if
     *         not.
     ***/
    public boolean isFile()         { return (_type == FILE_TYPE); }
  
    /***
     * Determine if the file is a symbolic link.
     * <p>
     * @return True if the file is of type <code>UNKNOWN_TYPE</code>, false if
     *         not.
     ***/
    public boolean isSymbolicLink() { return (_type == SYMBOLIC_LINK_TYPE); }
  
    /***
     * Determine if the type of the file is unknown.
     * <p>
     * @return True if the file is of type <code>UNKNOWN_TYPE</code>, false if
     *         not.
     ***/
    public boolean isUnknown()      { return (_type == UNKNOWN_TYPE); }
  
  
    /***
     * Set the type of the file (<code>DIRECTORY_TYPE</code>,
     * <code>FILE_TYPE</code>, etc.).
     * <p>
     * @param type  The integer code representing the type of the file.
     ***/
    public void setType(int type) { _type = type; }
  
  
    /***
     * Return the type of the file (one of the <code>_TYPE</code> constants),
     * e.g., if it is a directory, a regular file, or a symbolic link.
     * <p>
     * @return The type of the file.
     ***/
    public int getType()            { return _type; }
  
  
    /***
     * Set the name of the file.
     * <p>
     * @param name  The name of the file.
     ***/
    public void setName(String name) { _name = name; }
  
    /***
     * Return the name of the file.
     * <p>
     * @return The name of the file.
     ***/
    public String getName()         { return _name; }
  
  
    /***
     * Set the file size in bytes.
     * <p>
     * @param The file size in bytes.
     ***/
    public void setSize(long size)   {  _size = size; }
  
  
    /***
     * Return the file size in bytes.
     * <p>
     * @return The file size in bytes.
     ***/
    public long getSize()            { return _size; }
  
  
    /***
     * Set the number of hard links to this file.  This is not to be
     * confused with symbolic links.
     * <p>
     * @param links  The number of hard links to this file.
     ***/
    public void setHardLinkCount(int links) { _hardLinkCount = links; }
  
  
    /***
     * Return the number of hard links to this file.  This is not to be
     * confused with symbolic links.
     * <p>
     * @return The number of hard links to this file.
     ***/
    public int getHardLinkCount()   { return _hardLinkCount; }
  
  
    /***
     * Set the name of the group owning the file.  This may be
     * a string representation of the group number.
     * <p>
     * @param group The name of the group owning the file.
     ***/
    public void setGroup(String group) { _group = group; }
  
  
    /***
     * Returns the name of the group owning the file.  Sometimes this will be
     * a string representation of the group number.
     * <p>
     * @return The name of the group owning the file.
     ***/
    public String getGroup()        { return _group; }
  
  
    /***
     * Set the name of the user owning the file.  This may be
     * a string representation of the user number;
     * <p>
     * @param user The name of the user owning the file.
     ***/
    public void setUser(String user) { _user = user; }
  
    /***
     * Returns the name of the user owning the file.  Sometimes this will be
     * a string representation of the user number.
     * <p>
     * @return The name of the user owning the file.
     ***/
    public String getUser()          { return _user; }
  
  
    /***
     * If the FTPFile is a symbolic link, use this method to set the name of the
     * file being pointed to by the symbolic link.
     * <p>
     * @param link  The file pointed to by the symbolic link.
     ***/
    public void setLink(String link) { _link = link; }
  
  
    /***
     * If the FTPFile is a symbolic link, this method returns the name of the
     * file being pointed to by the symbolic link.  Otherwise it returns null.
     * <p>
     * @return The file pointed to by the symbolic link (null if the FTPFile
     *         is not a symbolic link).
     ***/
    public String getLink()         { return _link; }
  
  
    /***
     * Set the file timestamp.  This usually the last modification time.
     * The parameter is not cloned, so do not alter its value after calling
     * this method.
     * <p>
     * @param date A Calendar instance representing the file timestamp.
     ***/
    public void setTimestamp(Calendar date) { _date = date; }
  
  
    /***
     * Returns the file timestamp.  This usually the last modification time.
     * <p>
     * @return A Calendar instance representing the file timestamp.
     ***/
    public Calendar getTimestamp()      { return _date; }
  
  
    /***
     * Set if the given access group (one of the <code> _ACCESS </code>
     * constants) has the given access permission (one of the
     * <code> _PERMISSION </code> constants) to the file.
     * <p>
     * @param access The access group (one of the <code> _ACCESS </code>
     *               constants)
     * @param permission The access permission (one of the 
     *               <code> _PERMISSION </code> constants)
     * @param value  True if permission is allowed, false if not.
     ***/
    public void setPermission(int access, int permission, boolean value) {
      _permissions[access][permission] = value;
    }
  
  
    /***
     * Determines if the given access group (one of the <code> _ACCESS </code>
     * constants) has the given access permission (one of the
     * <code> _PERMISSION </code> constants) to the file.
     * <p>
     * @param access The access group (one of the <code> _ACCESS </code>
     *               constants)
     * @param permission The access permission (one of the 
     *               <code> _PERMISSION </code> constants)
     ***/
    public boolean hasPermission(int access, int permission) {
      return _permissions[access][permission];
    }
  
  
    /***
     * Returns a string representation of the FTPFile information.  This
     * will be the raw FTP server listing that was used to initialize the
     * FTPFile instance.
     * <p>
     * @return A string representation of the FTPFile information.
     ***/
    public String toString()        { return _rawListing; }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/net/src/java/org/apache/commons/net/ftp/FTPFileListParser.java
  
  Index: FTPFileListParser.java
  ===================================================================
  package org.apache.commons.net.ftp;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Commons" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  import java.io.*;
  
  /***
   * FTPFileListParser defines the interface for parsing FTP file listings
   * and converting that information into an array of
   * <a href="org.apache.commons.net.ftp.FTPFile.html"> FTPFile </a> instances.
   * Sometimes you will want to parse unusual listing formats, in which
   * case you would create your own implementation of FTPFileListParser and
   * if necessary, subclass FTPFile.
   * <p>
   * <p>
   * @author Daniel F. Savarese
   * @see FTPFile
   * @see FTPClient#listFiles
   ***/
  
  public interface FTPFileListParser {
  
    /***
     * Parses an FTP server file listing and converts it into a usable format
     * in the form of an array of <code> FTPFile </code> instances.  If the
     * file list contains no files, <code> null </code> should be
     * returned, otherwise an array of <code> FTPFile </code> instances
     * representing the files in the directory is returned.
     * <p>
     * @param listStream The InputStream from which the file list should be
     *        read.
     * @return The list of file information contained in the given path.  null
     *     if the list could not be obtained or if there are no files in
     *     the directory.
     * @exception IOException  If an I/O error occurs reading the listStream.
     ***/
    public FTPFile[] parseFileList(InputStream listStream) throws IOException;
  
  } 
  
  
  
  1.1                  jakarta-commons-sandbox/net/src/java/org/apache/commons/net/ftp/FTPReply.java
  
  Index: FTPReply.java
  ===================================================================
  package org.apache.commons.net.ftp;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Commons" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  import java.net.*;
  import java.io.*;
  
  /***
   * FTPReply stores a set of constants for FTP reply codes.  To interpret
   * the meaning of the codes, familiarity with RFC 959 is assumed.
   * The mnemonic constant names are transcriptions from the code descriptions
   * of RFC 959.  For those who think in terms of the actual reply code values,
   * a set of CODE_NUM constants are provided where NUM is the numerical value
   * of the code.
   * <p>
   * <p>
   * @author Daniel F. Savarese
   ***/
  
  public final class FTPReply {
  
    public static final int CODE_110 = 110;
    public static final int CODE_120 = 120;
    public static final int CODE_125 = 125;
    public static final int CODE_150 = 150;
    public static final int CODE_200 = 200;
    public static final int CODE_202 = 202;
    public static final int CODE_211 = 211;
    public static final int CODE_212 = 212;
    public static final int CODE_213 = 213;
    public static final int CODE_214 = 214;
    public static final int CODE_215 = 215;
    public static final int CODE_220 = 220;
    public static final int CODE_221 = 221;
    public static final int CODE_225 = 225;
    public static final int CODE_226 = 226;
    public static final int CODE_227 = 227;
    public static final int CODE_230 = 230;
    public static final int CODE_250 = 250;
    public static final int CODE_257 = 257;
    public static final int CODE_331 = 331;
    public static final int CODE_332 = 332;
    public static final int CODE_350 = 350;
    public static final int CODE_421 = 421;
    public static final int CODE_425 = 425;
    public static final int CODE_426 = 426;
    public static final int CODE_450 = 450;
    public static final int CODE_451 = 451;
    public static final int CODE_452 = 452;
    public static final int CODE_500 = 500;
    public static final int CODE_501 = 501;
    public static final int CODE_502 = 502;
    public static final int CODE_503 = 503;
    public static final int CODE_504 = 504;
    public static final int CODE_530 = 530;
    public static final int CODE_532 = 532;
    public static final int CODE_550 = 550;
    public static final int CODE_551 = 551;
    public static final int CODE_552 = 552;
    public static final int CODE_553 = 553;
  
    public static final int RESTART_MARKER                     = CODE_110;
    public static final int SERVICE_NOT_READY                  = CODE_120;
    public static final int DATA_CONNECTION_ALREADY_OPEN       = CODE_125;
    public static final int FILE_STATUS_OK                     = CODE_150;
    public static final int COMMAND_OK                         = CODE_200;
    public static final int COMMAND_IS_SUPERFLUOUS             = CODE_202;
    public static final int SYSTEM_STATUS                      = CODE_211;
    public static final int DIRECTORY_STATUS                   = CODE_212;
    public static final int FILE_STATUS                        = CODE_213;
    public static final int HELP_MESSAGE                       = CODE_214;
    public static final int NAME_SYSTEM_TYPE                   = CODE_215;
    public static final int SERVICE_READY                      = CODE_220;
    public static final int SERVICE_CLOSING_CONTROL_CONNECTION = CODE_221;
    public static final int DATA_CONNECTION_OPEN               = CODE_225;
    public static final int CLOSING_DATA_CONNECTION            = CODE_226;
    public static final int ENTERING_PASSIVE_MODE              = CODE_227;
    public static final int USER_LOGGED_IN                     = CODE_230;
    public static final int FILE_ACTION_OK                     = CODE_250;
    public static final int PATHNAME_CREATED                   = CODE_257;
    public static final int NEED_PASSWORD                      = CODE_331;
    public static final int NEED_ACCOUNT                       = CODE_332;
    public static final int FILE_ACTION_PENDING                = CODE_350;
    public static final int SERVICE_NOT_AVAILABLE              = CODE_421;
    public static final int CANNOT_OPEN_DATA_CONNECTION        = CODE_425;
    public static final int TRANSFER_ABORTED                   = CODE_426;
    public static final int FILE_ACTION_NOT_TAKEN              = CODE_450;
    public static final int ACTION_ABORTED                     = CODE_451;
    public static final int INSUFFICIENT_STORAGE               = CODE_452;
    public static final int UNRECOGNIZED_COMMAND               = CODE_500;
    public static final int SYNTAX_ERROR_IN_ARGUMENTS          = CODE_501;
    public static final int COMMAND_NOT_IMPLEMENTED            = CODE_502;
    public static final int BAD_COMMAND_SEQUENCE               = CODE_503;
    public static final int COMMAND_NOT_IMPLEMENTED_FOR_PARAMETER = CODE_504;
    public static final int NOT_LOGGED_IN                      = CODE_530;
    public static final int NEED_ACCOUNT_FOR_STORING_FILES     = CODE_532;
    public static final int FILE_UNAVAILABLE                   = CODE_550;
    public static final int PAGE_TYPE_UNKNOWN                  = CODE_551;
    public static final int STORAGE_ALLOCATION_EXCEEDED        = CODE_552;
    public static final int FILE_NAME_NOT_ALLOWED              = CODE_553;
  
    // Cannot be instantiated
    private FTPReply() {}
  
    /***
     * Determine if a reply code is a positive preliminary response.  All
     * codes beginning with a 1 are positive preliminary responses.
     * Postitive preliminary responses are used to indicate tentative success.
     * No further commands can be issued to the FTP server after a positive
     * preliminary response until a follow up response is received from the
     * server.
     * <p>
     * @param reply  The reply code to test.
     * @return True if a reply code is a postive preliminary response, false
     *         if not.
     ***/
    public static boolean isPositivePreliminary(int reply) {
      return (reply >= 100 && reply < 200);
    }
  
    /***
     * Determine if a reply code is a positive completion response.  All
     * codes beginning with a 2 are positive completion responses.
     * The FTP server will send a positive completion response on the final
     * successful completion of a command.
     * <p>
     * @param reply  The reply code to test.
     * @return True if a reply code is a postive completion response, false
     *         if not.
     ***/
    public static boolean isPositiveCompletion(int reply) {
      return (reply >= 200 && reply < 300);
    }
  
    /***
     * Determine if a reply code is a positive intermediate response.  All
     * codes beginning with a 3 are positive intermediate responses.
     * The FTP server will send a positive intermediate response on the
     * successful completion of one part of a multi-part sequence of
     * commands.  For example, after a successful USER command, a positive
     * intermediate response will be sent to indicate that the server is
     * ready for the PASS command.
     * <p>
     * @param reply  The reply code to test.
     * @return True if a reply code is a postive intermediate response, false
     *         if not.
     ***/
    public static boolean isPositiveIntermediate(int reply) {
      return (reply >= 300 && reply < 400);
    }
  
    /***
     * Determine if a reply code is a negative transient response.  All
     * codes beginning with a 4 are negative transient responses.
     * The FTP server will send a negative transient response on the
     * failure of a command that can be reattempted with success.
     * <p>
     * @param reply  The reply code to test.
     * @return True if a reply code is a negative transient response, false
     *         if not.
     ***/
    public static boolean isNegativeTransient(int reply) {
      return (reply >= 400 && reply < 500);
    }
  
    /***
     * Determine if a reply code is a negative permanent response.  All
     * codes beginning with a 5 are negative permanent responses.
     * The FTP server will send a negative permanent response on the
     * failure of a command that cannot be reattempted with success.
     * <p>
     * @param reply  The reply code to test.
     * @return True if a reply code is a negative permanent response, false
     *         if not.
     ***/
    public static boolean isNegativePermanent(int reply) {
      return (reply >= 500 && reply < 600);
    }
  
  }
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>