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

lutoff
01.31.2007 31aab4e99942d2582ab17fa70dcb4f9e7e852e11
Fix for issues #1342 and #1343

Modifications done in dsframework CLI are:
- implement subcommand for global admin user management inside
the admin registry

The dsframework help output is in attachment in addition to the svndiff
file and new added file.
1 files added
5 files modified
1049 ■■■■■ changed files
opends/src/ads/org/opends/admin/ads/ADSContext.java 154 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliGlobalAdmin.java 797 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliParser.java 3 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliServer.java 6 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/messages/AdminMessages.java 72 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/ToolConstants.java 17 ●●●●● patch | view | raw | blame | history
opends/src/ads/org/opends/admin/ads/ADSContext.java
@@ -66,7 +66,7 @@
   * Enumeration containing the different server properties syntaxes
   * that could be stored in the ADS.
   */
  public enum ServerPropertySyntax
  public enum ADSPropertySyntax
  {
    /**
     * String syntax.
@@ -93,80 +93,80 @@
    /**
     * The ID used to identify the server.
     */
    ID("id",ServerPropertySyntax.STRING),
    ID("id",ADSPropertySyntax.STRING),
    /**
     * The host name of the server.
     */
    HOST_NAME("hostname",ServerPropertySyntax.STRING),
    HOST_NAME("hostname",ADSPropertySyntax.STRING),
    /**
     * The LDAP port of the server.
     */
    LDAP_PORT("ldapport",ServerPropertySyntax.INTEGER),
    LDAP_PORT("ldapport",ADSPropertySyntax.INTEGER),
    /**
     * The JMX port of the server.
     */
    JMX_PORT("jmxport",ServerPropertySyntax.INTEGER),
    JMX_PORT("jmxport",ADSPropertySyntax.INTEGER),
    /**
     * The JMX secure port of the server.
     */
    JMXS_PORT("jmxsport",ServerPropertySyntax.INTEGER),
    JMXS_PORT("jmxsport",ADSPropertySyntax.INTEGER),
    /**
     * The LDAPS port of the server.
     */
    LDAPS_PORT("ldapsport",ServerPropertySyntax.INTEGER),
    LDAPS_PORT("ldapsport",ADSPropertySyntax.INTEGER),
    /**
     * The certificate used by the server.
     */
    CERTIFICATE("certificate",ServerPropertySyntax.STRING),
    CERTIFICATE("certificate",ADSPropertySyntax.STRING),
    /**
     * The path where the server is installed.
     */
    INSTANCE_PATH("instancepath",ServerPropertySyntax.STRING),
    INSTANCE_PATH("instancepath",ADSPropertySyntax.STRING),
    /**
     * The description of the server.
     */
    DESCRIPTION("description",ServerPropertySyntax.STRING),
    DESCRIPTION("description",ADSPropertySyntax.STRING),
    /**
     * The OS of the machine where the server is installed.
     */
    HOST_OS("os",ServerPropertySyntax.STRING),
    HOST_OS("os",ADSPropertySyntax.STRING),
    /**
     * Whether LDAP is enabled or not.
     */
    LDAP_ENABLED("ldapEnabled",ServerPropertySyntax.BOOLEAN),
    LDAP_ENABLED("ldapEnabled",ADSPropertySyntax.BOOLEAN),
    /**
     * Whether LDAPS is enabled or not.
     */
    LDAPS_ENABLED("ldapsEnabled",ServerPropertySyntax.BOOLEAN),
    LDAPS_ENABLED("ldapsEnabled",ADSPropertySyntax.BOOLEAN),
    /**
     * Whether StartTLS is enabled or not.
     */
    STARTTLS_ENABLED("startTLSEnabled",ServerPropertySyntax.BOOLEAN),
    STARTTLS_ENABLED("startTLSEnabled",ADSPropertySyntax.BOOLEAN),
    /**
     * Whether JMX is enabled or not.
     */
    JMX_ENABLED("jmxEnabled",ServerPropertySyntax.BOOLEAN),
    JMX_ENABLED("jmxEnabled",ADSPropertySyntax.BOOLEAN),
    /**
     * Whether JMX is enabled or not.
     */
    JMXS_ENABLED("jmxsEnabled",ServerPropertySyntax.BOOLEAN),
    JMXS_ENABLED("jmxsEnabled",ADSPropertySyntax.BOOLEAN),
    /**
     * The location of the server.
     */
    LOCATION("location",ServerPropertySyntax.STRING),
    LOCATION("location",ADSPropertySyntax.STRING),
    /**
     * The groups to which this server belongs.
     */
    GROUPS("memberofgroups",ServerPropertySyntax.STRING);
    GROUPS("memberofgroups",ADSPropertySyntax.STRING);
    private String attrName;
    private ServerPropertySyntax attSyntax;
    private ADSPropertySyntax attSyntax;
    /**
     * Private constructor.
     * @param n the name of the attribute.
     */
    private ServerProperty(String n,ServerPropertySyntax s)
    private ServerProperty(String n,ADSPropertySyntax s)
    {
      attrName = n;
      attSyntax = s ;
@@ -185,13 +185,14 @@
     * Returns the attribute syntax.
     * @return the attribute syntax.
     */
    public ServerPropertySyntax getAttributeSyntax()
    public ADSPropertySyntax getAttributeSyntax()
    {
      return attSyntax;
    }
  };
  private static HashMap<String, ServerProperty> nameToServerProperty = null;
  /**
   * Get a ServerProperty associated to a name.
   * @param name The name of the property to retrieve.
@@ -199,7 +200,7 @@
   * @return The corresponding ServerProperty or null if name
   * doesn't match with an existing property.
   */
  public static ServerProperty getPropFromName(String name)
  public static ServerProperty getServerPropFromName(String name)
  {
    if (nameToServerProperty == null)
    {
@@ -286,20 +287,74 @@
    /**
     * The UID of the administrator.
     */
    UID,
    UID("id",ADSPropertySyntax.STRING),
    /**
     * The password of the administrator.
     */
    PASSWORD,
    PASSWORD("password",ADSPropertySyntax.STRING),
    /**
     * The description of the administrator.
     */
    DESCRIPTION,
    DESCRIPTION("description",ADSPropertySyntax.STRING),
    /**
     * The DN of the administrator.
     */
    ADMINISTRATOR_DN
  };
    ADMINISTRATOR_DN("administrator dn",ADSPropertySyntax.STRING);
    private String attrName;
    private ADSPropertySyntax attSyntax;
    /**
     * Private constructor.
     * @param n the name of the attribute.
     */
    private AdministratorProperty(String n,ADSPropertySyntax s)
    {
      attrName = n;
      attSyntax = s ;
    }
    /**
     * Returns the attribute name.
     * @return the attribute name.
     */
    public String getAttributeName()
    {
      return attrName;
    }
    /**
     * Returns the attribute syntax.
     * @return the attribute syntax.
     */
    public ADSPropertySyntax getAttributeSyntax()
    {
      return attSyntax;
    }
  }
  private static HashMap<String, AdministratorProperty>
    nameToAdminUSerProperty = null;
  /**
   * Get a AdministratorProperty associated to a name.
   * @param name The name of the property to retrieve.
   *
   * @return The corresponding AdministratorProperty or null if name
   * doesn't match with an existing property.
   */
  public static AdministratorProperty getAdminUSerPropFromName(String name)
  {
    if (nameToAdminUSerProperty == null)
    {
      nameToAdminUSerProperty = new HashMap<String, AdministratorProperty>();
      for (AdministratorProperty u : AdministratorProperty.values())
      {
        nameToAdminUSerProperty.put(u.getAttributeName(), u);
      }
    }
    return nameToAdminUSerProperty.get(name);
  }
  // The context used to retrieve information
  InitialLdapContext dirContext;
@@ -897,7 +952,7 @@
    LdapName dnCentralAdmin =
      makeDNFromAdministratorProperties(adminProperties);
    BasicAttributes attrs = makeAttrsFromAdministratorProperties(
        adminProperties);
        adminProperties, true);
    try
    {
@@ -962,22 +1017,39 @@
  /**
   * Updates and administrator registered in the ADS.
   * @param adminProperties the new properties of the administrator.
   * @param newAdminUserId The new admin user Identifier, or null.
   * @throws ADSContextException if something goes wrong.
   */
  public void updateAdministrator(
      Map<AdministratorProperty, Object> adminProperties)
      Map<AdministratorProperty, Object> adminProperties, String newAdminUserId)
  throws ADSContextException
  {
    LdapName dnCentralAdmin =
      makeDNFromAdministratorProperties(adminProperties);
    BasicAttributes attrs = makeAttrsFromAdministratorProperties(
        adminProperties);
    try
    {
      dirContext.modifyAttributes(dnCentralAdmin, DirContext.REPLACE_ATTRIBUTE,
          attrs);
      // Entry renaming
      if (newAdminUserId != null)
      {
        HashMap<AdministratorProperty, Object> newAdminUserProps =
          new HashMap<AdministratorProperty, Object>(adminProperties);
        newAdminUserProps.put(AdministratorProperty.UID,newAdminUserId);
        LdapName newDn = makeDNFromAdministratorProperties(newAdminUserProps);
        dirContext.rename(dnCentralAdmin, newDn);
        dnCentralAdmin = newDn ;
        adminProperties.put(AdministratorProperty.UID,newAdminUserId);
      }
      // Replace properties, if needed.
      if (adminProperties.size() > 1)
      {
        BasicAttributes attrs =
          makeAttrsFromAdministratorProperties(adminProperties, false);
        dirContext.modifyAttributes(dnCentralAdmin,
            DirContext.REPLACE_ATTRIBUTE, attrs);
      }
    }
    catch (NameNotFoundException x)
    {
@@ -1128,21 +1200,31 @@
  /**
   * Returns the attributes for some administrator properties.
   * @param adminProperties the administrator properties.
   * @param passwordRequired Indicates if the properties should include
   * the password.
   * @return the attributes for the given administrator properties.
   * @throws ADSContextException if something goes wrong.
   */
  private static BasicAttributes makeAttrsFromAdministratorProperties(
      Map<AdministratorProperty, Object> adminProperties)
      Map<AdministratorProperty, Object> adminProperties,
      boolean passwordRequired)
  throws ADSContextException
  {
    BasicAttributes attrs = new BasicAttributes();
    String adminPassword = getAdministratorPassword(adminProperties);
    Attribute oc = new BasicAttribute("objectclass");
    if (passwordRequired)
    {
      attrs.put("userPassword", getAdministratorPassword(adminProperties));
    }
    oc.add("top");
    oc.add("person");
    attrs.put(oc);
    attrs.put("sn", "admin");
    attrs.put("userPassword", adminPassword);
    if (adminProperties.containsKey(AdministratorProperty.DESCRIPTION))
    {
      attrs.put("description", adminProperties
          .get(AdministratorProperty.DESCRIPTION));
    }
    Attribute privilege = new BasicAttribute("ds-privilege-name");
    privilege.add("bypass-acl");
    privilege.add("modify-acl");
opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliGlobalAdmin.java
New file
@@ -0,0 +1,797 @@
/*
 * 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.admin.client.cli;
import static org.opends.server.messages.AdminMessages.*;
import static org.opends.server.messages.MessageHandler.getMessage;
import static org.opends.server.messages.ToolMessages.*;
import static org.opends.server.tools.ToolConstants.*;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.naming.NamingException;
import javax.naming.ldap.InitialLdapContext;
import org.opends.admin.ads.ADSContext;
import org.opends.admin.ads.ADSContextException;
import org.opends.admin.ads.ADSContext.AdministratorProperty;
import org.opends.admin.ads.ADSContextException.ErrorType;
import org.opends.server.admin.client.cli.DsFrameworkCliReturnCode.ReturnCode;
import org.opends.server.tools.dsconfig.ArgumentExceptionFactory;
import org.opends.server.util.args.Argument;
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.args.BooleanArgument;
import org.opends.server.util.args.StringArgument;
import org.opends.server.util.args.SubCommand;
import org.opends.server.util.table.TableBuilder;
import org.opends.server.util.table.TextTablePrinter;
/**
 * This class is handling user Admin CLI.
 */
public class DsFrameworkCliGlobalAdmin implements DsFrameworkCliSubCommandGroup
{
  // Strings used in property help.
  private final static String DESCRIPTION_OPTIONS_TITLE =
    getMessage(MSGID_DSCFG_HELP_DESCRIPTION_OPTION);
  private final static String DESCRIPTION_OPTIONS_READ =
    getMessage(MSGID_DSCFG_HELP_DESCRIPTION_READ);
  private final static String DESCRIPTION_OPTIONS_WRITE =
    getMessage(MSGID_DSCFG_HELP_DESCRIPTION_WRITE);
  private final static String DESCRIPTION_OPTIONS_MANDATORY =
    getMessage(MSGID_DSCFG_HELP_DESCRIPTION_MANDATORY);
  private final static String DESCRIPTION_OPTIONS_SINGLE =
    getMessage(MSGID_DSCFG_HELP_DESCRIPTION_SINGLE_VALUED);
  /**
   * The subcommand Parser.
   */
  private DsFrameworkCliParser argParser;
  /**
   * The verbose argument.
   */
  private BooleanArgument verboseArg;
  /**
   * The enumeration containing the different subCommand names.
   */
  private enum SubCommandNameEnum
  {
    /**
     * The create-admin-user subcommand.
     */
    CREATE_ADMIN_USER("create-admin-user"),
    /**
     * The delete-admin-user subcommand.
     */
    DELETE_ADMIN_USER("delete-admin-user"),
    /**
     * The list-admin-user subcommand.
     */
    LIST_ADMIN_USER("list-admin-user"),
    /**
     * The list-admin-user-properties subcommand.
     */
    LIST_ADMIN_USER_PROPERTIES("list-admin-user-properties"),
    /**
     * The get-admin-user-properties subcommand.
     */
    GET_ADMIN_USER_PROPERTIES("get-admin-user-properties"),
    /**
     * The set-admin-user-properties subcommand.
     */
    SET_ADMIN_USER_PROPERTIES("set-admin-user-properties");
    // String representation of the value.
    private final String name;
    // Private constructor.
    private SubCommandNameEnum(String name)
    {
      this.name = name;
    }
    /**
     * {@inheritDoc}
     */
    public String toString()
    {
      return name;
    }
    // A lookup table for resolving a unit from its name.
    private static final List<String> nameToSubCmdName;
    static
    {
      nameToSubCmdName = new ArrayList<String>();
      for (SubCommandNameEnum subCmd : SubCommandNameEnum.values())
      {
        nameToSubCmdName.add(subCmd.toString());
      }
    }
    public static boolean isSubCommand(String name)
    {
      return nameToSubCmdName.contains(name);
    }
  }
  /**
   * The create-admin-user subcommand.
   */
  private SubCommand createAdminUserSubCmd;
  /**
   * The 'userID' argument of the 'create-admin-user' subcommand.
   */
  private StringArgument createAdminUserUserIdArg;
  /**
   * The 'set' argument of the 'create-admin-user' subcommand.
   */
  private StringArgument createAdminUserSetArg ;
  /**
   * The delete-admin-user subcommand.
   */
  private SubCommand deleteAdminUserSubCmd;
  /**
   * The 'userID' argument of the 'delete-admin-user' subcommand.
   */
  private StringArgument deleteAdminUserUserIdArg;
  /**
   * The list-admin-user subcommand.
   */
  private SubCommand listAdminUserSubCmd;
  /**
   * The get-admin-user-properties subcommand.
   */
  private SubCommand getAdminUserPropertiesSubCmd;
  /**
   * The 'userID' argument of the 'get-admin-user-properties' subcommand.
   */
  private StringArgument getAdminUserPropertiesUserIdArg;
  /**
   * The set-admin-user-properties subcommand.
   */
  private SubCommand setAdminUserPropertiesSubCmd;
  /**
   * The 'userID' argument of the 'set-admin-user-properties' subcommand.
   */
  private StringArgument setAdminUserPropertiesUserIdArg;
  /**
   * The 'set' argument of the 'set-admin-user-properties' subcommand.
   */
  private StringArgument setAdminUserPropertiesSetArg;
  /**
   * The list-admin-user-properties subcommand.
   */
  private SubCommand listAdminUserPropertiesSubCmd;
  /**
   * Association between ADSContext enum and properties.
   */
  private HashMap<AdministratorProperty, Argument> userAdminProperties;
  /**
   * List of read-only server properties.
   */
  private HashSet<AdministratorProperty> readonlyadminUserProperties;
  /**
   * The subcommand list.
   */
  private HashSet<SubCommand> subCommands = new HashSet<SubCommand>();
  /**
   * Indicates whether this subCommand should be hidden in the usage
   * information.
   */
  private boolean isHidden;
  /**
   * The subcommand group name.
   */
  private String groupName;
  /**
   * {@inheritDoc}
   */
  public Set<SubCommand> getSubCommands()
  {
    return subCommands;
  }
  /**
   * {@inheritDoc}
   */
  public boolean isHidden()
  {
    return isHidden;
  }
  /**
   * {@inheritDoc}
   */
  public String getGroupName()
  {
    return groupName;
  }
  /**
   * {@inheritDoc}
   */
  public void initializeCliGroup(DsFrameworkCliParser argParser,
      BooleanArgument verboseArg) throws ArgumentException
  {
    this.verboseArg = verboseArg;
    isHidden = false;
    groupName = "admin-user";
    this.argParser = argParser;
    // create-admin-user subcommand.
    createAdminUserSubCmd = new SubCommand(argParser,
        SubCommandNameEnum.CREATE_ADMIN_USER.toString(),
        MSGID_ADMIN_SUBCMD_CREATE_ADMIN_USER_DESCRIPTION);
    subCommands.add(createAdminUserSubCmd);
    createAdminUserUserIdArg = new StringArgument("userID", null,
        OPTION_LONG_USERID, false, true, OPTION_VALUE_USERID,
        MSGID_ADMIN_ARG_USERID_DESCRIPTION);
    createAdminUserSubCmd.addArgument(createAdminUserUserIdArg);
    createAdminUserSetArg = new StringArgument(OPTION_LONG_SET,
        OPTION_SHORT_SET, OPTION_LONG_SET, false, true, true,
        OPTION_VALUE_SET, null, null, MSGID_DSCFG_DESCRIPTION_PROP_VAL);
    createAdminUserSubCmd.addArgument(createAdminUserSetArg);
    // delete-admin-user subcommand.
    deleteAdminUserSubCmd = new SubCommand(argParser,
        SubCommandNameEnum.DELETE_ADMIN_USER.toString(),
        MSGID_ADMIN_SUBCMD_DELETE_ADMIN_USER_DESCRIPTION);
    subCommands.add(deleteAdminUserSubCmd);
    deleteAdminUserUserIdArg = new StringArgument("userID", null,
        OPTION_LONG_USERID, false, true, OPTION_VALUE_USERID,
        MSGID_ADMIN_ARG_USERID_DESCRIPTION);
    deleteAdminUserSubCmd.addArgument(deleteAdminUserUserIdArg);
    // list-admin-user subcommand.
    listAdminUserSubCmd = new SubCommand(argParser,
        SubCommandNameEnum.LIST_ADMIN_USER.toString(),
        MSGID_ADMIN_SUBCMD_LIST_ADMIN_USER_DESCRIPTION);
    subCommands.add(listAdminUserSubCmd);
    // get-admin-user-properties subcommand.
    getAdminUserPropertiesSubCmd = new SubCommand(argParser,
        SubCommandNameEnum.GET_ADMIN_USER_PROPERTIES.toString(),
        MSGID_ADMIN_SUBCMD_GET_ADMIN_USER_PROPERTIES_DESCRIPTION);
    subCommands.add(getAdminUserPropertiesSubCmd);
    getAdminUserPropertiesUserIdArg = new StringArgument("userID", null,
        OPTION_LONG_USERID, false, true, OPTION_VALUE_USERID,
        MSGID_ADMIN_ARG_USERID_DESCRIPTION);
    getAdminUserPropertiesUserIdArg.setMultiValued(true);
    getAdminUserPropertiesSubCmd.addArgument(getAdminUserPropertiesUserIdArg);
    // set-admin-user-properties subcommand.
    setAdminUserPropertiesSubCmd = new SubCommand(argParser,
        SubCommandNameEnum.SET_ADMIN_USER_PROPERTIES.toString(),
        MSGID_ADMIN_SUBCMD_SET_ADMIN_USER_PROPERTIES_DESCRIPTION);
    subCommands.add(setAdminUserPropertiesSubCmd);
    setAdminUserPropertiesUserIdArg = new StringArgument("userID", null,
        OPTION_LONG_USERID, false, true, OPTION_VALUE_USERID,
        MSGID_ADMIN_ARG_USERID_DESCRIPTION);
    setAdminUserPropertiesSubCmd.addArgument(setAdminUserPropertiesUserIdArg);
    setAdminUserPropertiesSetArg = new StringArgument(OPTION_LONG_SET,
        OPTION_SHORT_SET, OPTION_LONG_SET, false, true, true,
        OPTION_VALUE_SET, null, null, MSGID_DSCFG_DESCRIPTION_PROP_VAL);
    setAdminUserPropertiesSubCmd.addArgument(setAdminUserPropertiesSetArg);
    // list-admin-user-properties subcommand.
    listAdminUserPropertiesSubCmd = new SubCommand(argParser,
        SubCommandNameEnum.LIST_ADMIN_USER_PROPERTIES.toString(),
        MSGID_ADMIN_SUBCMD_LIST_ADMIN_USER_PROPERTIES_DESCRIPTION);
    subCommands.add(listAdminUserPropertiesSubCmd);
    // Create association between ADSContext enum and server
    // properties
    // Server properties are mapped to Argument.
    userAdminProperties = new HashMap<AdministratorProperty, Argument>();
    readonlyadminUserProperties = new HashSet<AdministratorProperty>();
    /**
     * The ID used to identify the user.
     */
    {
      AdministratorProperty prop = AdministratorProperty.UID;
      String attName = prop.getAttributeName();
      StringArgument arg = new StringArgument(attName, null,
          prop.getAttributeName(), false, false, true, "", null, null, -1);
      userAdminProperties.put(prop, arg);
    }
    /**
     * The PASSWORD used to identify the user.
     */
    {
      // TODO : Allow file based password
      AdministratorProperty prop = AdministratorProperty.PASSWORD;
      String attName = prop.getAttributeName();
      StringArgument arg = new StringArgument(attName, null,
          prop.getAttributeName(), false, false, true, "", null, null, -1);
      userAdminProperties.put(prop, arg);
    }
    /**
     * The DESCRIPTION used to identify the user.
     */
    {
      AdministratorProperty prop = AdministratorProperty.DESCRIPTION;
      String attName = prop.getAttributeName();
      StringArgument arg = new StringArgument(attName, null,
          prop.getAttributeName(), false, false, true, "", null, null, -1);
      userAdminProperties.put(prop, arg);
    }
    /**
     * The ADMINISTRATOR_DN used to identify the user.
     */
    {
      AdministratorProperty prop = AdministratorProperty.ADMINISTRATOR_DN;
      String attName = prop.getAttributeName();
      StringArgument arg = new StringArgument(attName, null,
          prop.getAttributeName(), false, false, true, "", null, null, -1);
      userAdminProperties.put(prop, arg);
      readonlyadminUserProperties.add(prop);
    }
  }
  /**
   * {@inheritDoc}
   */
  public boolean isSubCommand(SubCommand subCmd)
  {
    return SubCommandNameEnum.isSubCommand(subCmd.getName());
  }
  /**
   * {@inheritDoc}
   */
  public ReturnCode performSubCommand(SubCommand subCmd,
      OutputStream outStream, OutputStream errStream)
      throws ADSContextException, ArgumentException
  {
    ADSContext adsCtx = null;
    InitialLdapContext ctx = null;
    ReturnCode returnCode = ReturnCode.ERROR_UNEXPECTED;
    try
    {
      // -----------------------
      // create-admin-user subcommand.
      // -----------------------
      if (subCmd.getName().equals(createAdminUserSubCmd.getName()))
      {
        String userId  = createAdminUserUserIdArg.getValue();
        Map<AdministratorProperty, Object> map =
          mapSetOptionsToMap(createAdminUserSetArg,true);
        map.put(AdministratorProperty.UID, userId);
        ctx = argParser.getContext(outStream, errStream);
        if (ctx == null)
        {
          return ReturnCode.CANNOT_CONNECT_TO_ADS;
        }
        adsCtx = new ADSContext(ctx);
        adsCtx.createAdministrator(map);
        returnCode = ReturnCode.SUCCESSFUL;
      }
      else
      // -----------------------
      // delete-admin-user subcommand.
      // -----------------------
      if (subCmd.getName().equals(deleteAdminUserSubCmd.getName()))
      {
        String userId  = deleteAdminUserUserIdArg.getValue();
        Map<AdministratorProperty, Object> map =
          new HashMap<AdministratorProperty, Object>();
        map.put(AdministratorProperty.UID, userId);
        ctx = argParser.getContext(outStream, errStream);
        if (ctx == null)
        {
          return ReturnCode.CANNOT_CONNECT_TO_ADS;
        }
        adsCtx = new ADSContext(ctx);
        adsCtx.deleteAdministrator(map);
        returnCode = ReturnCode.SUCCESSFUL;
      }
      else
      // -----------------------
      // list-admin-user subcommand.
      // -----------------------
      if (subCmd.getName().equals(listAdminUserSubCmd.getName()))
      {
        ctx = argParser.getContext(outStream, errStream);
        if (ctx == null)
        {
          return ReturnCode.CANNOT_CONNECT_TO_ADS;
        }
        adsCtx = new ADSContext(ctx);
        Set<Map<AdministratorProperty, Object>> adminUserList = adsCtx
            .readAdministratorRegistry();
        PrintStream out = new PrintStream(outStream);
        for (Map<AdministratorProperty, Object> user : adminUserList)
        {
          // print out server ID
          out.println(AdministratorProperty.UID.getAttributeName() + ": "
              + user.get(AdministratorProperty.UID));
        }
        returnCode = ReturnCode.SUCCESSFUL;
      }
      else
      // -----------------------
      // get-admin-user-properties subcommand.
      // -----------------------
      if (subCmd.getName().equals(getAdminUserPropertiesSubCmd.getName()))
      {
        ctx = argParser.getContext(outStream, errStream);
        if (ctx == null)
        {
          return ReturnCode.CANNOT_CONNECT_TO_ADS;
        }
        adsCtx = new ADSContext(ctx);
        Set<Map<AdministratorProperty, Object>> adsAdminUserList = adsCtx
            .readAdministratorRegistry();
        LinkedList<String> userAdminUserList = getAdminUserPropertiesUserIdArg
            .getValues();
        PrintStream out = new PrintStream(outStream);
        for (Map<AdministratorProperty, Object> adminUser : adsAdminUserList)
        {
          String adminUserID = (String) adminUser
              .get(AdministratorProperty.UID);
          if (!userAdminUserList.contains(adminUserID))
          {
            continue;
          }
          // print out the Admin User ID
          out.println(AdministratorProperty.UID.getAttributeName() + ": "
              + adminUser.get(AdministratorProperty.UID));
          for (AdministratorProperty ap : adminUser.keySet())
          {
            if (ap.equals(AdministratorProperty.UID))
            {
              continue;
            }
            out.println(ap.getAttributeName() + ": " + adminUser.get(ap));
          }
          out.println();
        }
        returnCode = ReturnCode.SUCCESSFUL;
      }
      else
      // -----------------------
      // set-admin-user-properties subcommand.
      // -----------------------
      if (subCmd.getName().equals(setAdminUserPropertiesSubCmd.getName()))
      {
        Map<AdministratorProperty, Object> map =
          mapSetOptionsToMap(setAdminUserPropertiesSetArg,false);
        // if the ID is specify in the --set list, it may mean that
        // the user wants to rename the serverID
        String newServerId = (String) map.get(AdministratorProperty.UID) ;
        // replace the serverID in the map
        map.put(AdministratorProperty.UID, setAdminUserPropertiesUserIdArg
            .getValue());
        ctx = argParser.getContext(outStream, errStream);
        if (ctx == null)
        {
          return ReturnCode.CANNOT_CONNECT_TO_ADS;
        }
        adsCtx = new ADSContext(ctx);
        adsCtx.updateAdministrator(map, newServerId);
        returnCode = ReturnCode.SUCCESSFUL;
      }
      else
      // -----------------------
      // list-admin-user-properties subcommand.
      // -----------------------
      if (subCmd.getName().equals(listAdminUserPropertiesSubCmd.getName()))
      {
        PrintStream out = new PrintStream(outStream);
        out.println(DESCRIPTION_OPTIONS_TITLE);
        out.println();
        out.print(" r -- ");
        out.println(DESCRIPTION_OPTIONS_READ);
        out.print(" w -- ");
        out.println(DESCRIPTION_OPTIONS_WRITE);
        out.print(" m -- ");
        out.println(DESCRIPTION_OPTIONS_MANDATORY);
        out.print(" s -- ");
        out.println(DESCRIPTION_OPTIONS_SINGLE);
        out.println();
        TableBuilder table = new TableBuilder();
        table.appendHeading(getMessage(MSGID_DSCFG_HEADING_PROPERTY_NAME));
        table.appendHeading(getMessage(MSGID_DSCFG_HEADING_PROPERTY_OPTIONS));
        table.appendHeading(getMessage(MSGID_DSCFG_HEADING_PROPERTY_SYNTAX));
        table.appendHeading(getMessage(
            MSGID_CLI_HEADING_PROPERTY_DEFAULT_VALUE));
        for (AdministratorProperty adminUserProp : userAdminProperties.keySet())
        {
          if (userAdminProperties.get(adminUserProp).isHidden())
          {
            continue;
          }
          table.startRow();
          table.appendCell(adminUserProp.getAttributeName());
          table.appendCell(getPropertyOptionSummary(userAdminProperties
              .get(adminUserProp)));
          table.appendCell(adminUserProp.getAttributeSyntax());
          if (userAdminProperties.get(adminUserProp).getDefaultValue() != null)
          {
            table.appendCell(userAdminProperties.get(adminUserProp)
                .getDefaultValue());
          }
          else
          {
            table.appendCell("-");
          }
        }
        TextTablePrinter printer = new TextTablePrinter(outStream);
        table.print(printer);
        returnCode = ReturnCode.SUCCESSFUL;
      }
      // -----------------------
      // ERROR
      // -----------------------
      else
      {
        // Should never occurs: If we are here, it means that the code
        // to handle to subcommand is not yet written.
        throw new ADSContextException(ErrorType.ERROR_UNEXPECTED);
      }
    }
    catch (ADSContextException e)
    {
      if (ctx != null)
      {
        try
        {
          ctx.close();
        }
        catch (NamingException x)
        {
        }
      }
      throw e;
    }
    // Close the connection, if needed
    if (ctx != null)
    {
      try
      {
        ctx.close();
      }
      catch (NamingException x)
      {
      }
    }
    // return part
    return returnCode;
  }
  /**
   * Translate a Set properties a to a MAP.
   *
   * @param propertySetArgument
   *          The input set argument.
   * @param checkMandatoryProps
   *          Indicates if we should check the presence of mandatory
   *          properties.
   * @return The created map.
   * @throws ArgumentException
   *           If error error occurs during set parsing.
   */
  private Map<AdministratorProperty, Object> mapSetOptionsToMap(
      StringArgument propertySetArgument, boolean checkMandatoryProps)
      throws ArgumentException
  {
    HashMap<AdministratorProperty, Object> map =
      new HashMap<AdministratorProperty, Object>();
    for (String m : propertySetArgument.getValues())
    {
      // Parse the property "property:value".
      int sep = m.indexOf(':');
      if (sep < 0)
      {
        throw ArgumentExceptionFactory.missingSeparatorInPropertyArgument(m);
      }
      if (sep == 0)
      {
        throw ArgumentExceptionFactory.missingNameInPropertyArgument(m);
      }
      String propertyName = m.substring(0, sep);
      String value = m.substring(sep + 1, m.length());
      if (value.length() == 0)
      {
        throw ArgumentExceptionFactory.missingValueInPropertyArgument(m);
      }
      // Check that propName is a known prop.
      AdministratorProperty adminUserProperty = ADSContext
          .getAdminUSerPropFromName(propertyName);
      if (adminUserProperty == null)
      {
        int msgID = MSGID_CLI_ERROR_PROPERTY_UNRECOGNIZED;
        String message = getMessage(msgID, propertyName);
        throw new ArgumentException(msgID, message);
      }
      // Check that propName is not hidden.
      if (userAdminProperties.get(adminUserProperty).isHidden())
      {
        int msgID = MSGID_CLI_ERROR_PROPERTY_UNRECOGNIZED;
        String message = getMessage(msgID, propertyName);
        throw new ArgumentException(msgID, message);
      }
      // Check the property Syntax.
      StringBuilder invalidReason = new StringBuilder();
      Argument arg = userAdminProperties.get(adminUserProperty) ;
      if ( ! arg.valueIsAcceptable(value, invalidReason))
      {
        int msgID = MSGID_CLI_ERROR_INVALID_PROPERTY_VALUE;
        String message = getMessage(msgID, propertyName, value);
        throw new ArgumentException(msgID, message);
      }
      userAdminProperties.get(adminUserProperty).addValue(value);
      // add to the map.
      map.put(adminUserProperty, value);
    }
    // Check that all mandatory props are set.
    if (! checkMandatoryProps)
    {
      return map ;
    }
    for (AdministratorProperty s : AdministratorProperty.values())
    {
      Argument arg = userAdminProperties.get(s);
      if (arg.isHidden())
      {
        continue;
      }
      if (map.containsKey(s))
      {
        continue ;
      }
      if ( ! arg.isRequired())
      {
        continue ;
      }
      // If we are here, it means that the argument is required
      // but not yet is the map. Check if we have a default value.
      if (arg.getDefaultValue() == null)
      {
        int msgID = MSGID_CLI_ERROR_MISSING_PROPERTY;
        String message = getMessage(msgID, s.getAttributeName());
        throw new ArgumentException(msgID, message);
      }
      else
      {
        map.put(s, arg.getDefaultValue());
      }
    }
    return map;
  }
  //Compute the options field.
  private String getPropertyOptionSummary(Argument arg)
  {
    StringBuilder b = new StringBuilder();
    if (readonlyadminUserProperties.contains(
        ADSContext.getServerPropFromName(arg.getName())))
    {
      b.append("r-"); //$NON-NLS-1$
    }
    else
    {
      b.append("rw"); //$NON-NLS-1$
    }
    if (arg.isRequired())
    {
      b.append('m');
    }
    else
    {
      b.append('-');
    }
    if (arg.isMultiValued())
    {
      b.append('-');
    }
    else
    {
      b.append('s');
    }
    return b.toString();
  }
}
opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliParser.java
@@ -232,6 +232,9 @@
    // Server Group cli
    cliGroup.add(new DsFrameworkCliServer());
    // User Admin cli
    cliGroup.add(new DsFrameworkCliGlobalAdmin());
    // Initialization
    Comparator<SubCommand> c = new Comparator<SubCommand>() {
opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliServer.java
@@ -362,7 +362,7 @@
    {
      ServerProperty prop = ServerProperty.ID;
      String attName = prop.getAttributeName();
      StringArgument arg = new StringArgument(prop.getAttributeName(), null,
      StringArgument arg = new StringArgument(attName, null,
          prop.getAttributeName(), false, false, true, "", null, null, -1);
      serverProperties.put(prop, arg);
    }
@@ -841,7 +841,7 @@
    StringBuilder b = new StringBuilder();
    if (readonlyServerProperties.contains(
        ADSContext.getPropFromName(arg.getName())))
        ADSContext.getServerPropFromName(arg.getName())))
    {
      b.append("r-"); //$NON-NLS-1$
    }
@@ -907,7 +907,7 @@
      // Check that propName is a known prop.
      ServerProperty serverProperty = ADSContext
          .getPropFromName(propertyName);
          .getServerPropFromName(propertyName);
      if (serverProperty == null)
      {
        int msgID = MSGID_CLI_ERROR_PROPERTY_UNRECOGNIZED;
opends/src/server/org/opends/server/messages/AdminMessages.java
@@ -564,6 +564,63 @@
  public static final int MSGID_ADMIN_SERVER_NOT_REGISTERED=
    CATEGORY_MASK_ADMIN | SEVERITY_MASK_FATAL_ERROR | 66;
  /**
   * The message ID for the message that will be used as the
   * description for the create-admin-user subcommand part of
   * dsservice tool. This does not take any arguments.
   */
  public static final int MSGID_ADMIN_SUBCMD_CREATE_ADMIN_USER_DESCRIPTION =
    CATEGORY_MASK_ADMIN | SEVERITY_MASK_INFORMATIONAL | 67;
  /**
   * The message ID for the message that will be used as the
   * description for the delete-admin-user subcommand part of
   * dsservice tool. This does not take any arguments.
   */
  public static final int MSGID_ADMIN_SUBCMD_DELETE_ADMIN_USER_DESCRIPTION =
    CATEGORY_MASK_ADMIN | SEVERITY_MASK_INFORMATIONAL | 68;
  /**
   * The message ID for the message that will be used as the
   * description for the list-admin-user subcommand part of
   * dsservice tool. This does not take any arguments.
   */
  public static final int MSGID_ADMIN_SUBCMD_LIST_ADMIN_USER_DESCRIPTION =
    CATEGORY_MASK_ADMIN | SEVERITY_MASK_INFORMATIONAL | 69;
  /**
   * The message ID for the message that will be used as the
   * description for the get-admin-user-properties subcommand part of
   * dsservice tool. This does not take any arguments.
   */
  public static final int
  MSGID_ADMIN_SUBCMD_GET_ADMIN_USER_PROPERTIES_DESCRIPTION =
    CATEGORY_MASK_ADMIN | SEVERITY_MASK_INFORMATIONAL | 70;
  /**
   * The message ID for the message that will be used as the
   * description for the set-admin-user-properties subcommand part of
   * dsservice tool. This does not take any arguments.
   */
  public static final int
  MSGID_ADMIN_SUBCMD_SET_ADMIN_USER_PROPERTIES_DESCRIPTION =
    CATEGORY_MASK_ADMIN | SEVERITY_MASK_INFORMATIONAL | 71;
  /**
   * The message ID for the message that will be used as the
   * description for the list-admin-user-properties subcommand part of
   * dsservice tool. This does not take any arguments.
   */
  public static final int
  MSGID_ADMIN_SUBCMD_LIST_ADMIN_USER_PROPERTIES_DESCRIPTION =
    CATEGORY_MASK_ADMIN | SEVERITY_MASK_INFORMATIONAL | 72;
  /**
   * The message ID for the message that will be used as the
   * description of the "userId" argument. This does not take any arguments.
   */
  public static final int MSGID_ADMIN_ARG_USERID_DESCRIPTION =
    CATEGORY_MASK_ADMIN | SEVERITY_MASK_INFORMATIONAL | 73;
  // Prevent instantiation.
  private AdminMessages() {
@@ -774,5 +831,20 @@
        "This is a required argument");
    registerMessage(MSGID_ADMIN_SERVER_NOT_REGISTERED,
        "The provided serverId is not registered");
    registerMessage(MSGID_ADMIN_SUBCMD_CREATE_ADMIN_USER_DESCRIPTION,
        "Creates a new administrator");
    registerMessage(MSGID_ADMIN_SUBCMD_DELETE_ADMIN_USER_DESCRIPTION,
        "Deletes an existing administrator");
    registerMessage(MSGID_ADMIN_SUBCMD_LIST_ADMIN_USER_DESCRIPTION,
        "Lists administrators that have been defined");
    registerMessage(MSGID_ADMIN_SUBCMD_GET_ADMIN_USER_PROPERTIES_DESCRIPTION,
        "Shows administrator's properties");
    registerMessage(MSGID_ADMIN_SUBCMD_SET_ADMIN_USER_PROPERTIES_DESCRIPTION,
        "Modifies administrator's properties");
    registerMessage(MSGID_ADMIN_SUBCMD_LIST_ADMIN_USER_PROPERTIES_DESCRIPTION,
        "Describes administrator's properties");
    registerMessage(MSGID_ADMIN_ARG_USERID_DESCRIPTION,
        "The administrator's unique identifier. " +
        "This is a required argument");
  }
}
opends/src/server/org/opends/server/tools/ToolConstants.java
@@ -605,6 +605,23 @@
  public static final String OPTION_VALUE_SERVERID = "{serverID}";
  /**
   * The value for the short option userID attributes.
   */
  public static final String OPTION_SHORT_USERID = null;
  /**
   * The value for the long option userID
   * attribute.
   */
  public static final String OPTION_LONG_USERID= "userID";
  /**
   * The placeholder value of userID that will be
   * displayed in usage information.
   */
  public static final String OPTION_VALUE_USERID = "{userID}";
  /**
   * The value for the short option set.
   */
  public static final Character OPTION_SHORT_SET = null;