mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

kenneth_suter
26.56.2007 4bf3814d7eefb7ce4e17af501c3711e1b21b5e67
Addresses issue 2143 which is intended to help with the readability of the usage statements by allowing options to be grouped logically by type.  Many of the utilities arguments have grown to such an extent that it is difficult to sort through the various types of arguments to find what you are looking for.  For instance the usage statement for the task schedulable arguments are mixed with the LDAP connection arguments which makes them difficult to ignore if they want to use the tool in offline mode.

This code also make consistent the position of standard options (e.g. help, version, quiet, verbose) within usage statements.

ArgumentParser (and SubCommandArgumentParse) have 4 built-in groups: General Options (for help and version commands), LDAP Connection Options (e.g. host, port), Utility Input/Output Options (e.g. quiet, verbose, no-prompt, argument file etc) and default options (for ungrouped arguments). The default group appears first in the list without a header to maintain backward consistency. Other groups can be defined for a usage statement by supplying an ArgumentGroup to the addArgument() method.

1 files added
14 files modified
770 ■■■■ changed files
opends/src/guitools/org/opends/guitools/uninstaller/UninstallerArgumentParser.java 4 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/tools.properties 8 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/utility.properties 4 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliParser.java 20 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/InstallDSArgumentParser.java 6 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/LDAPDelete.java 3 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/LDAPSearch.java 7 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/ManageTasks.java 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/ToolConstants.java 69 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/DSConfig.java 12 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/tasks/TaskTool.java 11 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/util/args/ArgumentGroup.java 175 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/util/args/ArgumentParser.java 347 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/util/args/LDAPConnectionArgumentParser.java 23 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/util/args/SubCommandArgumentParser.java 79 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/uninstaller/UninstallerArgumentParser.java
@@ -180,7 +180,7 @@
    args.add(quietArg);
    adminUidArg = new StringArgument("adminUID", 'I',
        "adminUID", false, false, true, "adminUID",
        OPTION_LONG_ADMIN_UID, false, false, true, "adminUID",
        Constants.GLOBAL_ADMIN_UID, null, INFO_DESCRIPTION_ADMIN_UID.get());
    ArrayList<Argument> defaultArgs =
@@ -203,7 +203,7 @@
    UserData uData = new UserData();
    referencedHostNameArg = new StringArgument("referencedHostName",
        ToolConstants.OPTION_SHORT_HOST,
        "referencedHostName", false, false, true,
        OPTION_LONG_REFERENCED_HOST_NAME, false, false, true,
        ToolConstants.OPTION_VALUE_HOST,
        uData.getHostName(), null, INFO_DESCRIPTION_REFERENCED_HOST.get());
    defaultArgs.add(referencedHostNameArg);
opends/src/messages/messages/tools.properties
@@ -2154,4 +2154,10 @@
INFO_DESCRIPTION_PROP_FILE_PATH_1461=Path to the file which contains default \
  properties value used for command line argument
INFO_DESCRIPTION_NO_PROP_FILE_1462=Indicates that we will not use properties \
  file to get default command line argument value
  file to get default command line argument value
INFO_DESCRIPTION_TASK_TASK_ARGS_1463=Task Scheduling Options
INFO_DESCRIPTION_TASK_LDAP_ARGS_1464=Task Backend Connection Options
INFO_DESCRIPTION_GENERAL_ARGS_1465=General Options
INFO_DESCRIPTION_IO_ARGS_1466=Utility Input/Output Options
INFO_DESCRIPTION_LDAP_CONNECTION_ARGS_1467=LDAP Connection Options
INFO_DESCRIPTION_CONFIG_OPTIONS_ARGS_1468=Configuration Options
opends/src/messages/messages/utility.properties
@@ -394,8 +394,7 @@
INFO_ARGPARSER_USAGE_152=Usage:
INFO_SUBCMDPARSER_SUBCMD_HEADING_153=Available subcommands:
INFO_SUBCMDPARSER_SUBCMD_REFERENCE_154=See "%s --help-{category}"
INFO_SUBCMDPARSER_GLOBAL_HEADING_155=The accepted value for global options \
 are:
INFO_SUBCMDPARSER_GLOBAL_HEADING_155=The global options are:
INFO_GLOBAL_HELP_REFERENCE_156=See "%s --help" to get more usage help
SEVERE_ERR_RENAMEFILE_CANNOT_RENAME_157=Failed to rename file %s to %s
SEVERE_ERR_RENAMEFILE_CANNOT_DELETE_TARGET_158=Failed to delete target file \
@@ -546,4 +545,5 @@
INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_ISSUER_257  =Issuer   : %s
INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_ALIASES_258=Which certificate do you want to use?
INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_ALIAS_259=%s (%s)
INFO_SUBCMDPARSER_GLOBAL_HEADING_PREFIX_260=Global %s
opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliParser.java
@@ -57,6 +57,7 @@
import org.opends.server.util.args.FileBasedArgument;
import org.opends.server.util.args.StringArgument;
import org.opends.server.util.args.SubCommandArgumentParser;
import org.opends.server.util.args.ArgumentGroup;
/**
 * This is a commodity class that can be used to check the arguments required
@@ -344,9 +345,26 @@
  protected void initializeGlobalArguments(Collection<Argument> args)
  throws ArgumentException
  {
    initializeGlobalArguments(args, null);
  }
  /**
   * Initialize the global options with the provided set of arguments.
   * @param args the arguments to use to initialize the global options.
   * @param argGroup to which args will be added
   * @throws ArgumentException if there is a conflict with the provided
   * arguments.
   */
  protected void initializeGlobalArguments(
          Collection<Argument> args,
          ArgumentGroup argGroup)
  throws ArgumentException
  {
    for (Argument arg : args)
    {
      addGlobalArgument(arg);
      addGlobalArgument(arg, argGroup);
    }
    // Set the propertiesFile argument
opends/src/server/org/opends/server/tools/InstallDSArgumentParser.java
@@ -296,19 +296,19 @@
        OPTION_LONG_KEYSTORE_PWD, false, false, true,
        OPTION_VALUE_KEYSTORE_PWD, null, null,
        INFO_INSTALLDS_DESCRIPTION_KEYSTOREPASSWORD.get());
    addArgument(keyStorePasswordArg);
    addDefaultArgument(keyStorePasswordArg);
    keyStorePasswordFileArg = new FileBasedArgument("keystorePasswordFile",
        OPTION_SHORT_KEYSTORE_PWD_FILE, OPTION_LONG_KEYSTORE_PWD_FILE, false,
        false, OPTION_VALUE_KEYSTORE_PWD_FILE, null, null,
        INFO_INSTALLDS_DESCRIPTION_KEYSTOREPASSWORD_FILE.get());
    addArgument(keyStorePasswordFileArg);
    addDefaultArgument(keyStorePasswordFileArg);
    certNicknameArg = new StringArgument("certnickname",
        OPTION_SHORT_CERT_NICKNAME, OPTION_LONG_CERT_NICKNAME,
        false, false, true, OPTION_VALUE_CERT_NICKNAME, null, null,
        INFO_INSTALLDS_DESCRIPTION_CERT_NICKNAME.get());
    addArgument(certNicknameArg);
    addDefaultArgument(certNicknameArg);
    showUsageArg = new BooleanArgument("help", OPTION_SHORT_HELP,
        OPTION_LONG_HELP,
opends/src/server/org/opends/server/tools/LDAPDelete.java
@@ -500,7 +500,8 @@
                                    null, INFO_DESCRIPTION_VERSION.get());
      argParser.addArgument(version);
      encodingStr = new StringArgument("encoding", 'i', "encoding", false,
      encodingStr = new StringArgument("encoding", 'i',
                                       OPTION_LONG_ENCODING, false,
                                       false, true, "{encoding}", null,  null,
                                       INFO_DESCRIPTION_ENCODING.get());
      argParser.addArgument(encodingStr);
opends/src/server/org/opends/server/tools/LDAPSearch.java
@@ -834,13 +834,13 @@
      argParser.addArgument(proxyAuthzID);
      reportAuthzID = new BooleanArgument(
              "reportauthzid", 'E', "reportAuthzID",
              "reportauthzid", 'E', OPTION_LONG_REPORT_AUTHZ_ID,
              INFO_DESCRIPTION_REPORT_AUTHZID.get());
      argParser.addArgument(reportAuthzID);
      usePasswordPolicyControl = new BooleanArgument(
              "usepwpolicycontrol", null,
              "usePasswordPolicyControl",
              OPTION_LONG_USE_PW_POLICY_CTL,
              INFO_DESCRIPTION_USE_PWP_CONTROL.get());
      argParser.addArgument(usePasswordPolicyControl);
@@ -940,7 +940,8 @@
                                      INFO_SEARCH_DESCRIPTION_TIME_LIMIT.get());
      argParser.addArgument(timeLimit);
      dontWrap = new BooleanArgument("dontwrap", 'T', "dontWrap",
      dontWrap = new BooleanArgument("dontwrap", 'T',
                                     "dontWrap",
                                     INFO_DESCRIPTION_DONT_WRAP.get());
      argParser.addArgument(dontWrap);
opends/src/server/org/opends/server/tools/ManageTasks.java
@@ -173,7 +173,7 @@
    LDAPConnectionArgumentParser argParser = new LDAPConnectionArgumentParser(
            "org.opends.server.tools.TaskInfo",
            INFO_TASKINFO_TOOL_DESCRIPTION.get(),
            false);
            false, null);
    // Initialize all the command-line argument types and register them with the
    // parser.
opends/src/server/org/opends/server/tools/ToolConstants.java
@@ -722,6 +722,16 @@
  public static final String OPTION_LONG_NO_PROMPT = "no-prompt";
  /**
   * Long form of script friendly option.
   */
  public static final String OPTION_LONG_SCRIPT_FRIENDLY = "script-friendly";
  /**
   * Short form of script friendly option.
   */
  public static final Character OPTION_SHORT_SCRIPT_FRIENDLY = 's';
  /**
   * Value for verbose option short form.
   */
  public static final Character OPTION_SHORT_VERBOSE = 'v';
@@ -752,6 +762,22 @@
  public static final String OPTION_LONG_PROP_FILE_PATH = "propertiesFilePath";
  /**
   * Argument that specifies that an operation be scheduled as a
   * task but the scheduling utility should not exit until the task
   * has completed.
   */
  public static final String OPTION_LONG_SYNCHRONOUS_TASK_MODE =
          "synchronousTaskMode";
  /**
   * Argument that specifies that an operation be scheduled as a
   * task but the scheduling utility should not exit until the task
   * has completed.
   */
  public static final Character OPTION_SHORT_SYNCHRONOUS_TASK_MODE = 'Y';
  /**
   * The placeholder value of propertiesFilePAth that will be
   * displayed in usage information.
   */
@@ -763,5 +789,48 @@
   */
  public static final String OPTION_LONG_NO_PROP_FILE = "noPropertiesFile";
  /**
   * Long form of referenced host name.
   */
  public static final String OPTION_LONG_REFERENCED_HOST_NAME =
          "referencedHostName";
  /**
   * Long form of admin UID.
   */
  public static final String OPTION_LONG_ADMIN_UID = "adminUID";
  /**
   * Long form of report authorization ID connection option.
   */
  public static final String OPTION_LONG_REPORT_AUTHZ_ID = "reportAuthzID";
  /**
   * Long form of use password policy control connection option.
   */
  public static final String OPTION_LONG_USE_PW_POLICY_CTL =
          "usePasswordPolicyControl";
  /**
   * Long form of use SASL external connection option.
   */
  public static final String OPTION_LONG_USE_SASL_EXTERNAL = "useSASLExternal";
  /**
   * Long form of option for the command-line encoding option.
   */
  public static final String OPTION_LONG_ENCODING = "encoding";
  /**
   * Long form of option specifying no wrapping of the command-line.
   */
  public static final String OPTION_LONG_DONT_WRAP = "dontWrap";
}
opends/src/server/org/opends/server/tools/dsconfig/DSConfig.java
@@ -66,6 +66,7 @@
import org.opends.server.util.args.StringArgument;
import org.opends.server.util.args.SubCommand;
import org.opends.server.util.args.SubCommandArgumentParser;
import org.opends.server.util.args.ArgumentGroup;
import org.opends.server.util.cli.CLIException;
import org.opends.server.util.cli.ConsoleApplication;
import org.opends.server.util.cli.Menu;
@@ -504,8 +505,9 @@
          OPTION_LONG_QUIET,
          INFO_DESCRIPTION_QUIET.get());
      scriptFriendlyArgument = new BooleanArgument("script-friendly", 's',
          "script-friendly", INFO_DESCRIPTION_SCRIPT_FRIENDLY.get());
      scriptFriendlyArgument = new BooleanArgument("script-friendly",
          OPTION_SHORT_SCRIPT_FRIENDLY, OPTION_LONG_SCRIPT_FRIENDLY,
          INFO_DESCRIPTION_SCRIPT_FRIENDLY.get());
      noPromptArgument = new BooleanArgument(
          OPTION_LONG_NO_PROMPT,
@@ -531,13 +533,17 @@
          INFO_DESCRIPTION_NO_PROP_FILE.get());
      // Register the global arguments.
      ArgumentGroup toolOptionsGroup = new ArgumentGroup(
        INFO_DESCRIPTION_CONFIG_OPTIONS_ARGS.get(), 2);
      parser.addGlobalArgument(advancedModeArgument, toolOptionsGroup);
      parser.addGlobalArgument(showUsageArgument);
      parser.setUsageArgument(showUsageArgument, getOutputStream());
      parser.addGlobalArgument(verboseArgument);
      parser.addGlobalArgument(quietArgument);
      parser.addGlobalArgument(scriptFriendlyArgument);
      parser.addGlobalArgument(noPromptArgument);
      parser.addGlobalArgument(advancedModeArgument);
      parser.addGlobalArgument(propertiesFileArgument);
      parser.setFilePropertiesArgument(propertiesFileArgument);
      parser.addGlobalArgument(noPropertiesFileArgument);
opends/src/server/org/opends/server/tools/tasks/TaskTool.java
@@ -30,6 +30,7 @@
import org.opends.server.util.args.LDAPConnectionArgumentParser;
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.args.StringArgument;
import org.opends.server.util.args.ArgumentGroup;
import static org.opends.server.util.StaticUtils.wrapText;
import static org.opends.server.util.StaticUtils.getExceptionMessage;
import static org.opends.server.util.ServerConstants.MAX_LINE_WIDTH;
@@ -101,8 +102,14 @@
  protected LDAPConnectionArgumentParser createArgParser(String className,
                                           Message toolDescription)
  {
    ArgumentGroup ldapGroup = new ArgumentGroup(
            INFO_DESCRIPTION_TASK_LDAP_ARGS.get(), 1001);
    argParser = new LDAPConnectionArgumentParser(className,
            toolDescription, false);
            toolDescription, false, ldapGroup);
    ArgumentGroup taskGroup = new ArgumentGroup(
            INFO_DESCRIPTION_TASK_TASK_ARGS.get(), 1000);
    try {
      startArg = new StringArgument(
@@ -112,7 +119,7 @@
              true, OPTION_VALUE_START_DATETIME,
              null, null,
              INFO_DESCRIPTION_START_DATETIME.get());
      argParser.addArgument(startArg);
      argParser.addArgument(startArg, taskGroup);
    } catch (ArgumentException e) {
      // should never happen
    }
opends/src/server/org/opends/server/util/args/ArgumentGroup.java
New file
@@ -0,0 +1,175 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.server.util.args;
import org.opends.messages.Message;
import java.util.List;
import java.util.LinkedList;
import java.util.Collections;
import java.util.Iterator;
/**
 * Class for organizing options into logical groups when arguement
 * usage is printed.  To use an argument group, create an instance
 * and use {@link org.opends.server.util.args.ArgumentParser
 * #addArgument(Argument, ArgumentGroup)} when adding arguments for
 * to the parser.
 */
public class ArgumentGroup implements Comparable<ArgumentGroup> {
  // Description for this group of arguments
  private Message description = null;
  // List of arguments belonging to this group
  private List<Argument> args = null;
  // Governs groups position within usage statement
  private Integer priority;
  /**
   * Creates a parameterized instance.
   *
   * @param description for options in this group that is printed before
   *        argument descriptions in usage output
   * @param priority number governing the position of this group within
   *        the usage statement.  Groups with higher priority values appear
   *        before groups with lower priority.
   */
  public ArgumentGroup(Message description, int priority) {
    this.description = description;
    this.priority = priority;
    this.args = new LinkedList<Argument>();
  }
  /**
   * Gets the description for this group of arguments.
   *
   * @return description for this argument group
   */
  public Message getDescription() {
    return this.description;
  }
  /**
   * Sets the description for this group of arguments.
   *
   * @param description for this argument group
   */
  public void setDescription(Message description) {
    this.description = description;
  }
  /**
   * Gets the list of arguments associated with this group.
   *
   * @return list of associated arguments
   */
  List<Argument> getArguments() {
    return Collections.unmodifiableList(args);
  }
  /**
   * {@inheritDoc}
   */
  public int compareTo(ArgumentGroup o)
  {
    // Groups with higher priority numbers appear before
    // those with lower priority in the usage output
    return -1 * priority.compareTo(o.priority);
  }
  /**
   * Indicates whether this group contains any members.
   *
   * @return boolean where true means this group contains members
   */
  boolean containsArguments()
  {
    return this.args.size() > 0;
  }
  /**
   * Indicates whether this group contains any non-hidden members.
   *
   * @return boolean where true means this group contains non-hidden members
   */
  boolean containsNonHiddenArguments()
  {
    for (Argument arg : args)
    {
      if (!arg.isHidden())
      {
        return true;
      }
    }
    return false;
  }
  /**
   * Adds an argument to this group.
   *
   * @param arg to add
   * @return boolean where true indicates the add was successful
   */
  boolean addArgument(Argument arg) {
    boolean success = false;
    if (arg != null) {
      Character newShort = arg.getShortIdentifier();
      String newLong = arg.getLongIdentifier();
      // See if there is already an argument in this group that the
      // new argument should replace
      for (Iterator<Argument> it = this.args.iterator(); it.hasNext();)
      {
        Argument a = it.next();
        if (newShort != null && newShort.equals(a.getShortIdentifier()) ||
                newLong != null && newLong.equals(a.getLongIdentifier())) {
          it.remove();
          break;
        }
      }
      success = this.args.add(arg);
    }
    return success;
  }
  /**
   * Removes an argument from this group.
   *
   * @param arg to remove
   * @return boolean where true indicates the remove was successful
   */
  boolean removeArgument(Argument arg) {
    return this.args.remove(arg);
  }
}
opends/src/server/org/opends/server/util/args/ArgumentParser.java
@@ -38,6 +38,8 @@
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Properties;
import java.util.TreeSet;
import java.util.Set;
import org.opends.server.core.DirectoryServer;
@@ -71,7 +73,7 @@
   * The argument that will be used to indicate that we'll not look for
   * default properties file.
   */
  private BooleanArgument NoPropertiesFileArgument;
  private BooleanArgument noPropertiesFileArgument;
  // The argument that will be used to trigger the display of usage information.
  private Argument usageArgument;
@@ -126,6 +128,43 @@
  // The raw set of command-line arguments that were provided.
  private String[] rawArguments;
  /** Set of argument groups. */
  protected Set<ArgumentGroup> argumentGroups;
  /**
   * Group for arguments that have not been explicitly grouped.
   * These will appear at the top of the usage statement without
   * a header.
   */
  protected ArgumentGroup defaultArgGroup = new ArgumentGroup(
          Message.EMPTY, Integer.MAX_VALUE);
  /**
   * Group for arguments that are related to utility input/output like
   * verbose, quite, no-prompt etc.  These will appear toward the bottom
   * of the usage statement.
   */
  protected ArgumentGroup ldapArgGroup = new ArgumentGroup(
          INFO_DESCRIPTION_LDAP_CONNECTION_ARGS.get(), Integer.MIN_VALUE + 2);
  /**
   * Group for arguments that are related to utility input/output like
   * verbose, quite, no-prompt etc.  These will appear toward the bottom
   * of the usage statement.
   */
  protected ArgumentGroup ioArgGroup = new ArgumentGroup(
          INFO_DESCRIPTION_IO_ARGS.get(), Integer.MIN_VALUE + 1);
  /**
   * Group for arguments that are general like help, version etc.
   * These will appear at the end of the usage statement.
   */
  protected ArgumentGroup generalArgGroup = new ArgumentGroup(
          INFO_DESCRIPTION_GENERAL_ARGS.get(), Integer.MIN_VALUE);
  /**
@@ -162,12 +201,15 @@
    rawArguments            = null;
    usageArgument           = null;
    filePropertiesPathArgument = null;
    NoPropertiesFileArgument = null;
    noPropertiesFileArgument = null;
    usageOutputStream       = System.out;
    initGroups();
  }
  /**
   * Creates a new instance of this argument parser with no arguments that may
   * or may not be allowed to have unnamed trailing arguments.
@@ -222,6 +264,7 @@
    rawArguments      = null;
    usageArgument     = null;
    usageOutputStream = System.out;
    initGroups();
  }
@@ -418,6 +461,50 @@
  /**
   * Sets the usage group description for the default argument group.
   *
   * @param description for the default group
   */
  public void setDefaultArgumentGroupDescription(Message description)
  {
    this.defaultArgGroup.setDescription(description);
  }
  /**
   * Sets the usage group description for the LDAP argument group.
   *
   * @param description for the LDAP group
   */
  public void setLdapArgumentGroupDescription(Message description)
  {
    this.ldapArgGroup.setDescription(description);
  }
  /**
   * Sets the usage group description for the input/output argument group.
   *
   * @param description for the input/output group
   */
  public void setInputOutputArgumentGroupDescription(Message description)
  {
    this.ioArgGroup.setDescription(description);
  }
  /**
   * Sets the usage group description for the general argument group.
   *
   * @param description for the general group
   */
  public void setGeneralArgumentGroupDescription(Message description)
  {
    this.generalArgGroup.setDescription(description);
  }
  /**
   * Adds the provided argument to the set of arguments handled by this parser.
   *
   * @param  argument  The argument to be added.
@@ -428,6 +515,82 @@
  public void addArgument(Argument argument)
         throws ArgumentException
  {
    addArgument(argument, null);
  }
  /**
   * Adds the provided argument to the set of arguments handled by this parser
   * and puts the arguement in the default group.
   *
   * @param  argument  The argument to be added.
   *
   * @throws  ArgumentException  If the provided argument conflicts with another
   *                             argument that has already been defined.
   */
  public void addDefaultArgument(Argument argument)
         throws ArgumentException
  {
    addArgument(argument, defaultArgGroup);
  }
  /**
   * Adds the provided argument to the set of arguments handled by this parser
   * and puts the arguement in the LDAP connection group.
   *
   * @param  argument  The argument to be added.
   *
   * @throws  ArgumentException  If the provided argument conflicts with another
   *                             argument that has already been defined.
   */
  public void addLdapConnectionArgument(Argument argument)
         throws ArgumentException
  {
    addArgument(argument, ldapArgGroup);
  }
  /**
   * Adds the provided argument to the set of arguments handled by this parser
   * and puts the arguement in the input/output group.
   *
   * @param  argument  The argument to be added.
   *
   * @throws  ArgumentException  If the provided argument conflicts with another
   *                             argument that has already been defined.
   */
  public void addInputOutputArgument(Argument argument)
         throws ArgumentException
  {
    addArgument(argument, ioArgGroup);
  }
  /**
   * Adds the provided argument to the set of arguments handled by this parser
   * and puts the arguement in the general group.
   *
   * @param  argument  The argument to be added.
   *
   * @throws  ArgumentException  If the provided argument conflicts with another
   *                             argument that has already been defined.
   */
  public void addGeneralArgument(Argument argument)
         throws ArgumentException
  {
    addArgument(argument, generalArgGroup);
  }
  /**
   * Adds the provided argument to the set of arguments handled by this parser.
   *
   * @param  argument  The argument to be added.
   * @param  group     The argument group to which the argument belongs.
   *
   * @throws  ArgumentException  If the provided argument conflicts with another
   *                             argument that has already been defined.
   */
  public void addArgument(Argument argument, ArgumentGroup group)
         throws ArgumentException
  {
    Character shortID = argument.getShortIdentifier();
    if ((shortID != null) && shortIDMap.containsKey(shortID))
    {
@@ -466,6 +629,12 @@
    }
    argumentList.add(argument);
    if (group == null) {
      group = getStandardGroup(argument);
    }
    group.addArgument(argument);
    argumentGroups.add(group);
  }
@@ -538,7 +707,7 @@
   */
  public void setNoPropertiesFileArgument(BooleanArgument argument)
  {
    NoPropertiesFileArgument= argument;
    noPropertiesFileArgument = argument;
  }
  /**
@@ -691,7 +860,7 @@
        Argument a = longIDMap.get(argName);
        if (a == null)
        {
          if (argName.equals("help"))
          if (argName.equals(OPTION_LONG_HELP))
          {
            // "--help" will always be interpreted as requesting usage
            // information.
@@ -1047,8 +1216,8 @@
      throws ArgumentException
  {
    // We don't look for properties file.
    if ((NoPropertiesFileArgument != null)
        && (NoPropertiesFileArgument.isPresent()))
    if ((noPropertiesFileArgument != null)
        && (noPropertiesFileArgument.isPresent()))
    {
      return null;
    }
@@ -1171,6 +1340,7 @@
    {
      buffer.append(wrapText(toolDescription.toString(), 79));
      buffer.append(EOL);
      buffer.append(EOL);
    }
    String scriptName = System.getProperty(PROPERTY_SCRIPT_NAME);
@@ -1202,35 +1372,42 @@
    buffer.append(EOL);
    buffer.append(INFO_SUBCMDPARSER_WHERE_OPTIONS_INCLUDE.get());
    buffer.append(EOL);
    // --version is a builtin option
    if (! shortIDMap.containsKey(OPTION_SHORT_PRODUCT_VERSION))
    {
      buffer.append("-" + OPTION_SHORT_PRODUCT_VERSION + ", ");
    }
    buffer.append("--" + OPTION_LONG_PRODUCT_VERSION);
    buffer.append(EOL);
    buffer.append("    ");
    buffer.append( INFO_DESCRIPTION_PRODUCT_VERSION.get());
    buffer.append(EOL);
    Argument helpArgument = null ;
    for (Argument a : argumentList)
    boolean printHeaders = printUsageGroupHeaders();
    for (ArgumentGroup argGroup : argumentGroups)
    {
      // If this argument is hidden, then skip it.
      if (a.isHidden())
      if (argGroup.containsArguments() && printHeaders)
      {
        continue;
        // Print the groups description if any
        Message groupDesc = argGroup.getDescription();
        if (groupDesc != null && !Message.EMPTY.equals(groupDesc)) {
          buffer.append(EOL);
          buffer.append(wrapText(groupDesc.toString(), 79));
          buffer.append(EOL);
          buffer.append(EOL);
        }
      }
      // Help argument should be printed at the end
      if ((usageArgument != null) ? usageArgument.getName().equals(a.getName())
          : false)
      for (Argument a : argGroup.getArguments())
      {
        helpArgument = a ;
        continue ;
        // If this argument is hidden, then skip it.
        if (a.isHidden())
        {
          continue;
        }
        // Help argument should be printed at the end
        if ((usageArgument != null) &&
                usageArgument.getName().equals(a.getName()))
        {
          helpArgument = a ;
          continue ;
        }
        printArgumentUsage(a, buffer);
      }
      printArgumentUsage(a, buffer);
    }
    if (helpArgument != null)
    {
@@ -1453,5 +1630,123 @@
      }
    }
  }
  /**
   * Given an argument, returns an appropriate group.  Arguments may
   * be part of one of the special groups or the default group.
   *
   * @param argument for which a group is requested
   * @return argument group appropriate for <code>argument</code>
   */
  protected ArgumentGroup getStandardGroup(Argument argument) {
    ArgumentGroup group;
    if (isInputOutputArgument(argument)) {
      group = ioArgGroup;
    } else if (isGeneralArgument(argument)) {
      group = generalArgGroup;
    } else if (isLdapConnectionArgument(argument)) {
      group = ldapArgGroup;
    } else {
      group = defaultArgGroup;
    }
    return group;
  }
  /**
   * Indicates whether or not argument group description headers
   * should be printed.
   *
   * @return boolean where true means print the descriptions
   */
  protected boolean printUsageGroupHeaders() {
    // If there is only a single group then we won't print them.
    int groupsContainingArgs = 0;
    for (ArgumentGroup argGroup : argumentGroups)
    {
      if (argGroup.containsNonHiddenArguments())
      {
        groupsContainingArgs++;
      }
    }
    return groupsContainingArgs > 1;
  }
  private void initGroups() {
    this.argumentGroups = new TreeSet<ArgumentGroup>();
    this.argumentGroups.add(defaultArgGroup);
    this.argumentGroups.add(ldapArgGroup);
    this.argumentGroups.add(generalArgGroup);
    this.argumentGroups.add(ioArgGroup);
    try {
      Argument version = new BooleanArgument(
              OPTION_LONG_PRODUCT_VERSION,
              OPTION_SHORT_PRODUCT_VERSION,
              OPTION_LONG_PRODUCT_VERSION,
              INFO_DESCRIPTION_PRODUCT_VERSION.get());
      this.generalArgGroup.addArgument(version);
    } catch (ArgumentException e) {
      // ignore
    }
  }
  private boolean isInputOutputArgument(Argument arg) {
    boolean io = false;
    if (arg != null) {
      String longId = arg.getLongIdentifier();
      io = OPTION_LONG_VERBOSE.equals(longId) ||
              OPTION_LONG_QUIET.equals(longId) ||
              OPTION_LONG_NO_PROMPT.equals(longId) ||
              OPTION_LONG_PROP_FILE_PATH.equals(longId) ||
              OPTION_LONG_NO_PROP_FILE.equals(longId) ||
              OPTION_LONG_SCRIPT_FRIENDLY.equals(longId) ||
              OPTION_LONG_DONT_WRAP.equals(longId) ||
              OPTION_LONG_ENCODING.equals(longId);
    }
    return io;
  }
  private boolean isLdapConnectionArgument(Argument arg) {
    boolean ldap = false;
    if (arg != null) {
      String longId = arg.getLongIdentifier();
      ldap = OPTION_LONG_USE_SSL.equals(longId) ||
              OPTION_LONG_START_TLS.equals(longId) ||
              OPTION_LONG_HOST.equals(longId) ||
              OPTION_LONG_PORT.equals(longId) ||
              OPTION_LONG_BINDDN.equals(longId) ||
              OPTION_LONG_BINDPWD.equals(longId) ||
              OPTION_LONG_BINDPWD_FILE.equals(longId) ||
              OPTION_LONG_SASLOPTION.equals(longId) ||
              OPTION_LONG_TRUSTALL.equals(longId) ||
              OPTION_LONG_TRUSTSTOREPATH.equals(longId) ||
              OPTION_LONG_TRUSTSTORE_PWD.equals(longId) ||
              OPTION_LONG_TRUSTSTORE_PWD_FILE.equals(longId) ||
              OPTION_LONG_KEYSTOREPATH.equals(longId) ||
              OPTION_LONG_KEYSTORE_PWD.equals(longId) ||
              OPTION_LONG_KEYSTORE_PWD_FILE.equals(longId) ||
              OPTION_LONG_CERT_NICKNAME.equals(longId) ||
              OPTION_LONG_REFERENCED_HOST_NAME.equals(longId) ||
              OPTION_LONG_ADMIN_UID.equals(longId) ||
              OPTION_LONG_REPORT_AUTHZ_ID.equals(longId) ||
              OPTION_LONG_USE_PW_POLICY_CTL.equals(longId) ||
              OPTION_LONG_USE_SASL_EXTERNAL.equals(longId) ||
              OPTION_LONG_PROTOCOL_VERSION.equals(longId);
    }
    return ldap;
  }
  private boolean isGeneralArgument(Argument arg) {
    boolean general = false;
    if (arg != null) {
      String longId = arg.getLongIdentifier();
      general = OPTION_LONG_HELP.equals(longId) ||
                    OPTION_LONG_PRODUCT_VERSION.equals(longId);
    }
    return general;
  }
}
opends/src/server/org/opends/server/util/args/LDAPConnectionArgumentParser.java
@@ -64,13 +64,17 @@
   *                                     tool, which will be included when
   *                                     displaying usage information.
   * @param  longArgumentsCaseSensitive  Indicates whether long arguments should
   *                                     be treated in a case-sensitive manner.
   * @param  argumentGroup               Group to which LDAP arguments will be
   *                                     added to the parser.  May be null to
   *                                     indicate that arguments should be
   *                                     added to the default group
   */
  public LDAPConnectionArgumentParser(String mainClassName,
                                      Message toolDescription,
                                      boolean longArgumentsCaseSensitive) {
                                      boolean longArgumentsCaseSensitive,
                                      ArgumentGroup argumentGroup) {
    super(mainClassName, toolDescription, longArgumentsCaseSensitive);
    addLdapConnectionArguments();
    addLdapConnectionArguments(argumentGroup);
  }
  /**
@@ -103,6 +107,10 @@
   *                                     as a placeholder for unnamed trailing
   *                                     arguments in the generated usage
   *                                     information.
   * @param  argumentGroup               Group to which LDAP arguments will be
   *                                     added to the parser.  May be null to
   *                                     indicate that arguments should be
   *                                     added to the default group
   */
  public LDAPConnectionArgumentParser(String mainClassName,
                                      Message toolDescription,
@@ -110,11 +118,12 @@
                                      boolean allowsTrailingArguments,
                                      int minTrailingArguments,
                                      int maxTrailingArguments,
                                      String trailingArgsDisplayName) {
                                      String trailingArgsDisplayName,
                                      ArgumentGroup argumentGroup) {
    super(mainClassName, toolDescription, longArgumentsCaseSensitive,
            allowsTrailingArguments, minTrailingArguments, maxTrailingArguments,
            trailingArgsDisplayName);
    addLdapConnectionArguments();
    addLdapConnectionArguments(argumentGroup);
  }
  /**
@@ -397,12 +406,12 @@
    return args;
  }
  private void addLdapConnectionArguments() {
  private void addLdapConnectionArguments(ArgumentGroup argGroup) {
    args = new SecureConnectionCliArgs();
    try {
      LinkedHashSet<Argument> argSet = args.createGlobalArguments();
      for (Argument arg : argSet) {
        addArgument(arg);
        addArgument(arg, argGroup);
      }
    }
    catch (ArgumentException ae) {
opends/src/server/org/opends/server/util/args/SubCommandArgumentParser.java
@@ -29,7 +29,6 @@
import org.opends.messages.MessageBuilder;
import static org.opends.messages.ToolMessages.*;
import static org.opends.messages.UtilityMessages.*;
import static org.opends.server.tools.ToolConstants.*;
import static org.opends.server.util.ServerConstants.*;
@@ -426,6 +425,24 @@
  public void addGlobalArgument(Argument argument)
         throws ArgumentException
  {
    addGlobalArgument(argument, null);
  }
  /**
   * Adds the provided argument to the set of global arguments handled by this
   * parser.
   *
   * @param  argument  The argument to be added.
   * @param  group     The argument group to which the argument belongs.
   * @throws  ArgumentException  If the provided argument conflicts with another
   *                             global or subcommand argument that has already
   *                             been defined.
   */
  public void addGlobalArgument(Argument argument, ArgumentGroup group)
         throws ArgumentException
  {
    String argumentName = argument.getName();
    if (globalArgumentMap.containsKey(argumentName))
    {
@@ -514,6 +531,12 @@
    }
    globalArgumentList.add(argument);
    if (group == null) {
      group = getStandardGroup(argument);
    }
    group.addArgument(argument);
    argumentGroups.add(group);
  }
  /**
@@ -1642,6 +1665,7 @@
    {
      buffer.append(wrapText(toolDescription, 79));
      buffer.append(EOL);
      buffer.append(EOL);
    }
    String scriptName = System.getProperty(PROPERTY_SCRIPT_NAME);
@@ -1733,42 +1757,33 @@
        buffer.append(INFO_SUBCMDPARSER_GLOBAL_HEADING.get());
        buffer.append(EOL);
      }
      buffer.append(EOL);
      // --version is a builtin option
      boolean dashVAccepted = true;
      if (globalShortIDMap.containsKey(OPTION_SHORT_PRODUCT_VERSION))
      {
        dashVAccepted = false;
      }
      else
      {
        for (SubCommand subCmd : subCommands.values())
        {
          if (subCmd.getArgument(OPTION_SHORT_PRODUCT_VERSION) != null)
          {
            dashVAccepted = false;
            break;
          }
        }
      }
      if (dashVAccepted)
      {
        buffer.append("-" + OPTION_SHORT_PRODUCT_VERSION + ", ");
      }
      buffer.append("--" + OPTION_LONG_PRODUCT_VERSION);
      buffer.append(EOL);
      buffer.append("    ");
      buffer.append( INFO_DESCRIPTION_PRODUCT_VERSION.get());
      buffer.append(EOL);
      boolean printGroupHeaders = printUsageGroupHeaders();
      // Display non-usage arguments.
      for (Argument a : globalArgumentList) {
        if (a.isHidden()) {
          continue;
      for (ArgumentGroup argGroup : argumentGroups)
      {
        if (argGroup.containsArguments() && printGroupHeaders)
        {
          // Print the groups description if any
          Message groupDesc = argGroup.getDescription();
          if (groupDesc != null && !Message.EMPTY.equals(groupDesc)) {
            buffer.append(EOL);
            buffer.append(wrapText(groupDesc.toString(), 79));
            buffer.append(EOL);
            buffer.append(EOL);
          }
        }
        if (!usageGroupArguments.containsKey(a)) {
          printArgumentUsage(a, buffer);
        for (Argument a : argGroup.getArguments()) {
          if (a.isHidden()) {
            continue;
          }
          if (!usageGroupArguments.containsKey(a)) {
            printArgumentUsage(a, buffer);
          }
        }
      }