//==============================================================================
// FTPClientRun.java
//==============================================================================

package tribble.net.ftp;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;

import java.lang.Exception;
import java.lang.Integer;
import java.lang.String;
import java.lang.System;

import java.util.ArrayList;


/*******************************************************************************
* Simple FTP client driver.
* Allows clients to establish FTP connections, send and receive files, get
* remote directory listings, etc.
*
* <!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
* <p>
* <b>References</b>
*
* <p>
* IETF RFC 959 - File Transfer Protocol (FTP) <br/>
* <a href="http://www.ietf.org/rfc/rfc0959.txt"
*  >www.ietf.org/rfc/rfc0959.txt</a>.
*
* <!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
* <dl>
* <dt> <b>Source code:</b> </dt>
*  <dd> Available at:
*   <a href="http://david.tribble.com/src/java/tribble/net/ftp/FTPClientRun.java"
*    >http://david.tribble.com/src/java/tribble/net/ftp/FTPClientRun.java</a>
*  </dd>
* <dt> <b>Documentation:</b> </dt>
*  <dd> Available at:
*   <a href="http://david.tribble.com/docs/tribble/net/ftp/FTPClientRun.html"
*    >http://david.tribble.com/docs/tribble/net/ftp/FTPClientRun.html</a>
*  </dd>
* </dl>
*
* <!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
* @version	API 2.0 $Revision: 1.12 $ $Date: 2010/07/12 21:28:59 $
* @since	API 1.0, 2006-04-06
* @author	David R. Tribble (david&#64;tribble.com).
*	<p>
*	Copyright ©2006-2010 by David R. Tribble, all rights reserved.<br/>
*	Permission is granted to any person or entity except those designated
*	by the United States Department of State as a terrorist, or terrorist
*	government or agency, to use and distribute this source code provided
*	that the original copyright notice remains present and unaltered.
*
* @see	FTPClientAdapter
* @see	FTPClientI
* @see	FTPClient
*/

public abstract class FTPClientRun
{
    /** Revision information. */
    static final String		REV =
        "@(#)tribble/net/ftp/FTPClientRun.java API 2.0 $Revision: 1.12 $ $Date: 2010/07/12 21:28:59 $\n";


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Static variables

    /** Debug tracing flag. */
    static boolean		s_debugs =	false;


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Static methods

    /***************************************************************************
    * Test driver.
    * This method may be called by the <tt>main()</tt> methods of classes that
    * implement {@link FTPClientI} or extend {@link FTPClientAdapter}.
    *
    * <p>
    * <b> Usage </b>
    * <p>
    * <tt>
    * java tribble.net.ftp.FTPClientRun
    *    <i>host</i> <i>port</i>[<i>:dport</i>]|-
    *    <i>user</i>|- <i>password</i> [-<i>action</i>...]
    * </tt>
    *
    * <!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
    * @param	clt
    * FTP client.
    *
    * @param	args
    * Command line arguments.
    *
    * @throws	Exception
    * Thrown if a non-ignored error occurs.
    *
    * @since	1.1, 2006-04-06
    */
    static void run(FTPClientI clt, String[] args)
        throws Exception
    {
        int	i =	0;

        // Handle special command options
        if (args.length > 4  &&  args[4].equals("-D"))
        {
            s_debugs = true;
            if (clt instanceof FTPClientAdapter)
            {
                System.out.println("] Debugs enabled");
                ((FTPClientAdapter) clt).m_debugOut = System.out;
            }
        }

        // Check args
        if (args.length-i < 4)
        {
            // Display a command usage message
            System.out.println("Simple FTP client.");
            System.out.println();

            System.out.println("usage:  java " + clt.getClass().getName());
            System.out.println("            "
                + "host cport[:dport]|- user|- password [-action...]");
            System.out.println();

            System.out.println("Actions:");
            System.out.println("    -D              "
                + "Enable debug tracing.");
            System.out.println("    -D-             "
                + "Disable debug tracing.");
            System.out.println("    -I              "
                + "Ignore exceptions.");
            System.out.println("    -I-             "
                + "Terminate if an exception occurs.");

            System.out.println("    -a              "
                + "Set text (ASCII) mode.");
            System.out.println("    -af file dest   "
                + "Append a renamed file; if 'file' is '-', read data from");
            System.out.println("                    "
                + "standard input.");
            System.out.println("    -app file       "
                + "Append to a remote file.");
            System.out.println("    -b              "
                + "Set binary mode.");
            System.out.println("    -cd dir         "
                + "Set remote directory.");
            System.out.println("    -cu             "
                + "Set remote directory up one level.");
            System.out.println("    -lcd dir        "
                + "Set local directory.");
            System.out.println("    -d              "
                + "Remote directory listing.");
            System.out.println("    -dl dir         "
                + "Remote directory listing.");
            System.out.println("    -ds             "
                + "Short directory listing.");
            System.out.println("    -g file         "
                + "Get a file.");
            System.out.println("    -gf file dest   "
                + "Get a renamed file; if 'dest' is '-', write data to");
            System.out.println("                    "
                + "standard output.");
            System.out.println("    -h              "
                + "Display FTP help.");
            System.out.println("    -mn             "
                + "Non-passive data port mode.");
            System.out.println("    -mp             "
                + "Passive data port mode.");
            System.out.println("    -p file         "
                + "Put a file.");
            System.out.println("    -pf file dest   "
                + "Put a renamed file; if 'file' is '-', read data from");
            System.out.println("                    "
                + "standard input.");
            System.out.println("    -ping           "
                + "Ping the remote FTP system.");
            System.out.println("    -md dir         "
                + "Create a remote directory.");
            System.out.println("    -mv file dest   "
                + "Rename a file.");
            System.out.println("    -pwd            "
                + "Get current remote directory.");
            System.out.println("    -rd dir         "
                + "Remove a remote directory.");
            System.out.println("    -rm file        "
                + "Remove a remote file.");
            System.out.println("    -stat           "
                + "Get remote system status.");
            System.out.println("    -sys            "
                + "Get remote system identification.");
            System.out.println("    -to secs        "
                + "Set socket I/O time-out (seconds).");

            // Punt
            System.exit(255);
        }

        // Create an FTP session
        clt.setPassive(true);

        clt.setHost(args[i+0]);

        if (!args[i+1].equals("-"))
        {
            int		j;

            j = args[i+1].indexOf(':');
            if (j > 0)
            {
                clt.setCommandPort(Integer.parseInt(args[i+1].substring(0, j)));
                clt.setDataPort(Integer.parseInt(args[i+1].substring(j+1)));
            }
            else
                clt.setCommandPort(Integer.parseInt(args[i+1]));
        }

        if (args[i+2].equals("-"))
            clt.setUserID("anonymous");
        else
            clt.setUserID(args[i+2]);

        clt.setPassword(args[i+3]);
        i += 4;

        try
        {
            // Open an FTP connection
            System.out.println("] Connecting: " + clt.getHost());
            clt.connect();

            // Log in to the FTP system
            System.out.println("] Logging on: " + clt.getUserID());
            clt.login();

            // Set text (ASCII) mode
            System.out.println("] Set text (ASCII) mode");
            clt.setTextMode(true);

            // Get current local working directory
            System.out.println("] Local directory is: "
                + clt.getLocalDir());
            System.out.println();

            // Process trailing commands
            runCommands(clt, args, i);
        }
        catch (Exception ex)
        {
            // FTP failure occurred
            System.out.println();
            System.out.println("*** Exception: " + ex.getClass().getName());
            System.out.println("*** " + ex.getMessage());
            System.out.println();
            throw (ex);
        }
        finally
        {
            // Clean up the FTP connection
            if (clt.isConnected())
            {
                System.out.println("] Disconnecting: " + clt.getHost());
                clt.disconnect();
            }
        }
    }


    /***************************************************************************
    * Test driver helper method.
    *
    * @param	clt
    * FTP client.
    *
    * @param	args
    * Command line arguments.
    *
    * @param	i
    * Index of the first command option to process from <tt>args[]</tt>.
    *
    * @throws	Exception
    * Thrown if a non-ignored error occurs.
    *
    * @since	1.6, 2006-04-06
    */
    private static void runCommands(FTPClientI clt, String[] args, int i)
        throws Exception
    {
        boolean		ignExcept =	false;

        // Process trailing commands
        for ( ;  i < args.length;  i++)
        {
            String	cmd =	"?";

            try
            {
                String	s;

                // Perform the command line option (action)
                cmd = args[i];
                if (cmd.equals("-a")  ||  cmd.equals("-asc")  ||
                    cmd.equals("-t"))
                {
                    System.out.println("] Set text (ASCII) mode");
                    clt.setTextMode(true);
                }
                else if (cmd.equals("-af")  ||  cmd.equals("-appf"))
                {
                    boolean	mode;

                    i += 2;
                    mode = clt.setTextMode(true);
                    clt.setTextMode(mode);
                    System.out.println("] Append file ("
                        + (mode ? "text" : "binary") + "): "
                        + args[i-1] + " to: " + args[i]);

                    if (args[i-1].equals("-"))
                        clt.appendFile(System.in, args[i]);
                    else
                        clt.appendFile(args[i-1], args[i]);
                }
                else if (cmd.equals("-app"))
                {
                    boolean	mode;

                    i++;
                    mode = clt.setTextMode(true);
                    clt.setTextMode(mode);
                    System.out.println("] Append file ("
                        + (mode ? "text" : "binary") + "): "
                        + args[i]);
                    clt.appendFile(args[i], args[i]);
                }
                else if (cmd.equals("-b")  ||  cmd.equals("-bin"))
                {
                    System.out.println("] Set binary mode");
                    clt.setTextMode(false);
                }
                else if (cmd.equals("-cd")  ||  cmd.equals("-chdir"))
                {
                    i++;
                    System.out.println("] Set remote directory: " + args[i]);
                    s = clt.setRemoteDir(args[i]);
                    System.out.println("] Remote directory is: " + s);
                }
                else if (cmd.equals("-cu")  ||  cmd.equals("-cdup"))
                {
                    System.out.println("] Set remote directory up");
                    s = clt.setRemoteDirUp();
                    System.out.println("] Remote directory is: " + s);
                }
                else if (cmd.equals("-d")  ||  cmd.equals("-dir")  ||
                    cmd.equals("-ls"))
                {
                    System.out.println("] Directory listing:");
                    clt.getDirectoryList("", System.out);
                }
                else if (cmd.equals("-D")  ||  cmd.equals("-D+"))
                {
                    s_debugs = true;
                    if (clt instanceof FTPClientAdapter)
                    {
                        System.out.println("] Debugs enabled");
                        ((FTPClientAdapter) clt).m_debugOut = System.out;
                    }
                }
                else if (cmd.equals("-D-"))
                {
                    s_debugs = false;
                    if (clt instanceof FTPClientAdapter)
                    {
                        System.out.println("] Debugs disabled");
                        ((FTPClientAdapter) clt).m_debugOut = null;
                    }
                }
                else if (cmd.equals("-dl"))
                {
                    i++;
                    System.out.println("] Directory listing: " + args[i]);
                    clt.getDirectoryList(args[i], System.out);
                }
                else if (cmd.equals("-ds"))
                {
                    System.out.println("] Short directory listing:");
                    clt.getDirectoryNames("", System.out);
                }
                else if (cmd.equals("-g")  ||  cmd.equals("-get"))
                {
                    boolean	mode;
                    File	fname;
                    String	dst;

                    i++;
                    fname = new File(args[i]);
                    dst = fname.getName();
                    mode = clt.setTextMode(true);
                    clt.setTextMode(mode);
                    System.out.println("] Get file ("
                        + (mode ? "text" : "binary") + "): "
                        + dst + " to " + args[i]);
                    clt.getFile(dst, args[i]);
                }
                else if (cmd.equals("-gf")  ||  cmd.equals("-getf"))
                {
                    boolean	mode;

                    i += 2;
                    mode = clt.setTextMode(true);
                    clt.setTextMode(mode);
                    System.out.println("] Get file ("
                        + (mode ? "text" : "binary") + "): "
                        + args[i-1] + " to: " + args[i]);

                    if (args[i].equals("-"))
                        clt.getFile(args[i-1], System.out);
                    else
                        clt.getFile(args[i-1], args[i]);
                }
                else if (cmd.equals("-h")  ||  cmd.equals("-help")  ||
                    cmd.equals("-?"))
                {
                    System.out.println("] Help list:");
                    clt.getHelp(System.out);
                }
                else if (cmd.equals("-I"))
                {
                    System.out.println("] Ignore exceptions");
                    ignExcept = true;
                }
                else if (cmd.equals("-I-"))
                {
                    System.out.println("] Terminate on exception");
                    ignExcept = false;
                }
                else if (cmd.equals("-lcd"))
                {
                    i++;
                    System.out.println("] Set local directory: " + args[i]);
                    clt.setLocalDir(args[i]);
                    System.out.println("] Local directory is: " + args[i]);
                }
                else if (cmd.equals("-md")  ||  cmd.equals("-mkdir"))
                {
                    i++;
                    System.out.println("] Create remote directory: " + args[i]);
                    clt.createDirectory(args[i]);
                }
                else if (cmd.equals("-mv")  ||  cmd.equals("-ren"))
                {
                    i += 2;
                    System.out.println("] Rename remote file: " + args[i-1]
                        + " to " + args[i]);
                    clt.rename(args[i-1], args[i]);
                }
                else if (cmd.equals("-mn")  ||  cmd.equals("-na")  ||
                    cmd.equals("-nopasv"))
                {
                    System.out.println("] Non-passive data port mode");
                    clt.setPassive(false);
                }
                else if (cmd.equals("-mp")  ||  cmd.equals("-np")  ||
                    cmd.equals("-pasv"))
                {
                    System.out.println("] Passive data port mode");
                    clt.setPassive(true);
                }
                else if (cmd.equals("-p")  ||  cmd.equals("-put"))
                {
                    boolean	mode;
                    File	fname;
                    String	dst;

                    i++;
                    fname = new File(args[i]);
                    dst = fname.getName();
                    mode = clt.setTextMode(true);
                    clt.setTextMode(mode);
                    System.out.println("] Put file ("
                        + (mode ? "text" : "binary") + "): "
                        + args[i] + " to " + dst);
                    clt.putFile(args[i], dst);
                }
                else if (cmd.equals("-pf")  ||  cmd.equals("-putf"))
                {
                    boolean	mode;

                    i += 2;
                    mode = clt.setTextMode(true);
                    clt.setTextMode(mode);
                    System.out.println("] Put file ("
                        + (mode ? "text" : "binary") + "): "
                        + args[i-1] + " to: " + args[i]);

                    if (args[i-1].equals("-"))
                        clt.putFile(System.in, args[i]);
                    else
                        clt.putFile(args[i-1], args[i]);
                }
                else if (cmd.equals("-ping"))
                {
                    System.out.println("] Ping: " + clt.getHost());
                    clt.ping();
                }
                else if (cmd.equals("-pwd"))
                {
                    s = clt.getRemoteDir();
                    System.out.println("] Remote directory is: " + s);
                }
                else if (cmd.equals("-rd")  ||  cmd.equals("-rmdir"))
                {
                    i++;
                    System.out.println("] Remove remote directory: " + args[i]);
                    clt.removeDirectory(args[i]);
                }
                else if (cmd.equals("-rm")  ||  cmd.equals("-del"))
                {
                    i++;
                    System.out.println("] Remove remote file: " + args[i]);
                    clt.removeFile(args[i]);
                }
                else if (cmd.equals("-stat"))
                {
                    System.out.println("] Get remote system status:");
                    clt.getStatus(System.out);
                }
                else if (cmd.equals("-sys"))
                {
                    System.out.println("] Remote system identification:");
                    clt.getSystemInfo(System.out);
                }
                else if (cmd.equals("-to")  ||  cmd.equals("-timeout"))
                {
                    i++;
                    System.out.println("] Set I/O time-out: " + args[i]);
                    clt.setTimeOut(Integer.parseInt(args[i]));
                }
                else
                    System.out.println("*** Bad option: '" + cmd + "'");

                if (s_debugs)
                    System.out.println();
            }
            catch (ArrayIndexOutOfBoundsException ex)
            {
                // Bad command usage, missing arg
                System.out.println("*** Missing command line argument for: "
                    + cmd);
                if (!ignExcept)
                    throw (ex);
            }
            catch (IOException ex)
            {
                // FTP failure occurred
                if (ignExcept)
                {
                    System.out.println("*** Exception: "
                        + ex.getClass().getName());
                    System.out.println("*** " + ex.getMessage());
                    System.out.println();
                }
                else
                    throw (ex);
            }
        }
    }
}

// End FTPClientRun.java
