/** BEGIN COPYRIGHT BLOCK
 * Copyright (C) 2001 Sun Microsystems, Inc.  Used by permission.
 * Copyright (C) 2005 Red Hat, Inc.
 * All rights reserved.
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; version 2
 * of the License.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 * 
 * END COPYRIGHT BLOCK **/
package com.netscape.management.admserv.cmdln;


import java.io.File;
import java.io.FileDescriptor;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Locale;
import java.util.Hashtable;
import java.util.Vector;
import java.util.StringTokenizer;
import com.netscape.management.client.cmd.CommandLineParser;
import com.netscape.management.client.util.AdmTask;
import com.netscape.management.client.util.URLByteEncoder;
import com.netscape.management.client.util.Debug;


/**
 * Netscape Admin Server Command Line (admconfig).
 *
 * @author   Peter Lee (phlee@netscape.com)
 * @version  %I%, %G%
 * @see      CommandLineParser
 * @see      CountLogEntriesTask
 * @see      ViewLogEntriesTask
 * @see      AdmpwTask
 */

public class CommandLine extends Object {

    // Needed to run multiple tasks from a single invocation.
    protected static String[]_fileArgs = null;
    protected static CommandLineParser _fileOpt = null;
    protected static CommandLineParser _opt = null;


    /**
     * Starting point for Netscape Admin Server Command Line (admconfig).
     * The CommandLine constructor parses all arguments to admconfig, and
     * the run invocations task the server using AdmTask.
     *
     * @param args  an array of strings representing the command line
     *              arguments
     */
    static public void main(String[] args) {
        //Debug.setTrace(true);
        CommandLine cl = new CommandLine(args);
        cl.run(_fileOpt, _fileArgs, false); // Invoke tasks specified in a file first
        cl.run(_opt, args, true); // Invoke tasks specified on the command line
        System.exit(0); // Return success!
    }



    // Task Codes
    protected static final int TC_SHOW_HELP = 0;
    protected static final int TC_RESTART = 1;
    protected static final int TC_STOP = 2;
    protected static final int TC_GET_SYSTEM_USER = 3;
    protected static final int TC_SET_SYSTEM_USER = 4;
    protected static final int TC_GET_PORT = 5;
    protected static final int TC_SET_PORT = 6;
    protected static final int TC_GET_ADMINUSERS = 7;
    protected static final int TC_SET_ADMINUSERS = 8;
    protected static final int TC_GET_ERRORLOG = 9;
    protected static final int TC_SET_ERRORLOG = 10;
    protected static final int TC_GET_ACCESSLOG = 11;
    protected static final int TC_SET_ACCESSLOG = 12;
    protected static final int TC_GET_HOSTS = 13;
    protected static final int TC_SET_HOSTS = 14;
    protected static final int TC_GET_ADDRESSES = 15;
    protected static final int TC_SET_ADDRESSES = 16;
    protected static final int TC_GET_ONEACLDIR = 17;
    protected static final int TC_SET_ONEACLDIR = 18;
    protected static final int TC_GET_DEFAULTACCEPTLANGUAGE = 19;
    protected static final int TC_SET_DEFAULTACCEPTLANGUAGE = 20;
    protected static final int TC_GET_CLASSNAME = 21;
    protected static final int TC_SET_CLASSNAME = 22;
    protected static final int TC_COUNT_ERRORLOG_ENTRIES = 23;
    protected static final int TC_VIEW_ERRORLOG_ENTRIES = 24;
    protected static final int TC_COUNT_ACCESSLOG_ENTRIES = 25;
    protected static final int TC_VIEW_ACCESSLOG_ENTRIES = 26;
    protected static final int TC_ENABLE_ENDUSER_ACCESS = 27;
    protected static final int TC_DISABLE_ENDUSER_ACCESS = 28;
    protected static final int TC_ENABLE_DSGW_ACCESS = 29;
    protected static final int TC_DISABLE_DSGW_ACCESS = 30;
    protected static final int TC_GET_ADMIN_UID = 31;
    protected static final int TC_SET_ADMIN_UID = 32;
    protected static final int TC_SET_ADMIN_PWD = 33;
    protected static final int TC_GET_DSCONFIG = 34;
    protected static final int TC_SET_DSCONFIG = 35;
    protected static final int TC_GET_CACHE_LIFETIME = 36;
    protected static final int TC_SET_CACHE_LIFETIME = 37;
    protected static final int TC_GET_SERVER_ADDRESS = 38;
    protected static final int TC_SET_SERVER_ADDRESS = 39;
    protected static final int TC_GET_UGDSCONFIG = 40;
    protected static final int TC_SET_UGDSCONFIG = 41;

    // Help file names
    protected static final String[]_admconfigHelpLookup = { "[help-main]",
    "[help-restart]", "[help-stop]", "[help-getsystemuser]",
    "[help-setsystemuser]", "[help-getport]", "[help-setport]",
    "[help-getadminusers]", "[help-setadminusers]", "[help-geterrorlog]",
    "[help-seterrorlog]", "[help-getaccesslog]", "[help-setaccesslog]",
    "[help-gethosts]", "[help-sethosts]", "[help-getaddresses]",
    "[help-setaddresses]", "[help-getoneacldir]", "[help-setoneacldir]",
    "[help-getdefaultacceptlanguage]", "[help-setdefaultacceptlanguage]",
    "[help-getclassname]", "[help-setclassname]", "[help-counterrorlogentries]",
    "[help-viewerrorlogentries]", "[help-countaccesslogentries]",
    "[help-viewaccesslogentries]", "[help-enableenduseraccess]",
    "[help-disableenduseraccess]", "[help-enabledsgwaccess]",
    "[help-disabledsgwaccess]", "[help-getadminuid]", "[help-setadminuid]",
    "[help-setadminpwd]", "[help-getdsconfig]", "[help-setdsconfig]",
    "[help-getcachelifetime]", "[help-setcachelifetime]", "[help-getserveraddress]",
    "[help-setserveraddress]", "[help-getugdsconfig]", "[help-setugdsconfig]" };

    // Task names
    protected static final String[]_admconfigTaskLookup = { "-restart",
    "-stop", "-getsystemuser", "-setsystemuser", "-getport",
    "-setport", "-getadminusers", "-setadminusers", "-geterrorlog",
    "-seterrorlog", "-getaccesslog", "-setaccesslog", "-gethosts",
    "-sethosts", "-getaddresses", "-setaddresses", "-getoneacldir",
    "-setoneacldir", "-getdefaultacceptlanguage", "-setdefaultacceptlanguage",
    "-getclassname", "-setclassname", "-counterrorlogentries",
    "-viewerrorlogentries", "-countaccesslogentries", "-viewaccesslogentries",
    "-enableenduseraccess", "-disableenduseraccess", "-enabledsgwaccess",
    "-disabledsgwaccess", "-getadminuid", "-setadminuid", "-setadminpwd",
    "-getdsconfig", "-setdsconfig", "-getcachelifetime", "-setcachelifetime",
    "-getserveraddress", "-setserveraddress", "-getugdsconfig",
    "-setugdsconfig" };

    // Option Control String Codes
    protected static final int OPT_ENCRYPTION = 0;
    protected static final int OPT_HELP = 1;
    protected static final int OPT_INPUT_FILE = 2;
    protected static final int OPT_QUIET_LEVEL = 3;
    protected static final int OPT_SERVER = 4;
    protected static final int OPT_USER = 5;
    protected static final int OPT_VERSION = 6;
    protected static final int OPT_CONTINUE_ON_ERROR = 7;
    protected static final int OPT_TASKS_OFFSET = 7;

    // Option Control strings. These are different than the task names!
    protected static final String[]_admconfigControlStrings = { "-encryption",
    "-help:", "-inputfile:", "-verbose:", "-server:", "-user:",
    "-version", "-continueonerror", "-restart", "-stop", "-getsystemuser",
    "-setsystemuser:", "-getport", "-setport:", "-getadminusers",
    "-setadminusers:", "-geterrorlog", "-seterrorlog:", "-getaccesslog",
    "-setaccesslog:", "-gethosts", "-sethosts:", "-getaddresses",
    "-setaddresses:", "-getoneacldir", "-setoneacldir:", "-getdefaultacceptlanguage",
    "-setdefaultacceptlanguage:", "-getclassname", "-setclassname:",
    "-counterrorlogentries", "-viewerrorlogentries:", "-countaccesslogentries",
    "-viewaccesslogentries:", "-enableenduseraccess", "-disableenduseraccess",
    "-enabledsgwaccess", "-disabledsgwaccess", "-getadminuid",
    "-setadminuid:", "-setadminpwd:", "-getdsconfig", "-setdsconfig:",
    "-getcachelifetime", "-setcachelifetime:", "-getserveraddress",
    "-setserveraddress:", "-getugdsconfig", "-setugdsconfig:" };


    protected static final String PACKAGE_DIR = "com/netscape/management/admserv/cmdln";
    protected static final String RESTART_TASK = "admin-serv/tasks/operation/Restart";
    protected static final String STOP_TASK = "admin-serv/tasks/operation/Stop";
    protected static final String READ_LOG_TASK = "admin-serv/tasks/configuration/ReadLog";
    protected static final String SERVER_SETUP_TASK = "admin-serv/tasks/configuration/ServerSetup";
    protected static final String ACCESS_SETUP_TASK = "admin-serv/tasks/configuration/AccessSetup";
    protected static final String DIRECTORY_SETUP_TASK = "admin-serv/tasks/configuration/DirectorySetup";
    protected static final String UG_DIRECTORY_SETUP_TASK = "admin-serv/tasks/configuration/UGDirectorySetup";
    protected static final String DATA_FILE = "admconfig.dat";
    protected static final String VERSION_FILE = "version.dat";


    protected String _protocol; // "http" or "https" depending on -e option
    protected String _server; // "hostname:port" combination
    protected String _admin; // administrator username
    protected String _password; // administrator password
    protected int _tc; // task code
    protected String _task; // user entered task string
    protected String _inputFile; // input file
    protected int _verbose; // screen message output level:
    //   (9=detailed, 0=none)
    protected String _newValue; // new value
    protected boolean _quitOnError;


    //task that require restart to take effect
    //-setAdminUID, -setAdminPwd, -setAdminUsers, -setDSConfig, -setPort,
    //-setSystemUser, -setUGDSConfig
    private void printRestartMessage() {
        System.out.println("\nRestart the Admin Server for the changes to take effect.");
    }


    /**
     * Constructor parses the command line arguments for admconfig. Since
     * different options cause admconfig to run differently, there is an
     * order of precedence for which option is "evaluated" first.
     * <p>
     * The first option that is checked is the -inputfile option for the
     * input file containing additional arguments. After the option file is
     * read in to a String, the arguments within the file are parsed exactly
     * the same way as the arguments supplied on the command line.
     * <p>
     * The next option checked is the -help option for help. If there is
     * -help anywhere in the command line argument, then help is displayed
     * and admconfig exits. For example, <code>admconfig -version -help</code>
     * will result only in the help being displayed.
     * <p>
     * The next option checked is the -version option for version information.
     * If there is -version anywhere in the argument list, then the version
     * information is displayed and admconfig exits. The only exception is in
     * the aforementioned case for -help.
     * <p>
     * The remaining admconfig options determine the parameters for the
     * server managing tasks. If there are duplicate information for an
     * option, for example,
     * <code>admconfig -server jaffer:31044 -server nugget:33333 ...</code>,
     * the <b>last</b> instance of the option (nugget:33333) is used.
     *
     * @param args  Command line arguments.
     */
    public CommandLine(String[] args) {

        if (args.length < 1) {
            showHelp(_admconfigHelpLookup[TC_SHOW_HELP]);
            System.exit(0);
        }

        // Parse the arguments into various options.
        _opt = new CommandLineParser(_admconfigControlStrings, args);

        _protocol = "http"; // Use regular protocol by default.
        _tc = TC_SHOW_HELP;
        _verbose = 5;
        _quitOnError = true;

        // Parse arguments provided in a file, if any.
        handleInputFile(_opt, args);

        // Parse the remaining arguments. Note that if there are
        // repeated arguments, the arguments in the _inputFile may
        // be overridden by ones on the command line. Since this
        // parses the remaining arguments, the required arguments
        // must be found, as indicated by the boolean parameter.
        // If the required arguments are not found, display usage
        // information and exit.
        parseArguments(_opt, args, true);
    }



    /**
      * Determines which tasks to run on the server. Supports running
      * multiple tasks during this instance of the command line. Reuses
      * options such as the server and user information. If the
      * <code>taskRequired</code> flag is <code>true</code>, then at
      * least one valid task must have been run or must be about to run.
      *
      * @param taskOpt       the CommandLineParser object to parse the taskArgs
      * @param taskArgs      an array of String arguments containing the tasks
      * @param taskRequired  a boolean flag indicating whether the task must be specified
      */
    public void run(CommandLineParser taskOpt, String[] taskArgs,
            boolean taskRequired) {

        if ((taskOpt == null) || (taskArgs == null) ||
                (taskArgs.length == 0)) {
            if (taskRequired == true) {
                // Task must be specified!
                System.err.println("ERROR admconfig:");
                System.err.println("    Task not specified.");
                System.err.println("    Try admconfig -h for help on using admconfig.\n");
                System.exit(1);
            } else {
                return; // Simply return.
            }
        }

        int tc = TC_SHOW_HELP;
        if (taskArgs != null) {
            for (int i = 0; i < taskArgs.length; i++) {
                _newValue = null;
                tc = getTaskCode(taskArgs[i], false); // Don't want error messages for mismatches
                switch (tc) {
                case TC_SET_SYSTEM_USER:
                case TC_SET_PORT:
                case TC_SET_ADMINUSERS:
                case TC_SET_ERRORLOG:
                case TC_SET_ACCESSLOG:
                case TC_SET_HOSTS:
                case TC_SET_ADDRESSES:
                case TC_SET_ONEACLDIR:
                case TC_SET_DEFAULTACCEPTLANGUAGE:
                case TC_SET_CLASSNAME:
                case TC_VIEW_ERRORLOG_ENTRIES:
                case TC_VIEW_ACCESSLOG_ENTRIES:
                case TC_SET_ADMIN_UID:
                case TC_SET_ADMIN_PWD:
                case TC_SET_DSCONFIG:
                case TC_SET_CACHE_LIFETIME:
                case TC_SET_SERVER_ADDRESS:
                    // Make sure there is a parameter for the above tasks!
                    _newValue = taskOpt.getOptionParam(
                            _admconfigControlStrings[tc +
                            OPT_TASKS_OFFSET]);
                    if (_newValue == null) {
                        System.err.println("ERROR admconfig:");
                        System.err.println("    Invalid number of parameters specified for task.");
                        showHelp(_admconfigHelpLookup[tc]);
                        if (_quitOnError) {
                            System.exit(1);
                        } else {
                            return; // Try the next valid task, if any.
                        }
                    }
                    break; // out of switch statement
                case TC_SET_UGDSCONFIG:
                    // parameter is optional for this task
                    _newValue = taskOpt.getOptionParam(
                            _admconfigControlStrings[tc +
                            OPT_TASKS_OFFSET]);
                    break; // out of switch statement
                default:
                    break; // out of switch statement
                }

                if (TC_SHOW_HELP != tc) {
                    // Cannot write over last good value. We need it to determine
                    // whether at least one task was specified.
                    _tc = tc;

                    // Display trace information if in full verbose mode.
                    if (9 == _verbose) {
                        System.out.println(
                                "\nadmconfig: about to run " + _task);
                        if (_newValue != null) {
                            System.out.println(
                                    "admconfig:        task arg: " +
                                    _newValue);
                        }
                    }

                    runTask(); // Task the server using AdmTask.
                }
            }
        }
        if ((true == taskRequired) && (TC_SHOW_HELP == _tc)) {
            // Task must be specified!
            System.err.println("ERROR admconfig:");
            System.err.println("    No valid task was specified.");
            System.err.println("    Try admconfig -h for help on using admconfig.\n");
            System.exit(1);
        }
    }


    /**
      * Runs the task that has been determined from the <code>run()</code>
      * method on the specified server.
      */
    public void runTask() {
        // Only need to encode arguments. HttpChannel already encodes
        // username and password.

        try {
            URL taskurl = null;
            String encodedFilename = null;
            StringTokenizer tokenizer = null;
            String startToken = null;
            String stopToken = null;
            String dsHostToken = null; // Used for both dsconfig and ugdsconfig
            String dsPortToken = null; // Used for both dsconfig and ugdsconfig
            String dsBaseDNToken = null; // Used for ugdsconfig
            String dsSSLFlagToken = null; // Used for both dsconfig and ugdsconfig
            String dsSSLFlagResult = null; // Used for dsconfig
            String dsBindDNToken = null; // Used for ugdsconfig
            String dsBindPwdToken = null; // Used for ugdsconfig
            String dsURL = null; // Used for ugdsconfig
            int logStart = 0;
            int logStop = 0;
            int dsPort = 0;
            int adminPort = 0;
            int cacheLifetime = 0;
            switch (_tc) {
            case TC_RESTART:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        RESTART_TASK + "?op=restart");
                break;
            case TC_STOP:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        STOP_TASK);
                break;
            case TC_GET_SYSTEM_USER:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=get&" +
                        URLByteEncoder.encodeUTF8("configuration.nssuitespotuser")
                        + "=");
                break;
            case TC_SET_SYSTEM_USER:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=set&" +
                        URLByteEncoder.encodeUTF8("configuration.nssuitespotuser")
                        + "=" + URLByteEncoder.encodeUTF8(_newValue));
                break;
            case TC_GET_PORT:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=get&" +
                        URLByteEncoder.encodeUTF8("configuration.nsserverport")
                        + "=");
                break;
            case TC_SET_PORT:
                adminPort = 0;
                try {
                    adminPort = Integer.parseInt(_newValue);
                } catch (NumberFormatException e) {
                    System.err.println("ERROR admconfig:");
                    System.err.println("    Cannot run " + _task);
                    System.err.println(
                            "    Specified server port is invalid: " +
                            _newValue);
                    System.err.println("");
                    if (_quitOnError) {
                        System.exit(1);
                    } else {
                        return;
                    }
                }
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=set&" +
                        URLByteEncoder.encodeUTF8("configuration.nsserverport")
                        + "=" + URLByteEncoder.encodeUTF8(_newValue));
                break;
            case TC_GET_ADMINUSERS:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=get&" +
                        URLByteEncoder.encodeUTF8("configuration.nsadminusers")
                        + "=");
                break;
            case TC_SET_ADMINUSERS:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=set&" +
                        URLByteEncoder.encodeUTF8("configuration.nsadminusers")
                        + "=" + URLByteEncoder.encodeUTF8(_newValue));
                break;
            case TC_GET_ERRORLOG:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=get&" +
                        URLByteEncoder.encodeUTF8("configuration.nserrorlog")
                        + "=");
                break;
            case TC_SET_ERRORLOG:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=set&" +
                        URLByteEncoder.encodeUTF8("configuration.nserrorlog")
                        + "=" + URLByteEncoder.encodeUTF8(_newValue));
                break;
            case TC_GET_ACCESSLOG:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=get&" +
                        URLByteEncoder.encodeUTF8("configuration.nsaccesslog")
                        + "=");
                break;
            case TC_SET_ACCESSLOG:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=set&" +
                        URLByteEncoder.encodeUTF8("configuration.nsaccesslog")
                        + "=" + URLByteEncoder.encodeUTF8(_newValue));
                break;
            case TC_GET_HOSTS:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=get&" +
                        URLByteEncoder.encodeUTF8("configuration.nsadminaccesshosts")
                        + "=");
                break;
            case TC_SET_HOSTS:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=set&" +
                        URLByteEncoder.encodeUTF8("configuration.nsadminaccesshosts")
                        + "=" + URLByteEncoder.encodeUTF8(_newValue));
                break;
            case TC_GET_ADDRESSES:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=get&" +
                        URLByteEncoder.encodeUTF8("configuration.nsadminaccessaddresses")
                        + "=");
                break;
            case TC_SET_ADDRESSES:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=set&" +
                        URLByteEncoder.encodeUTF8("configuration.nsadminaccessaddresses")
                        + "=" + URLByteEncoder.encodeUTF8(_newValue));
                break;
            case TC_GET_ONEACLDIR:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=get&" +
                        URLByteEncoder.encodeUTF8("configuration.nsadminoneacldir")
                        + "=");
                break;
            case TC_SET_ONEACLDIR:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=set&" +
                        URLByteEncoder.encodeUTF8("configuration.nsadminoneacldir")
                        + "=" + URLByteEncoder.encodeUTF8(_newValue));
                break;
            case TC_GET_DEFAULTACCEPTLANGUAGE:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=get&" +
                        URLByteEncoder.encodeUTF8("configuration.nsdefaultacceptlanguage")
                        + "=");
                break;
            case TC_SET_DEFAULTACCEPTLANGUAGE:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=set&" +
                        URLByteEncoder.encodeUTF8("configuration.nsdefaultacceptlanguage")
                        + "=" + URLByteEncoder.encodeUTF8(_newValue));
                break;
            case TC_GET_CLASSNAME:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=get&" +
                        URLByteEncoder.encodeUTF8("configuration.nsclassname")
                        + "=");
                break;
            case TC_SET_CLASSNAME:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=set&" +
                        URLByteEncoder.encodeUTF8("configuration.nsclassname")
                        + "=" + URLByteEncoder.encodeUTF8(_newValue));
                break;
            case TC_GET_CACHE_LIFETIME:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=get&" +
                        URLByteEncoder.encodeUTF8("configuration.nsadmincachelifetime")
                        + "=");
                break;
            case TC_SET_CACHE_LIFETIME:
                cacheLifetime = 0;
                try {
                    cacheLifetime = Integer.parseInt(_newValue);
                } catch (NumberFormatException e) {
                    System.err.println("ERROR admconfig:");
                    System.err.println("    Cannot run " + _task);
                    System.err.println(
                            "    Specified cache lifetime is invalid: " +
                            _newValue);
                    System.err.println("");
                    if (_quitOnError) {
                        System.exit(1);
                    } else {
                        return;
                    }
                }
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=set&" +
                        URLByteEncoder.encodeUTF8("configuration.nsadmincachelifetime")
                        + "=" + URLByteEncoder.encodeUTF8(_newValue));
                break;
            case TC_GET_SERVER_ADDRESS:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=get&" +
                        URLByteEncoder.encodeUTF8("configuration.nsserveraddress")
                        + "=");
                break;
            case TC_SET_SERVER_ADDRESS:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=set&" +
                        URLByteEncoder.encodeUTF8("configuration.nsserveraddress")
                        + "=" + URLByteEncoder.encodeUTF8(_newValue));
                break;
            case TC_COUNT_ERRORLOG_ENTRIES:
                encodedFilename = getLog("configuration.nserrorlog");
                if (encodedFilename == null) {
                    // We can simply return if null. The getLog method would
                    // have exited already if _quitOnError was true.
                    return;
                }
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        READ_LOG_TASK + "?op=count&" + "name=" +
                        encodedFilename);
                break;
            case TC_VIEW_ERRORLOG_ENTRIES:
                tokenizer = new StringTokenizer(_newValue);
                if (tokenizer.countTokens() != 2) {
                    System.err.println("ERROR admconfig:");
                    System.err.println("    Cannot run " + _task);
                    System.err.println(
                            "    Invalid number of arguments for the task: " +
                            tokenizer.countTokens());
                    System.err.println("");
                    if (_quitOnError) {
                        System.exit(1);
                    } else {
                        return;
                    }
                }
                // First token is the entry number to start displaying from.
                startToken = tokenizer.nextToken();
                logStart = 0;
                try {
                    logStart = Integer.parseInt(startToken);
                } catch (NumberFormatException e) {
                    System.err.println("ERROR admconfig:");
                    System.err.println("    Cannot run " + _task);
                    System.err.println(
                            "    The entry number to start viewing is invalid: " +
                            startToken);
                    System.err.println("");
                    if (_quitOnError) {
                        System.exit(1);
                    } else {
                        return;
                    }
                }
                // Second token is the last entry number to display.
                stopToken = tokenizer.nextToken();
                logStop = 0;
                try {
                    logStop = Integer.parseInt(stopToken);
                } catch (NumberFormatException e) {
                    System.err.println("ERROR admconfig:");
                    System.err.println("    Cannot run " + _task);
                    System.err.println(
                            "    The entry number to stop viewing is invalid: " +
                            stopToken);
                    System.err.println("");
                    if (_quitOnError) {
                        System.exit(1);
                    } else {
                        return;
                    }
                }
                encodedFilename = getLog("configuration.nserrorlog");
                if (encodedFilename == null) {
                    // We can simply return if null. The getLog method would
                    // have exited already if _quitOnError was true.
                    return;
                }
                // Finally, set the task url.
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        READ_LOG_TASK + "?op=read&" + "name=" +
                        encodedFilename + "&start=" + startToken +
                        "&stop=" + stopToken);
                break;
            case TC_COUNT_ACCESSLOG_ENTRIES:
                encodedFilename = getLog("configuration.nsaccesslog");
                if (encodedFilename == null) {
                    // We can simply return if null. The getLog method would
                    // have exited already if _quitOnError was true.
                    return;
                }
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        READ_LOG_TASK + "?op=count&" + "name=" +
                        encodedFilename);
                break;
            case TC_VIEW_ACCESSLOG_ENTRIES:
                tokenizer = new StringTokenizer(_newValue);
                if (tokenizer.countTokens() != 2) {
                    System.err.println("ERROR admconfig:");
                    System.err.println("    Cannot run " + _task);
                    System.err.println(
                            "    Invalid number of arguments for the task: " +
                            tokenizer.countTokens());
                    System.err.println("");
                    if (_quitOnError) {
                        System.exit(1);
                    } else {
                        return;
                    }
                }
                // First token is the entry number to start displaying from.
                startToken = tokenizer.nextToken();
                logStart = 0;
                try {
                    logStart = Integer.parseInt(startToken);
                } catch (NumberFormatException e) {
                    System.err.println("ERROR admconfig:");
                    System.err.println("    Cannot run " + _task);
                    System.err.println(
                            "    The entry number to start viewing is invalid: " +
                            startToken);
                    System.err.println("");
                    if (_quitOnError) {
                        System.exit(1);
                    } else {
                        return;
                    }
                }
                // Second token is the last entry number to display.
                stopToken = tokenizer.nextToken();
                logStop = 0;
                try {
                    logStop = Integer.parseInt(stopToken);
                } catch (NumberFormatException e) {
                    System.err.println("ERROR admconfig:");
                    System.err.println("    Cannot run " + _task);
                    System.err.println(
                            "    The entry number to stop viewing is invalid: " +
                            stopToken);
                    System.err.println("");
                    if (_quitOnError) {
                        System.exit(1);
                    } else {
                        return;
                    }
                }
                encodedFilename = getLog("configuration.nsaccesslog");
                if (encodedFilename == null) {
                    // We can simply return if null. The getLog method would
                    // have exited already if _quitOnError was true.
                    return;
                }
                // Finally, set the task url.
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        READ_LOG_TASK + "?op=read&" + "name=" +
                        encodedFilename + "&start=" + startToken +
                        "&stop=" + stopToken);
                break;
            case TC_ENABLE_ENDUSER_ACCESS:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=force_set&" +
                        URLByteEncoder.encodeUTF8("configuration.nsadminenableenduser")
                        + "=");
                break;
            case TC_DISABLE_ENDUSER_ACCESS:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=force_set&" +
                        URLByteEncoder.encodeUTF8("configuration.nsadminenableenduser")
                        + "=off");
                break;
            case TC_ENABLE_DSGW_ACCESS:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=force_set&" +
                        URLByteEncoder.encodeUTF8("configuration.nsadminenabledsgw")
                        + "=");
                break;
            case TC_DISABLE_DSGW_ACCESS:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        SERVER_SETUP_TASK + "?op=force_set&" +
                        URLByteEncoder.encodeUTF8("configuration.nsadminenabledsgw")
                        + "=off");
                break;
            case TC_GET_ADMIN_UID:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        ACCESS_SETUP_TASK + "?op=get&" +
                        URLByteEncoder.encodeUTF8("admpw.uid") + "=");
                break;
            case TC_SET_ADMIN_UID:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        ACCESS_SETUP_TASK + "?op=set&" +
                        URLByteEncoder.encodeUTF8("admpw.uid") + "=" +
                        URLByteEncoder.encodeUTF8(_newValue));
                break;
            case TC_SET_ADMIN_PWD:
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        ACCESS_SETUP_TASK + "?op=set&" +
                        URLByteEncoder.encodeUTF8("admpw.pw") + "=" +
                        URLByteEncoder.encodeUTF8(_newValue));
                break;
            case TC_GET_DSCONFIG:
                // The arguments are set below using the AdmTask.setArguments method.
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        DIRECTORY_SETUP_TASK);
                break;
            case TC_SET_DSCONFIG:
                // The arguments are set below using the AdmTask.setArguments method.
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        DIRECTORY_SETUP_TASK);
                tokenizer = new StringTokenizer(_newValue);
                if (tokenizer.countTokens() != 3) {
                    System.err.println("ERROR admconfig:");
                    System.err.println("    Cannot run " + _task);
                    System.err.println(
                            "    Invalid number of arguments for the task: " +
                            tokenizer.countTokens());
                    System.err.println("");
                    if (_quitOnError) {
                        System.exit(1);
                    } else {
                        return;
                    }
                }
                // First token is the dsconfig.host parameter.
                dsHostToken = tokenizer.nextToken();
                // Second token is the dsconfig.port parameter.
                dsPortToken = tokenizer.nextToken();
                dsPort = 0;
                try {
                    dsPort = Integer.parseInt(dsPortToken);
                } catch (NumberFormatException e) {
                    System.err.println("ERROR admconfig:");
                    System.err.println("    Cannot run " + _task);
                    System.err.println(
                            "    The dsconfig.port parameter is invalid: " +
                            dsPortToken);
                    System.err.println("");
                    if (_quitOnError) {
                        System.exit(1);
                    } else {
                        return;
                    }
                }
                // Third token is the dsconfig.ssl parameter.
                dsSSLFlagToken = tokenizer.nextToken();
                if (dsSSLFlagToken.equalsIgnoreCase("true") == false &&
                        dsSSLFlagToken.equalsIgnoreCase("false") == false) {
                    System.err.println("ERROR admconfig:");
                    System.err.println("    Cannot run " + _task);
                    System.err.println(
                            "    The dsconfig.ssl parameter is invalid: " +
                            dsSSLFlagToken);
                    System.err.println("");
                    if (_quitOnError) {
                        System.exit(1);
                    } else {
                        return;
                    }
                }
                break;
            case TC_GET_UGDSCONFIG:
                // The arguments are set below using the AdmTask.setArguments method.
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        UG_DIRECTORY_SETUP_TASK);
                break;
            case TC_SET_UGDSCONFIG:
                // The arguments are set below using the AdmTask.setArguments method.
                taskurl = new URL(_protocol + "://" + _server + "/" +
                        UG_DIRECTORY_SETUP_TASK);
                if (_newValue == null) {
                    break;
                }
                tokenizer = new StringTokenizer(_newValue);
                if (tokenizer.countTokens() != 6) {
                    System.err.println("ERROR admconfig:");
                    System.err.println("    Cannot run " + _task);
                    System.err.println(
                            "    Invalid number of arguments for the task: " +
                            tokenizer.countTokens());
                    System.err.println("");
                    if (_quitOnError) {
                        System.exit(1);
                    } else {
                        return;
                    }
                }
                // First token is the ugdsconfig.host parameter.
                dsHostToken = tokenizer.nextToken();
                // Second token is the ugdsconfig.port parameter.
                dsPortToken = tokenizer.nextToken();
                dsPort = 0;
                try {
                    dsPort = Integer.parseInt(dsPortToken);
                } catch (NumberFormatException e) {
                    System.err.println("ERROR admconfig:");
                    System.err.println("    Cannot run " + _task);
                    System.err.println(
                            "    The port parameter is invalid: " +
                            dsPortToken);
                    System.err.println("");
                    if (_quitOnError) {
                        System.exit(1);
                    } else {
                        return;
                    }
                }
                // Third token is the ugdsconfig.baseDN parameter.
                dsBaseDNToken = tokenizer.nextToken();
                dsBaseDNToken = dsBaseDNToken.replace('+', ' ');
                // Fourth token is the ssl parameter.
                dsSSLFlagToken = tokenizer.nextToken();
                if (dsSSLFlagToken.equalsIgnoreCase("true") == false &&
                        dsSSLFlagToken.equalsIgnoreCase("false") == false) {
                    System.err.println("ERROR admconfig:");
                    System.err.println("    Cannot run " + _task);
                    System.err.println(
                            "    The ssl parameter is invalid: " +
                            dsSSLFlagToken);
                    System.err.println("");
                    if (_quitOnError) {
                        System.exit(1);
                    } else {
                        return;
                    }
                }
                // Fifth token is the ugdsconfig.binddn parameter.
                dsBindDNToken = tokenizer.nextToken();
                dsBindDNToken = dsBindDNToken.replace('+', ' ');
                // Sixth token is the ugdsconfig.bindpw parameter.
                dsBindPwdToken = tokenizer.nextToken();
                dsBindPwdToken = dsBindPwdToken.replace('+', ' ');
                break;
            default:
                System.err.println("ERROR admconfig:");
                System.err.println("    Invalid task specified = " + _tc);
                System.err.println("");
                if (_quitOnError) {
                    System.exit(1);
                } else {
                    return;
                }
            }

            AdmTask task;
            // Some tasks require a specialized AdmTask.
            switch (_tc) {
            case TC_GET_ADMIN_UID:
            case TC_SET_ADMIN_UID:
            case TC_SET_ADMIN_PWD:
                task = new AdmpwTask(taskurl, _admin, _password);
                break;
            case TC_COUNT_ERRORLOG_ENTRIES:
            case TC_COUNT_ACCESSLOG_ENTRIES:
                task = new CountLogEntriesTask(taskurl, _admin, _password);
                break;
            case TC_VIEW_ERRORLOG_ENTRIES:
            case TC_VIEW_ACCESSLOG_ENTRIES:
                task = new ViewLogEntriesTask(taskurl, _admin, _password);
                break;
            case TC_GET_DSCONFIG:
                task = new AdmTask(taskurl, _admin, _password);
                // Providing the arguments as part of the URL does not work with
                // the DIRECTORY_SETUP_TASK CGI.
                task.setArguments("op=getconfig");
                break;
            case TC_SET_DSCONFIG:
                task = new AdmTask(taskurl, _admin, _password);
                // Providing the arguments as part of the URL does not work with
                // the DIRECTORY_SETUP_TASK CGI.
                task.setArguments("op=setconfig&" +
                        URLByteEncoder.encodeUTF8("dsconfig.host") +
                        "=" + URLEncoder.encode(dsHostToken) + "&" +
                        URLByteEncoder.encodeUTF8("dsconfig.port") +
                        "=" + dsPortToken + "&" +
                        URLByteEncoder.encodeUTF8("dsconfig.ssl") +
                        "=" + dsSSLFlagToken);
                break;
            case TC_GET_UGDSCONFIG:
                task = new AdmTask(taskurl, _admin, _password);
                // Providing the arguments as part of the URL does not work with
                // the UG_DIRECTORY_SETUP_TASK CGI.
                task.setArguments("op=getconfig");
                break;
            case TC_SET_UGDSCONFIG:
                task = new AdmTask(taskurl, _admin, _password);
                // Providing the arguments as part of the URL does not work with
                // the UG_DIRECTORY_SETUP_TASK CGI.
                if (_newValue == null) {
                    task.setArguments("op=setconfig&" +
                            URLByteEncoder.encodeUTF8("ugdsconfig.inforef")
                            + "=" + URLByteEncoder.encodeUTF8("default"));
                } else {
                    if (dsSSLFlagToken.equalsIgnoreCase("true")) {
                        dsURL = "ldaps://"+dsHostToken + ":"+
                                dsPortToken + "/"+dsBaseDNToken;
                    } else {
                        dsURL = "ldap://"+dsHostToken + ":"+
                                dsPortToken + "/"+dsBaseDNToken;
                    }
                    task.setArguments("op=setconfig&" +
                            URLByteEncoder.encodeUTF8("ugdsconfig.dirurl")
                            + "=" + URLByteEncoder.encodeUTF8(dsURL) +
                            "&" + URLByteEncoder.encodeUTF8("ugdsconfig.binddn")
                            + "=" +
                            URLByteEncoder.encodeUTF8(dsBindDNToken) +
                            "&" + URLByteEncoder.encodeUTF8("ugdsconfig.bindpw")
                            + "=" +
                            URLByteEncoder.encodeUTF8(dsBindPwdToken));
                }
                break;
            default:
                task = new AdmTask(taskurl, _admin, _password);
                break;
            }
            int execStatus = task.exec();
            if (execStatus != 0) {
                System.err.println("Status = " + execStatus);
                System.err.println("    exec failed for " + _task);
                System.err.println(""); // Separate output for next command.
                if (_quitOnError) {
                    System.exit(execStatus);
                } else {
                    return;
                }
            } else {
                int status = task.getStatus();
                if (status == 3 && (_tc == TC_RESTART || _tc == TC_STOP)) {
                    // Do nothing. This is okay. We get status == 3 for TC_RESTART and
                    // TC_STOP because the admin server process we were talking to has
                    // gone down (and restarted for TC_RESTART).
                } else if (status != 0) {
                    System.err.println("Status = " + status);
                    System.err.println("    Task " + _task +
                            " failed: " + task.getResult("NMC_ErrInfo"));
                    System.err.println(""); // Separate output for next command.
                    if (_quitOnError) {
                        System.exit(status);
                    } else {
                        return;
                    }
                }

                System.out.println("Task " + _task +
                        " succeeded with status = " + status);
                switch (_tc) {
                case TC_RESTART:
                    System.out.println("    Server has been restarted.");
                    System.out.println("\nWaiting 15 seconds for the server to come up before continuing.");
                    System.out.println("Press Ctrl-C to exit admconfig.");
                    Thread.sleep(15000);
                    break;
                case TC_STOP:
                    System.out.println("    Server has been stopped.");
                    System.out.println("\nThe server must be started before any more tasks can be run.\n");
                    System.exit(0);
                    break;
                case TC_GET_SYSTEM_USER:
                    System.out.println(
                            "    configuration.nssuitespotuser = " +
                            task.getResult("configuration.nssuitespotuser"));
                    break;
                case TC_GET_PORT:
                    System.out.println(
                            "    configuration.nsserverport = " +
                            task.getResult("configuration.nsserverport"));
                    break;
                case TC_GET_ADMINUSERS:
                    System.out.println(
                            "    configuration.nsadminusers = " +
                            task.getResult("configuration.nsadminusers"));
                    break;
                case TC_GET_ERRORLOG:
                    System.out.println( "    configuration.nserrorlog = " +
                            task.getResult("configuration.nserrorlog"));
                    break;
                case TC_GET_ACCESSLOG:
                    System.out.println( "    configuration.nsaccesslog = " +
                            task.getResult("configuration.nsaccesslog"));
                    break;
                case TC_GET_HOSTS:
                    System.out.println(
                            "    configuration.nsadminaccesshosts = " +
                            task.getResult("configuration.nsadminaccesshosts"));
                    break;
                case TC_GET_ADDRESSES:
                    System.out.println(
                            "    configuration.nsadminaccessaddresses = " +
                            task.getResult("configuration.nsadminaccessaddresses"));
                    break;
                case TC_GET_ONEACLDIR:
                    System.out.println(
                            "    configuration.nsadminoneacldir = " +
                            task.getResult("configuration.nsadminoneacldir"));
                    break;
                case TC_GET_DEFAULTACCEPTLANGUAGE:
                    System.out.println(
                            "    configuration.nsdefaultacceptlanguage = " +
                            task.getResult("configuration.nsdefaultacceptlanguage"));
                    break;
                case TC_GET_CLASSNAME:
                    System.out.println( "    configuration.nsclassname = " +
                            task.getResult("configuration.nsclassname"));
                    break;
                case TC_GET_CACHE_LIFETIME:
                    System.out.println(
                            "    configuration.nsadmincachelifetime = " +
                            task.getResult("configuration.nsadmincachelifetime"));
                    break;
                case TC_GET_SERVER_ADDRESS:
                    System.out.println(
                            "    configuration.nsserveraddress = " +
                            task.getResult("configuration.nsserveraddress"));
                    break;
                case TC_COUNT_ERRORLOG_ENTRIES:
                case TC_COUNT_ACCESSLOG_ENTRIES:
                    System.out.println("    count = " +
                            task.getResult("count"));
                    break;
                case TC_VIEW_ERRORLOG_ENTRIES:
                case TC_VIEW_ACCESSLOG_ENTRIES:
                    System.out.println(task.getResult("result"));
                    break;
                case TC_ENABLE_ENDUSER_ACCESS:
                    System.out.println("    End user access has been enabled.");
                    break;
                case TC_DISABLE_ENDUSER_ACCESS:
                    System.out.println("    End user access has been disabled.");
                    break;
                case TC_ENABLE_DSGW_ACCESS:
                    System.out.println("    Directory Server Gateway access has been enabled.");
                    break;
                case TC_DISABLE_DSGW_ACCESS:
                    System.out.println("    Directory Server Gateway access has been disabled.");
                    break;
                case TC_GET_ADMIN_UID:
                    System.out.println("    admpw.uid = " +
                            task.getResult("admpw.uid"));
                    break;
                case TC_GET_DSCONFIG:
                    System.out.println("    dsconfig.host   = " +
                            task.getResult("dsconfig.host"));
                    System.out.println("    dsconfig.port   = " +
                            task.getResult("dsconfig.port"));
                    dsSSLFlagResult = (String) task.getResult("dsconfig.ssl");
                    if (dsSSLFlagResult == null ||
                            dsSSLFlagResult.equalsIgnoreCase("false")) {
                        System.out.println("    dsconfig.ssl    = false");
                    } else {
                        System.out.println("    dsconfig.ssl    = true");
                    }
                    break;
                case TC_GET_UGDSCONFIG:
                    System.out.println( "    ugdsconfig.inforef      = " +
                            task.getResult("ugdsconfig.inforef"));
                    System.out.println( "    ugdsconfig.globaldirurl = " +
                            task.getResult("ugdsconfig.globaldirurl"));
                    System.out.println( "    ugdsconfig.dirurl       = " +
                            task.getResult("ugdsconfig.dirurl"));
                    System.out.println( "    ugdsconfig.binddn       = " +
                            task.getResult("ugdsconfig.binddn"));
                    //System.out.println("    ugdsconfig.bindpw       = " + task.getResult("ugdsconfig.bindpw"));
                    break;
                case TC_SET_SYSTEM_USER:
                case TC_SET_PORT:
                case TC_SET_ADMINUSERS:
                case TC_SET_ERRORLOG:
                case TC_SET_ACCESSLOG:
                case TC_SET_HOSTS:
                case TC_SET_ADDRESSES:
                case TC_SET_ONEACLDIR:
                case TC_SET_DEFAULTACCEPTLANGUAGE:
                case TC_SET_CLASSNAME:
                case TC_SET_CACHE_LIFETIME:
                case TC_SET_SERVER_ADDRESS:
                case TC_SET_ADMIN_UID:
                case TC_SET_ADMIN_PWD:
                case TC_SET_DSCONFIG:
                case TC_SET_UGDSCONFIG:
                    break;
                }

                switch (_tc) {
                case TC_SET_PORT:
                case TC_SET_ADMIN_UID:
                case TC_SET_ADMIN_PWD:
                case TC_SET_DSCONFIG:
                case TC_SET_UGDSCONFIG:
                case TC_SET_ADMINUSERS:
                case TC_SET_SYSTEM_USER:
		  printRestartMessage();
		  break;
		}

                System.out.println(""); // Separate output for next command.
                return; // Success!
            }
        }
        catch (Exception e) {
            System.err.println("ERROR admconfig:");
            System.err.println("    Task " + _task + " caused an exception.");
            System.err.println("    Exception: " + e);
            System.err.println("");
            if (_quitOnError) {
                System.exit(1);
            } else {
                return;
            }
        }
    }



    /**
      * Parse arguments using the provided parser. The <code>argRequired</code>
      * parameter is used to determine whether a particular argument must be
      * specified. This allows some options to be specified in a file. As a
      * a fallback, all required options must be provided on the command
      * line if an input file is not used.
      *
      * @param opt          the CommandLineParser object for parsing args
      * @param args         an array of String arguments
      * @param argRequired  a boolean flag indicating whether the argument must be specified
      */
    protected void parseArguments(CommandLineParser opt, String args[],
            boolean argRequired) {

        // If help option was specified, display the help info and exit.
        handleHelp(opt);

        // If version option was specified, display the version info and exit.
        handleVersion(opt);

        if (opt.hasOption(_admconfigControlStrings[OPT_QUIET_LEVEL])) {
            String verbose = opt.getOptionParam(
                    _admconfigControlStrings[OPT_QUIET_LEVEL]);
            if (null == verbose) {
                _verbose = 9; // Max level
            } else {
                try {
                    _verbose = Integer.parseInt(verbose);
                } catch (NumberFormatException e) {
                    System.err.println("WARNING admconfig:");
                    System.err.println(
                            "    Parameter for -verbose option is not a number: " +
                            verbose);
                    System.err.println("    Setting verbose level to 9.");
                    _verbose = 9;
                }

                if (_verbose < 0 || _verbose > 9) {
                    System.err.println("WARNING admconfig:");
                    System.err.println("    Invalid level: " + _verbose);
                    System.err.println("    Setting verbose level to default value of 5.");
                    _verbose = 5;
                }
            }

            // Display trace information if in full verbose mode.
            if (9 == _verbose) {
                System.out.println("admconfig:         verbose: " +
                        _verbose);
            }
        }

        if (opt.hasOption(_admconfigControlStrings[OPT_ENCRYPTION])) {
            _protocol = "https";

            // Display trace information if in full verbose mode.
            if (9 == _verbose) {
                System.out.println("admconfig:        protocol: " +
                        _protocol);
            }
        }

        if (opt.hasOption(
                _admconfigControlStrings[OPT_CONTINUE_ON_ERROR])) {
            _quitOnError = false;

            // Display trace information if in full verbose mode.
            if (9 == _verbose) {
                System.out.println("admconfig:   quit on error: " +
                        _quitOnError);
            }
        }

        if (opt.hasOption(_admconfigControlStrings[OPT_SERVER])) {
            String serverInfo = opt.getOptionParam(
                    _admconfigControlStrings[OPT_SERVER]);
            if (null == serverInfo) {
                System.err.println("ERROR admconfig:");
                System.err.println("    Required parameter for the -server option was not specified.");
                showHelp(_admconfigHelpLookup[TC_SHOW_HELP]);
                System.exit(1);
            } else {
                // Use default localhost if none specified.
                int colonIndex = serverInfo.indexOf(':');
                if ((-1 == colonIndex) ||
                        ((colonIndex + 1) == serverInfo.length())) {
                    // Port is required field for now.
                    System.err.println("ERROR admconfig:");
                    System.err.println("    Server port was not specified.");
                    System.err.println("    Try admconfig -h for help on using admconfig.\n");
                    System.exit(1);
                }
                if (0 == colonIndex) {
                    _server = "localhost" + serverInfo;
                } else {
                    _server = serverInfo;
                }
            }

            // Display trace information if in full verbose mode.
            if (9 == _verbose) {
                System.out.println("admconfig:          server: " +
                        _server);
            }
        }
        if ((true == argRequired) && (null == _server)) {
            System.err.println("ERROR admconfig:");
            System.err.println("    Server name and port number were not specified.");
            System.err.println("    Try admconfig -h for help on using admconfig.\n");
            System.exit(1);
        }

        if (opt.hasOption(_admconfigControlStrings[OPT_USER])) {
            String userInfo = opt.getOptionParam(
                    _admconfigControlStrings[OPT_USER]);
            if (null == userInfo) {
                System.err.println("ERROR admconfig:");
                System.err.println("    Required parameter for the -user option was not specified.");
                showHelp(_admconfigHelpLookup[TC_SHOW_HELP]);
                System.exit(1);
            } else {
                // Use user name if none specified.
                int colonIndex = userInfo.indexOf(':');

                if (-1 == colonIndex) {
                    _admin = userInfo;
                } else if (0 == colonIndex) {
                    _admin = System.getProperty("user.name");
                } else {
                    _admin = userInfo.substring(0, colonIndex);
                }

                if ((-1 == colonIndex) ||
                        ((colonIndex + 1) == (userInfo.length()))) {
                    promptForPassword();
                } else {
                    _password = userInfo.substring((colonIndex + 1));
                }
            }

            // Display trace information if in full verbose mode.
            if (9 == _verbose) {
                System.out.println("admconfig:          userid: " + _admin);
                System.out.println("admconfig:        password: " +
                        _password);
            }
        }
        if (true == argRequired) {
            if ((null == _admin) && (null == _password)) {
                promptForAdminInfo();

                // This case implies that there were no -u option at all. So, need to
                // display trace information if in full verbose mode.
                if (9 == _verbose) {
                    System.out.println("admconfig:          userid: " +
                            _admin);
                    System.out.println("admconfig:        password: " +
                            _password);
                }
            } else if (null == _admin || _admin.length() == 0) {
                _admin = System.getProperty("user.name");
            } else if (null == _password || _password.length() == 0) {
                promptForPassword();
            }
        }
    }



    /**
      * Handles parsing arguments from an input file, if applicable.
      * If the command line has been invoked with the -inputfile option,
      * the filename specified as the parameter to the option will be
      * opened, read into a string array, and parsed like the arguments
      * on the command line.
      *
      * @param opt   the CommandLineParser object for args
      * @param args  an array of String arguments
      */
    protected void handleInputFile(CommandLineParser opt, String args[]) {

        _inputFile = null;
        if (opt.hasOption(_admconfigControlStrings[OPT_INPUT_FILE])) {
            String inputFile = opt.getOptionParam(
                    _admconfigControlStrings[OPT_INPUT_FILE]);
            if (null == inputFile) {
                System.err.println("ERROR admconfig:");
                System.err.println("    No file specified for the -inputFile option. Ignoring option.");
            } else {
                _inputFile = inputFile;
            }
        }

        if (_inputFile != null) {
            try {
                // Read and parse the remaining arguments from the file.
                File f = new File(_inputFile);
                FileReader fr = new FileReader(f);
                long fsize = f.length();
                char[] data = new char[(int) fsize];
                long bytesRead = 0;
                while (bytesRead < fsize) {
                    bytesRead += fr.read(data, (int) bytesRead,
                            (int)(fsize - bytesRead));
                }
                fr.close();

                String dataString = new String(data);
                StringTokenizer tokenizer = new StringTokenizer(dataString);
                String token = null;
                Vector v = new Vector();
                while (tokenizer.hasMoreTokens()) {
                    token = tokenizer.nextToken();
                    Debug.println(
                            "TRACE CommandLine.handleInputFile: token from file: " +
                            token);
                    v.addElement(token);
                }

                int vsize = v.size();
                _fileArgs = new String[vsize];
                v.copyInto(_fileArgs);
                _fileOpt = new CommandLineParser(
                        _admconfigControlStrings, _fileArgs);

                // Parse the arguments from the file. Since the user can
                // opt to provide only SOME of the options in the file,
                // and the rest in the command line, the required arguments
                // do not necessarily have to be found here, as indicated
                // by the boolean parameter. If the required arguments are
                // not all provided in the file, then they must be provided
                // in the command line. See the calling routine.
                parseArguments(_fileOpt, _fileArgs, false);
            } catch (IOException e) {
                System.err.println("ERROR admconfig:");
                System.err.println("    IOException: " + e);
                System.err.println("");
                System.exit(1);
            }
        }
    }



    /**
      * Handles displaying the help information, if applicable.
      * If the command line has been invoked with the -help [<task>]
      * option, it displays the appropriate help information and
      * exits the program.
      *
      * @param opt  the CommandLineParser object
      */
    protected void handleHelp(CommandLineParser opt) {

        if (opt.hasOption(_admconfigControlStrings[OPT_HELP])) {
            String helpTask = opt.getOptionParam(
                    _admconfigControlStrings[OPT_HELP]);
            if (null == helpTask) {
                // Just show main help.
                _tc = TC_SHOW_HELP;
            } else {
                // Show help for specific task. Prepend with the "-" to get the
                // desired task code.
                _tc = getTaskCode("-" + helpTask, true);
            }
            showHelp(_admconfigHelpLookup[_tc]);
            System.exit(0);
        }
    }



    /**
      * Handles displaying the version information, if applicable.
      * If the command line has been invoked with the -version option,
      * it displays the version information and exits the program.
      *
      * @param opt  the CommandLineParser object
      */
    protected void handleVersion(CommandLineParser opt) {

        if (opt.hasOption(_admconfigControlStrings[OPT_VERSION])) {
            showVersion();
            System.exit(0);
        }
    }



    /**
      * Shows the contents of the help data file that matches the
      * lookupString.
      *
      * @param lookupString  the String key used to lookup the help info
      */
    protected void showHelp(String lookupString) {
        String filename = DATA_FILE;
        if (filename != null) {
            try {
                // Read and parse the remaining arguments from the file.
                ClassLoader loader = this.getClass().getClassLoader();
                InputStream is =
                        loader.getSystemResourceAsStream(PACKAGE_DIR +
                        "/" + filename);
                InputStreamReader isr = new InputStreamReader(is);
                BufferedReader br = new BufferedReader(isr);
                String line = null;
                // Find the lookupString
                while ((line = br.readLine()) != null) {
                    if (line.equalsIgnoreCase(lookupString)) {
                        break; // Found the string.
                    }
                }
                if (line == null) {
                    System.err.println("ERROR admconfig:");
                    System.err.println(
                            "    No help information available for " +
                            lookupString);
                    System.err.println("");
                    System.exit(1);
                }
                // Write out everything until either null or '[' is
                // is encountered. '[' indicates a different help info.
                // Must check for length > 0 because fails on NT.
                while ((line = br.readLine()) != null) {
                    if (line.length() > 0 && line.charAt(0) == '[') {
                        break;
                    }
                    System.out.println(line);
                }
                br.close();
            }
            catch (IOException e) {
                System.err.println("ERROR admconfig:");
                System.err.println("    IOException: " + e);
                System.err.println("");
                System.exit(1);
            }
        }
    }



    /**
      * Shows the contents of the version file.
      */
    protected void showVersion() {
        String filename = VERSION_FILE;
        if (filename != null) {
            try {
                // Read and parse the remaining arguments from the file.
                ClassLoader loader = this.getClass().getClassLoader();
                InputStream is =
                        loader.getSystemResourceAsStream(PACKAGE_DIR +
                        "/" + filename);
                InputStreamReader isr = new InputStreamReader(is);
                BufferedReader br = new BufferedReader(isr);
                String line = null;
                while ((line = br.readLine()) != null) {
                    System.out.println(line);
                }
                br.close();
            } catch (IOException e) {
                System.err.println("ERROR admconfig:");
                System.err.println("    IOException: " + e);
                System.err.println("");
                System.exit(1);
            }
        }
    }



    /**
      * Prompts for administrator password only.
      */
    protected void promptForPassword() {

        // Password is required field. Prompt for it securely,
        // i.e. do not echo what user types in!
        try {
            FileReader fr = new FileReader(FileDescriptor.in);
            BufferedReader br = new BufferedReader(fr);
            while (true) {
                System.out.print("Password: ");
                _password = br.readLine();
                if (_password.length() > 0) {
                    br.close();
                    return; // Done.
                }
            }
        } catch (IOException e) {
            System.err.println("ERROR admconfig:");
            System.err.println("    IOException: " + e);
            System.err.println("");
            System.exit(1);
        }
    }



    /**
      * Prompts for the administrator user name and password.
      * Side note: tried reusing promptForPassword(), but get
      * IOException.
      */
    protected void promptForAdminInfo() {

        try {
            FileReader fr = new FileReader(FileDescriptor.in);
            BufferedReader br = new BufferedReader(fr);
            while (true) {
                System.out.print("Username: ");
                _admin = br.readLine();
                if (_admin.length() > 0) {
                    break; // Done.
                }
            }
            while (true) {
                System.out.print("Password: ");
                _password = br.readLine();
                if (_password.length() > 0) {
                    br.close();
                    return; // Done.
                }
            }
        } catch (IOException e) {
            System.err.println("ERROR admconfig:");
            System.err.println("    IOException: " + e);
            System.err.println("");
            System.exit(1);
        }
    }


    /**
      * Looks up the task code for the specified task. If the specified
      * task does not exist, then the task code for displaying help is
      * returned.
      *
      * @param taskString       the task to lookup
      * @param alertOnMismatch  a boolean flag indicating whether to print error message on mismatches
      * @return                 integer task code matching the specified task, or TC_SHOW_HELP if no match
      */
    protected int getTaskCode(String taskString, boolean alertOnMismatch) {
        int count = 0;
        int taskCode = TC_SHOW_HELP;
        String lowerCaseTaskString = taskString.toLowerCase();

        for (int i = 0; i < _admconfigTaskLookup.length; i++) {
            if (_admconfigTaskLookup[i].startsWith(lowerCaseTaskString)) {
                count++;
                taskCode = i + 1; // Task indices are 1 less
                _task = taskString + " (" + _admconfigTaskLookup[i] + ")";
            }
        }

        if (count == 0 || count > 1) {
            if (alertOnMismatch == true) {
                System.err.println("ERROR admconfig:");
                System.err.println("    Unknown or ambiguous task: " +
                        taskString);
            }
            return TC_SHOW_HELP;
        }

        return taskCode;
    }


    /**
      * Gets the name of the specified log file from the Admin Server. It is used
      * by the tasks dealing with the error log and access log. It invokes a task
      * to retrieve the value of the specified log file in the Admin Server config.
      *
      * @param log  the log file to retrieve
      * @return     the name of the log file
      */
    protected String getLog(String log) {
        String encodedResult = null;
        try {
            // Invoke task to get the log.
            URL getLogURL = new URL(_protocol + "://" + _server + "/" +
                    SERVER_SETUP_TASK + "?op=get&" +
                    URLByteEncoder.encodeUTF8(log) + "=");
            AdmTask getLogTask = new AdmTask(getLogURL, _admin, _password);
            // Check for errors.
            int execStatus = getLogTask.exec();
            if (execStatus != 0) {
                System.err.println("Status = " + execStatus);
                System.err.println("    Failed to get " + log);
                System.err.println("");
                if (_quitOnError) {
                    System.exit(execStatus);
                } else {
                    return null;
                }
            } else {
                int taskStatus = getLogTask.getStatus();
                if (taskStatus != 0) {
                    System.err.println("Status = " + taskStatus);
                    System.err.println("    Failed to get " + log +
                            ": " + getLogTask.getResult("NMC_ErrInfo"));
                    System.err.println("");
                    if (_quitOnError) {
                        System.exit(taskStatus);
                    } else {
                        return null;
                    }
                }
            }
            // Get the log!
            String result = (String) getLogTask.getResult(log);
            // Make sure it is valid.
            if (result.startsWith("admin-serv/") &&
                    result.indexOf("..") == -1) {
                encodedResult = URLByteEncoder.encodeUTF8("../../../../" +
                        result);
            } else {
                System.err.println("ERROR admconfig:");
                System.err.println("    Cannot run " + _task);
                System.err.println("    Invalid log name: " + result);
                System.err.println("    Log names must start with \"admin-serv/\" and no \"..\" are allowed.\n");
                if (_quitOnError) {
                    System.exit(1);
                } else {
                    return null;
                }
            }
            // Success!
        }
        catch (Exception e) {
            System.err.println("ERROR admconfig:");
            System.err.println("    Exception: " + e);
            System.err.println("");
            if (_quitOnError) {
                System.exit(1);
            } else {
                return null; // Error
            }
        }

        // Okay so return result.
        return encodedResult;
    }
}
