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

matthew_swift
26.01.2007 54c2799f45256fef4a981fa2a6a7c97a9708ac8b
Partial fix for issue 1831 - dsconfig interactive mode.

With this change, dsconfig now prompts for component names if they are not specified on the command-line. Where more than one choice is available, dsconfig displays a list of choices. For create-xxx sub-commands dsconfig also prompts for the component type (-t flag) if it is not specified. Users can, at this point, request help which displays a detailed description of each type.

A subsequent change will add support for interactively setting property values.

A major part of this change includes improvements to the type-safety of the client admin APIs (e.g. use of raw types), which were being flagged in the latest version of Eclipse (apologies: I should have committed these separately, but they got too tangled up in this change).
3 files added
48 files modified
2820 ■■■■ changed files
opends/resource/admin/clientMO.xsl 16 ●●●● patch | view | raw | blame | history
opends/resource/admin/metaMO.xsl 4 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java 4 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java 15 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/AggregationRelationDefinition.java 10 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/DefaultBehaviorException.java 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/IllegalPropertyValueException.java 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/IllegalPropertyValueStringException.java 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/ManagedObjectDefinitionI18NResource.java 14 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/ManagedObjectDefinitionResource.java 9 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/ManagedObjectPath.java 71 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/PropertyDefinition.java 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/PropertyDefinitionUsageBuilder.java 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/PropertyDefinitionVisitor.java 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/PropertyIsMandatoryException.java 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/PropertyIsReadOnlyException.java 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/PropertyIsSingleValuedException.java 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java 3 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/UnknownPropertyDefinitionException.java 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/client/ManagedObject.java 209 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/client/PropertySet.java 8 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/client/ldap/JNDIDirContextAdaptor.java 10 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/client/ldap/LDAPConnection.java 5 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java 270 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/client/ldap/LDAPNameBuilder.java 11 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/server/ConfigAddListenerAdaptor.java 8 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/server/ConfigChangeListenerAdaptor.java 24 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java 12 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/server/DNBuilder.java 10 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/server/ServerManagedObject.java 43 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/messages/ToolMessages.java 188 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/ArgumentExceptionFactory.java 111 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/ConsoleApplication.java 494 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/CreateSubCommandHandler.java 268 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/DSConfig.java 298 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/DeleteSubCommandHandler.java 87 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/GetPropSubCommandHandler.java 55 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/HelpCallback.java 43 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/HelpSubCommandHandler.java 124 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/InternalManagementContextFactory.java 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/LDAPManagementContextFactory.java 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/ListSubCommandHandler.java 54 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/ManagementContextFactory.java 4 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/SetPropSubCommandHandler.java 39 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/SubCommandBuilder.java 39 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java 164 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/ValidationCallback.java 59 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/messages.properties 3 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgClient.java 4 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java 4 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/MockLDAPConnection.java 2 ●●● patch | view | raw | blame | history
opends/resource/admin/clientMO.xsl
@@ -195,7 +195,7 @@
        </xsl:call-template>
        <xsl:value-of
          select="concat('  &lt;C extends ', $java-class-name,'CfgClient&gt; C create', $java-relation-name, '(&#xa;',
                           '      ManagedObjectDefinition&lt;C, ?&gt; d, Collection&lt;DefaultBehaviorException&gt; exceptions);&#xa;')" />
                           '      ManagedObjectDefinition&lt;C, ? extends ', $java-class-name,'Cfg&gt; d, Collection&lt;DefaultBehaviorException&gt; exceptions);&#xa;')" />
        <xsl:text>&#xa;</xsl:text>
        <xsl:text>&#xa;</xsl:text>
        <xsl:text>&#xa;</xsl:text>
@@ -312,7 +312,7 @@
        </xsl:call-template>
        <xsl:value-of
          select="concat('  &lt;C extends ', $java-class-name,'CfgClient&gt; C create', $java-relation-name, '(&#xa;',
                           '      ManagedObjectDefinition&lt;C, ?&gt; d, String name, Collection&lt;DefaultBehaviorException&gt; exceptions) throws IllegalManagedObjectNameException;&#xa;')" />
                           '      ManagedObjectDefinition&lt;C, ? extends ', $java-class-name,'Cfg&gt; d, String name, Collection&lt;DefaultBehaviorException&gt; exceptions) throws IllegalManagedObjectNameException;&#xa;')" />
        <xsl:text>&#xa;</xsl:text>
        <xsl:text>&#xa;</xsl:text>
        <xsl:text>&#xa;</xsl:text>
@@ -396,6 +396,18 @@
            org.opends.server.admin.client.CommunicationException
          </import>
        </xsl:if>
        <xsl:for-each select="$this-local-relations[adm:one-to-zero-or-one]|$this-local-relations[adm:one-to-many]">
          <xsl:variable name="java-class-name">
            <xsl:call-template name="name-to-java">
              <xsl:with-param name="value"
                select="@managed-object-name" />
            </xsl:call-template>
          </xsl:variable>
          <xsl:element name="import">
            <xsl:value-of
              select="concat(@managed-object-package, '.server.', $java-class-name, 'Cfg')" />
          </xsl:element>
        </xsl:for-each>
        <xsl:if
          test="$this-local-relations/adm:one-to-zero-or-one|$this-local-relations/adm:one-to-many">
          <import>java.util.Collection</import>
opends/resource/admin/metaMO.xsl
@@ -1201,7 +1201,7 @@
                         '     * {@inheritDoc}&#xa;',
                         '     */&#xa;',
                         '    public &lt;M extends ', $java-class-name, 'CfgClient&gt; M create', $java-relation-name, '(&#xa;',
                         '        ManagedObjectDefinition&lt;M, ?&gt; d, Collection&lt;DefaultBehaviorException&gt; exceptions) {&#xa;',
                         '        ManagedObjectDefinition&lt;M, ? extends ', $java-class-name,'Cfg&gt; d, Collection&lt;DefaultBehaviorException&gt; exceptions) {&#xa;',
                         '      return impl.createChild(INSTANCE.get', $java-relation-name,'RelationDefinition(), d, exceptions).getConfiguration();&#xa;',
                         '    }&#xa;')" />
        <xsl:text>&#xa;</xsl:text>
@@ -1254,7 +1254,7 @@
                         '     * {@inheritDoc}&#xa;',
                         '     */&#xa;',
                         '    public &lt;M extends ', $java-class-name, 'CfgClient&gt; M create', $java-relation-name, '(&#xa;',
                         '        ManagedObjectDefinition&lt;M, ?&gt; d, String name, Collection&lt;DefaultBehaviorException&gt; exceptions) throws IllegalManagedObjectNameException {&#xa;',
                         '        ManagedObjectDefinition&lt;M, ? extends ', $java-class-name,'Cfg&gt; d, String name, Collection&lt;DefaultBehaviorException&gt; exceptions) throws IllegalManagedObjectNameException {&#xa;',
                         '      return impl.createChild(INSTANCE.get', $java-relation-plural-name,'RelationDefinition(), d, name, exceptions).getConfiguration();&#xa;',
                         '    }&#xa;')" />
        <xsl:text>&#xa;</xsl:text>
opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java
@@ -41,7 +41,7 @@
    DefaultBehaviorProvider<T> {
  // The absolute path to the managed object containing the property.
  private final ManagedObjectPath path;
  private final ManagedObjectPath<?, ?> path;
  // The name of the property containing the inherited default values.
  private final String propertyName;
@@ -104,7 +104,7 @@
   * @return Returns the absolute path of the managed object
   *         containing the property which has the default values.
   */
  public ManagedObjectPath getManagedObjectPath() {
  public ManagedObjectPath<?, ?> getManagedObjectPath() {
    return path;
  }
opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java
@@ -334,13 +334,13 @@
   *           If the specified property name was null or empty or if
   *           the requested property definition was not found.
   */
  public final PropertyDefinition getPropertyDefinition(String name)
  public final PropertyDefinition<?> getPropertyDefinition(String name)
      throws IllegalArgumentException {
    if ((name == null) || (name.length() == 0)) {
      throw new IllegalArgumentException("null or empty property name");
    }
    PropertyDefinition d = allPropertyDefinitions.get(name);
    PropertyDefinition<?> d = allPropertyDefinitions.get(name);
    if (d == null) {
      throw new IllegalArgumentException("property definition \"" + name
          + "\" not found");
@@ -380,13 +380,13 @@
   *           If the specified relation name was null or empty or if
   *           the requested relation definition was not found.
   */
  public final RelationDefinition getRelationDefinition(String name)
  public final RelationDefinition<?, ?> getRelationDefinition(String name)
      throws IllegalArgumentException {
    if ((name == null) || (name.length() == 0)) {
      throw new IllegalArgumentException("null or empty relation name");
    }
    RelationDefinition d = allRelationDefinitions.get(name);
    RelationDefinition<?, ?> d = allRelationDefinitions.get(name);
    if (d == null) {
      throw new IllegalArgumentException("relation definition \"" + name
          + "\" not found");
@@ -642,7 +642,8 @@
   * @param d
   *          The relation definition to be deregistered.
   */
  protected final void deregisterRelationDefinition(RelationDefinition d) {
  protected final void deregisterRelationDefinition(
      RelationDefinition<?, ?> d) {
    String name = d.getName();
    relationDefinitions.remove(name);
@@ -660,7 +661,7 @@
   * @param d
   *          The property definition to be registered.
   */
  protected final void registerPropertyDefinition(PropertyDefinition d) {
  protected final void registerPropertyDefinition(PropertyDefinition<?> d) {
    String name = d.getName();
    propertyDefinitions.put(name, d);
@@ -678,7 +679,7 @@
   * @param d
   *          The relation definition to be registered.
   */
  protected final void registerRelationDefinition(RelationDefinition d) {
  protected final void registerRelationDefinition(RelationDefinition<?, ?> d) {
    String name = d.getName();
    relationDefinitions.put(name, d);
opends/src/server/org/opends/server/admin/AggregationRelationDefinition.java
@@ -70,7 +70,7 @@
    // The path identifying the location of the referenced managed
    // objects.
    private ManagedObjectPath path;
    private ManagedObjectPath<?, ?> path;
    // The plural name of the relation.
    private final String pluralName;
@@ -131,7 +131,7 @@
     *          The path identifying the location of the referenced
     *          managed objects.
     */
    public void setPath(ManagedObjectPath path) {
    public void setPath(ManagedObjectPath<?, ?> path) {
      this.path = path;
    }
@@ -157,7 +157,7 @@
  // The path identifying the location of the referenced managed
  // objects.
  private final ManagedObjectPath path;
  private final ManagedObjectPath<?, ?> path;
  // The plural name of the relation.
  private final String pluralName;
@@ -166,7 +166,7 @@
  // Private constructor.
  private AggregationRelationDefinition(Common<C, S> common, String pluralName,
      ManagedObjectPath path, int minOccurs, int maxOccurs)
      ManagedObjectPath<?, ?> path, int minOccurs, int maxOccurs)
      throws IllegalArgumentException {
    super(common);
@@ -228,7 +228,7 @@
   * @return Returns the path identifying the location of the
   *         referenced managed objects.
   */
  public ManagedObjectPath getPath() {
  public ManagedObjectPath<?, ?> getPath() {
    return path;
  }
opends/src/server/org/opends/server/admin/DefaultBehaviorException.java
@@ -62,7 +62,7 @@
   *          The exception that prevented the default values from
   *          being determined.
   */
  public DefaultBehaviorException(PropertyDefinition pd, Throwable cause) {
  public DefaultBehaviorException(PropertyDefinition<?> pd, Throwable cause) {
    super(pd);
    this.cause = cause;
  }
opends/src/server/org/opends/server/admin/IllegalPropertyValueException.java
@@ -53,7 +53,7 @@
   * @param value
   *          The illegal property value.
   */
  public IllegalPropertyValueException(PropertyDefinition d, Object value) {
  public IllegalPropertyValueException(PropertyDefinition<?> d, Object value) {
    super(d);
    this.value = value;
  }
opends/src/server/org/opends/server/admin/IllegalPropertyValueStringException.java
@@ -53,7 +53,7 @@
   * @param value
   *          The illegal property value string.
   */
  public IllegalPropertyValueStringException(PropertyDefinition d,
  public IllegalPropertyValueStringException(PropertyDefinition<?> d,
      String value) {
    super(d);
    this.value = value;
opends/src/server/org/opends/server/admin/ManagedObjectDefinitionI18NResource.java
@@ -95,7 +95,7 @@
  // Mapping from definition to locale-based resource bundle.
  private final Map<AbstractManagedObjectDefinition,
  private final Map<AbstractManagedObjectDefinition<?, ?>,
    Map<Locale, ResourceBundle>> resources;
@@ -107,7 +107,7 @@
  // Private constructor.
  private ManagedObjectDefinitionI18NResource(String prefix) {
    this.resources = new HashMap<AbstractManagedObjectDefinition,
    this.resources = new HashMap<AbstractManagedObjectDefinition<?, ?>,
      Map<Locale, ResourceBundle>>();
    this.prefix = prefix;
  }
@@ -127,7 +127,7 @@
   * @throws MissingResourceException
   *           If the key was not found.
   */
  public String getMessage(AbstractManagedObjectDefinition d,
  public String getMessage(AbstractManagedObjectDefinition<?, ?> d,
      String key) throws MissingResourceException {
    return getMessage(d, key, Locale.getDefault(), (String[]) null);
  }
@@ -149,7 +149,7 @@
   * @throws MissingResourceException
   *           If the key was not found.
   */
  public String getMessage(AbstractManagedObjectDefinition d,
  public String getMessage(AbstractManagedObjectDefinition<?, ?> d,
      String key, Locale locale) throws MissingResourceException {
    return getMessage(d, key, locale, (String[]) null);
  }
@@ -174,7 +174,7 @@
   * @throws MissingResourceException
   *           If the key was not found.
   */
  public String getMessage(AbstractManagedObjectDefinition d,
  public String getMessage(AbstractManagedObjectDefinition<?, ?> d,
      String key, Locale locale, String... args)
      throws MissingResourceException {
    ResourceBundle resource = getResourceBundle(d, locale);
@@ -205,7 +205,7 @@
   * @throws MissingResourceException
   *           If the key was not found.
   */
  public String getMessage(AbstractManagedObjectDefinition d,
  public String getMessage(AbstractManagedObjectDefinition<?, ?> d,
      String key, String... args) throws MissingResourceException {
    return getMessage(d, key, Locale.getDefault(), args);
  }
@@ -215,7 +215,7 @@
  // Retrieve the resource bundle associated with a managed object and
  // locale, lazily loading it if necessary.
  private synchronized ResourceBundle getResourceBundle(
      AbstractManagedObjectDefinition d, Locale locale)
      AbstractManagedObjectDefinition<?, ?> d, Locale locale)
      throws MissingResourceException {
    // First get the locale-resource mapping, creating it if
    // necessary.
opends/src/server/org/opends/server/admin/ManagedObjectDefinitionResource.java
@@ -46,7 +46,8 @@
public final class ManagedObjectDefinitionResource {
  // Mapping from definition to property tables.
  private final Map<AbstractManagedObjectDefinition, Properties> properties;
  private final Map<AbstractManagedObjectDefinition<?, ?>,
      Properties> properties;
  // The resource name prefix.
  private final String prefix;
@@ -71,7 +72,7 @@
  // Private constructor.
  private ManagedObjectDefinitionResource(String prefix) {
    this.properties =
      new HashMap<AbstractManagedObjectDefinition, Properties>();
      new HashMap<AbstractManagedObjectDefinition<?, ?>, Properties>();
    this.prefix = prefix;
  }
@@ -89,7 +90,7 @@
   * @throws MissingResourceException
   *           If the key was not found.
   */
  public String getString(AbstractManagedObjectDefinition d,
  public String getString(AbstractManagedObjectDefinition<?, ?> d,
      String key) throws MissingResourceException {
    Properties p = getProperties(d);
    String result = p.getProperty(key);
@@ -111,7 +112,7 @@
  // lazily
  // loading it if necessary.
  private synchronized Properties getProperties(
      AbstractManagedObjectDefinition d)
      AbstractManagedObjectDefinition<?, ?> d)
      throws MissingResourceException {
    Properties p = properties.get(d);
opends/src/server/org/opends/server/admin/ManagedObjectPath.java
@@ -150,6 +150,18 @@
    /**
     * Get the name associated with this element if applicable.
     *
     * @return Returns the name associated with this element if
     *         applicable.
     */
    public String getName() {
      return null;
    }
    /**
     * Get the relation definition associated with this element.
     *
     * @return Returns the relation definition associated with this
@@ -211,6 +223,16 @@
     * {@inheritDoc}
     */
    @Override
    public String getName() {
      return name;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public InstantiableRelationDefinition<? super C, ? super S>
        getRelationDefinition() {
      return r;
@@ -395,8 +417,8 @@
    // Common element serialization.
    private <M, N> void serializeElement(RelationDefinition r,
        AbstractManagedObjectDefinition d) {
    private <M, N> void serializeElement(RelationDefinition<?, ?> r,
        AbstractManagedObjectDefinition<?, ?> d) {
      // Always specify the relation name.
      builder.append("/relation=");
      builder.append(r.getName());
@@ -636,6 +658,49 @@
  /**
   * Creates a new managed object path which has the same structure as
   * this path except that the final path element is associated with
   * the specified managed object definition.
   *
   * @param <CC>
   *          The type of client managed object configuration that
   *          this path will reference.
   * @param <SS>
   *          The type of server managed object configuration that
   *          this path will reference.
   * @param nd
   *          The new managed object definition.
   * @return Returns a new managed object path which has the same
   *         structure as this path except that the final path element
   *         is associated with the specified managed object
   *         definition.
   */
  @SuppressWarnings("unchecked")
  public <CC extends C, SS extends S> ManagedObjectPath<CC, SS> asSubType(
      AbstractManagedObjectDefinition<CC, SS> nd) {
    if (r instanceof InstantiableRelationDefinition) {
      InstantiableRelationDefinition<? super C, ? super S> ir =
        (InstantiableRelationDefinition<? super C, ? super S>) r;
      if (elements.size() == 0) {
        return parent().child(ir, nd, null);
      } else {
        return parent().child(ir, nd,
            elements.get(elements.size() - 1).getName());
      }
    } else if (r instanceof OptionalRelationDefinition) {
      OptionalRelationDefinition<? super C, ? super S> or =
        (OptionalRelationDefinition<? super C, ? super S>) r;
      return parent().child(or, nd);
    } else {
      SingletonRelationDefinition<? super C, ? super S> sr =
        (SingletonRelationDefinition<? super C, ? super S>) r;
      return parent().child(sr, nd);
    }
  }
  /**
   * Creates a new child managed object path beneath the provided
   * parent path having the specified managed object definition.
   *
@@ -804,7 +869,7 @@
    if (obj == this) {
      return true;
    } else if (obj instanceof ManagedObjectPath) {
      ManagedObjectPath other = (ManagedObjectPath) obj;
      ManagedObjectPath<?, ?> other = (ManagedObjectPath<?, ?>) obj;
      return toString().equals(other.toString());
    } else {
      return false;
opends/src/server/org/opends/server/admin/PropertyDefinition.java
@@ -417,7 +417,7 @@
    if (this == o) {
      return true;
    } else if (o instanceof PropertyDefinition) {
      PropertyDefinition other = (PropertyDefinition) o;
      PropertyDefinition<?> other = (PropertyDefinition<?>) o;
      if (propertyName.equals(other.propertyName)) {
        if (theClass.equals(other.theClass)) {
          return true;
opends/src/server/org/opends/server/admin/PropertyDefinitionUsageBuilder.java
@@ -311,7 +311,7 @@
     * {@inheritDoc}
     */
    @Override
    public String visitUnknown(PropertyDefinition d, Void p)
    public String visitUnknown(PropertyDefinition<?> d, Void p)
        throws UnknownPropertyDefinitionException {
      return "?";
    }
opends/src/server/org/opends/server/admin/PropertyDefinitionVisitor.java
@@ -250,7 +250,7 @@
   *           Visitor implementations may optionally throw this
   *           exception.
   */
  public R visitUnknown(PropertyDefinition d, P p)
  public R visitUnknown(PropertyDefinition<?> d, P p)
      throws UnknownPropertyDefinitionException {
    throw new UnknownPropertyDefinitionException(d, p);
  }
opends/src/server/org/opends/server/admin/PropertyIsMandatoryException.java
@@ -47,7 +47,7 @@
   * @param d
   *          The property definition.
   */
  public PropertyIsMandatoryException(PropertyDefinition d) {
  public PropertyIsMandatoryException(PropertyDefinition<?> d) {
    super(d);
  }
opends/src/server/org/opends/server/admin/PropertyIsReadOnlyException.java
@@ -47,7 +47,7 @@
   * @param d
   *          The property definition.
   */
  public PropertyIsReadOnlyException(PropertyDefinition d) {
  public PropertyIsReadOnlyException(PropertyDefinition<?> d) {
    super(d);
  }
opends/src/server/org/opends/server/admin/PropertyIsSingleValuedException.java
@@ -48,7 +48,7 @@
   * @param d
   *          The property definition.
   */
  public PropertyIsSingleValuedException(PropertyDefinition d) {
  public PropertyIsSingleValuedException(PropertyDefinition<?> d) {
    super(d);
  }
opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java
@@ -118,7 +118,8 @@
   * @return Returns the absolute path of the managed object
   *         containing the property which has the default values.
   */
  public ManagedObjectPath getManagedObjectPath(ManagedObjectPath path) {
  public ManagedObjectPath<?, ?> getManagedObjectPath(
      ManagedObjectPath<?, ?> path) {
    return path.parent(offset);
  }
opends/src/server/org/opends/server/admin/UnknownPropertyDefinitionException.java
@@ -53,7 +53,7 @@
   * @param p
   *          The visitor parameter if there was one.
   */
  public UnknownPropertyDefinitionException(PropertyDefinition d, Object p) {
  public UnknownPropertyDefinitionException(PropertyDefinition<?> d, Object p) {
    super(d);
    this.parameter = p;
  }
opends/src/server/org/opends/server/admin/client/ManagedObject.java
@@ -32,6 +32,8 @@
import java.util.Collection;
import java.util.SortedSet;
import org.opends.server.admin.AbstractManagedObjectDefinition;
import org.opends.server.admin.Configuration;
import org.opends.server.admin.DefaultBehaviorException;
import org.opends.server.admin.DefinitionDecodingException;
import org.opends.server.admin.IllegalPropertyValueException;
@@ -84,11 +86,11 @@
 * <li>or, an empty set of values, if there are no default values.
 * </ul>
 *
 * @param <C>
 * @param <T>
 *          The type of client configuration represented by the client
 *          managed object.
 */
public interface ManagedObject<C extends ConfigurationClient> extends
public interface ManagedObject<T extends ConfigurationClient> extends
    PropertyProvider {
  /**
@@ -138,10 +140,13 @@
   * Once the managed object has been configured it can be added to
   * the server using the {@link #commit()} method.
   *
   * @param <M>
   * @param <C>
   *          The expected type of the child managed object
   *          configuration client.
   * @param <N>
   * @param <S>
   *          The expected type of the child managed object
   *          server configuration.
   * @param <CC>
   *          The actual type of the added managed object
   *          configuration client.
   * @param r
@@ -163,9 +168,10 @@
   *           If the relation definition is not associated with this
   *           managed object's definition.
   */
  <M extends ConfigurationClient, N extends M> ManagedObject<N> createChild(
      InstantiableRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
      String name, Collection<DefaultBehaviorException> exceptions)
  <C extends ConfigurationClient, S extends Configuration, CC extends C>
  ManagedObject<CC> createChild(InstantiableRelationDefinition<C, S> r,
      ManagedObjectDefinition<CC, ? extends S> d, String name,
      Collection<DefaultBehaviorException> exceptions)
      throws IllegalManagedObjectNameException, IllegalArgumentException;
@@ -177,10 +183,13 @@
   * Once the managed object has been configured it can be added to
   * the server using the {@link #commit()} method.
   *
   * @param <M>
   * @param <C>
   *          The expected type of the child managed object
   *          configuration client.
   * @param <N>
   * @param <S>
   *          The expected type of the child managed object
   *          server configuration.
   * @param <CC>
   *          The actual type of the added managed object
   *          configuration client.
   * @param r
@@ -198,8 +207,9 @@
   *           If the relation definition is not associated with this
   *           managed object's definition.
   */
  <M extends ConfigurationClient, N extends M> ManagedObject<N> createChild(
      OptionalRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
  <C extends ConfigurationClient, S extends Configuration, CC extends C>
  ManagedObject<CC> createChild(OptionalRelationDefinition<C, S> r,
      ManagedObjectDefinition<CC, ? extends S> d,
      Collection<DefaultBehaviorException> exceptions)
      throws IllegalArgumentException;
@@ -208,10 +218,13 @@
  /**
   * Retrieve an instantiable child managed object.
   *
   * @param <M>
   * @param <C>
   *          The requested type of the child managed object
   *          configuration client.
   * @param d
   * @param <S>
   *          The type of server managed object configuration that the
   *          relation definition refers to.
   * @param r
   *          The instantiable relation definition.
   * @param name
   *          The name of the child managed object.
@@ -239,9 +252,9 @@
   *           If the client cannot contact the server due to an
   *           underlying communication problem.
   */
  <M extends ConfigurationClient> ManagedObject<? extends M> getChild(
      InstantiableRelationDefinition<M, ?> d, String name)
      throws IllegalArgumentException, DefinitionDecodingException,
  <C extends ConfigurationClient, S extends Configuration>
  ManagedObject<? extends C> getChild(InstantiableRelationDefinition<C, S> r,
      String name) throws IllegalArgumentException, DefinitionDecodingException,
      ManagedObjectDecodingException, ManagedObjectNotFoundException,
      ConcurrentModificationException, AuthorizationException,
      CommunicationException;
@@ -251,10 +264,13 @@
  /**
   * Retrieve an optional child managed object.
   *
   * @param <M>
   * @param <C>
   *          The requested type of the child managed object
   *          configuration client.
   * @param d
   * @param <S>
   *          The type of server managed object configuration that the
   *          relation definition refers to.
   * @param r
   *          The optional relation definition.
   * @return Returns the optional child managed object.
   * @throws IllegalArgumentException
@@ -280,21 +296,25 @@
   *           If the client cannot contact the server due to an
   *           underlying communication problem.
   */
  <M extends ConfigurationClient> ManagedObject<? extends M> getChild(
      OptionalRelationDefinition<M, ?> d) throws IllegalArgumentException,
      DefinitionDecodingException, ManagedObjectDecodingException,
      ManagedObjectNotFoundException, ConcurrentModificationException,
      AuthorizationException, CommunicationException;
  <C extends ConfigurationClient, S extends Configuration>
  ManagedObject<? extends C> getChild(OptionalRelationDefinition<C, S> r)
      throws IllegalArgumentException, DefinitionDecodingException,
      ManagedObjectDecodingException, ManagedObjectNotFoundException,
      ConcurrentModificationException, AuthorizationException,
      CommunicationException;
  /**
   * Retrieve a singleton child managed object.
   *
   * @param <M>
   * @param <C>
   *          The requested type of the child managed object
   *          configuration client.
   * @param d
   * @param <S>
   *          The type of server managed object configuration that the
   *          relation definition refers to.
   * @param r
   *          The singleton relation definition.
   * @return Returns the singleton child managed object.
   * @throws IllegalArgumentException
@@ -320,11 +340,12 @@
   *           If the client cannot contact the server due to an
   *           underlying communication problem.
   */
  <M extends ConfigurationClient> ManagedObject<? extends M> getChild(
      SingletonRelationDefinition<M, ?> d) throws IllegalArgumentException,
      DefinitionDecodingException, ManagedObjectDecodingException,
      ManagedObjectNotFoundException, ConcurrentModificationException,
      AuthorizationException, CommunicationException;
  <C extends ConfigurationClient, S extends Configuration>
  ManagedObject<? extends C> getChild(SingletonRelationDefinition<C, S> r)
      throws IllegalArgumentException, DefinitionDecodingException,
      ManagedObjectDecodingException, ManagedObjectNotFoundException,
      ConcurrentModificationException, AuthorizationException,
      CommunicationException;
@@ -336,7 +357,7 @@
   * @return Returns a client configuration view of this managed
   *         object.
   */
  C getConfiguration();
  T getConfiguration();
@@ -346,7 +367,8 @@
   * @return Returns the definition associated with this managed
   *         object.
   */
  ManagedObjectDefinition<C, ?> getManagedObjectDefinition();
  ManagedObjectDefinition<T, ? extends Configuration>
    getManagedObjectDefinition();
@@ -355,7 +377,7 @@
   *
   * @return Returns the path of this managed object.
   */
  ManagedObjectPath getManagedObjectPath();
  ManagedObjectPath<T, ? extends Configuration> getManagedObjectPath();
@@ -365,9 +387,9 @@
   * See the class description for more information about how the
   * effective property value is derived.
   *
   * @param <T>
   * @param <P>
   *          The type of the property to be retrieved.
   * @param d
   * @param pd
   *          The property to be retrieved.
   * @return Returns the property's effective value, or
   *         <code>null</code> if there is no effective value
@@ -376,7 +398,7 @@
   *           If the property definition is not associated with this
   *           managed object's definition.
   */
  <T> T getPropertyValue(PropertyDefinition<T> d)
  <P> P getPropertyValue(PropertyDefinition<P> pd)
      throws IllegalArgumentException;
@@ -387,9 +409,9 @@
   * See the class description for more information about how the
   * effective property values are derived.
   *
   * @param <T>
   * @param <P>
   *          The type of the property to be retrieved.
   * @param d
   * @param pd
   *          The property to be retrieved.
   * @return Returns the property's effective values, or an empty set
   *         if there are no effective values defined.
@@ -397,7 +419,7 @@
   *           If the property definition is not associated with this
   *           managed object's definition.
   */
  <T> SortedSet<T> getPropertyValues(PropertyDefinition<T> d)
  <P> SortedSet<P> getPropertyValues(PropertyDefinition<P> pd)
      throws IllegalArgumentException;
@@ -406,7 +428,13 @@
   * Determines whether or not the optional managed object associated
   * with the specified optional relations exists.
   *
   * @param d
   * @param <C>
   *          The type of client managed object configuration that the
   *          relation definition refers to.
   * @param <S>
   *          The type of server managed object configuration that the
   *          relation definition refers to.
   * @param r
   *          The optional relation definition.
   * @return Returns <code>true</code> if the optional managed
   *         object exists, <code>false</code> otherwise.
@@ -423,7 +451,8 @@
   *           If the client cannot contact the server due to an
   *           underlying communication problem.
   */
  boolean hasChild(OptionalRelationDefinition<?, ?> d)
  <C extends ConfigurationClient, S extends Configuration>
  boolean hasChild(OptionalRelationDefinition<C, S> r)
      throws IllegalArgumentException, ConcurrentModificationException,
      AuthorizationException, CommunicationException;
@@ -433,7 +462,13 @@
   * Lists the child managed objects associated with the specified
   * instantiable relation.
   *
   * @param d
   * @param <C>
   *          The type of client managed object configuration that the
   *          relation definition refers to.
   * @param <S>
   *          The type of server managed object configuration that the
   *          relation definition refers to.
   * @param r
   *          The instantiable relation definition.
   * @return Returns the names of the child managed objects.
   * @throws IllegalArgumentException
@@ -450,7 +485,47 @@
   *           If the client cannot contact the server due to an
   *           underlying communication problem.
   */
  String[] listChildren(InstantiableRelationDefinition<?, ?> d)
  <C extends ConfigurationClient, S extends Configuration>
  String[] listChildren(InstantiableRelationDefinition<C, S> r)
      throws IllegalArgumentException, ConcurrentModificationException,
      AuthorizationException, CommunicationException;
  /**
   * Lists the child managed objects associated with the specified
   * instantiable relation which are a sub-type of the specified
   * managed object definition.
   *
   * @param <C>
   *          The type of client managed object configuration that the
   *          relation definition refers to.
   * @param <S>
   *          The type of server managed object configuration that the
   *          relation definition refers to.
   * @param r
   *          The instantiable relation definition.
   * @param d
   *          The managed object definition.
   * @return Returns the names of the child managed objects which are
   *         a sub-type of the specified managed object definition.
   * @throws IllegalArgumentException
   *           If the relation definition is not associated with this
   *           managed object's definition.
   * @throws ConcurrentModificationException
   *           If this managed object has been removed from the server
   *           by another client.
   * @throws AuthorizationException
   *           If the server refuses to list the managed objects
   *           because the client does not have the correct
   *           privileges.
   * @throws CommunicationException
   *           If the client cannot contact the server due to an
   *           underlying communication problem.
   */
  <C extends ConfigurationClient, S extends Configuration>
  String[] listChildren(InstantiableRelationDefinition<C, S> r,
      AbstractManagedObjectDefinition<? extends C, ? extends S> d)
      throws IllegalArgumentException, ConcurrentModificationException,
      AuthorizationException, CommunicationException;
@@ -459,10 +534,13 @@
  /**
   * Removes the named instantiable child managed object.
   *
   * @param <M>
   *          The type of the child managed object configuration
   *          client.
   * @param d
   * @param <C>
   *          The type of client managed object configuration that the
   *          relation definition refers to.
   * @param <S>
   *          The type of server managed object configuration that the
   *          relation definition refers to.
   * @param r
   *          The instantiable relation definition.
   * @param name
   *          The name of the child managed object to be removed.
@@ -488,8 +566,8 @@
   *           If the client cannot contact the server due to an
   *           underlying communication problem.
   */
  <M extends ConfigurationClient> void removeChild(
      InstantiableRelationDefinition<M, ?> d, String name)
  <C extends ConfigurationClient, S extends Configuration>
  void removeChild(InstantiableRelationDefinition<C, S> r, String name)
      throws IllegalArgumentException, ManagedObjectNotFoundException,
      OperationRejectedException, ConcurrentModificationException,
      AuthorizationException, CommunicationException;
@@ -499,10 +577,13 @@
  /**
   * Removes an optional child managed object.
   *
   * @param <M>
   *          The type of the child managed object configuration
   *          client.
   * @param d
   * @param <C>
   *          The type of client managed object configuration that the
   *          relation definition refers to.
   * @param <S>
   *          The type of server managed object configuration that the
   *          relation definition refers to.
   * @param r
   *          The optional relation definition.
   * @throws IllegalArgumentException
   *           If the relation definition is not associated with this
@@ -526,11 +607,11 @@
   *           If the client cannot contact the server due to an
   *           underlying communication problem.
   */
  <M extends ConfigurationClient> void removeChild(
      OptionalRelationDefinition<M, ?> d) throws IllegalArgumentException,
      ManagedObjectNotFoundException, OperationRejectedException,
      ConcurrentModificationException, AuthorizationException,
      CommunicationException;
  <C extends ConfigurationClient, S extends Configuration>
  void removeChild(OptionalRelationDefinition<C, S> r)
      throws IllegalArgumentException, ManagedObjectNotFoundException,
      OperationRejectedException, ConcurrentModificationException,
      AuthorizationException, CommunicationException;
@@ -540,9 +621,9 @@
   * See the class description for more information regarding pending
   * values.
   *
   * @param <T>
   * @param <P>
   *          The type of the property to be modified.
   * @param d
   * @param pd
   *          The property to be modified.
   * @param value
   *          The new pending value for the property, or
@@ -560,7 +641,7 @@
   *           If the specified property definition is not associated
   *           with this managed object.
   */
  <T> void setPropertyValue(PropertyDefinition<T> d, T value)
  <P> void setPropertyValue(PropertyDefinition<P> pd, P value)
      throws IllegalPropertyValueException, PropertyIsReadOnlyException,
      PropertyIsMandatoryException, IllegalArgumentException;
@@ -572,9 +653,9 @@
   * See the class description for more information regarding pending
   * values.
   *
   * @param <T>
   * @param <P>
   *          The type of the property to be modified.
   * @param d
   * @param pd
   *          The property to be modified.
   * @param values
   *          A non-<code>null</code> set of new pending values for
@@ -596,7 +677,7 @@
   *           If the specified property definition is not associated
   *           with this managed object.
   */
  <T> void setPropertyValues(PropertyDefinition<T> d, Collection<T> values)
  <P> void setPropertyValues(PropertyDefinition<P> pd, Collection<P> values)
      throws IllegalPropertyValueException, PropertyIsSingleValuedException,
      PropertyIsReadOnlyException, PropertyIsMandatoryException,
      IllegalArgumentException;
opends/src/server/org/opends/server/admin/client/PropertySet.java
@@ -220,7 +220,7 @@
  }
  // The properties.
  private final Map<PropertyDefinition, MyProperty> properties;
  private final Map<PropertyDefinition<?>, MyProperty<?>> properties;
@@ -228,7 +228,7 @@
   * Creates a new empty property set.
   */
  public PropertySet() {
    this.properties = new HashMap<PropertyDefinition, MyProperty>();
    this.properties = new HashMap<PropertyDefinition<?>, MyProperty<?>>();
  }
@@ -286,7 +286,7 @@
      throw new IllegalArgumentException("Unknown property " + d.getName());
    }
    return properties.get(d);
    return (Property<T>) properties.get(d);
  }
@@ -445,7 +445,7 @@
  public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append('{');
    for (Map.Entry<PropertyDefinition, MyProperty> entry : properties
    for (Map.Entry<PropertyDefinition<?>, MyProperty<?>> entry : properties
        .entrySet()) {
      builder.append(entry.getKey().getName());
      builder.append('=');
opends/src/server/org/opends/server/admin/client/ldap/JNDIDirContextAdaptor.java
@@ -152,7 +152,7 @@
  @Override
  public void deleteSubtree(LdapName dn) throws NamingException {
    // Delete the children first.
    for (LdapName child : listEntries(dn)) {
    for (LdapName child : listEntries(dn, null)) {
      deleteSubtree(child);
    }
@@ -189,8 +189,12 @@
   * {@inheritDoc}
   */
  @Override
  public Collection<LdapName> listEntries(LdapName dn) throws NamingException {
    String filter = "(objectClass=*)";
  public Collection<LdapName> listEntries(LdapName dn, String filter)
      throws NamingException {
    if (filter == null) {
      filter = "(objectClass=*)";
    }
    SearchControls controls = new SearchControls();
    controls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
opends/src/server/org/opends/server/admin/client/ldap/LDAPConnection.java
@@ -100,11 +100,14 @@
   *
   * @param dn
   *          The name of the entry to list.
   * @param filter
   *          An LDAP filter string, or <code>null</code> indicating
   *          the default filter of <code>(objectclass=*)</code>.
   * @return Returns the names of the children.
   * @throws NamingException
   *           If an error occurred whilst listing the children.
   */
  public abstract Collection<LdapName> listEntries(LdapName dn)
  public abstract Collection<LdapName> listEntries(LdapName dn, String filter)
      throws NamingException;
opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java
@@ -54,6 +54,7 @@
import org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider;
import org.opends.server.admin.AbstractManagedObjectDefinition;
import org.opends.server.admin.AliasDefaultBehaviorProvider;
import org.opends.server.admin.Configuration;
import org.opends.server.admin.ConfigurationClient;
import org.opends.server.admin.DefaultBehaviorException;
import org.opends.server.admin.DefaultBehaviorProviderVisitor;
@@ -98,12 +99,12 @@
/**
 * A managed object bound to an LDAP connection.
 *
 * @param <C>
 * @param <T>
 *          The type of client configuration represented by the client
 *          managed object.
 */
final class LDAPManagedObject<C extends ConfigurationClient> implements
    ManagedObject<C> {
final class LDAPManagedObject<T extends ConfigurationClient> implements
    ManagedObject<T> {
  /**
   * A default behavior visitor used for retrieving the default values
@@ -135,7 +136,7 @@
     *           decoded properly.
     */
    public static <T> Collection<T> getDefaultValues(
        LDAPManagementContext context, ManagedObjectPath p,
        LDAPManagementContext context, ManagedObjectPath<?, ?> p,
        PropertyDefinition<T> pd, boolean isCreate)
        throws DefaultBehaviorException {
      DefaultValueFinder<T> v = new DefaultValueFinder<T>(context, p, isCreate);
@@ -153,10 +154,10 @@
    private final boolean isCreate;
    // The path of the managed object containing the first property.
    private final ManagedObjectPath firstPath;
    private final ManagedObjectPath<?, ?> firstPath;
    // The path of the managed object containing the next property.
    private ManagedObjectPath nextPath = null;
    private ManagedObjectPath<?, ?> nextPath = null;
    // The next property whose default values were required.
    private PropertyDefinition<T> nextProperty = null;
@@ -165,7 +166,7 @@
    // Private constructor.
    private DefaultValueFinder(LDAPManagementContext context,
        ManagedObjectPath p, boolean isCreate) {
        ManagedObjectPath<?, ?> p, boolean isCreate) {
      this.context = context;
      this.firstPath = p;
      this.isCreate = isCreate;
@@ -248,7 +249,8 @@
    // Find the default values for the next path/property.
    private Collection<T> find(ManagedObjectPath p, PropertyDefinition<T> pd)
    private Collection<T> find(ManagedObjectPath<?, ?> p,
        PropertyDefinition<T> pd)
        throws DefaultBehaviorException {
      this.nextPath = p;
      this.nextProperty = pd;
@@ -403,10 +405,10 @@
  // Determine the type of managed object associated with the named
  // entry.
  private static <M extends ConfigurationClient>
      ManagedObjectDefinition<? extends M, ?> getEntryDefinition(
  private static <M extends ConfigurationClient, N extends Configuration>
      ManagedObjectDefinition<? extends M, ? extends N> getEntryDefinition(
      final LDAPManagementContext context,
      AbstractManagedObjectDefinition<M, ?> d, LdapName dn)
      AbstractManagedObjectDefinition<M, N> d, LdapName dn)
      throws NamingException, DefinitionDecodingException {
    Attributes attributes = context.getLDAPConnection().readEntry(dn,
        Collections.singleton("objectclass"));
@@ -449,7 +451,7 @@
  // The managed object definition associated with this managed
  // object.
  private final ManagedObjectDefinition<C, ?> definition;
  private final ManagedObjectDefinition<T, ? extends Configuration> definition;
  // Indicates whether or not this managed object exists on the server
  // (false means the managed object is new and has not been
@@ -460,7 +462,7 @@
  private final PropertyDefinition<?> namingPropertyDefinition;
  // The path associated with this managed object.
  private ManagedObjectPath<?, ?> path;
  private ManagedObjectPath<T, ? extends Configuration> path;
  // The managed object's properties.
  private final PropertySet properties;
@@ -469,7 +471,8 @@
  // Create an new LDAP managed object with the provided JNDI context.
  private LDAPManagedObject(LDAPManagementContext context,
      ManagedObjectDefinition<C, ?> d, ManagedObjectPath path,
      ManagedObjectDefinition<T, ? extends Configuration> d,
      ManagedObjectPath<T, ? extends Configuration> path,
      PropertySet properties, boolean existsOnServer,
      PropertyDefinition<?> namingPropertyDefinition) {
    this.definition = d;
@@ -518,10 +521,10 @@
  /**
   * {@inheritDoc}
   */
  public <M extends ConfigurationClient, N extends M>
      ManagedObject<N> createChild(
      InstantiableRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
      String name, Collection<DefaultBehaviorException> exceptions)
  public <C extends ConfigurationClient, S extends Configuration, CC extends C>
  ManagedObject<CC> createChild(InstantiableRelationDefinition<C, S> r,
      ManagedObjectDefinition<CC, ? extends S> d, String name,
      Collection<DefaultBehaviorException> exceptions)
      throws IllegalManagedObjectNameException, IllegalArgumentException {
    validateRelationDefinition(r);
@@ -541,7 +544,7 @@
      }
    }
    ManagedObjectPath childPath = path.child(r, name);
    ManagedObjectPath<CC, ? extends S> childPath = path.child(r, d, name);
    return createNewManagedObject(d, childPath, pd, name, exceptions);
  }
@@ -550,14 +553,13 @@
  /**
   * {@inheritDoc}
   */
  @SuppressWarnings("unchecked")
  public <M extends ConfigurationClient, N extends M>
      ManagedObject<N> createChild(
      OptionalRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
  public <C extends ConfigurationClient, S extends Configuration, CC extends C>
  ManagedObject<CC> createChild(OptionalRelationDefinition<C, S> r,
      ManagedObjectDefinition<CC, ? extends S> d,
      Collection<DefaultBehaviorException> exceptions)
      throws IllegalArgumentException {
    validateRelationDefinition(r);
    ManagedObjectPath childPath = path.child(r);
    ManagedObjectPath<CC, ? extends S> childPath = path.child(r, d);
    return createNewManagedObject(d, childPath, null, null, exceptions);
  }
@@ -566,15 +568,31 @@
  /**
   * {@inheritDoc}
   */
  public <M extends ConfigurationClient> ManagedObject<? extends M> getChild(
      InstantiableRelationDefinition<M, ?> d, String name)
  public <C extends ConfigurationClient, S extends Configuration>
  ManagedObject<? extends C> getChild(InstantiableRelationDefinition<C, S> r,
      String name) throws IllegalArgumentException, DefinitionDecodingException,
      ManagedObjectDecodingException, ManagedObjectNotFoundException,
      ConcurrentModificationException, AuthorizationException,
      CommunicationException {
    validateRelationDefinition(r);
    ensureThisManagedObjectExists();
    return readManagedObject(r.getChildDefinition(), path.child(r, name));
  }
  /**
   * {@inheritDoc}
   */
  public <C extends ConfigurationClient, S extends Configuration>
  ManagedObject<? extends C> getChild(OptionalRelationDefinition<C, S> r)
      throws IllegalArgumentException, DefinitionDecodingException,
      ManagedObjectDecodingException, ManagedObjectNotFoundException,
      ConcurrentModificationException, AuthorizationException,
      CommunicationException {
    validateRelationDefinition(d);
    validateRelationDefinition(r);
    ensureThisManagedObjectExists();
    return readManagedObject(d.getChildDefinition(), path.child(d, name));
    return readManagedObject(r.getChildDefinition(), path.child(r));
  }
@@ -582,14 +600,15 @@
  /**
   * {@inheritDoc}
   */
  public <M extends ConfigurationClient> ManagedObject<? extends M> getChild(
      OptionalRelationDefinition<M, ?> d) throws IllegalArgumentException,
  public <C extends ConfigurationClient, S extends Configuration>
  ManagedObject<? extends C> getChild(
      SingletonRelationDefinition<C, S> r) throws IllegalArgumentException,
      DefinitionDecodingException, ManagedObjectDecodingException,
      ManagedObjectNotFoundException, ConcurrentModificationException,
      AuthorizationException, CommunicationException {
    validateRelationDefinition(d);
    validateRelationDefinition(r);
    ensureThisManagedObjectExists();
    return readManagedObject(d.getChildDefinition(), path.child(d));
    return readManagedObject(r.getChildDefinition(), path.child(r));
  }
@@ -597,22 +616,7 @@
  /**
   * {@inheritDoc}
   */
  public <M extends ConfigurationClient> ManagedObject<? extends M> getChild(
      SingletonRelationDefinition<M, ?> d) throws IllegalArgumentException,
      DefinitionDecodingException, ManagedObjectDecodingException,
      ManagedObjectNotFoundException, ConcurrentModificationException,
      AuthorizationException, CommunicationException {
    validateRelationDefinition(d);
    ensureThisManagedObjectExists();
    return readManagedObject(d.getChildDefinition(), path.child(d));
  }
  /**
   * {@inheritDoc}
   */
  public C getConfiguration() {
  public T getConfiguration() {
    return definition.createClientConfiguration(this);
  }
@@ -621,7 +625,8 @@
  /**
   * {@inheritDoc}
   */
  public ManagedObjectDefinition<C, ?> getManagedObjectDefinition() {
  public ManagedObjectDefinition<T, ? extends Configuration>
  getManagedObjectDefinition() {
    return definition;
  }
@@ -630,7 +635,7 @@
  /**
   * {@inheritDoc}
   */
  public ManagedObjectPath getManagedObjectPath() {
  public ManagedObjectPath<T, ? extends Configuration> getManagedObjectPath() {
    return path;
  }
@@ -639,9 +644,9 @@
  /**
   * {@inheritDoc}
   */
  public <T> T getPropertyValue(PropertyDefinition<T> d)
  public <P> P getPropertyValue(PropertyDefinition<P> pd)
      throws IllegalArgumentException {
    return properties.getPropertyValue(d);
    return properties.getPropertyValue(pd);
  }
@@ -649,9 +654,9 @@
  /**
   * {@inheritDoc}
   */
  public <T> SortedSet<T> getPropertyValues(PropertyDefinition<T> d)
  public <P> SortedSet<P> getPropertyValues(PropertyDefinition<P> pd)
      throws IllegalArgumentException {
    return properties.getPropertyValues(d);
    return properties.getPropertyValues(pd);
  }
@@ -659,13 +664,14 @@
  /**
   * {@inheritDoc}
   */
  public boolean hasChild(OptionalRelationDefinition<?, ?> d)
  public <C extends ConfigurationClient, S extends Configuration>
  boolean hasChild(OptionalRelationDefinition<C, S> r)
      throws IllegalArgumentException, ConcurrentModificationException,
      AuthorizationException, CommunicationException {
    validateRelationDefinition(d);
    validateRelationDefinition(r);
    ensureThisManagedObjectExists();
    ManagedObjectPath p = path.child(d);
    ManagedObjectPath<C, S> p = path.child(r);
    LdapName dn = LDAPNameBuilder.create(p, context.getLDAPProfile());
    return entryExists(dn);
  }
@@ -675,16 +681,41 @@
  /**
   * {@inheritDoc}
   */
  public String[] listChildren(InstantiableRelationDefinition<?, ?> d)
  public <C extends ConfigurationClient, S extends Configuration>
  String[] listChildren(InstantiableRelationDefinition<C, S> r)
      throws IllegalArgumentException, ConcurrentModificationException,
      AuthorizationException, CommunicationException {
    validateRelationDefinition(d);
    return listChildren(r, r.getChildDefinition());
  }
  /**
   * {@inheritDoc}
   */
  public <C extends ConfigurationClient, S extends Configuration>
  String[] listChildren(InstantiableRelationDefinition<C, S> r,
      AbstractManagedObjectDefinition<? extends C, ? extends S> d)
      throws IllegalArgumentException, ConcurrentModificationException,
      AuthorizationException, CommunicationException {
    validateRelationDefinition(r);
    ensureThisManagedObjectExists();
    // Get the search base DN.
    LdapName dn = LDAPNameBuilder.create(path, r, context.getLDAPProfile());
    // Retrieve only those entries which are sub-types of the
    // specified definition.
    StringBuilder builder = new StringBuilder();
    builder.append("(objectclass=");
    builder.append(context.getLDAPProfile().getObjectClass(d));
    builder.append(')');
    String filter = builder.toString();
    List<String> children = new ArrayList<String>();
    LdapName dn = LDAPNameBuilder.create(path, d, context.getLDAPProfile());
    try {
      for (LdapName child : context.getLDAPConnection().listEntries(dn)) {
      for (LdapName child :
          context.getLDAPConnection().listEntries(dn, filter)) {
        children.add(child.getRdn(child.size() - 1).getValue().toString());
      }
    } catch (NameNotFoundException e) {
@@ -702,14 +733,14 @@
  /**
   * {@inheritDoc}
   */
  public <M extends ConfigurationClient> void removeChild(
      InstantiableRelationDefinition<M, ?> d, String name)
  public <C extends ConfigurationClient, S extends Configuration>
  void removeChild(InstantiableRelationDefinition<C, S> r, String name)
      throws IllegalArgumentException, ManagedObjectNotFoundException,
      OperationRejectedException, ConcurrentModificationException,
      AuthorizationException, CommunicationException {
    validateRelationDefinition(d);
    validateRelationDefinition(r);
    ensureThisManagedObjectExists();
    ManagedObjectPath p = path.child(d, name);
    ManagedObjectPath<C, S> p = path.child(r, name);
    removeManagedObject(p);
  }
@@ -718,14 +749,14 @@
  /**
   * {@inheritDoc}
   */
  public <M extends ConfigurationClient> void removeChild(
      OptionalRelationDefinition<M, ?> d) throws IllegalArgumentException,
      ManagedObjectNotFoundException, OperationRejectedException,
      ConcurrentModificationException, AuthorizationException,
      CommunicationException {
    validateRelationDefinition(d);
  public <C extends ConfigurationClient, S extends Configuration>
  void removeChild(OptionalRelationDefinition<C, S> r)
      throws IllegalArgumentException, ManagedObjectNotFoundException,
        OperationRejectedException, ConcurrentModificationException,
        AuthorizationException, CommunicationException {
    validateRelationDefinition(r);
    ensureThisManagedObjectExists();
    ManagedObjectPath p = path.child(d);
    ManagedObjectPath<C, S> p = path.child(r);
    removeManagedObject(p);
  }
@@ -734,13 +765,13 @@
  /**
   * {@inheritDoc}
   */
  public <T> void setPropertyValue(PropertyDefinition<T> d, T value)
  public <P> void setPropertyValue(PropertyDefinition<P> pd, P value)
      throws IllegalPropertyValueException, PropertyIsReadOnlyException,
      PropertyIsMandatoryException, IllegalArgumentException {
    if (value == null) {
      setPropertyValues(d, Collections.<T> emptySet());
      setPropertyValues(pd, Collections.<P> emptySet());
    } else {
      setPropertyValues(d, Collections.singleton(value));
      setPropertyValues(pd, Collections.singleton(value));
    }
  }
@@ -749,24 +780,24 @@
  /**
   * {@inheritDoc}
   */
  public <T> void setPropertyValues(PropertyDefinition<T> d,
      Collection<T> values) throws IllegalPropertyValueException,
  public <P> void setPropertyValues(PropertyDefinition<P> pd,
      Collection<P> values) throws IllegalPropertyValueException,
      PropertyIsSingleValuedException, PropertyIsReadOnlyException,
      PropertyIsMandatoryException, IllegalArgumentException {
    if (d.hasOption(PropertyOption.MONITORING)) {
      throw new PropertyIsReadOnlyException(d);
    if (pd.hasOption(PropertyOption.MONITORING)) {
      throw new PropertyIsReadOnlyException(pd);
    }
    if (existsOnServer && d.hasOption(PropertyOption.READ_ONLY)) {
      throw new PropertyIsReadOnlyException(d);
    if (existsOnServer && pd.hasOption(PropertyOption.READ_ONLY)) {
      throw new PropertyIsReadOnlyException(pd);
    }
    properties.setPropertyValues(d, values);
    properties.setPropertyValues(pd, values);
    // If this is a naming property then update the name.
    if (d.equals(namingPropertyDefinition)) {
    if (pd.equals(namingPropertyDefinition)) {
      // The property must be single-valued and mandatory.
      String newName = d.encodeValue(values.iterator().next());
      String newName = pd.encodeValue(values.iterator().next());
      path = path.rename(newName);
    }
  }
@@ -933,28 +964,29 @@
  // Create a managed object which already exists on the server.
  private <M extends ConfigurationClient>
  private <M extends ConfigurationClient, N extends Configuration>
      ManagedObject<M> createExistingManagedObject(
      ManagedObjectDefinition<M, ?> d, ManagedObjectPath p,
      PropertySet properties) {
      ManagedObjectDefinition<M, N> d,
      ManagedObjectPath<? super M, ? super N> p, PropertySet properties) {
    RelationDefinition<?, ?> rd = p.getRelationDefinition();
    PropertyDefinition<?> pd = null;
    if (rd instanceof InstantiableRelationDefinition) {
      InstantiableRelationDefinition<?, ?> ird =
        (InstantiableRelationDefinition) rd;
        (InstantiableRelationDefinition<?, ?>) rd;
      pd = ird.getNamingPropertyDefinition();
    }
    return new LDAPManagedObject<M>(context, d, p, properties, true, pd);
    return new LDAPManagedObject<M>(context, d, p.asSubType(d), properties,
        true, pd);
  }
  // Creates a new managed object with no active values, just default
  // values.
  private <M extends ConfigurationClient, T>
  private <M extends ConfigurationClient, P>
      ManagedObject<M> createNewManagedObject(
      ManagedObjectDefinition<M, ?> d, ManagedObjectPath p,
      PropertyDefinition<T> namingPropertyDefinition, String name,
      ManagedObjectDefinition<M, ?> d, ManagedObjectPath<M, ?> p,
      PropertyDefinition<P> namingPropertyDefinition, String name,
      Collection<DefaultBehaviorException> exceptions) {
    PropertySet childProperties = new PropertySet();
    for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
@@ -970,7 +1002,7 @@
    // Set the naming property if there is one.
    if (namingPropertyDefinition != null) {
      T value = namingPropertyDefinition.decodeValue(name);
      P value = namingPropertyDefinition.decodeValue(name);
      childProperties.setPropertyValue(namingPropertyDefinition, value);
    }
@@ -981,16 +1013,17 @@
  // Create an empty property.
  private <T> void createProperty(PropertySet properties, ManagedObjectPath p,
      PropertyDefinition<T> pd) throws DefaultBehaviorException {
  private <P> void createProperty(PropertySet properties,
      ManagedObjectPath<?, ?> p, PropertyDefinition<P> pd)
      throws DefaultBehaviorException {
    try {
      Collection<T> defaultValues = DefaultValueFinder.getDefaultValues(
      Collection<P> defaultValues = DefaultValueFinder.getDefaultValues(
          context, p, pd, true);
      properties.addProperty(pd, defaultValues, Collections.<T> emptySet());
      properties.addProperty(pd, defaultValues, Collections.<P> emptySet());
    } catch (DefaultBehaviorException e) {
      // Make sure that we have still created the property.
      properties.addProperty(pd, Collections.<T> emptySet(), Collections
          .<T> emptySet());
      properties.addProperty(pd, Collections.<P> emptySet(), Collections
          .<P> emptySet());
      throw e;
    }
  }
@@ -998,13 +1031,13 @@
  // Create a property using the provided string values.
  private <T> void decodeProperty(PropertySet newProperties,
      ManagedObjectPath p, PropertyDefinition<T> pd, List<String> values)
  private <P> void decodeProperty(PropertySet newProperties,
      ManagedObjectPath<?, ?> p, PropertyDefinition<P> pd, List<String> values)
      throws PropertyException {
    PropertyException exception = null;
    // Get the property's active values.
    Collection<T> activeValues = new ArrayList<T>(values.size());
    Collection<P> activeValues = new ArrayList<P>(values.size());
    for (String value : values) {
      try {
        activeValues.add(pd.decodeValue(value));
@@ -1016,7 +1049,7 @@
    if (activeValues.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
      // This exception takes precedence over previous exceptions.
      exception = new PropertyIsSingleValuedException(pd);
      T value = activeValues.iterator().next();
      P value = activeValues.iterator().next();
      activeValues.clear();
      activeValues.add(value);
    }
@@ -1029,7 +1062,7 @@
    }
    // Get the property's default values.
    Collection<T> defaultValues;
    Collection<P> defaultValues;
    try {
      defaultValues = DefaultValueFinder.getDefaultValues(context, p, pd,
          false);
@@ -1047,18 +1080,18 @@
  // Encode a property into LDAP string values.
  private <T> void encodeProperty(Attribute attribute,
      PropertyDefinition<T> pd, PropertySet properties) {
    Property<T> p = properties.getProperty(pd);
  private <P> void encodeProperty(Attribute attribute,
      PropertyDefinition<P> pd, PropertySet properties) {
    Property<P> p = properties.getProperty(pd);
    if (pd.hasOption(PropertyOption.MANDATORY)) {
      // For mandatory properties we fall-back to the default values
      // if defined which can sometimes be the case e.g when a
      // mandatory property is overridden.
      for (T value : p.getEffectiveValues()) {
      for (P value : p.getEffectiveValues()) {
        attribute.add(pd.encodeValue(value));
      }
    } else {
      for (T value : p.getPendingValues()) {
      for (P value : p.getPendingValues()) {
        attribute.add(pd.encodeValue(value));
      }
    }
@@ -1096,17 +1129,17 @@
  // Read the entry identified by the path and which is a sub-type of
  // the specified definition.
  private <M extends ConfigurationClient>
      ManagedObject<? extends M> readManagedObject(
      AbstractManagedObjectDefinition<M, ?> d, ManagedObjectPath p)
  private <C extends ConfigurationClient, S extends Configuration>
      ManagedObject<? extends C> readManagedObject(
      AbstractManagedObjectDefinition<C, S> d, ManagedObjectPath<C, S> p)
      throws DefinitionDecodingException, ManagedObjectDecodingException,
      ManagedObjectNotFoundException, AuthorizationException,
      CommunicationException {
    try {
      // Read the entry associated with the managed object.
      LdapName dn = LDAPNameBuilder.create(p, context.getLDAPProfile());
      ManagedObjectDefinition<? extends M, ?> mod = getEntryDefinition(context,
          d, dn);
      ManagedObjectDefinition<? extends C, ? extends S> mod =
        getEntryDefinition(context, d, dn);
      ArrayList<String> attrIds = new ArrayList<String>();
      for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
@@ -1144,9 +1177,8 @@
      // If there were no decoding problems then return the object,
      // otherwise throw an operations exception.
      ManagedObject<? extends M> mo = createExistingManagedObject(mod, p,
      ManagedObject<? extends C> mo = createExistingManagedObject(mod, p,
          newProperties);
      if (exceptions.isEmpty()) {
        return mo;
      } else {
@@ -1164,7 +1196,7 @@
  // Remove the named managed object.
  private void removeManagedObject(ManagedObjectPath p)
  private void removeManagedObject(ManagedObjectPath<?, ?> p)
      throws CommunicationException, AuthorizationException,
      OperationRejectedException, ManagedObjectNotFoundException {
    LdapName dn = LDAPNameBuilder.create(p, context.getLDAPProfile());
@@ -1189,8 +1221,8 @@
  // object.
  private void validateRelationDefinition(RelationDefinition<?, ?> rd)
      throws IllegalArgumentException {
    ManagedObjectDefinition d = getManagedObjectDefinition();
    RelationDefinition tmp = d.getRelationDefinition(rd.getName());
    ManagedObjectDefinition<T, ?> d = getManagedObjectDefinition();
    RelationDefinition<?, ?> tmp = d.getRelationDefinition(rd.getName());
    if (tmp != rd) {
      throw new IllegalArgumentException("The relation " + rd.getName()
          + " is not associated with a " + d.getName());
opends/src/server/org/opends/server/admin/client/ldap/LDAPNameBuilder.java
@@ -65,7 +65,8 @@
   * @return Returns a new LDAP name representing the specified
   *         managed object path.
   */
  public static LdapName create(ManagedObjectPath path, LDAPProfile profile) {
  public static LdapName create(ManagedObjectPath<?, ?> path,
      LDAPProfile profile) {
    LDAPNameBuilder builder = new LDAPNameBuilder(profile);
    path.serialize(builder);
    return builder.getInstance();
@@ -87,7 +88,7 @@
   * @return Returns a new LDAP name representing the specified
   *         managed object path and instantiable relation.
   */
  public static LdapName create(ManagedObjectPath path,
  public static LdapName create(ManagedObjectPath<?, ?> path,
      InstantiableRelationDefinition<?, ?> relation, LDAPProfile profile) {
    LDAPNameBuilder builder = new LDAPNameBuilder(profile);
    path.serialize(builder);
@@ -125,7 +126,7 @@
          InstantiableRelationDefinition<? super C, ? super S> r,
          AbstractManagedObjectDefinition<C, S> d, String name) {
    // Add the RDN sequence representing the relation.
    appendManagedObjectPathElement((RelationDefinition) r);
    appendManagedObjectPathElement((RelationDefinition<?, ?>) r);
    // Now add the single RDN representing the named instance.
    String type = profile.getInstantiableRelationChildRDNType(r);
@@ -167,7 +168,7 @@
          OptionalRelationDefinition<? super C, ? super S> r,
          AbstractManagedObjectDefinition<C, S> d) {
    // Add the RDN sequence representing the relation.
    appendManagedObjectPathElement((RelationDefinition) r);
    appendManagedObjectPathElement((RelationDefinition<?, ?>) r);
  }
@@ -180,7 +181,7 @@
          SingletonRelationDefinition<? super C, ? super S> r,
          AbstractManagedObjectDefinition<C, S> d) {
    // Add the RDN sequence representing the relation.
    appendManagedObjectPathElement((RelationDefinition) r);
    appendManagedObjectPathElement((RelationDefinition<?, ?>) r);
  }
opends/src/server/org/opends/server/admin/server/ConfigAddListenerAdaptor.java
@@ -85,7 +85,7 @@
   * @param listener
   *          The underlying add listener.
   */
  public ConfigAddListenerAdaptor(ManagedObjectPath path,
  public ConfigAddListenerAdaptor(ManagedObjectPath<?, ?> path,
      InstantiableRelationDefinition<?, S> relation,
      ConfigurationAddListener<S> listener) {
    this.path = path;
@@ -108,7 +108,7 @@
   * @param listener
   *          The underlying add listener.
   */
  public ConfigAddListenerAdaptor(ManagedObjectPath path,
  public ConfigAddListenerAdaptor(ManagedObjectPath<?, ?> path,
      OptionalRelationDefinition<?, S> relation,
      ConfigurationAddListener<S> listener) {
    this.path = path;
@@ -129,7 +129,7 @@
      // Optional managed objects are located directly beneath the
      // parent and have a well-defined name. We need to make sure
      // that we are handling the correct entry.
      ManagedObjectPath childPath = path.child(optionalRelation);
      ManagedObjectPath<?, ?> childPath = path.child(optionalRelation);
      DN expectedDN = DNBuilder.create(childPath);
      if (!configEntry.getDN().equals(expectedDN)) {
        // Doesn't apply to us.
@@ -153,7 +153,7 @@
    AttributeValue av = dn.getRDN().getAttributeValue(0);
    String name = av.getStringValue().trim();
    ManagedObjectPath childPath;
    ManagedObjectPath<?, ?> childPath;
    RelationDefinition<?, S> r;
    if (instantiableRelation != null) {
      childPath = path.child(instantiableRelation, name);
opends/src/server/org/opends/server/admin/server/ConfigChangeListenerAdaptor.java
@@ -85,7 +85,7 @@
   *          The type of property.
   */
  private static final class Visitor<T> implements
      DefaultBehaviorProviderVisitor<T, Void, ManagedObjectPath> {
      DefaultBehaviorProviderVisitor<T, Void, ManagedObjectPath<?, ?>> {
    /**
     * Finds the dependencies associated with the provided property
@@ -100,7 +100,7 @@
     * @param dependencies
     *          Add dependencies names to this collection.
     */
    public static <T> void find(ManagedObjectPath path,
    public static <T> void find(ManagedObjectPath<?, ?> path,
        PropertyDefinition<T> pd, Collection<DN> dependencies) {
      Visitor<T> v = new Visitor<T>(dependencies);
      DefaultBehaviorProvider<T> db = pd.getDefaultBehaviorProvider();
@@ -123,8 +123,9 @@
     * {@inheritDoc}
     */
    public Void visitAbsoluteInherited(
        AbsoluteInheritedDefaultBehaviorProvider<T> d, ManagedObjectPath p) {
      ManagedObjectPath next = d.getManagedObjectPath();
        AbsoluteInheritedDefaultBehaviorProvider<T> d,
        ManagedObjectPath<?, ?> p) {
      ManagedObjectPath<?, ?> next = d.getManagedObjectPath();
      dependencies.add(DNBuilder.create(next));
      // If the dependent property uses inherited defaults then
@@ -144,7 +145,7 @@
     * {@inheritDoc}
     */
    public Void visitAlias(AliasDefaultBehaviorProvider<T> d,
        ManagedObjectPath p) {
        ManagedObjectPath<?, ?> p) {
      return null;
    }
@@ -154,7 +155,7 @@
     * {@inheritDoc}
     */
    public Void visitDefined(DefinedDefaultBehaviorProvider<T> d,
        ManagedObjectPath p) {
        ManagedObjectPath<?, ?> p) {
      return null;
    }
@@ -164,8 +165,9 @@
     * {@inheritDoc}
     */
    public Void visitRelativeInherited(
        RelativeInheritedDefaultBehaviorProvider<T> d, ManagedObjectPath p) {
      ManagedObjectPath next = d.getManagedObjectPath(p);
        RelativeInheritedDefaultBehaviorProvider<T> d,
        ManagedObjectPath<?, ?> p) {
      ManagedObjectPath<?, ?> next = d.getManagedObjectPath(p);
      dependencies.add(DNBuilder.create(next));
      // If the dependent property uses inherited defaults then
@@ -185,7 +187,7 @@
     * {@inheritDoc}
     */
    public Void visitUndefined(UndefinedDefaultBehaviorProvider<T> d,
        ManagedObjectPath p) {
        ManagedObjectPath<?, ?> p) {
      return null;
    }
  }
@@ -215,7 +217,7 @@
  private final ConfigurationChangeListener<? super S> listener;
  // The managed object path.
  private final ManagedObjectPath path;
  private final ManagedObjectPath<?, ?> path;
@@ -229,7 +231,7 @@
   * @param listener
   *          The underlying change listener.
   */
  public ConfigChangeListenerAdaptor(ManagedObjectPath path,
  public ConfigChangeListenerAdaptor(ManagedObjectPath<?, ?> path,
      AbstractManagedObjectDefinition<?, S> d,
      ConfigurationChangeListener<? super S> listener) {
    this.path = path;
opends/src/server/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java
@@ -87,7 +87,7 @@
   * @param listener
   *          The underlying delete listener.
   */
  public ConfigDeleteListenerAdaptor(ManagedObjectPath path,
  public ConfigDeleteListenerAdaptor(ManagedObjectPath<?, ?> path,
      InstantiableRelationDefinition<?, S> relation,
      ConfigurationDeleteListener<S> listener) {
    this.path = path;
@@ -110,7 +110,7 @@
   * @param listener
   *          The underlying delete listener.
   */
  public ConfigDeleteListenerAdaptor(ManagedObjectPath path,
  public ConfigDeleteListenerAdaptor(ManagedObjectPath<?, ?> path,
      OptionalRelationDefinition<?, S> relation,
      ConfigurationDeleteListener<S> listener) {
    this.path = path;
@@ -131,7 +131,7 @@
      // Optional managed objects are located directly beneath the
      // parent and have a well-defined name. We need to make sure
      // that we are handling the correct entry.
      ManagedObjectPath childPath = path.child(optionalRelation);
      ManagedObjectPath<?, ?> childPath = path.child(optionalRelation);
      DN expectedDN = DNBuilder.create(childPath);
      if (!configEntry.getDN().equals(expectedDN)) {
        // Doesn't apply to us.
@@ -155,7 +155,7 @@
    AttributeValue av = dn.getRDN().getAttributeValue(0);
    String name = av.getStringValue().trim();
    ManagedObjectPath childPath;
    ManagedObjectPath<?, ?> childPath;
    RelationDefinition<?, S> r;
    if (instantiableRelation != null) {
      childPath = path.child(instantiableRelation, name);
@@ -197,10 +197,10 @@
  /**
   * Get the configuiration delete listener associated with this
   * Get the configuration delete listener associated with this
   * adaptor.
   *
   * @return Returns the configuiration delete listener associated
   * @return Returns the configuration delete listener associated
   *         with this adaptor.
   */
  ConfigurationDeleteListener<S> getConfigurationDeleteListener() {
opends/src/server/org/opends/server/admin/server/DNBuilder.java
@@ -60,7 +60,7 @@
   *          The managed object path.
   * @return Returns a new DN representing the specified managed object path.
   */
  public static DN create(ManagedObjectPath path) {
  public static DN create(ManagedObjectPath<?, ?> path) {
    DNBuilder builder = new DNBuilder();
    path.serialize(builder);
    return builder.getInstance();
@@ -79,7 +79,7 @@
   * @return Returns a new DN representing the specified managed
   *         object path and relation.
   */
  public static DN create(ManagedObjectPath path,
  public static DN create(ManagedObjectPath<?, ?> path,
      RelationDefinition<?, ?> relation) {
    DNBuilder builder = new DNBuilder();
    path.serialize(builder);
@@ -113,7 +113,7 @@
          InstantiableRelationDefinition<? super C, ? super S> r,
          AbstractManagedObjectDefinition<C, S> d, String name) {
    // Add the RDN sequence representing the relation.
    appendManagedObjectPathElement((RelationDefinition) r);
    appendManagedObjectPathElement((RelationDefinition<?, ?>) r);
    // Now add the single RDN representing the named instance.
    String type = profile.getInstantiableRelationChildRDNType(r);
@@ -151,7 +151,7 @@
          OptionalRelationDefinition<? super C, ? super S> r,
          AbstractManagedObjectDefinition<C, S> d) {
    // Add the RDN sequence representing the relation.
    appendManagedObjectPathElement((RelationDefinition) r);
    appendManagedObjectPathElement((RelationDefinition<?, ?>) r);
  }
@@ -164,7 +164,7 @@
          SingletonRelationDefinition<? super C, ? super S> r,
          AbstractManagedObjectDefinition<C, S> d) {
    // Add the RDN sequence representing the relation.
    appendManagedObjectPathElement((RelationDefinition) r);
    appendManagedObjectPathElement((RelationDefinition<?, ?>) r);
  }
opends/src/server/org/opends/server/admin/server/ServerManagedObject.java
@@ -128,7 +128,7 @@
     *           If the default values could not be retrieved or
     *           decoded properly.
     */
    public static <T> Collection<T> getDefaultValues(ManagedObjectPath p,
    public static <T> Collection<T> getDefaultValues(ManagedObjectPath<?, ?> p,
        PropertyDefinition<T> pd, ConfigEntry newConfigEntry)
        throws DefaultBehaviorException {
      DefaultValueFinder<T> v = new DefaultValueFinder<T>(newConfigEntry);
@@ -140,7 +140,7 @@
    private DefaultBehaviorException exception = null;
    // The path of the managed object containing the next property.
    private ManagedObjectPath nextPath = null;
    private ManagedObjectPath<?, ?> nextPath = null;
    // The next property whose default values were required.
    private PropertyDefinition<T> nextProperty = null;
@@ -232,8 +232,8 @@
    // Find the default values for the next path/property.
    private Collection<T> find(ManagedObjectPath p, PropertyDefinition<T> pd)
        throws DefaultBehaviorException {
    private Collection<T> find(ManagedObjectPath<?, ?> p,
        PropertyDefinition<T> pd) throws DefaultBehaviorException {
      nextPath = p;
      nextProperty = pd;
@@ -393,7 +393,8 @@
   *           not be decoded.
   */
  static <S extends Configuration> ServerManagedObject<? extends S> decode(
      ManagedObjectPath path, AbstractManagedObjectDefinition<?, S> definition,
      ManagedObjectPath<?, ?> path,
      AbstractManagedObjectDefinition<?, S> definition,
      ConfigEntry configEntry) throws DefinitionDecodingException,
      ServerManagedObjectDecodingException {
    return decode(path, definition, configEntry, null);
@@ -427,7 +428,8 @@
   *           not be decoded.
   */
  static <S extends Configuration> ServerManagedObject<? extends S> decode(
      ManagedObjectPath path, AbstractManagedObjectDefinition<?, S> definition,
      ManagedObjectPath<?, ?> path,
      AbstractManagedObjectDefinition<?, S> definition,
      ConfigEntry configEntry, ConfigEntry newConfigEntry)
      throws DefinitionDecodingException, ServerManagedObjectDecodingException {
    // First determine the correct definition to use for the entry.
@@ -476,7 +478,7 @@
  // Decode helper method required to avoid generics warning.
  private static <S extends Configuration> ServerManagedObject<S> decodeAux(
      ManagedObjectPath path, ManagedObjectDefinition<?, S> d,
      ManagedObjectPath<?, ?> path, ManagedObjectDefinition<?, S> d,
      Map<PropertyDefinition<?>, SortedSet<?>> properties,
      ConfigEntry configEntry) {
    return new ServerManagedObject<S>(path, d, properties, configEntry);
@@ -487,7 +489,7 @@
  // Create a property using the provided string values.
  private static <T> void decodeProperty(
      Map<PropertyDefinition<?>, SortedSet<?>> properties,
      ManagedObjectPath path, PropertyDefinition<T> pd,
      ManagedObjectPath<?, ?> path, PropertyDefinition<T> pd,
      List<String> stringValues, ConfigEntry newConfigEntry)
      throws PropertyException {
    PropertyException exception = null;
@@ -611,7 +613,7 @@
  // Create an new server side managed object.
  private ServerManagedObject(ManagedObjectPath path,
  private ServerManagedObject(ManagedObjectPath<?, ?> path,
      ManagedObjectDefinition<?, S> d,
      Map<PropertyDefinition<?>, SortedSet<?>> properties,
      ConfigEntry configEntry) {
@@ -681,7 +683,8 @@
      ConfigurationChangeListener<? super S> listener) {
    for (ConfigChangeListener l : configEntry.getChangeListeners()) {
      if (l instanceof ConfigChangeListenerAdaptor) {
        ConfigChangeListenerAdaptor adaptor = (ConfigChangeListenerAdaptor) l;
        ConfigChangeListenerAdaptor<?> adaptor =
          (ConfigChangeListenerAdaptor<?>) l;
        if (adaptor.getConfigurationChangeListener() == listener) {
          configEntry.deregisterChangeListener(adaptor);
        }
@@ -761,7 +764,7 @@
      InstantiableRelationDefinition<?, M> d, String name)
      throws IllegalArgumentException, ConfigException {
    validateRelationDefinition(d);
    ManagedObjectPath childPath = path.child(d, name);
    ManagedObjectPath<?, ?> childPath = path.child(d, name);
    return getChild(childPath, d);
  }
@@ -787,7 +790,7 @@
      OptionalRelationDefinition<?, M> d) throws IllegalArgumentException,
      ConfigException {
    validateRelationDefinition(d);
    ManagedObjectPath childPath = path.child(d);
    ManagedObjectPath<?, ?> childPath = path.child(d);
    return getChild(childPath, d);
  }
@@ -813,7 +816,7 @@
      SingletonRelationDefinition<?, M> d) throws IllegalArgumentException,
      ConfigException {
    validateRelationDefinition(d);
    ManagedObjectPath childPath = path.child(d);
    ManagedObjectPath<?, ?> childPath = path.child(d);
    return getChild(childPath, d);
  }
@@ -866,7 +869,7 @@
   *
   * @return Returns the path of this server managed object.
   */
  public ManagedObjectPath getManagedObjectPath() {
  public ManagedObjectPath<?, ?> getManagedObjectPath() {
    return path;
  }
@@ -1159,7 +1162,8 @@
      if (configEntry != null) {
        for (ConfigAddListener l : configEntry.getAddListeners()) {
          if (l instanceof ConfigAddListenerAdaptor) {
            ConfigAddListenerAdaptor adaptor = (ConfigAddListenerAdaptor) l;
            ConfigAddListenerAdaptor<?> adaptor =
              (ConfigAddListenerAdaptor<?>) l;
            if (adaptor.getConfigurationAddListener() == listener) {
              configEntry.deregisterAddListener(adaptor);
            }
@@ -1184,8 +1188,8 @@
      if (configEntry != null) {
        for (ConfigDeleteListener l : configEntry.getDeleteListeners()) {
          if (l instanceof ConfigDeleteListenerAdaptor) {
            ConfigDeleteListenerAdaptor adaptor =
              (ConfigDeleteListenerAdaptor) l;
            ConfigDeleteListenerAdaptor<?> adaptor =
              (ConfigDeleteListenerAdaptor<?>) l;
            if (adaptor.getConfigurationDeleteListener() == listener) {
              configEntry.deregisterDeleteListener(adaptor);
            }
@@ -1204,7 +1208,7 @@
  // Get a child managed object.
  private <M extends Configuration> ServerManagedObject<? extends M> getChild(
      ManagedObjectPath childPath, RelationDefinition<?, M> d)
      ManagedObjectPath<?, ?> childPath, RelationDefinition<?, M> d)
      throws ConfigException {
    // Get the configuration entry.
    DN targetDN = DNBuilder.create(childPath);
@@ -1310,7 +1314,8 @@
  // object.
  private void validateRelationDefinition(RelationDefinition<?, ?> rd)
      throws IllegalArgumentException {
    RelationDefinition tmp = definition.getRelationDefinition(rd.getName());
    RelationDefinition<?, ?> tmp =
      definition.getRelationDefinition(rd.getName());
    if (tmp != rd) {
      throw new IllegalArgumentException("The relation " + rd.getName()
          + " is not associated with a " + definition.getName());
opends/src/server/org/opends/server/messages/ToolMessages.java
@@ -9231,6 +9231,151 @@
  public static final int MSGID_REVERT_DESCRIPTION_SILENT =
          CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1222;
  /**
   * The message ID for the message which should be used when an
   * argument, which is mandatory when the application is
   * non-interactive, has not been specified. This takes a
   * single arguments which is the long name of the missing argument.
   */
  public static final int MSGID_DSCFG_ERROR_MISSING_NON_INTERACTIVE_ARG =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1223;
  /**
   * The message ID for the message that will be used if dsconfig cannot
   * read input from the console. This takes a single argument, which
   * is a message explaining the problem that occurred.
   */
  public static final int MSGID_DSCFG_ERROR_CANNOT_READ_CONSOLE_INPUT =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1224;
  /**
   * The message ID for the message that will be used as the prompt
   * for the type of component to be created when using the create-xxx
   * sub-command interactively. This takes a single argument which is
   * the user friendly name for the type of managed objects being
   * created.
   */
  public static final int MSGID_DSCFG_CREATE_TYPE_PROMPT =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1225;
  /**
   * The message ID for the message that will be used as the prompt
   * for the name of the component to be created when using the
   * create-xxx sub-command interactively. This takes a single
   * argument which is the user friendly name for the type of managed
   * objects being created.
   */
  public static final int MSGID_DSCFG_CREATE_NAME_PROMPT =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1226;
  /**
   * The message ID for the message that will be used when a child
   * managed object name the was specified interactively cannot be
   * used because there is already a managed object with the same
   * name. This takes two arguments which are the type of managed
   * object being created and the name of the existing managed object.
   */
  public static final int MSGID_DSCFG_ERROR_CREATE_NAME_ALREADY_EXISTS =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1227;
  /**
   * The message ID for the message that will be used as the type
   * heading in interactive help. This does not require any arguments.
   */
  public static final int MSGID_DSCFG_DESCRIPTION_CREATE_HELP_HEADING_TYPE =
    CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1228;
  /**
   * The message ID for the message that will be used as the description
   * heading in interactive help. This does not require any arguments.
   */
  public static final int MSGID_DSCFG_DESCRIPTION_CREATE_HELP_HEADING_DESCR =
    CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1229;
  /**
   * The message ID for the message that will be used when a user
   * requests to interactively select the name of acomponent, but
   * there are none available. This takes a single argument which is
   * the user friendly plural name of the component type.
   */
  public static final int MSGID_DSCFG_ERROR_FINDER_NO_CHILDREN =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1230;
  /**
   * The message ID for the message that will be used when a user
   * requests to interactively select the name of a component, but
   * there was only one available and the user did not select it. This
   * takes a single argument which is the user friendly name of the
   * component type.
   */
  public static final int MSGID_DSCFG_ERROR_FINDER_SINGLE_CHILD_REJECTED =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1231;
  /**
   * The message ID for the message that will be used as the prompt
   * when a user requests to interactively select the name of a
   * component and there is only one option. This takes two arguments
   * which are the user friendly name of the component type and the
   * single available choice.
   */
  public static final int MSGID_DSCFG_FINDER_PROMPT_SINGLE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1232;
  /**
   * The message ID for the message that will be used as the prompt
   * when a user requests to interactively select the name of a
   * component and there is more than one option. This takes a single
   * argument which is the user friendly name of the component type.
   */
  public static final int MSGID_DSCFG_FINDER_PROMPT_MANY =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1233;
  /**
   * The message ID for the word that will be used in confirmation
   * messages to indicate "yes".
   */
  public static final int MSGID_DSCFG_GENERAL_CONFIRM_NO =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1234;
  /**
   * The message ID for the word that will be used in confirmation
   * messages to indicate "yes".
   */
  public static final int MSGID_DSCFG_GENERAL_CONFIRM_YES =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1235;
  /**
   * The message ID for the message that will be used when a user
   * fails to input a valid response to a confirmation message. This
   * takes two arguments which are the word for "yes" and the word for
   * "no".
   */
  public static final int MSGID_DSCFG_ERROR_GENERAL_CONFIRM =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1236;
  /**
   * The message ID for the prompt that will be used in choice menus
   * when no help is available. This takes a single argument which is
   * the choice upper-bound.
   */
  public static final int MSGID_DSCFG_GENERAL_CHOICE_PROMPT_NOHELP =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1237;
  /**
   * The message ID for the prompt that will be used in choice menus
   * when help is available. This takes a single argument which is the
   * choice upper-bound.
   */
  public static final int MSGID_DSCFG_GENERAL_CHOICE_PROMPT_HELP =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1238;
  /**
   * The message ID for the message that will be used when a user
   * fails to input a valid response to a choice prompt. This takes a
   * single argument which is the choice's upper-bound.
   */
  public static final int MSGID_DSCFG_ERROR_GENERAL_CHOICE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1239;
  /**
   * Associates a set of generic messages with the message IDs defined in this
@@ -11510,6 +11655,10 @@
                    "The LDAP bind password could not be read due to the" +
                    " following error: %s");
    registerMessage(MSGID_DSCFG_ERROR_CANNOT_READ_CONSOLE_INPUT,
                    "The response could not be read from the console due " +
                    "to the following error: %s");
    registerMessage(MSGID_DSCFG_ERROR_BIND_PASSWORD_NONINTERACTIVE,
                    "The LDAP bind password was not specified and " +
                    "cannot be read interactively");
@@ -11566,6 +11715,12 @@
                    "The type of %s which should be created (Default: %s). " +
                    "The value for TYPE can be one of: %s");
    registerMessage(MSGID_DSCFG_CREATE_TYPE_PROMPT,
                    "Select the type of %s that you want to create:");
    registerMessage(MSGID_DSCFG_CREATE_NAME_PROMPT,
                    "Enter a name for the %s that you want to create:");
    registerMessage(MSGID_DSCFG_DESCRIPTION_PROP,
                    "The name of a property to be displayed");
@@ -11713,6 +11868,9 @@
                    "The %s could not be created because there is " +
                    "already an existing one with the same name");
    registerMessage(MSGID_DSCFG_ERROR_CREATE_NAME_ALREADY_EXISTS,
                    "There is already another %s with the name \"%s\"");
    registerMessage(MSGID_DSCFG_ERROR_CREATE_MMPE,
                    "The %s could not be created because the " +
                    "following mandatory properties must be defined: %s");
@@ -11888,6 +12046,10 @@
                    "The property modification \"%s\" is incompatible" +
                    " with a previous modification to the same property");
    registerMessage(MSGID_DSCFG_ERROR_MISSING_NON_INTERACTIVE_ARG,
                    "The argument \"--%s\" must be specified when " +
                    "this application is used non-interactively");
    registerMessage(MSGID_DSCFG_ERROR_SUB_TYPE_UNRECOGNIZED,
                    "The sub-type \"%s\" is not a recognized type of %s. " +
                    "It should be one of: %s");
@@ -12217,7 +12379,31 @@
                    "Prompt for any required information rather than fail");
    registerMessage(MSGID_REVERT_DESCRIPTION_SILENT,
                    "Perform a silent reversion");
    registerMessage(MSGID_DSCFG_DESCRIPTION_CREATE_HELP_HEADING_TYPE,
                    "Type");
    registerMessage(MSGID_DSCFG_DESCRIPTION_CREATE_HELP_HEADING_DESCR,
                    "Description");
    registerMessage(MSGID_DSCFG_FINDER_PROMPT_SINGLE,
                    "There is only one %s: \"%s\". Are you sure that " +
                    "this is the correct one?");
    registerMessage(MSGID_DSCFG_FINDER_PROMPT_MANY,
                    "Select the %s from the following list:");
    registerMessage(MSGID_DSCFG_ERROR_FINDER_NO_CHILDREN,
                    "Unable to continue since there are no %s currently " +
                    "configured on the server");
    registerMessage(MSGID_DSCFG_ERROR_FINDER_SINGLE_CHILD_REJECTED,
                    "Unable to continue because the only available %s was " +
                    "not selected");
    registerMessage(MSGID_DSCFG_GENERAL_CONFIRM_NO, "no");
    registerMessage(MSGID_DSCFG_GENERAL_CONFIRM_YES, "yes");
    registerMessage(MSGID_DSCFG_GENERAL_CHOICE_PROMPT_HELP,
                    "Enter choice [1 - %s,  ? - help]:");
    registerMessage(MSGID_DSCFG_GENERAL_CHOICE_PROMPT_NOHELP,
                    "Enter choice [1 - %s]:");
    registerMessage(MSGID_DSCFG_ERROR_GENERAL_CHOICE,
                    "Invalid response. Please enter a value between 1 and %s");
    registerMessage(MSGID_DSCFG_ERROR_GENERAL_CONFIRM,
                    "Invalid response. Please enter \"%s\" or \"%s\"");
  }
}
opends/src/server/org/opends/server/tools/dsconfig/ArgumentExceptionFactory.java
@@ -45,6 +45,7 @@
import org.opends.server.admin.RelationDefinition;
import org.opends.server.admin.client.IllegalManagedObjectNameException;
import org.opends.server.admin.client.MissingMandatoryPropertiesException;
import org.opends.server.util.args.Argument;
import org.opends.server.util.args.ArgumentException;
@@ -66,7 +67,8 @@
   * @return Returns an argument exception.
   */
  public static ArgumentException adaptIllegalManagedObjectNameException(
      IllegalManagedObjectNameException e, AbstractManagedObjectDefinition d) {
      IllegalManagedObjectNameException e,
      AbstractManagedObjectDefinition<?, ?> d) {
    String illegalName = e.getIllegalName();
    PropertyDefinition<?> pd = e.getNamingPropertyDefinition();
@@ -112,7 +114,7 @@
   */
  public static ArgumentException adaptMissingMandatoryPropertiesException(
      MissingMandatoryPropertiesException e,
      AbstractManagedObjectDefinition d) {
      AbstractManagedObjectDefinition<?, ?> d) {
    int msgID = MSGID_DSCFG_ERROR_CREATE_MMPE;
    StringBuilder builder = new StringBuilder();
    boolean isFirst = true;
@@ -139,7 +141,7 @@
   * @return Returns an argument exception.
   */
  public static ArgumentException adaptPropertyException(PropertyException e,
      AbstractManagedObjectDefinition d) {
      AbstractManagedObjectDefinition<?, ?> d) {
    if (e instanceof IllegalPropertyValueException) {
      IllegalPropertyValueException pe = (IllegalPropertyValueException) e;
      return adapt(d, pe);
@@ -203,6 +205,24 @@
  /**
   * Creates an argument exception which should be used when an
   * argument, which is mandatory when the application is
   * non-interactive, has not been specified.
   *
   * @param arg
   *          The missing argument.
   * @return Returns an argument exception.
   */
  public static ArgumentException missingMandatoryNonInteractiveArgument(
      Argument arg) {
    int msgID = MSGID_DSCFG_ERROR_MISSING_NON_INTERACTIVE_ARG;
    String msg = getMessage(msgID, arg.getLongIdentifier());
    return new ArgumentException(msgID, msg);
  }
  /**
   * Creates an argument exception which should be used when a
   * property value argument is invalid because it does not a property
   * name.
@@ -309,26 +329,6 @@
  /**
   * Creates an argument exception which should be used when an
   * attempt is made to set the naming property for a managed object
   * during creation.
   *
   * @param d
   *          The managed object definition.
   * @param pd
   *          The naming property definition.
   * @return Returns an argument exception.
   */
  public static ArgumentException unableToSetNamingProperty(
      AbstractManagedObjectDefinition d, PropertyDefinition<?> pd) {
    int msgID = MSGID_DSCFG_ERROR_UNABLE_TO_SET_NAMING_PROPERTY;
    String message = getMessage(msgID, pd.getName(), d.getUserFriendlyName());
    return new ArgumentException(msgID, message);
  }
  /**
   * Creates an argument exception which should be used when the bind
   * password could not be read from the standard input.
   *
@@ -360,6 +360,22 @@
  /**
   * Creates an argument exception which should be used when
   * interaction with the console fails due to an IO exception.
   *
   * @param cause
   *          The reason why console input failed.
   * @return Returns an argument exception.
   */
  public static ArgumentException unableToReadConsoleInput(Exception cause) {
    int msgID = MSGID_DSCFG_ERROR_CANNOT_READ_CONSOLE_INPUT;
    String message = getMessage(msgID, cause.getMessage());
    return new ArgumentException(msgID, message, cause);
  }
  /**
   * Creates an argument exception which should be used when an
   * attempt is made to reset a mandatory property that does not have
   * any default values.
@@ -374,7 +390,7 @@
   * @return Returns an argument exception.
   */
  public static ArgumentException unableToResetMandatoryProperty(
      AbstractManagedObjectDefinition d, String name, String setOption) {
      AbstractManagedObjectDefinition<?, ?> d, String name, String setOption) {
    int msgID = MSGID_DSCFG_ERROR_UNABLE_TO_RESET_MANDATORY_PROPERTY;
    String message = getMessage(msgID, d.getUserFriendlyPluralName(), name,
        setOption);
@@ -384,6 +400,26 @@
  /**
   * Creates an argument exception which should be used when an
   * attempt is made to set the naming property for a managed object
   * during creation.
   *
   * @param d
   *          The managed object definition.
   * @param pd
   *          The naming property definition.
   * @return Returns an argument exception.
   */
  public static ArgumentException unableToSetNamingProperty(
      AbstractManagedObjectDefinition<?, ?> d, PropertyDefinition<?> pd) {
    int msgID = MSGID_DSCFG_ERROR_UNABLE_TO_SET_NAMING_PROPERTY;
    String message = getMessage(msgID, pd.getName(), d.getUserFriendlyName());
    return new ArgumentException(msgID, message);
  }
  /**
   * Creates an argument exception which should be used when a
   * property name is not recognized.
   *
@@ -394,7 +430,7 @@
   * @return Returns an argument exception.
   */
  public static ArgumentException unknownProperty(
      AbstractManagedObjectDefinition d, String name) {
      AbstractManagedObjectDefinition<?, ?> d, String name) {
    int msgID = MSGID_DSCFG_ERROR_PROPERTY_UNRECOGNIZED;
    String message = getMessage(msgID, name, d.getUserFriendlyPluralName());
    return new ArgumentException(msgID, message);
@@ -414,7 +450,7 @@
   *          A usage string describing the allowed sub-types.
   * @return Returns an argument exception.
   */
  public static ArgumentException unknownSubType(RelationDefinition r,
  public static ArgumentException unknownSubType(RelationDefinition<?, ?> r,
      String typeName, String typeUsage) {
    int msgID = MSGID_DSCFG_ERROR_SUB_TYPE_UNRECOGNIZED;
    String msg = getMessage(msgID, typeName, r.getUserFriendlyName(),
@@ -451,8 +487,8 @@
   *          The definition of the managed object that was retrieved.
   * @return Returns an argument exception.
   */
  public static ArgumentException wrongManagedObjectType(RelationDefinition r,
      ManagedObjectDefinition d) {
  public static ArgumentException wrongManagedObjectType(
      RelationDefinition<?, ?> r, ManagedObjectDefinition<?, ?> d) {
    int msgID = MSGID_DSCFG_ERROR_TYPE_UNRECOGNIZED;
    String msg = getMessage(msgID, r.getUserFriendlyName(), d
        .getUserFriendlyName());
@@ -470,8 +506,8 @@
   *          The default behavior exception.
   * @return Returns an argument exception.
   */
  private static ArgumentException adapt(AbstractManagedObjectDefinition d,
      DefaultBehaviorException e) {
  private static ArgumentException adapt(
      AbstractManagedObjectDefinition<?, ?> d, DefaultBehaviorException e) {
    int msgID = MSGID_DSCFG_ERROR_PROPERTY_DEFAULT_BEHAVIOR;
    String message = getMessage(msgID, d.getUserFriendlyName(), e
        .getPropertyDefinition().getName(), e.getMessage());
@@ -490,7 +526,8 @@
   *          The illegal property value exception.
   * @return Returns an argument exception.
   */
  private static ArgumentException adapt(AbstractManagedObjectDefinition d,
  private static ArgumentException adapt(
      AbstractManagedObjectDefinition<?, ?> d,
      IllegalPropertyValueException e) {
    PropertyDefinitionUsageBuilder b = new PropertyDefinitionUsageBuilder(true);
    String syntax = b.getUsage(e.getPropertyDefinition());
@@ -518,7 +555,8 @@
   *          The illegal property string value exception.
   * @return Returns an argument exception.
   */
  private static ArgumentException adapt(AbstractManagedObjectDefinition d,
  private static ArgumentException adapt(
      AbstractManagedObjectDefinition<?, ?> d,
      IllegalPropertyValueStringException e) {
    PropertyDefinitionUsageBuilder b = new PropertyDefinitionUsageBuilder(true);
    String syntax = b.getUsage(e.getPropertyDefinition());
@@ -547,7 +585,8 @@
   *          The property is mandatory exception.
   * @return Returns an argument exception.
   */
  private static ArgumentException adapt(AbstractManagedObjectDefinition d,
  private static ArgumentException adapt(
      AbstractManagedObjectDefinition<?, ?> d,
      PropertyIsMandatoryException e) {
    int msgID = MSGID_DSCFG_ERROR_PROPERTY_MANDATORY;
    String message = getMessage(msgID, d.getUserFriendlyName(), e
@@ -567,7 +606,8 @@
   *          The property is read-only exception.
   * @return Returns an argument exception.
   */
  private static ArgumentException adapt(AbstractManagedObjectDefinition d,
  private static ArgumentException adapt(
      AbstractManagedObjectDefinition<?, ?> d,
      PropertyIsReadOnlyException e) {
    int msgID = MSGID_DSCFG_ERROR_PROPERTY_READ_ONLY;
    String message = getMessage(msgID, d.getUserFriendlyName(), e
@@ -587,7 +627,8 @@
   *          The property is single-valued exception.
   * @return Returns an argument exception.
   */
  private static ArgumentException adapt(AbstractManagedObjectDefinition d,
  private static ArgumentException adapt(
      AbstractManagedObjectDefinition<?, ?> d,
      PropertyIsSingleValuedException e) {
    int msgID = MSGID_DSCFG_ERROR_PROPERTY_SINGLE_VALUED;
    String message = getMessage(msgID, d.getUserFriendlyName(), e
opends/src/server/org/opends/server/tools/dsconfig/ConsoleApplication.java
New file
@@ -0,0 +1,494 @@
/*
 * 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.tools.dsconfig;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Reader;
import java.util.List;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.tools.ClientException;
import org.opends.server.types.NullOutputStream;
import org.opends.server.util.PasswordReader;
import org.opends.server.util.Validator;
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.table.TableBuilder;
import org.opends.server.util.table.TextTablePrinter;
/**
 * This class provides an abstract base class which can be used as the
 * basis of a console-based application.
 */
public abstract class ConsoleApplication {
  // The error stream which this application should use.
  private final PrintStream err;
  // The input stream reader which this application should use.
  private final BufferedReader in;
  // The output stream which this application should use.
  private final PrintStream out;
  /**
   * Creates a new console application instance.
   *
   * @param in
   *          The application input stream.
   * @param out
   *          The application output stream.
   * @param err
   *          The application error stream.
   */
  protected ConsoleApplication(InputStream in, OutputStream out,
      OutputStream err) {
    if (in != null) {
      this.in = new BufferedReader(new InputStreamReader(in));
    } else {
      this.in = new BufferedReader(new Reader() {
        /**
         * {@inheritDoc}
         */
        @Override
        public void close() throws IOException {
          // Do nothing.
        }
        /**
         * {@inheritDoc}
         */
        @Override
        public int read(char[] cbuf, int off, int len) throws IOException {
          return -1;
        }
      });
    }
    if (out != null) {
      this.out = new PrintStream(out);
    } else {
      this.out = NullOutputStream.printStream();
    }
    if (err != null) {
      this.err = new PrintStream(err);
    } else {
      this.err = NullOutputStream.printStream();
    }
  }
  /**
   * Interactively confirms whether a user wishes to perform an
   * action. If the application is non-interactive, then the action is
   * granted by default.
   *
   * @param prompt
   *          The prompt describing the action.
   * @return Returns <code>true</code> if the user wishes the action
   *         to be performed, or <code>false</code> if they refused,
   *         or if an exception occurred.
   * @throws ArgumentException
   *           If the user's response could not be read from the
   *           console for some reason.
   */
  public final boolean confirmAction(String prompt) throws ArgumentException {
    if (!isInteractive()) {
      return true;
    }
    final String yes = getMessage(MSGID_DSCFG_GENERAL_CONFIRM_YES);
    final String no = getMessage(MSGID_DSCFG_GENERAL_CONFIRM_NO);
    final String errMsg =
      getMessage(MSGID_DSCFG_ERROR_GENERAL_CONFIRM, yes, no);
    prompt = prompt + String.format(" (%s / %s): ", yes, no);
    ValidationCallback<Boolean> validator = new ValidationCallback<Boolean>() {
      public Boolean validate(ConsoleApplication app, String input) {
        String ninput = input.toLowerCase().trim();
        if (ninput.length() == 0) {
          // Empty input.
          app.printMessage(errMsg);
        } else if (no.startsWith(ninput)) {
          return false;
        } else if (yes.startsWith(ninput)) {
          return true;
        } else {
          // Try again...
          app.printMessage(errMsg);
        }
        return null;
      }
    };
    try {
      return readValidatedInput(prompt, validator);
    } catch (ClientException e) {
      // Should never happen.
      throw new RuntimeException(e);
    }
  }
  /**
   * Displays a message to the error stream.
   *
   * @param msg
   *          The message.
   */
  public final void printMessage(String msg) {
    err.println(wrapText(msg, MAX_LINE_WIDTH));
  }
  /**
   * Displays a blank line to the error stream.
   */
  public final void println() {
    err.println();
  }
  /**
   * Displays a message to the error stream if verbose mode is
   * enabled.
   *
   * @param msg
   *          The verbose message.
   */
  public final void printVerboseMessage(String msg) {
    if (isVerbose()) {
      err.println(wrapText(msg, MAX_LINE_WIDTH));
    }
  }
  /**
   * Gets the application error stream.
   *
   * @return Returns the application error stream.
   */
  public final PrintStream getErrorStream() {
    return err;
  }
  /**
   * Gets the application input stream.
   *
   * @return Returns the application input stream.
   */
  public final BufferedReader getInputStream() {
    return in;
  }
  /**
   * Gets the management context which sub-commands should use in
   * order to manage the directory server.
   *
   * @return Returns the management context which sub-commands should
   *         use in order to manage the directory server.
   * @throws ArgumentException
   *           If a management context related argument could not be
   *           parsed successfully.
   * @throws ClientException
   *           If the management context could not be created.
   */
  public abstract ManagementContext getManagementContext()
      throws ArgumentException, ClientException;
  /**
   * Gets the application output stream.
   *
   * @return Returns the application output stream.
   */
  public final PrintStream getOutputStream() {
    return out;
  }
  /**
   * Indicates whether or not the user has requested interactive
   * behavior.
   *
   * @return Returns <code>true</code> if the user has requested
   *         interactive behavior.
   */
  public abstract boolean isInteractive();
  /**
   * Indicates whether or not the user has requested quiet output.
   *
   * @return Returns <code>true</code> if the user has requested
   *         quiet output.
   */
  public abstract boolean isQuiet();
  /**
   * Indicates whether or not the user has requested script-friendly
   * output.
   *
   * @return Returns <code>true</code> if the user has requested
   *         script-friendly output.
   */
  public abstract boolean isScriptFriendly();
  /**
   * Indicates whether or not the user has requested verbose output.
   *
   * @return Returns <code>true</code> if the user has requested
   *         verbose output.
   */
  public abstract boolean isVerbose();
  /**
   * Interactively prompts the user to select from a choice of
   * options.
   *
   * @param <T>
   *          The type of the values represented by each choice.
   * @param prompt
   *          The prompt which should appear before the list of
   *          choices.
   * @param descriptions
   *          The descriptions of each choice.
   * @param values
   *          The choices.
   * @param helpCallback
   *          An optional help call-back which can be used to display
   *          additional help.
   * @return Returns the selected value.
   * @throws ArgumentException
   *           If the user input could not be retrieved for some
   *           reason.
   */
  public final <T> T readChoice(final String prompt, List<String> descriptions,
      List<T> values, final HelpCallback helpCallback)
      throws ArgumentException {
    Validator.ensureTrue(descriptions.size() == values.size());
    // Output main prompt.
    println();
    printMessage(prompt);
    println();
    // Build the table of choices.
    final TableBuilder builder = new TableBuilder();
    final int size = descriptions.size();
    for (int i = 0; i < size; i++) {
      builder.startRow();
      builder.appendCell("[" + (i + 1) + "]");
      builder.appendCell(descriptions.get(i));
    }
    // Display the table of choices.
    final TextTablePrinter printer = new TextTablePrinter(err);
    printer.setDisplayHeadings(false);
    printer.setColumnWidth(1, 0);
    builder.print(printer);
    // Get the user input.
    String promptMsg;
    if (helpCallback != null) {
      promptMsg = getMessage(MSGID_DSCFG_GENERAL_CHOICE_PROMPT_HELP, size);
    } else {
      promptMsg = getMessage(MSGID_DSCFG_GENERAL_CHOICE_PROMPT_NOHELP, size);
    }
    ValidationCallback<Integer> validator = new ValidationCallback<Integer>() {
      public Integer validate(ConsoleApplication app, String input) {
        String ninput = input.trim();
        if (ninput.equals("?") && helpCallback != null) {
          app.println();
          helpCallback.display(app);
          app.println();
          // Output main prompt.
          printMessage(prompt);
          println();
          builder.print(printer);
          println();
          return null;
        } else {
          try {
            int i = Integer.parseInt(ninput);
            if (i < 1 || i > size) {
              throw new NumberFormatException();
            }
            return i;
          } catch (NumberFormatException e) {
            app.println();
            String errMsg = getMessage(MSGID_DSCFG_ERROR_GENERAL_CHOICE, size);
            app.printMessage(errMsg);
            app.println();
            return null;
          }
        }
      }
    };
    // Get the choice.
    int choice;
    try {
      choice = readValidatedInput(promptMsg, validator);
    } catch (ClientException e) {
      // Should never happen.
      throw new RuntimeException(e);
    }
    return values.get(choice - 1);
  }
  /**
   * Interactively retrieves a line of input from the console.
   *
   * @param prompt
   *          The prompt.
   * @return Returns the line of input, or <code>null</code> if the
   *         end of input has been reached.
   * @throws ArgumentException
   *           If the line of input could not be retrieved for some
   *           reason.
   */
  public final String readLineOfInput(String prompt) throws ArgumentException {
    err.println();
    err.print(wrapText(prompt.trim() + " ", MAX_LINE_WIDTH));
    try {
      return in.readLine();
    } catch (IOException e) {
      throw ArgumentExceptionFactory.unableToReadConsoleInput(e);
    }
  }
  /**
   * Interactively retrieves a password from the console.
   *
   * @param prompt
   *          The password prompt.
   * @return Returns the password.
   * @throws ArgumentException
   *           If the password could not be retrieved for some reason.
   */
  public final String readPassword(String prompt) throws ArgumentException {
    err.print(wrapText(prompt + " ", MAX_LINE_WIDTH));
    char[] pwChars;
    try {
      pwChars = PasswordReader.readPassword();
    } catch (Exception e) {
      throw ArgumentExceptionFactory.unableToReadConsoleInput(e);
    }
    return new String(pwChars);
  }
  /**
   * Interactively prompts for user input and continues until valid
   * input is provided.
   *
   * @param <T>
   *          The type of decoded user input.
   * @param prompt
   *          The interactive prompt which should be displayed on each
   *          input attempt.
   * @param validator
   *          An input validator responsible for validating and
   *          decoding the user's response.
   * @return Returns the decoded user's response.
   * @throws ArgumentException
   *           If the line of input could not be retrieved for some
   *           reason.
   * @throws ClientException
   *           If an unexpected error occurred which prevented
   *           validation.
   */
  public final <T> T readValidatedInput(String prompt,
      ValidationCallback<T> validator) throws ArgumentException,
      ClientException {
    while (true) {
      String response = readLineOfInput(prompt);
      if (response == null) {
        throw ArgumentExceptionFactory
            .unableToReadConsoleInput(new EOFException("End of input"));
      }
      T value = validator.validate(this, response);
      if (value != null) {
        return value;
      }
    }
  }
}
opends/src/server/org/opends/server/tools/dsconfig/CreateSubCommandHandler.java
@@ -31,7 +31,7 @@
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -43,6 +43,7 @@
import java.util.TreeMap;
import org.opends.server.admin.AbstractManagedObjectDefinition;
import org.opends.server.admin.Configuration;
import org.opends.server.admin.ConfigurationClient;
import org.opends.server.admin.DefaultBehaviorException;
import org.opends.server.admin.DefinitionDecodingException;
@@ -65,7 +66,6 @@
import org.opends.server.admin.client.IllegalManagedObjectNameException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagedObjectDecodingException;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.client.MissingMandatoryPropertiesException;
import org.opends.server.admin.client.OperationRejectedException;
import org.opends.server.protocols.ldap.LDAPResultCode;
@@ -74,6 +74,8 @@
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.table.TableBuilder;
import org.opends.server.util.table.TextTablePrinter;
@@ -84,9 +86,12 @@
 *
 * @param <C>
 *          The type of managed object which can be created.
 * @param <S>
 *          The type of server managed object which can be created.
 */
final class CreateSubCommandHandler<C extends ConfigurationClient> extends
    SubCommandHandler {
final class CreateSubCommandHandler<C extends ConfigurationClient,
    S extends Configuration> extends SubCommandHandler {
  /**
   * A property provider which uses the command-line arguments to
@@ -95,8 +100,8 @@
  private static class MyPropertyProvider implements PropertyProvider {
    // Decoded set of properties.
    private final Map<PropertyDefinition, Collection> properties =
      new HashMap<PropertyDefinition, Collection>();
    private final Map<PropertyDefinition<?>, Collection<?>> properties =
      new HashMap<PropertyDefinition<?>, Collection<?>>();
@@ -162,7 +167,7 @@
     * @return Returns the set of parsed property definitions that
     *         have values specified.
     */
    public Set<PropertyDefinition> getProperties() {
    public Set<PropertyDefinition<?>> getProperties() {
      return properties.keySet();
    }
@@ -174,7 +179,7 @@
    @SuppressWarnings("unchecked")
    public <T> Collection<T> getPropertyValues(PropertyDefinition<T> d)
        throws IllegalArgumentException {
      Collection<T> values = properties.get(d);
      Collection<T> values = (Collection<T>) properties.get(d);
      if (values == null) {
        return Collections.emptySet();
      } else {
@@ -195,7 +200,7 @@
        throw ArgumentExceptionFactory.adaptPropertyException(e, d);
      }
      Collection<T> values = properties.get(pd);
      Collection<T> values = (Collection<T>) properties.get(pd);
      if (values == null) {
        values = new LinkedList<T>();
      }
@@ -210,6 +215,53 @@
    }
  }
  /**
   * A help call-back which displays help about available component types.
   */
  private final class TypeHelpCallback implements HelpCallback {
    /**
     * {@inheritDoc}
     */
    public void display(ConsoleApplication app) {
      // Create a table containing a description of each component type.
      TableBuilder builder = new TableBuilder();
      int msgID = MSGID_DSCFG_DESCRIPTION_CREATE_HELP_HEADING_TYPE;
      builder.appendHeading(getMessage(msgID));
      msgID = MSGID_DSCFG_DESCRIPTION_CREATE_HELP_HEADING_DESCR;
      builder.appendHeading(getMessage(msgID));
      boolean isFirst = true;
      for (ManagedObjectDefinition<?, ?> d : types.values()) {
        if (!isFirst) {
          builder.startRow();
          builder.startRow();
        } else {
          isFirst = false;
        }
        builder.startRow();
        builder.appendCell(d.getUserFriendlyName());
        builder.appendCell(d.getSynopsis());
        if (d.getDescription() != null) {
          builder.startRow();
          builder.startRow();
          builder.appendCell();
          builder.appendCell(d.getDescription());
        }
      }
      TextTablePrinter printer = new TextTablePrinter(app.getErrorStream());
      printer.setColumnWidth(1, 0);
      printer.setColumnSeparator(":");
      builder.print(printer);
    }
  }
  /**
   * The value for the -t argument which will be used for the most
   * generic managed object when it is instantiable.
@@ -244,6 +296,10 @@
   *
   * @param <C>
   *          The type of managed object which can be created.
   * @param <S>
   *          The type of server managed object which can be created.
   * @param app
   *          The console application.
   * @param parser
   *          The sub-command argument parser.
   * @param p
@@ -254,10 +310,12 @@
   * @throws ArgumentException
   *           If the sub-command could not be created successfully.
   */
  public static <C extends ConfigurationClient> CreateSubCommandHandler create(
      SubCommandArgumentParser parser, ManagedObjectPath<?, ?> p,
      InstantiableRelationDefinition<C, ?> r) throws ArgumentException {
    return new CreateSubCommandHandler<C>(parser, p, r, r
  public static <C extends ConfigurationClient, S extends Configuration>
      CreateSubCommandHandler<C, S> create(
      ConsoleApplication app, SubCommandArgumentParser parser,
      ManagedObjectPath<?, ?> p, InstantiableRelationDefinition<C, S> r)
      throws ArgumentException {
    return new CreateSubCommandHandler<C, S>(app, parser, p, r, r
        .getNamingPropertyDefinition(), p.child(r, "DUMMY"));
  }
@@ -268,6 +326,10 @@
   *
   * @param <C>
   *          The type of managed object which can be created.
   * @param <S>
   *          The type of server managed object which can be created.
   * @param app
   *          The console application.
   * @param parser
   *          The sub-command argument parser.
   * @param p
@@ -278,10 +340,13 @@
   * @throws ArgumentException
   *           If the sub-command could not be created successfully.
   */
  public static <C extends ConfigurationClient> CreateSubCommandHandler create(
      SubCommandArgumentParser parser, ManagedObjectPath<?, ?> p,
      OptionalRelationDefinition<C, ?> r) throws ArgumentException {
    return new CreateSubCommandHandler<C>(parser, p, r, null, p.child(r));
  public static <C extends ConfigurationClient, S extends Configuration>
      CreateSubCommandHandler<C, S> create(
      ConsoleApplication app, SubCommandArgumentParser parser,
      ManagedObjectPath<?, ?> p, OptionalRelationDefinition<C, S> r)
      throws ArgumentException {
    return new CreateSubCommandHandler<C, S>(app, parser, p, r, null, p
        .child(r));
  }
  // The sub-commands naming arguments.
@@ -298,7 +363,7 @@
  private final StringArgument propertySetArgument;
  // The relation which should be used for creating children.
  private final RelationDefinition<C, ?> relation;
  private final RelationDefinition<C, S> relation;
  // The sub-command associated with this handler.
  private final SubCommand subCommand;
@@ -310,7 +375,7 @@
  // The set of instantiable managed object definitions and their
  // associated type option value.
  private final SortedMap<String,
    ManagedObjectDefinition<? extends C, ?>> types;
    ManagedObjectDefinition<? extends C, ? extends S>> types;
  // The syntax of the type argument.
  private final String typeUsage;
@@ -318,10 +383,13 @@
  // Common constructor.
  private CreateSubCommandHandler(SubCommandArgumentParser parser,
      ManagedObjectPath<?, ?> p, RelationDefinition<C, ?> r,
  private CreateSubCommandHandler(ConsoleApplication app,
      SubCommandArgumentParser parser,
      ManagedObjectPath<?, ?> p, RelationDefinition<C, S> r,
      PropertyDefinition<?> pd, ManagedObjectPath<?, ?> c)
      throws ArgumentException {
    super(app);
    this.path = p;
    this.relation = r;
    this.namingPropertyDefinition = pd;
@@ -359,9 +427,9 @@
    this.typeUsage = builder.toString();
    if (!types.containsKey(GENERIC_TYPE)) {
      // The option is mandatory.
      // The option is mandatory when non-interactive.
      this.typeArgument = new StringArgument("type", OPTION_DSCFG_SHORT_TYPE,
          OPTION_DSCFG_LONG_TYPE, true, false, true, "{TYPE}", null, null,
          OPTION_DSCFG_LONG_TYPE, false, false, true, "{TYPE}", null, null,
          MSGID_DSCFG_DESCRIPTION_TYPE, r.getChildDefinition()
              .getUserFriendlyName(), typeUsage);
    } else {
@@ -399,11 +467,40 @@
   * {@inheritDoc}
   */
  @Override
  public int run(DSConfig app, PrintStream out, PrintStream err)
      throws ArgumentException, ClientException {
  public int run() throws ArgumentException, ClientException {
    // Determine the type of managed object to be created.
    String typeName = typeArgument.getValue();
    ManagedObjectDefinition<? extends C, ?> d = types.get(typeName);
    String typeName;
    if (!typeArgument.isPresent()) {
      if (getConsoleApplication().isInteractive()) {
        // Let the user choose.
        // If there is only one choice then return immediately.
        if (types.size() == 1) {
          typeName = types.keySet().iterator().next();
        } else {
          List<String> values = new ArrayList<String>(types.keySet());
          List<String> descriptions = new ArrayList<String>(values.size());
          for (ManagedObjectDefinition<?, ?> d : types.values()) {
            descriptions.add(d.getUserFriendlyName());
          }
          int msgID = MSGID_DSCFG_CREATE_TYPE_PROMPT;
          String msg = getMessage(msgID, relation.getChildDefinition()
              .getUserFriendlyName());
          typeName = getConsoleApplication().readChoice(msg, descriptions,
              values, new TypeHelpCallback());
        }
      } else if (typeArgument.getDefaultValue() != null) {
        typeName = typeArgument.getDefaultValue();
      } else {
        throw ArgumentExceptionFactory
            .missingMandatoryNonInteractiveArgument(typeArgument);
      }
    } else {
      typeName = typeArgument.getValue();
    }
    ManagedObjectDefinition<? extends C, ? extends S> d = types.get(typeName);
    if (d == null) {
      throw ArgumentExceptionFactory.unknownSubType(relation, typeName,
          typeUsage);
@@ -418,10 +515,9 @@
        namingPropertyDefinition, propertyArgs);
    // Add the child managed object.
    ManagementContext context = app.getManagementContext();
    ManagedObject<?> parent;
    try {
      parent = getManagedObject(context, path, names);
      parent = getManagedObject(path, names);
    } catch (AuthorizationException e) {
      int msgID = MSGID_DSCFG_ERROR_CREATE_AUTHZ;
      String msg = getMessage(msgID, d.getUserFriendlyName());
@@ -459,18 +555,28 @@
      List<DefaultBehaviorException> exceptions =
        new LinkedList<DefaultBehaviorException>();
      if (relation instanceof InstantiableRelationDefinition) {
        InstantiableRelationDefinition<C, ?> irelation =
          (InstantiableRelationDefinition<C, ?>) relation;
        InstantiableRelationDefinition<C, S> irelation =
          (InstantiableRelationDefinition<C, S>) relation;
        String name = names.get(names.size() - 1);
        if (name == null) {
          if (getConsoleApplication().isInteractive()) {
            child = createChildInteractively(parent, irelation, d, exceptions);
          } else {
            throw ArgumentExceptionFactory
                .missingMandatoryNonInteractiveArgument(namingArgs.get(names
                    .size() - 1));
          }
        } else {
        try {
          child = parent.createChild(irelation, d, name, exceptions);
        } catch (IllegalManagedObjectNameException e) {
          throw ArgumentExceptionFactory
              .adaptIllegalManagedObjectNameException(e, d);
        }
        }
      } else {
        OptionalRelationDefinition<C, ?> orelation =
          (OptionalRelationDefinition<C, ?>) relation;
        OptionalRelationDefinition<C, S> orelation =
          (OptionalRelationDefinition<C, S>) relation;
        child = parent.createChild(orelation, d, exceptions);
      }
@@ -485,11 +591,11 @@
      // Confirm commit.
      String prompt = String.format(Messages.getString("create.confirm"), d
          .getUserFriendlyName());
      if (!app.confirmAction(prompt)) {
      if (!getConsoleApplication().confirmAction(prompt)) {
        // Output failure message.
        String msg = String.format(Messages.getString("create.failed"), d
            .getUserFriendlyName());
        app.displayVerboseMessage(msg);
        getConsoleApplication().printVerboseMessage(msg);
        return 1;
      }
@@ -499,7 +605,7 @@
      // Output success message.
      String msg = String.format(Messages.getString("create.done"), d
          .getUserFriendlyName());
      app.displayVerboseMessage(msg);
      getConsoleApplication().printVerboseMessage(msg);
    } catch (MissingMandatoryPropertiesException e) {
      throw ArgumentExceptionFactory.adaptMissingMandatoryPropertiesException(
          e, d);
@@ -535,28 +641,100 @@
  // Interactively create the child by prompting for the name.
  private ManagedObject<? extends C> createChildInteractively(
      final ManagedObject<?> parent,
      final InstantiableRelationDefinition<C, S> irelation,
      final ManagedObjectDefinition<? extends C, ? extends S> d,
      final List<DefaultBehaviorException> exceptions)
      throws ArgumentException, ClientException {
    int msgID = MSGID_DSCFG_CREATE_NAME_PROMPT;
    String msg = getMessage(msgID, relation.getUserFriendlyName());
    ValidationCallback<ManagedObject<? extends C>> validator =
      new ValidationCallback<ManagedObject<? extends C>>() {
      public ManagedObject<? extends C> validate(ConsoleApplication app,
          String input) throws ClientException {
        ManagedObject<? extends C> child;
        // First attempt to create the child, this will guarantee that
        // the name is acceptable.
        try {
          child = parent.createChild(irelation, d, input, exceptions);
        } catch (IllegalManagedObjectNameException e) {
          ArgumentException ae = ArgumentExceptionFactory
              .adaptIllegalManagedObjectNameException(e, d);
          app.printMessage(ae.getMessage());
          return null;
        }
        // Make sure that there are not any other children with the
        // same name.
        try {
          // Attempt to retrieve a child using this name.
          parent.getChild(irelation, input);
        } catch (AuthorizationException e) {
          int msgID = MSGID_DSCFG_ERROR_CREATE_AUTHZ;
          String msg = getMessage(msgID, irelation.getUserFriendlyName());
          throw new ClientException(LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS,
              msgID, msg);
        } catch (ConcurrentModificationException e) {
          int msgID = MSGID_DSCFG_ERROR_CREATE_CME;
          String msg = getMessage(msgID, irelation.getUserFriendlyName());
          throw new ClientException(LDAPResultCode.CONSTRAINT_VIOLATION, msgID,
              msg);
        } catch (CommunicationException e) {
          int msgID = MSGID_DSCFG_ERROR_CREATE_CE;
          String msg = getMessage(msgID, irelation.getUserFriendlyName(), e
              .getMessage());
          throw new ClientException(LDAPResultCode.CLIENT_SIDE_SERVER_DOWN,
              msgID, msg);
        } catch (DefinitionDecodingException e) {
          // Do nothing.
        } catch (ManagedObjectDecodingException e) {
          // Do nothing.
        } catch (ManagedObjectNotFoundException e) {
          // The child does not already exist so this name is ok.
          return child;
        }
        // A child with the specified name must already exist.
        int msgID = MSGID_DSCFG_ERROR_CREATE_NAME_ALREADY_EXISTS;
        String msg = getMessage(msgID, relation.getUserFriendlyName(), input);
        app.printMessage(msg);
        return null;
      }
    };
    return getConsoleApplication().readValidatedInput(msg, validator);
  }
  // Generate the type name - definition mapping table.
  @SuppressWarnings("unchecked")
  private SortedMap<String, ManagedObjectDefinition<? extends C, ?>>
      getSubTypes(AbstractManagedObjectDefinition<C, ?> d) {
    SortedMap<String, ManagedObjectDefinition<? extends C, ?>> map;
    map = new TreeMap<String, ManagedObjectDefinition<? extends C, ?>>();
  private SortedMap<String, ManagedObjectDefinition<? extends C, ? extends S>>
      getSubTypes(AbstractManagedObjectDefinition<C, S> d) {
    SortedMap<String, ManagedObjectDefinition<? extends C, ? extends S>> map;
    map =
      new TreeMap<String, ManagedObjectDefinition<? extends C, ? extends S>>();
    // If the top-level definition is instantiable, we use the value
    // "generic".
    if (d instanceof ManagedObjectDefinition) {
      ManagedObjectDefinition<? extends C, ?> mod =
        (ManagedObjectDefinition<? extends C, ?>) d;
      ManagedObjectDefinition<? extends C, ? extends S> mod =
        (ManagedObjectDefinition<? extends C, ? extends S>) d;
      map.put(GENERIC_TYPE, mod);
    }
    // Process its sub-definitions.
    String suffix = "-" + d.getName();
    for (AbstractManagedObjectDefinition<? extends C, ?> c :
    for (AbstractManagedObjectDefinition<? extends C, ? extends S> c :
        d.getAllChildren()) {
      if (c instanceof ManagedObjectDefinition) {
        ManagedObjectDefinition<? extends C, ?> mod =
          (ManagedObjectDefinition<? extends C, ?>) c;
        ManagedObjectDefinition<? extends C, ? extends S> mod =
          (ManagedObjectDefinition<? extends C, ? extends S>) c;
        // For the type name we shorten it, if possible, by stripping
        // off the trailing part of the name which matches the
opends/src/server/org/opends/server/tools/dsconfig/DSConfig.java
@@ -32,16 +32,10 @@
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
import static org.opends.server.tools.ToolConstants.*;
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Reader;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
@@ -62,13 +56,13 @@
import org.opends.server.tools.ClientException;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.InitializationException;
import org.opends.server.types.NullOutputStream;
import org.opends.server.util.PasswordReader;
import org.opends.server.util.StaticUtils;
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.args.BooleanArgument;
import org.opends.server.util.args.SubCommand;
import org.opends.server.util.args.SubCommandArgumentParser;
import org.opends.server.util.table.TableBuilder;
import org.opends.server.util.table.TextTablePrinter;
@@ -76,7 +70,7 @@
 * This class provides a command-line tool which enables
 * administrators to configure the Directory Server.
 */
public final class DSConfig {
public final class DSConfig extends ConsoleApplication {
  /**
   * The tracer object for the debug logger.
@@ -100,35 +94,38 @@
    }
  }
  /**
   * Provides the command-line arguments to the main application for
   * processing and returns the exit code as an integer.
   *
   * @param  args              The set of command-line arguments provided to
   *                           this program.
   * @param  initializeServer  Indicates whether to perform basic initialization
   *                           (which should not be done if the tool is running
   *                           in the same JVM as the server).
   * @param  outStream         The output stream for standard output.
   * @param  errStream         The output stream for standard error.
   *
   * @return  Zero to indicate that the program completed successfully, or
   *          non-zero to indicate that an error occurred.
   * @param args
   *          The set of command-line arguments provided to this
   *          program.
   * @param initializeServer
   *          Indicates whether to perform basic initialization (which
   *          should not be done if the tool is running in the same
   *          JVM as the server).
   * @param outStream
   *          The output stream for standard output.
   * @param errStream
   *          The output stream for standard error.
   * @return Zero to indicate that the program completed successfully,
   *         or non-zero to indicate that an error occurred.
   */
  public static int main(String[] args, boolean initializeServer,
                         OutputStream outStream, OutputStream errStream)
  {
      OutputStream outStream, OutputStream errStream) {
    DSConfig app = new DSConfig(System.in, outStream, errStream,
        new LDAPManagementContextFactory());
    // Only initialize the client environment when run as a standalone
    // application.
    if (initializeServer)
    {
    if (initializeServer) {
      try {
        app.initializeClientEnvironment();
      } catch (InitializationException e) {
        // TODO: is this ok as an error message?
        System.err.println(wrapText(e.getMessage(), MAX_LINE_WIDTH));
        app.printMessage(e.getMessage());
        return 1;
      }
    }
@@ -141,9 +138,6 @@
  // already been initialized.
  private boolean environmentInitialized = false;
  // The error stream which this application should use.
  private final PrintStream err;
  // The factory which the application should use to retrieve its
  // management context.
  private final ManagementContextFactory factory;
@@ -156,16 +150,10 @@
  private final Map<SubCommand, SubCommandHandler> handlers =
    new HashMap<SubCommand, SubCommandHandler>();
  // The input stream reader which this application should use.
  private final BufferedReader in;
  // The argument which should be used to request interactive
  // behavior.
  private BooleanArgument interactiveArgument;
  // The output stream which this application should use.
  private final PrintStream out;
  // The command-line argument parser.
  private final SubCommandArgumentParser parser;
@@ -203,126 +191,17 @@
   */
  public DSConfig(InputStream in, OutputStream out, OutputStream err,
      ManagementContextFactory factory) {
    super(in, out, err);
    this.parser = new SubCommandArgumentParser(this.getClass().getName(),
        getMessage(MSGID_CONFIGDS_TOOL_DESCRIPTION), false);
    if (in != null) {
      this.in = new BufferedReader(new InputStreamReader(in));
    } else {
      this.in = new BufferedReader(new Reader() {
        @Override
        public void close() throws IOException {
          // Do nothing.
        }
        @Override
        public int read(char[] cbuf, int off, int len) throws IOException {
          return -1;
        }
      });
    }
    if (out != null) {
      this.out = new PrintStream(out);
    } else {
      this.out = NullOutputStream.printStream();
    }
    if (err != null) {
      this.err = new PrintStream(err);
    } else {
      this.err = NullOutputStream.printStream();
    }
    this.factory = factory;
  }
  /**
   * Interactively confirms whether a user wishes to perform an
   * action. If the application is non-interactive, then the action is
   * granted by default.
   *
   * @param prompt
   *          The prompt describing the action.
   * @return Returns <code>true</code> if the user wishes the action
   *         to be performed, or <code>false</code> if they refused,
   *         or if an exception occurred.
   */
  public boolean confirmAction(String prompt) {
    if (!isInteractive()) {
      return true;
    }
    String yes = Messages.getString("general.yes");
    String no = Messages.getString("general.no");
    String errMsg = Messages.getString("general.confirm.error");
    String error = String.format(errMsg, yes, no);
    prompt = prompt + String.format(" (%s / %s): ", yes, no);
    while (true) {
      String response;
      try {
        response = readLineOfInput(prompt);
      } catch (Exception e) {
        return false;
      }
      if (response == null) {
        // End of input.
        return false;
      }
      response = response.toLowerCase().trim();
      if (response.length() == 0) {
        // Empty input.
        err.println(wrapText(error, MAX_LINE_WIDTH));
      } else if (no.startsWith(response)) {
        return false;
      } else if (yes.startsWith(response)) {
        return true;
      } else {
        // Try again...
        err.println(wrapText(error, MAX_LINE_WIDTH));
      }
    }
  }
  /**
   * Displays a message to the error stream.
   *
   * @param msg
   *          The message.
   */
  public void displayMessage(String msg) {
    err.println(wrapText(msg, MAX_LINE_WIDTH));
  }
  /**
   * Displays a message to the error stream if verbose mode is
   * enabled.
   *
   * @param msg
   *          The verbose message.
   */
  public void displayVerboseMessage(String msg) {
    if (isVerbose()) {
      err.println(wrapText(msg, MAX_LINE_WIDTH));
    }
  }
  /**
   * Initializes core APIs for use when dsconfig will be run as a
   * standalone application.
   *
@@ -350,11 +229,7 @@
  /**
   * Indicates whether or not the user has requested interactive
   * behavior.
   *
   * @return Returns <code>true</code> if the user has requested
   *         interactive behavior.
   * {@inheritDoc}
   */
  public boolean isInteractive() {
    return interactiveArgument.isPresent();
@@ -363,10 +238,7 @@
  /**
   * Indicates whether or not the user has requested quiet output.
   *
   * @return Returns <code>true</code> if the user has requested
   *         quiet output.
   * {@inheritDoc}
   */
  public boolean isQuiet() {
    return quietArgument.isPresent();
@@ -375,11 +247,7 @@
  /**
   * Indicates whether or not the user has requested script-friendly
   * output.
   *
   * @return Returns <code>true</code> if the user has requested
   *         script-friendly output.
   * {@inheritDoc}
   */
  public boolean isScriptFriendly() {
    return scriptFriendlyArgument.isPresent();
@@ -388,10 +256,7 @@
  /**
   * Indicates whether or not the user has requested verbose output.
   *
   * @return Returns <code>true</code> if the user has requested
   *         verbose output.
   * {@inheritDoc}
   */
  public boolean isVerbose() {
    return verboseArgument.isPresent();
@@ -400,59 +265,24 @@
  /**
   * Interactively retrieves a line of input from the console.
   *
   * @param prompt
   *          The prompt.
   * @return Returns the line of input, or <code>null</code> if the
   *         end of input has been reached.
   * @throws Exception
   *           If the line of input could not be retrieved for some
   *           reason.
   * {@inheritDoc}
   */
  public String readLineOfInput(String prompt) throws Exception {
    err.print(wrapText(prompt, MAX_LINE_WIDTH));
    return in.readLine();
  }
  /**
   * Interactively retrieves a password from the console.
   *
   * @param prompt
   *          The password prompt.
   * @return Returns the password.
   * @throws Exception
   *           If the password could not be retrieved for some reason.
   */
  public String readPassword(String prompt) throws Exception {
    err.print(wrapText(prompt, MAX_LINE_WIDTH));
    char[] pwChars = PasswordReader.readPassword();
    return new String(pwChars);
  }
  /**
   * Gets the management context which sub-commands should use in
   * order to manage the directory server.
   *
   * @return Returns the management context which sub-commands should
   *         use in order to manage the directory server.
   * @throws ArgumentException
   *           If a management context related argument could not be
   *           parsed successfully.
   * @throws ClientException
   *           If the management context could not be created.
   */
  ManagementContext getManagementContext() throws ArgumentException,
  public ManagementContext getManagementContext() throws ArgumentException,
      ClientException {
    return factory.getManagementContext(this);
  }
  // Displays the provided message followed by a help usage reference.
  private void displayMessageAndUsageReference(String message) {
    printMessage(message);
    printMessage("");
    printMessage(parser.getHelpUsageReference());
  }
  /**
   * Registers the global arguments with the argument parser.
   *
@@ -478,7 +308,7 @@
      // Register the global arguments.
      parser.addGlobalArgument(showUsageArgument);
      parser.setUsageArgument(showUsageArgument, out);
      parser.setUsageArgument(showUsageArgument, getOutputStream());
      parser.addGlobalArgument(verboseArgument);
      parser.addGlobalArgument(quietArgument);
      parser.addGlobalArgument(scriptFriendlyArgument);
@@ -515,7 +345,8 @@
      Map<Tag, SortedSet<SubCommand>> groups =
        new TreeMap<Tag, SortedSet<SubCommand>>();
      SortedSet<SubCommand> allSubCommands = new TreeSet<SubCommand>(c);
      for (SubCommandHandler handler : builder.getSubCommandHandlers(parser)) {
      for (SubCommandHandler handler : builder.getSubCommandHandlers(this,
          parser)) {
        SubCommand sc = handler.getSubCommand();
        handlers.put(sc, handler);
@@ -578,7 +409,7 @@
    } catch (ArgumentException e) {
      int msgID = MSGID_CANNOT_INITIALIZE_ARGS;
      String message = getMessage(msgID, e.getMessage());
      err.println(wrapText(message, MAX_LINE_WIDTH));
      printMessage(message);
      return 1;
    }
@@ -588,9 +419,7 @@
    } catch (ArgumentException ae) {
      int msgID = MSGID_ERROR_PARSING_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      err.println(wrapText(message, MAX_LINE_WIDTH));
      err.println();
      err.println(parser.getHelpUsageReference());
      displayMessageAndUsageReference(message);
      return 1;
    }
@@ -605,9 +434,7 @@
      int msgID = MSGID_ERROR_PARSING_ARGS;
      String message = getMessage(msgID,
          getMessage(MSGID_DSCFG_ERROR_MISSING_SUBCOMMAND));
      err.println(wrapText(message, MAX_LINE_WIDTH));
      err.println();
      err.println(parser.getHelpUsageReference());
      displayMessageAndUsageReference(message);
      return 1;
    }
@@ -615,9 +442,7 @@
      int msgID = MSGID_TOOL_CONFLICTING_ARGS;
      String message = getMessage(msgID, quietArgument.getLongIdentifier(),
          verboseArgument.getLongIdentifier());
      err.println(wrapText(message, MAX_LINE_WIDTH));
      err.println();
      err.println(parser.getHelpUsageReference());
      displayMessageAndUsageReference(message);
      return 1;
    }
@@ -625,9 +450,7 @@
      int msgID = MSGID_TOOL_CONFLICTING_ARGS;
      String message = getMessage(msgID, quietArgument.getLongIdentifier(),
          interactiveArgument.getLongIdentifier());
      err.println(wrapText(message, MAX_LINE_WIDTH));
      err.println();
      err.println(parser.getHelpUsageReference());
      displayMessageAndUsageReference(message);
      return 1;
    }
@@ -635,9 +458,7 @@
      int msgID = MSGID_TOOL_CONFLICTING_ARGS;
      String message = getMessage(msgID, scriptFriendlyArgument
          .getLongIdentifier(), verboseArgument.getLongIdentifier());
      err.println(wrapText(message, MAX_LINE_WIDTH));
      err.println();
      err.println(parser.getHelpUsageReference());
      displayMessageAndUsageReference(message);
      return 1;
    }
@@ -645,37 +466,44 @@
    try {
      factory.validateGlobalArguments();
    } catch (ArgumentException e) {
      err.println(wrapText(e.getMessage(), MAX_LINE_WIDTH));
      printMessage(e.getMessage());
      return 1;
    }
    // Retrieve the sub-command implementation and run it.
    SubCommandHandler handler = handlers.get(parser.getSubCommand());
    try {
      return handler.run(this, out, err);
      return handler.run();
    } catch (ArgumentException e) {
      err.println(wrapText(e.getMessage(), MAX_LINE_WIDTH));
      printMessage(e.getMessage());
      return 1;
    } catch (ClientException e) {
      // If the client exception was caused by a decoding exception
      // then we should display the causes.
      err.println(wrapText(e.getMessage(), MAX_LINE_WIDTH));
      printMessage(e.getMessage());
      Throwable cause = e.getCause();
      if (cause instanceof ManagedObjectDecodingException) {
        // FIXME: use a table.
        ManagedObjectDecodingException de =
          (ManagedObjectDecodingException) cause;
        err.println();
        printMessage("");
        TableBuilder builder = new TableBuilder();
        for (PropertyException pe : de.getCauses()) {
          AbstractManagedObjectDefinition<?, ?> d = de
              .getPartialManagedObject().getManagedObjectDefinition();
          ArgumentException ae = ArgumentExceptionFactory
              .adaptPropertyException(pe, d);
          err.println(wrapText(" * " + ae.getMessage(), MAX_LINE_WIDTH));
          builder.startRow();
          builder.appendCell("*");
          builder.appendCell(ae.getMessage());
        }
        err.println();
        TextTablePrinter printer = new TextTablePrinter(getErrorStream());
        printer.setDisplayHeadings(false);
        printer.setColumnWidth(1, 0);
        builder.print(printer);
        printMessage("");
      }
      return 1;
@@ -683,7 +511,7 @@
      if (debugEnabled()) {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      err.println(wrapText(StaticUtils.stackTraceToString(e), MAX_LINE_WIDTH));
      printMessage(StaticUtils.stackTraceToString(e));
      return 1;
    }
  }
opends/src/server/org/opends/server/tools/dsconfig/DeleteSubCommandHandler.java
@@ -31,7 +31,6 @@
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
import java.io.PrintStream;
import java.util.List;
import org.opends.server.admin.DefinitionDecodingException;
@@ -45,7 +44,6 @@
import org.opends.server.admin.client.ConcurrentModificationException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagedObjectDecodingException;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.client.OperationRejectedException;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.tools.ClientException;
@@ -81,6 +79,8 @@
   * Creates a new delete-xxx sub-command for an instantiable
   * relation.
   *
   * @param app
   *          The console application.
   * @param parser
   *          The sub-command argument parser.
   * @param p
@@ -91,10 +91,10 @@
   * @throws ArgumentException
   *           If the sub-command could not be created successfully.
   */
  public static DeleteSubCommandHandler create(SubCommandArgumentParser parser,
      ManagedObjectPath<?, ?> p, InstantiableRelationDefinition<?, ?> r)
      throws ArgumentException {
    return new DeleteSubCommandHandler(parser, p, r, p.child(r, "DUMMY"));
  public static DeleteSubCommandHandler create(ConsoleApplication app,
      SubCommandArgumentParser parser, ManagedObjectPath<?, ?> p,
      InstantiableRelationDefinition<?, ?> r) throws ArgumentException {
    return new DeleteSubCommandHandler(app, parser, p, r, p.child(r, "DUMMY"));
  }
@@ -102,6 +102,8 @@
  /**
   * Creates a new delete-xxx sub-command for an optional relation.
   *
   * @param app
   *          The console application.
   * @param parser
   *          The sub-command argument parser.
   * @param p
@@ -112,10 +114,10 @@
   * @throws ArgumentException
   *           If the sub-command could not be created successfully.
   */
  public static DeleteSubCommandHandler create(SubCommandArgumentParser parser,
      ManagedObjectPath<?, ?> p, OptionalRelationDefinition<?, ?> r)
      throws ArgumentException {
    return new DeleteSubCommandHandler(parser, p, r, p.child(r));
  public static DeleteSubCommandHandler create(ConsoleApplication app,
      SubCommandArgumentParser parser, ManagedObjectPath<?, ?> p,
      OptionalRelationDefinition<?, ?> r) throws ArgumentException {
    return new DeleteSubCommandHandler(app, parser, p, r, p.child(r));
  }
  // The argument which should be used to force deletion.
@@ -137,9 +139,12 @@
  // Private constructor.
  private DeleteSubCommandHandler(SubCommandArgumentParser parser,
      ManagedObjectPath<?, ?> p, RelationDefinition<?, ?> r,
      ManagedObjectPath<?, ?> c) throws ArgumentException {
  private DeleteSubCommandHandler(ConsoleApplication app,
      SubCommandArgumentParser parser, ManagedObjectPath<?, ?> p,
      RelationDefinition<?, ?> r, ManagedObjectPath<?, ?> c)
      throws ArgumentException {
    super(app);
    this.path = p;
    this.relation = r;
@@ -179,16 +184,14 @@
   * {@inheritDoc}
   */
  @Override
  public int run(DSConfig app, PrintStream out, PrintStream err)
      throws ArgumentException, ClientException {
  public int run() throws ArgumentException, ClientException {
    // Get the naming argument values.
    List<String> names = getNamingArgValues(namingArgs);
    // Delete the child managed object.
    ManagementContext context = app.getManagementContext();
    ManagedObject<?> parent = null;
    try {
      parent = getManagedObject(context, path, names);
      parent = getManagedObject(path, names);
    } catch (AuthorizationException e) {
      int msgID = MSGID_DSCFG_ERROR_DELETE_AUTHZ;
      String msg = getMessage(msgID, relation.getUserFriendlyName());
@@ -213,8 +216,8 @@
    } catch (ConcurrentModificationException e) {
      int msgID = MSGID_DSCFG_ERROR_DELETE_CME;
      String msg = getMessage(msgID, relation.getUserFriendlyName());
      throw new ClientException(LDAPResultCode.CONSTRAINT_VIOLATION, msgID,
          msg);
      throw new ClientException(LDAPResultCode.CONSTRAINT_VIOLATION,
          msgID, msg);
    } catch (ManagedObjectNotFoundException e) {
      // Ignore the error if the deletion is being forced.
      if (!forceArgument.isPresent()) {
@@ -227,25 +230,28 @@
    if (parent != null) {
      try {
        // Confirm deletion.
        String prompt = String.format(Messages.getString("delete.confirm"),
            relation.getUserFriendlyName());
        if (!app.confirmAction(prompt)) {
          // Output failure message.
          String msg = String.format(Messages.getString("delete.failed"),
              relation.getUserFriendlyName());
          app.displayVerboseMessage(msg);
          return 1;
        }
        if (relation instanceof InstantiableRelationDefinition) {
          InstantiableRelationDefinition<?, ?> irelation =
            (InstantiableRelationDefinition<?, ?>) relation;
          parent.removeChild(irelation, names.get(names.size() - 1));
          String childName = names.get(names.size() - 1);
          if (childName == null) {
            childName = readChildName(parent, irelation, null);
          }
          if (confirmDeletion()) {
            parent.removeChild(irelation, childName);
          } else {
            return 1;
          }
        } else if (relation instanceof OptionalRelationDefinition) {
          OptionalRelationDefinition<?, ?> orelation =
            (OptionalRelationDefinition<?, ?>) relation;
          if (confirmDeletion()) {
          parent.removeChild(orelation);
          } else {
            return 1;
          }
        }
      } catch (AuthorizationException e) {
        int msgID = MSGID_DSCFG_ERROR_DELETE_AUTHZ;
@@ -282,9 +288,26 @@
    // Output success message.
    String msg = String.format(Messages.getString("delete.done"), relation
        .getUserFriendlyName());
    app.displayVerboseMessage(msg);
    getConsoleApplication().printVerboseMessage(msg);
    return 0;
  }
  // Confirm deletion.
  private boolean confirmDeletion() throws ArgumentException {
    String prompt = String.format(Messages.getString("delete.confirm"),
        relation.getUserFriendlyName());
    if (!getConsoleApplication().confirmAction(prompt)) {
      // Output failure message.
      String msg = String.format(Messages.getString("delete.failed"), relation
          .getUserFriendlyName());
      getConsoleApplication().printVerboseMessage(msg);
      return false;
    } else {
      return true;
    }
  }
}
opends/src/server/org/opends/server/tools/dsconfig/GetPropSubCommandHandler.java
@@ -59,7 +59,6 @@
import org.opends.server.admin.client.ConcurrentModificationException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagedObjectDecodingException;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.tools.ClientException;
import org.opends.server.util.args.ArgumentException;
@@ -84,6 +83,8 @@
   * Creates a new get-xxx-prop sub-command for an instantiable
   * relation.
   *
   * @param app
   *          The console application.
   * @param parser
   *          The sub-command argument parser.
   * @param path
@@ -94,15 +95,19 @@
   * @throws ArgumentException
   *           If the sub-command could not be created successfully.
   */
  public static GetPropSubCommandHandler create(
  public static GetPropSubCommandHandler create(ConsoleApplication app,
      SubCommandArgumentParser parser, ManagedObjectPath<?, ?> path,
      InstantiableRelationDefinition<?, ?> r) throws ArgumentException {
    return new GetPropSubCommandHandler(parser, path.child(r, "DUMMY"), r);
    return new GetPropSubCommandHandler(app, parser, path.child(r, "DUMMY"), r);
  }
  /**
   * Creates a new get-xxx-prop sub-command for an optional relation.
   *
   * @param app
   *          The console application.
   * @param parser
   *          The sub-command argument parser.
   * @param path
@@ -113,15 +118,19 @@
   * @throws ArgumentException
   *           If the sub-command could not be created successfully.
   */
  public static GetPropSubCommandHandler create(
  public static GetPropSubCommandHandler create(ConsoleApplication app,
      SubCommandArgumentParser parser, ManagedObjectPath<?, ?> path,
      OptionalRelationDefinition<?, ?> r) throws ArgumentException {
    return new GetPropSubCommandHandler(parser, path.child(r), r);
    return new GetPropSubCommandHandler(app, parser, path.child(r), r);
  }
  /**
   * Creates a new get-xxx-prop sub-command for a singleton relation.
   *
   * @param app
   *          The console application.
   * @param parser
   *          The sub-command argument parser.
   * @param path
@@ -132,10 +141,10 @@
   * @throws ArgumentException
   *           If the sub-command could not be created successfully.
   */
  public static GetPropSubCommandHandler create(
  public static GetPropSubCommandHandler create(ConsoleApplication app,
      SubCommandArgumentParser parser, ManagedObjectPath<?, ?> path,
      SingletonRelationDefinition<?, ?> r) throws ArgumentException {
    return new GetPropSubCommandHandler(parser, path.child(r), r);
    return new GetPropSubCommandHandler(app, parser, path.child(r), r);
  }
  // The sub-commands naming arguments.
@@ -150,9 +159,11 @@
  // Private constructor.
  private GetPropSubCommandHandler(SubCommandArgumentParser parser,
      ManagedObjectPath<?, ?> path, RelationDefinition<?, ?> r)
      throws ArgumentException {
  private GetPropSubCommandHandler(ConsoleApplication app,
      SubCommandArgumentParser parser, ManagedObjectPath<?, ?> path,
      RelationDefinition<?, ?> r) throws ArgumentException {
    super(app);
    this.path = path;
    // Create the sub-command.
@@ -192,21 +203,19 @@
   * {@inheritDoc}
   */
  @Override
  public int run(DSConfig app, PrintStream out, PrintStream err)
      throws ArgumentException, ClientException {
  public int run() throws ArgumentException, ClientException {
    // Get the property names.
    Set<String> propertyNames = getPropertyNames();
    PropertyValuePrinter valuePrinter = new PropertyValuePrinter(getSizeUnit(),
        getTimeUnit(), app.isScriptFriendly());
        getTimeUnit(), getConsoleApplication().isScriptFriendly());
    // Get the naming argument values.
    List<String> names = getNamingArgValues(namingArgs);
    // Get the targeted managed object.
    ManagementContext context = app.getManagementContext();
    ManagedObject<?> child;
    try {
      child = getManagedObject(context, path, names);
      child = getManagedObject(path, names);
    } catch (AuthorizationException e) {
      int msgID = MSGID_DSCFG_ERROR_GET_CHILD_AUTHZ;
      String ufn = path.getManagedObjectDefinition().getUserFriendlyName();
@@ -273,11 +282,12 @@
      }
      if (propertyNames.isEmpty() || propertyNames.contains(pd.getName())) {
        displayProperty(app, builder, child, pd, valuePrinter);
        displayProperty(builder, child, pd, valuePrinter);
      }
    }
    if (app.isScriptFriendly()) {
    PrintStream out = getConsoleApplication().getOutputStream();
    if (getConsoleApplication().isScriptFriendly()) {
      TablePrinter printer = createScriptFriendlyTablePrinter(out);
      builder.print(printer);
    } else {
@@ -293,9 +303,8 @@
  // Display the set of values associated with a property.
  private <T> void displayProperty(final DSConfig app, TableBuilder builder,
      ManagedObject<?> mo, PropertyDefinition<T> pd,
      PropertyValuePrinter valuePrinter) {
  private <T> void displayProperty(TableBuilder builder, ManagedObject<?> mo,
      PropertyDefinition<T> pd, PropertyValuePrinter valuePrinter) {
    SortedSet<T> values = mo.getPropertyValues(pd);
    if (values.isEmpty()) {
      // There are no values or default values. Display the default
@@ -313,7 +322,7 @@
        public String visitAlias(AliasDefaultBehaviorProvider<T> d, Void p) {
          if (app.isVerbose()) {
          if (getConsoleApplication().isVerbose()) {
            return d.getSynopsis();
          } else {
            return null;
@@ -351,7 +360,7 @@
      String content = pd.getDefaultBehaviorProvider().accept(visitor, null);
      if (content == null) {
        if (app.isScriptFriendly()) {
        if (getConsoleApplication().isScriptFriendly()) {
          builder.appendCell();
        } else {
          builder.appendCell("-");
@@ -370,7 +379,7 @@
        builder.startRow();
        builder.appendCell(pd.getName());
        if (app.isScriptFriendly()) {
        if (getConsoleApplication().isScriptFriendly()) {
          for (T value : values) {
            builder.appendCell(valuePrinter.print(pd, value));
          }
opends/src/server/org/opends/server/tools/dsconfig/HelpCallback.java
New file
@@ -0,0 +1,43 @@
/*
 * 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.tools.dsconfig;
/**
 * An interface for displaying help interactively.
 */
interface HelpCallback {
  /**
   * Displays help to the provided application console.
   *
   * @param app
   *          The console application.
   */
  void display(ConsoleApplication app);
}
opends/src/server/org/opends/server/tools/dsconfig/HelpSubCommandHandler.java
@@ -294,7 +294,7 @@
       * {@inheritDoc}
       */
      @Override
      public Void visitUnknown(PropertyDefinition d, PrintStream p)
      public Void visitUnknown(PropertyDefinition<?> d, PrintStream p)
          throws UnknownPropertyDefinitionException {
        PropertyDefinitionUsageBuilder usageBuilder =
          new PropertyDefinitionUsageBuilder(true);
@@ -458,19 +458,43 @@
  /**
   * Creates a new help-properties sub-command.
   *
   * @param app
   *          The console application.
   * @param parser
   *          The sub-command argument parser.
   * @return Returns the new help-properties sub-command.
   * @throws ArgumentException
   *           If the sub-command could not be created successfully.
   */
  public static HelpSubCommandHandler create(SubCommandArgumentParser parser)
  public static synchronized HelpSubCommandHandler create(
      ConsoleApplication app, SubCommandArgumentParser parser)
      throws ArgumentException {
    return new HelpSubCommandHandler(parser);
    if (INSTANCE == null) {
      INSTANCE = new HelpSubCommandHandler(app, parser);
    }
    return INSTANCE;
  }
  /**
   * Gets the application-wide help sub-command handler.
   *
   * @return Returns the application-wide help sub-command handler.
   */
  public static synchronized HelpSubCommandHandler getInstance() {
    if (INSTANCE == null) {
      throw new RuntimeException("Help sub-command handler not initialized");
    } else {
      return INSTANCE;
    }
  }
  // The singleton instance.
  private static HelpSubCommandHandler INSTANCE = null;
  // The sub-command associated with this handler.
  private final SubCommand subCommand;
@@ -482,8 +506,10 @@
  private final Map<String, AbstractManagedObjectDefinition<?, ?>> types;
  // Private constructor.
  private HelpSubCommandHandler(SubCommandArgumentParser parser)
      throws ArgumentException {
  private HelpSubCommandHandler(ConsoleApplication app,
      SubCommandArgumentParser parser) throws ArgumentException {
    super(app);
    // Create the sub-command.
    String name = "list-properties";
    int descriptionID = MSGID_DSCFG_DESCRIPTION_SUBCMD_HELPPROP;
@@ -649,7 +675,7 @@
   * {@inheritDoc}
   */
  @Override
  public int run(DSConfig app, PrintStream out, PrintStream err)
  public int run()
      throws ArgumentException, ClientException {
    String typeName = typeArgument.getValue();
    Set<String> propertyNames = getPropertyNames();
@@ -682,10 +708,10 @@
      defns = Collections.<AbstractManagedObjectDefinition<?, ?>> singleton(d);
    }
    if (!app.isVerbose()) {
      displayNonVerbose(app, out, err, defns, propertyNames);
    if (!getConsoleApplication().isVerbose()) {
      displayNonVerbose(defns, propertyNames);
    } else {
      displayVerbose(app, out, err, defns, propertyNames);
      displayVerbose(defns, propertyNames);
    }
    return 0;
  }
@@ -693,10 +719,11 @@
  // Output property summary table.
  private void displayNonVerbose(DSConfig app, PrintStream out,
      PrintStream err, Collection<AbstractManagedObjectDefinition<?, ?>> defns,
  private void displayNonVerbose(
      Collection<AbstractManagedObjectDefinition<?, ?>> defns,
      Set<String> propertyNames) {
    if (!app.isScriptFriendly()) {
    PrintStream out = getConsoleApplication().getOutputStream();
    if (!getConsoleApplication().isScriptFriendly()) {
      out.println(DESCRIPTION_OPTIONS_TITLE);
      out.println();
      out.print(" r -- ");
@@ -728,7 +755,7 @@
    // Generate the table content.
    for (AbstractManagedObjectDefinition<?, ?> mod : defns) {
      Collection<PropertyDefinition<?>> pds;
      if (app.isScriptFriendly()) {
      if (getConsoleApplication().isScriptFriendly()) {
        pds = mod.getAllPropertyDefinitions();
      } else {
        pds = mod.getPropertyDefinitions();
@@ -767,7 +794,7 @@
    }
    TablePrinter printer;
    if (app.isScriptFriendly()) {
    if (getConsoleApplication().isScriptFriendly()) {
      printer = createScriptFriendlyTablePrinter(out);
    } else {
      printer = new TextTablePrinter(out);
@@ -778,9 +805,11 @@
  // Display detailed help on managed objects and their properties.
  private void displayVerbose(DSConfig app, PrintStream out, PrintStream err,
  private void displayVerbose(
      Collection<AbstractManagedObjectDefinition<?, ?>> defns,
      Set<String> propertyNames) {
    PrintStream out = getConsoleApplication().getOutputStream();
    // Construct line used to separate consecutive sections.
    char[] c1 = new char[MAX_LINE_WIDTH];
    Arrays.fill(c1, '=');
@@ -843,71 +872,6 @@
  // Display description of the single managed object.
  /*private void displaySummaryForSingleManagedObject(DSConfig app,
      PrintStream out, PrintStream err,
      AbstractManagedObjectDefinition<?, ?> d, Set<String> propertyNames) {
    // Display the title.
    out.println(wrapText(String.format(HEADING_MANAGED_OBJECT, d
        .getUserFriendlyName()), MAX_LINE_WIDTH));
    out.println();
    out.println(wrapText(d.getSynopsis(), MAX_LINE_WIDTH));
    if (d.getDescription() != null) {
      out.println();
      out.println(wrapText(d.getDescription(), MAX_LINE_WIDTH));
    }
    // Output table of properties.
    TableBuilder builder = new TableBuilder();
    // Headings.
    builder.appendHeading(getMessage(MSGID_DSCFG_HEADING_PROPERTY_NAME));
    builder.appendHeading(getMessage(MSGID_DSCFG_HEADING_PROPERTY_OPTIONS));
    builder.appendHeading(getMessage(MSGID_DSCFG_HEADING_PROPERTY_SYNTAX));
    // Sort keys.
    builder.addSortKey(0);
    // Generate the table content.
    for (String name : propertyNames) {
      PropertyDefinition<?> pd = d.getPropertyDefinition(name);
      if (pd.hasOption(PropertyOption.HIDDEN)) {
        continue;
      }
      // Display a property.
      builder.startRow();
      builder.appendCell(pd.getName());
      // Display the options.
      builder.appendCell(getPropertyOptionSummary(pd));
      // Display the syntax.
      PropertyDefinitionUsageBuilder v =
        new PropertyDefinitionUsageBuilder(false);
      String syntax = v.getUsage(pd);
      if (syntax.length() < 40) {
        builder.appendCell(syntax);
      } else {
        String msg = getMessage(MSGID_DSCFG_DESCRIPTION_PROPERTY_SYNTAX_HELP);
        builder.appendCell(msg);
      }
    }
    TextTablePrinter factory = new TextTablePrinter(out);
    // Let the syntax column be expandable.
    factory.setColumnWidth(2, 0);
    out.println();
    builder.print(factory);
  }*/
  // Compute the options field.
  private String getPropertyOptionSummary(PropertyDefinition<?> pd) {
    StringBuilder b = new StringBuilder();
opends/src/server/org/opends/server/tools/dsconfig/InternalManagementContextFactory.java
@@ -63,7 +63,7 @@
  /**
   * {@inheritDoc}
   */
  public ManagementContext getManagementContext(DSConfig app)
  public ManagementContext getManagementContext(ConsoleApplication app)
      throws ArgumentException, ClientException {
    return context;
  }
opends/src/server/org/opends/server/tools/dsconfig/LDAPManagementContextFactory.java
@@ -94,7 +94,7 @@
  /**
   * {@inheritDoc}
   */
  public ManagementContext getManagementContext(DSConfig app)
  public ManagementContext getManagementContext(ConsoleApplication app)
      throws ArgumentException, ClientException {
    // Lazily create the LDAP management context.
    if (context == null) {
opends/src/server/org/opends/server/tools/dsconfig/ListSubCommandHandler.java
@@ -51,7 +51,6 @@
import org.opends.server.admin.client.ConcurrentModificationException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagedObjectDecodingException;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.tools.ClientException;
import org.opends.server.util.args.ArgumentException;
@@ -75,6 +74,8 @@
  /**
   * Creates a new list-xxx sub-command for an instantiable relation.
   *
   * @param app
   *          The console application.
   * @param parser
   *          The sub-command argument parser.
   * @param p
@@ -85,10 +86,10 @@
   * @throws ArgumentException
   *           If the sub-command could not be created successfully.
   */
  public static ListSubCommandHandler create(SubCommandArgumentParser parser,
      ManagedObjectPath<?, ?> p, InstantiableRelationDefinition<?, ?> r)
      throws ArgumentException {
    return new ListSubCommandHandler(parser, p, r, r.getPluralName(), r
  public static ListSubCommandHandler create(ConsoleApplication app,
      SubCommandArgumentParser parser, ManagedObjectPath<?, ?> p,
      InstantiableRelationDefinition<?, ?> r) throws ArgumentException {
    return new ListSubCommandHandler(app, parser, p, r, r.getPluralName(), r
        .getUserFriendlyPluralName());
  }
@@ -97,6 +98,8 @@
  /**
   * Creates a new list-xxx sub-command for an optional relation.
   *
   * @param app
   *          The console application.
   * @param parser
   *          The sub-command argument parser.
   * @param p
@@ -107,10 +110,10 @@
   * @throws ArgumentException
   *           If the sub-command could not be created successfully.
   */
  public static ListSubCommandHandler create(SubCommandArgumentParser parser,
      ManagedObjectPath<?, ?> p, OptionalRelationDefinition<?, ?> r)
      throws ArgumentException {
    return new ListSubCommandHandler(parser, p, r, r.getName(), r
  public static ListSubCommandHandler create(ConsoleApplication app,
      SubCommandArgumentParser parser, ManagedObjectPath<?, ?> p,
      OptionalRelationDefinition<?, ?> r) throws ArgumentException {
    return new ListSubCommandHandler(app, parser, p, r, r.getName(), r
        .getUserFriendlyName());
  }
@@ -129,9 +132,12 @@
  // Private constructor.
  private ListSubCommandHandler(SubCommandArgumentParser parser,
      ManagedObjectPath<?, ?> p, RelationDefinition<?, ?> r, String rname,
      String rufn) throws ArgumentException {
  private ListSubCommandHandler(ConsoleApplication app,
      SubCommandArgumentParser parser, ManagedObjectPath<?, ?> p,
      RelationDefinition<?, ?> r, String rname, String rufn)
      throws ArgumentException {
    super(app);
    this.path = p;
    this.relation = r;
@@ -169,7 +175,7 @@
   * {@inheritDoc}
   */
  @Override
  public int run(DSConfig app, PrintStream out, PrintStream err)
  public int run()
      throws ArgumentException, ClientException {
    // Get the property names.
    Set<String> propertyNames = getPropertyNames();
@@ -181,7 +187,7 @@
    }
    PropertyValuePrinter valuePrinter = new PropertyValuePrinter(getSizeUnit(),
        getTimeUnit(), app.isScriptFriendly());
        getTimeUnit(), getConsoleApplication().isScriptFriendly());
    // Get the naming argument values.
    List<String> names = getNamingArgValues(namingArgs);
@@ -196,10 +202,9 @@
    }
    // List the children.
    ManagementContext context = app.getManagementContext();
    ManagedObject<?> parent;
    try {
      parent = getManagedObject(context, path, names);
      parent = getManagedObject(path, names);
    } catch (AuthorizationException e) {
      int msgID = MSGID_DSCFG_ERROR_LIST_AUTHZ;
      String msg = getMessage(msgID, ufn);
@@ -315,8 +320,9 @@
    }
    // Output the results.
    if (app.isScriptFriendly()) {
    if (getConsoleApplication().isScriptFriendly()) {
      // Output just the names of the children.
      PrintStream out = getConsoleApplication().getOutputStream();
      for (String name : children.keySet()) {
        out.println(name);
      }
@@ -359,11 +365,11 @@
        for (String propertyName : propertyNames) {
          try {
            PropertyDefinition<?> pd = d.getPropertyDefinition(propertyName);
            displayProperty(app, builder, child, pd, valuePrinter);
            displayProperty(builder, child, pd, valuePrinter);
          } catch (IllegalArgumentException e) {
            // Assume this child managed object does not support this
            // property.
            if (app.isScriptFriendly()) {
            if (getConsoleApplication().isScriptFriendly()) {
              builder.appendCell();
            } else {
              builder.appendCell("-");
@@ -372,7 +378,8 @@
        }
      }
      if (app.isScriptFriendly()) {
      PrintStream out = getConsoleApplication().getOutputStream();
      if (getConsoleApplication().isScriptFriendly()) {
        TablePrinter printer = createScriptFriendlyTablePrinter(out);
        builder.print(printer);
      } else {
@@ -388,12 +395,11 @@
  // Display the set of values associated with a property.
  private <T> void displayProperty(DSConfig app, TableBuilder builder,
      ManagedObject<?> mo, PropertyDefinition<T> pd,
      PropertyValuePrinter valuePrinter) {
  private <T> void displayProperty(TableBuilder builder, ManagedObject<?> mo,
      PropertyDefinition<T> pd, PropertyValuePrinter valuePrinter) {
    SortedSet<T> values = mo.getPropertyValues(pd);
    if (values.isEmpty()) {
      if (app.isScriptFriendly()) {
      if (getConsoleApplication().isScriptFriendly()) {
        builder.appendCell();
      } else {
        builder.appendCell("-");
opends/src/server/org/opends/server/tools/dsconfig/ManagementContextFactory.java
@@ -59,8 +59,8 @@
   * @throws ClientException
   *           If the management context could not be created.
   */
  ManagementContext getManagementContext(DSConfig app) throws ArgumentException,
      ClientException;
  ManagementContext getManagementContext(ConsoleApplication app)
      throws ArgumentException, ClientException;
opends/src/server/org/opends/server/tools/dsconfig/SetPropSubCommandHandler.java
@@ -31,7 +31,6 @@
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -57,7 +56,6 @@
import org.opends.server.admin.client.ConcurrentModificationException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagedObjectDecodingException;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.client.MissingMandatoryPropertiesException;
import org.opends.server.admin.client.OperationRejectedException;
import org.opends.server.protocols.ldap.LDAPResultCode;
@@ -144,6 +142,8 @@
   * Creates a new set-xxx-prop sub-command for an instantiable
   * relation.
   *
   * @param app
   *          The console application.
   * @param parser
   *          The sub-command argument parser.
   * @param path
@@ -154,10 +154,10 @@
   * @throws ArgumentException
   *           If the sub-command could not be created successfully.
   */
  public static SetPropSubCommandHandler create(
  public static SetPropSubCommandHandler create(ConsoleApplication app,
      SubCommandArgumentParser parser, ManagedObjectPath<?, ?> path,
      InstantiableRelationDefinition<?, ?> r) throws ArgumentException {
    return new SetPropSubCommandHandler(parser, path.child(r, "DUMMY"), r);
    return new SetPropSubCommandHandler(app, parser, path.child(r, "DUMMY"), r);
  }
@@ -165,6 +165,8 @@
  /**
   * Creates a new set-xxx-prop sub-command for an optional relation.
   *
   * @param app
   *          The console application.
   * @param parser
   *          The sub-command argument parser.
   * @param path
@@ -175,10 +177,10 @@
   * @throws ArgumentException
   *           If the sub-command could not be created successfully.
   */
  public static SetPropSubCommandHandler create(
  public static SetPropSubCommandHandler create(ConsoleApplication app,
      SubCommandArgumentParser parser, ManagedObjectPath<?, ?> path,
      OptionalRelationDefinition<?, ?> r) throws ArgumentException {
    return new SetPropSubCommandHandler(parser, path.child(r), r);
    return new SetPropSubCommandHandler(app, parser, path.child(r), r);
  }
@@ -186,6 +188,8 @@
  /**
   * Creates a new set-xxx-prop sub-command for a singleton relation.
   *
   * @param app
   *          The console application.
   * @param parser
   *          The sub-command argument parser.
   * @param path
@@ -196,10 +200,10 @@
   * @throws ArgumentException
   *           If the sub-command could not be created successfully.
   */
  public static SetPropSubCommandHandler create(
  public static SetPropSubCommandHandler create(ConsoleApplication app,
      SubCommandArgumentParser parser, ManagedObjectPath<?, ?> path,
      SingletonRelationDefinition<?, ?> r) throws ArgumentException {
    return new SetPropSubCommandHandler(parser, path.child(r), r);
    return new SetPropSubCommandHandler(app, parser, path.child(r), r);
  }
  // The sub-commands naming arguments.
@@ -230,9 +234,11 @@
  // Private constructor.
  private SetPropSubCommandHandler(SubCommandArgumentParser parser,
      ManagedObjectPath<?, ?> path, RelationDefinition<?, ?> r)
      throws ArgumentException {
  private SetPropSubCommandHandler(ConsoleApplication app,
      SubCommandArgumentParser parser, ManagedObjectPath<?, ?> path,
      RelationDefinition<?, ?> r) throws ArgumentException {
    super(app);
    this.path = path;
    // Create the sub-command.
@@ -289,15 +295,14 @@
   */
  @SuppressWarnings("unchecked")
  @Override
  public int run(DSConfig app, PrintStream out, PrintStream err)
  public int run()
      throws ArgumentException, ClientException {
    // Get the naming argument values.
    List<String> names = getNamingArgValues(namingArgs);
    ManagementContext context = app.getManagementContext();
    ManagedObject<?> child;
    try {
      child = getManagedObject(context, path, names);
      child = getManagedObject(path, names);
    } catch (AuthorizationException e) {
      int msgID = MSGID_DSCFG_ERROR_MODIFY_AUTHZ;
      String ufn = path.getManagedObjectDefinition().getUserFriendlyName();
@@ -493,11 +498,11 @@
      // Confirm commit.
      String prompt = String.format(Messages.getString("modify.confirm"), d
          .getUserFriendlyName());
      if (!app.confirmAction(prompt)) {
      if (!getConsoleApplication().confirmAction(prompt)) {
        // Output failure message.
        String msg = String.format(Messages.getString("modify.failed"), d
            .getUserFriendlyName());
        app.displayVerboseMessage(msg);
        getConsoleApplication().printVerboseMessage(msg);
        return 1;
      }
@@ -506,7 +511,7 @@
      // Output success message.
      String msg = String.format(Messages.getString("modify.done"), d
          .getUserFriendlyName());
      app.displayVerboseMessage(msg);
      getConsoleApplication().printVerboseMessage(msg);
    } catch (MissingMandatoryPropertiesException e) {
      throw ArgumentExceptionFactory.adaptMissingMandatoryPropertiesException(
          e, d);
opends/src/server/org/opends/server/tools/dsconfig/SubCommandBuilder.java
@@ -61,6 +61,9 @@
  private static final class Visitor implements
      RelationDefinitionVisitor<Void, ManagedObjectPath<?, ?>> {
    // The application.
    private final ConsoleApplication app;
    // Any exception that occurred whilst creating the sub-commands.
    private ArgumentException exception = null;
@@ -74,7 +77,8 @@
    private final SubCommandArgumentParser parser;
    // Private constructor.
    private Visitor(SubCommandArgumentParser parser) {
    private Visitor(ConsoleApplication app, SubCommandArgumentParser parser) {
      this.app = app;
      this.parser = parser;
    }
@@ -93,7 +97,7 @@
        handlers = new LinkedList<SubCommandHandler>();
        // We always need a help properties sub-command handler.
        helpHandler = HelpSubCommandHandler.create(parser);
        helpHandler = HelpSubCommandHandler.create(app, parser);
        handlers.add(helpHandler);
        processPath(ManagedObjectPath.emptyPath());
@@ -126,11 +130,11 @@
        ManagedObjectPath<?, ?> p) {
      try {
        // Create the sub-commands.
        handlers.add(CreateSubCommandHandler.create(parser, p, r));
        handlers.add(DeleteSubCommandHandler.create(parser, p, r));
        handlers.add(ListSubCommandHandler.create(parser, p, r));
        handlers.add(GetPropSubCommandHandler.create(parser, p, r));
        handlers.add(SetPropSubCommandHandler.create(parser, p, r));
        handlers.add(CreateSubCommandHandler.create(app, parser, p, r));
        handlers.add(DeleteSubCommandHandler.create(app, parser, p, r));
        handlers.add(ListSubCommandHandler.create(app, parser, p, r));
        handlers.add(GetPropSubCommandHandler.create(app, parser, p, r));
        handlers.add(SetPropSubCommandHandler.create(app, parser, p, r));
        // Process the referenced managed object definition and its
        // sub-types.
@@ -151,11 +155,11 @@
        ManagedObjectPath<?, ?> p) {
      try {
        // Create the sub-commands.
        handlers.add(CreateSubCommandHandler.create(parser, p, r));
        handlers.add(DeleteSubCommandHandler.create(parser, p, r));
        handlers.add(ListSubCommandHandler.create(parser, p, r));
        handlers.add(GetPropSubCommandHandler.create(parser, p, r));
        handlers.add(SetPropSubCommandHandler.create(parser, p, r));
        handlers.add(CreateSubCommandHandler.create(app, parser, p, r));
        handlers.add(DeleteSubCommandHandler.create(app, parser, p, r));
        handlers.add(ListSubCommandHandler.create(app, parser, p, r));
        handlers.add(GetPropSubCommandHandler.create(app, parser, p, r));
        handlers.add(SetPropSubCommandHandler.create(app, parser, p, r));
        // Process the referenced managed object definition and its
        // sub-types.
@@ -176,8 +180,8 @@
        ManagedObjectPath<?, ?> p) {
      try {
        // Create the sub-commands.
        handlers.add(GetPropSubCommandHandler.create(parser, p, r));
        handlers.add(SetPropSubCommandHandler.create(parser, p, r));
        handlers.add(GetPropSubCommandHandler.create(app, parser, p, r));
        handlers.add(SetPropSubCommandHandler.create(app, parser, p, r));
        // Process the referenced managed object definition and its
        // sub-types.
@@ -281,6 +285,8 @@
  /**
   * Get the set of sub-command handlers constructed by this builder.
   *
   * @param app
   *          The console application.
   * @param parser
   *          The sub-command argument parser.
   * @return Returns the set of sub-command handlers constructed by
@@ -289,8 +295,9 @@
   *           If a sub-command could not be created successfully.
   */
  public Collection<SubCommandHandler> getSubCommandHandlers(
      SubCommandArgumentParser parser) throws ArgumentException {
    Visitor v = new Visitor(parser);
      ConsoleApplication app, SubCommandArgumentParser parser)
      throws ArgumentException {
    Visitor v = new Visitor(app, parser);
    return v.getSubCommandHandlers();
  }
opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java
@@ -82,12 +82,10 @@
   * A path serializer which is used to retrieve a managed object
   * based on a path and a list of path arguments.
   */
  private static class ManagedObjectFinder implements
      ManagedObjectPathSerializer {
  private class ManagedObjectFinder implements ManagedObjectPathSerializer {
    // Any argument exception that was caught when attempting to find
    // the
    // managed object.
    // the managed object.
    private ArgumentException ae;
    // The index of the next path argument to be retrieved.
@@ -103,8 +101,7 @@
    private ConcurrentModificationException cme;
    // Any operation exception that was caught when attempting to find
    // the
    // managed object.
    // the managed object.
    private DefinitionDecodingException dde;
    // Flag indicating whether or not an exception occurred during
@@ -133,6 +130,18 @@
        String childName = args.get(argIndex++);
        try {
          // If the name is null then we must be interactive - so let
          // the user choose.
          if (childName == null) {
            try {
              childName = readChildName(managedObject, r, d);
            } catch (ArgumentException e) {
              ae = e;
              gotException = true;
              return;
            }
          }
          ManagedObject<?> child = managedObject.getChild(r, childName);
          // Check that child is a sub-type of the specified
@@ -377,14 +386,14 @@
    // arguments.
    private ArgumentException e = null;
    // The sub-command.
    private final SubCommand subCommand;
    // Indicates whether the sub-command is a create-xxx
    // sub-command, in which case the final path element will
    // have different usage information.
    private final boolean isCreate;
    // The sub-command.
    private final SubCommand subCommand;
    // The number of path elements to expect.
    private int sz;
@@ -435,17 +444,17 @@
            PropertyDefinitionUsageBuilder b =
              new PropertyDefinitionUsageBuilder(false);
            String usage = "{" + b.getUsage(pd) + "}";
            arg = new StringArgument(argName, null, argName, true, true, usage,
                MSGID_DSCFG_DESCRIPTION_NAME_CREATE_EXT, d
            arg = new StringArgument(argName, null, argName, false, true,
                usage, MSGID_DSCFG_DESCRIPTION_NAME_CREATE_EXT, d
                    .getUserFriendlyName(), pd.getName(), pd.getSynopsis());
          } else {
            arg = new StringArgument(argName, null, argName, true, true,
            arg = new StringArgument(argName, null, argName, false, true,
                "{NAME}", MSGID_DSCFG_DESCRIPTION_NAME_CREATE, d
                    .getUserFriendlyName());
          }
        } else {
          // A normal naming argument.
          arg = new StringArgument(argName, null, argName, true, true,
          arg = new StringArgument(argName, null, argName, false, true,
              "{NAME}", MSGID_DSCFG_DESCRIPTION_NAME, d.getUserFriendlyName());
        }
        subCommand.addArgument(arg);
@@ -534,6 +543,9 @@
  // The argument which should be used to request advanced mode.
  private BooleanArgument advancedModeArgument;
  // The application instance.
  private final ConsoleApplication app;
  // The argument which should be used to specify zero or more
  // property names.
  private StringArgument propertyArgument;
@@ -554,9 +566,12 @@
  /**
   * Create a new sub-command handler.
   *
   * @param app
   *          The application instance.
   */
  protected SubCommandHandler() {
    // No implementation required.
  protected SubCommandHandler(ConsoleApplication app) {
    this.app = app;
  }
@@ -585,12 +600,6 @@
  /**
   * Run this sub-command handler.
   *
   * @param app
   *          The application.
   * @param out
   *          The application output stream.
   * @param err
   *          The application error stream.
   * @return Returns zero if the sub-command completed successfully or
   *         non-zero if it did not.
   * @throws ArgumentException
@@ -599,8 +608,7 @@
   * @throws ClientException
   *           If the management context could not be created.
   */
  public abstract int run(DSConfig app, PrintStream out, PrintStream err)
      throws ArgumentException, ClientException;
  public abstract int run() throws ArgumentException, ClientException;
@@ -685,11 +693,20 @@
  /**
   * Gets the console application instance.
   *
   * @return Returns the console application instance.
   */
  protected final ConsoleApplication getConsoleApplication() {
    return app;
  }
  /**
   * Get the managed object referenced by the provided managed object
   * path.
   *
   * @param context
   *          The management context.
   * @param path
   *          The managed object path.
   * @param args
@@ -718,15 +735,17 @@
   * @throws ArgumentException
   *           If one of the naming arguments referenced a managed
   *           object of the wrong type.
   * @throws ClientException
   *           If the management context could not be created.
   */
  protected final ManagedObject<?> getManagedObject(ManagementContext context,
  protected final ManagedObject<?> getManagedObject(
      ManagedObjectPath<?, ?> path, List<String> args)
      throws ArgumentException, AuthorizationException,
      DefinitionDecodingException, ManagedObjectDecodingException,
      CommunicationException, ConcurrentModificationException,
      ManagedObjectNotFoundException {
      ManagedObjectNotFoundException, ClientException {
    ManagedObjectFinder finder = new ManagedObjectFinder();
    return finder.find(context, path, args);
    return finder.find(app.getManagementContext(), path, args);
  }
@@ -737,12 +756,22 @@
   * @param namingArgs
   *          The naming arguments.
   * @return Returns the values of the naming arguments.
   * @throws ArgumentException
   *           If one of the naming arguments is missing and the
   *           application is non-interactive.
   */
  protected final List<String> getNamingArgValues(
      List<StringArgument> namingArgs) {
      List<StringArgument> namingArgs) throws ArgumentException {
    ArrayList<String> values = new ArrayList<String>(namingArgs.size());
    for (StringArgument arg : namingArgs) {
      values.add(arg.getValue());
      String value = arg.getValue();
      if (value == null && !app.isInteractive()) {
        throw ArgumentExceptionFactory
            .missingMandatoryNonInteractiveArgument(arg);
      } else {
        values.add(value);
      }
    }
    return values;
  }
@@ -854,6 +883,81 @@
  /**
   * Interactively prompts the user to select from a choice of child
   * managed objects.
   * <p>
   * This method will adapt according to the available choice. For
   * example, if there is only one choice, then a question will be
   * asked. If there are no children then an
   * <code>ArgumentException</code> will be thrown.
   *
   * @param <C>
   *          The type of child client configuration.
   * @param <S>
   *          The type of child server configuration.
   * @param parent
   *          The parent managed object.
   * @param r
   *          The relation between the parent and the children.
   * @param d
   *          The type of child managed object to choose from.
   * @return Returns the name of the managed object that the user
   *         selected.
   * @throws CommunicationException
   *           If the server cannot be contacted.
   * @throws ConcurrentModificationException
   *           If the parent managed object has been deleted.
   * @throws AuthorizationException
   *           If the children cannot be listed due to an
   *           authorization failure.
   * @throws ArgumentException
   *           If the user input can be read from the console or if
   *           there are no children.
   */
  protected final <C extends ConfigurationClient, S extends Configuration>
      String readChildName(ManagedObject<?> parent,
      InstantiableRelationDefinition<C, S> r,
      AbstractManagedObjectDefinition<? extends C, ? extends S> d)
      throws AuthorizationException, ConcurrentModificationException,
      CommunicationException, ArgumentException {
    if (d == null) {
      d = r.getChildDefinition();
    }
    String[] children = parent.listChildren(r, d);
    switch (children.length) {
    case 0: {
      // No options available - abort.
      int msgID = MSGID_DSCFG_ERROR_FINDER_NO_CHILDREN;
      String msg = getMessage(msgID, d.getUserFriendlyPluralName());
      throw new ArgumentException(msgID, msg);
    }
    case 1: {
      // Only one option available so confirm that the user wishes to
      // access it.
      int msgID = MSGID_DSCFG_FINDER_PROMPT_SINGLE;
      String msg = getMessage(msgID, d.getUserFriendlyName(), children[0]);
      if (getConsoleApplication().confirmAction(msg)) {
        return children[0];
      } else {
        msgID = MSGID_DSCFG_ERROR_FINDER_SINGLE_CHILD_REJECTED;
        msg = getMessage(msgID, d.getUserFriendlyName());
        throw new ArgumentException(msgID, msg);
      }
    }
    default: {
      // Display a menu.
      List<String> choices = Arrays.asList(children);
      int msgID = MSGID_DSCFG_FINDER_PROMPT_MANY;
      String msg = getMessage(msgID, d.getUserFriendlyName());
      return getConsoleApplication().readChoice(msg, choices, choices, null);
    }
    }
  }
  /**
   * Registers the advanced mode argument with the sub-command.
   *
   * @param subCommand
opends/src/server/org/opends/server/tools/dsconfig/ValidationCallback.java
New file
@@ -0,0 +1,59 @@
/*
 * 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.tools.dsconfig;
import org.opends.server.tools.ClientException;
/**
 * An interface for validating user input.
 *
 * @param <T>
 *          The type of the decoded input.
 */
interface ValidationCallback<T> {
  /**
   * Validates and decodes the user-provided input. Implementations
   * must validate <code>input</code> and return the decoded value
   * if the input is acceptable. If the input is unacceptable,
   * implementations must return <code>null</code> and output a user
   * friendly error message to the provided application console.
   *
   * @param app
   *          The console application.
   * @param input
   *          The user input to be validated.
   * @return Returns the decoded input if the input is valid, or
   *         <code>null</code> if it is not.
   * @throws ClientException
   *           If an unexpected error occurred which prevented
   *           validation.
   */
  T validate(ConsoleApplication app, String input) throws ClientException;
}
opends/src/server/org/opends/server/tools/dsconfig/messages.properties
@@ -1,6 +1,3 @@
general.no=no
general.yes=yes
general.confirm.error=Invalid response. Please enter "%s" or "%s".
help-properties.field.enum=one of the following values:
help-properties.field.undefined=undefined
help-properties.field.inherits.abs=inherits from the property "%s" in the %s.
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgClient.java
@@ -244,7 +244,7 @@
   *          If the name is invalid.
   */
  <C extends TestChildCfgClient> C createTestChild(
      ManagedObjectDefinition<C, ?> d, String name, Collection<DefaultBehaviorException> exceptions) throws IllegalManagedObjectNameException;
      ManagedObjectDefinition<C, ? extends TestChildCfg> d, String name, Collection<DefaultBehaviorException> exceptions) throws IllegalManagedObjectNameException;
@@ -343,7 +343,7 @@
   * @return Returns a new Optional Test Child configuration instance.
   */
  <C extends TestChildCfgClient> C createOptionalTestChild(
      ManagedObjectDefinition<C, ?> d, Collection<DefaultBehaviorException> exceptions);
      ManagedObjectDefinition<C, ? extends TestChildCfg> d, Collection<DefaultBehaviorException> exceptions);
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java
@@ -427,7 +427,7 @@
     * {@inheritDoc}
     */
    public <M extends TestChildCfgClient> M createTestChild(
        ManagedObjectDefinition<M, ?> d, String name, Collection<DefaultBehaviorException> exceptions) throws IllegalManagedObjectNameException {
        ManagedObjectDefinition<M, ? extends TestChildCfg> d, String name, Collection<DefaultBehaviorException> exceptions) throws IllegalManagedObjectNameException {
      return impl.createChild(INSTANCE.getTestChildrenRelationDefinition(), d, name, exceptions).getConfiguration();
    }
@@ -470,7 +470,7 @@
     * {@inheritDoc}
     */
    public <M extends TestChildCfgClient> M createOptionalTestChild(
        ManagedObjectDefinition<M, ?> d, Collection<DefaultBehaviorException> exceptions) {
        ManagedObjectDefinition<M, ? extends TestChildCfg> d, Collection<DefaultBehaviorException> exceptions) {
      return impl.createChild(INSTANCE.getOptionalTestChildRelationDefinition(), d, exceptions).getConfiguration();
    }
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/MockLDAPConnection.java
@@ -209,7 +209,7 @@
   * {@inheritDoc}
   */
  @Override
  public Collection<LdapName> listEntries(LdapName dn) throws NamingException {
  public Collection<LdapName> listEntries(LdapName dn, String filter) throws NamingException {
    MockEntry entry = getEntry(dn);
    if (entry == null) {