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

matthew_swift
13.46.2007 79cb3d38939c48e71eb1d83592f61765d3983cf0
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/MockLDAPProfile.java
@@ -28,23 +28,10 @@
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.opends.server.admin.AbstractManagedObjectDefinition;
import org.opends.server.admin.InstantiableRelationDefinition;
import org.opends.server.admin.LDAPProfile;
import org.opends.server.admin.ManagedObjectDefinition;
import org.opends.server.admin.PropertyDefinition;
import org.opends.server.admin.RelationDefinition;
/**
 * A mock LDAP profile for testing purposes.
 * A mock LDAP profile wrapper for testing purposes.
 */
public final class MockLDAPProfile extends LDAPProfile {
public final class MockLDAPProfile extends LDAPProfile.Wrapper {
  /**
   * Creates a new mock LDAP profile.
@@ -61,7 +48,44 @@
  @Override
  public String getAttributeName(ManagedObjectDefinition<?, ?> d,
      PropertyDefinition<?> pd) {
    return "ds-cfg-" + pd.getName();
    if (d == TestParentCfgDefn.getInstance()) {
      TestParentCfgDefn td = TestParentCfgDefn.getInstance();
      if (pd == td.getMandatoryBooleanPropertyPropertyDefinition()) {
        return "ds-cfg-virtual-attribute-enabled";
      } else if (pd == td.getMandatoryClassPropertyPropertyDefinition()) {
        return "ds-cfg-virtual-attribute-class";
      } else if (pd == td
          .getMandatoryReadOnlyAttributeTypePropertyPropertyDefinition()) {
        return "ds-cfg-virtual-attribute-type";
      } else if (pd == td.getOptionalMultiValuedDNPropertyPropertyDefinition()) {
        return "ds-cfg-virtual-attribute-base-dn";
      } else {
        throw new RuntimeException("Unexpected test-parent property"
            + pd.getName());
      }
    } else if (d == TestChildCfgDefn.getInstance()) {
      TestChildCfgDefn td = TestChildCfgDefn.getInstance();
      if (pd == td.getMandatoryBooleanPropertyPropertyDefinition()) {
        return "ds-cfg-virtual-attribute-enabled";
      } else if (pd == td.getMandatoryClassPropertyPropertyDefinition()) {
        return "ds-cfg-virtual-attribute-class";
      } else if (pd == td
          .getMandatoryReadOnlyAttributeTypePropertyPropertyDefinition()) {
        return "ds-cfg-virtual-attribute-type";
      } else if (pd == td.getOptionalMultiValuedDNProperty1PropertyDefinition()) {
        return "ds-cfg-virtual-attribute-base-dn";
      } else if (pd == td.getOptionalMultiValuedDNProperty2PropertyDefinition()) {
        return "ds-cfg-virtual-attribute-group-dn";
      } else {
        throw new RuntimeException("Unexpected test-child property"
            + pd.getName());
      }
    }
    // Not known.
    return null;
  }
@@ -72,18 +96,13 @@
  @Override
  public String getInstantiableRelationChildRDNType(
      InstantiableRelationDefinition<?, ?> r) {
    return "cn";
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public List<String> getInstantiableRelationObjectClasses(
      InstantiableRelationDefinition<?, ?> r) {
    return Arrays.asList(new String[] { "top", "ds-cfg-branch" });
    if (r == TestCfg.RD_TEST_ONE_TO_MANY_PARENT
        || r == TestParentCfgDefn.getInstance()
            .getTestChildrenRelationDefinition()) {
      return "cn";
    } else {
      return null;
    }
  }
@@ -93,25 +112,14 @@
   */
  @Override
  public String getObjectClass(AbstractManagedObjectDefinition<?, ?> d) {
    return "ds-cfg-" + d.getName();
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public List<String> getObjectClasses(AbstractManagedObjectDefinition<?, ?> d) {
    LinkedList<String> objectClasses = new LinkedList<String>();
    for (AbstractManagedObjectDefinition<?, ?> i = d; i != null; i = i
        .getParent()) {
      objectClasses.addFirst(getObjectClass(i));
    if (d == TestParentCfgDefn.getInstance()) {
      return "ds-cfg-virtual-attribute";
    } else if (d == TestChildCfgDefn.getInstance()) {
      return "ds-cfg-virtual-attribute";
    } else {
      // Not known.
      return null;
    }
    // Make sure that we have top.
    objectClasses.addFirst("top");
    return objectClasses;
  }
@@ -121,11 +129,18 @@
   */
  @Override
  public String getRelationRDNSequence(RelationDefinition<?, ?> r) {
    if (r instanceof InstantiableRelationDefinition) {
      InstantiableRelationDefinition<?, ?> i = (InstantiableRelationDefinition<?, ?>) r;
      return "cn=" + i.getPluralName();
    if (r == TestCfg.RD_TEST_ONE_TO_MANY_PARENT) {
      return "cn=test parents,cn=config";
    } else if (r == TestCfg.RD_TEST_ONE_TO_ZERO_OR_ONE_PARENT) {
      return "cn=optional test parent,cn=config";
    } else if (r == TestParentCfgDefn.getInstance()
        .getTestChildrenRelationDefinition()) {
      return "cn=test children";
    } else if (r == TestParentCfgDefn.getInstance()
        .getOptionalTestChildRelationDefinition()) {
      return "cn=optional test child";
    } else {
      return "cn=" + r.getName();
      return null;
    }
  }
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProviderTest.java
@@ -46,7 +46,7 @@
  private static final TestParentCfgDefn d;
  private RelativeInheritedDefaultBehaviorProvider<Integer> ridbp = null;
  private RelativeInheritedDefaultBehaviorProvider<Boolean> ridbp = null;
  static
  {
@@ -63,8 +63,8 @@
   */
  @BeforeClass
  public void setUp() {
    this.ridbp = new RelativeInheritedDefaultBehaviorProvider<Integer>(d, d
        .getMaximumLengthPropertyDefinition().getName(), OFFSET);
    this.ridbp = new RelativeInheritedDefaultBehaviorProvider<Boolean>(d, d
        .getMandatoryBooleanPropertyPropertyDefinition().getName(), OFFSET);
  }
@@ -74,7 +74,7 @@
   */
  @Test
  public void testAccept() {
    ridbp.accept(new DefaultBehaviorProviderVisitor<Integer, Object, Object>() {
    ridbp.accept(new DefaultBehaviorProviderVisitor<Boolean, Object, Object>() {
      public Object visitAbsoluteInherited(
          AbsoluteInheritedDefaultBehaviorProvider d, Object o) {
@@ -127,7 +127,7 @@
  @Test
  public void testGetPropertyDefinition() {
    assertEquals(ridbp.getPropertyName(), d
        .getMaximumLengthPropertyDefinition().getName());
        .getMandatoryBooleanPropertyPropertyDefinition().getName());
  }
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestCfg.java
New file
@@ -0,0 +1,75 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.server.admin;
import org.opends.server.admin.std.meta.RootCfgDefn;
/**
 * Common methods for hooking in the test components.
 */
public final class TestCfg {
  // Prevent instantiation.
  private TestCfg() {
    // No implementation required.
  }
  /**
   * A one-to-many relation between the root and test-parent
   * components.
   */
  public static final InstantiableRelationDefinition<TestParentCfgClient, TestParentCfg> RD_TEST_ONE_TO_MANY_PARENT;
  /**
   * A one-to-zero-or-one relation between the root and a test-parent
   * component.
   */
  public static final OptionalRelationDefinition<TestParentCfgClient, TestParentCfg> RD_TEST_ONE_TO_ZERO_OR_ONE_PARENT;
  // Create a one-to-many relation for test-parent components.
  static {
    RD_TEST_ONE_TO_MANY_PARENT = new InstantiableRelationDefinition<TestParentCfgClient, TestParentCfg>(
        RootCfgDefn.getInstance(), "test-one-to-many-parent",
        "test-one-to-many-parents", TestParentCfgDefn.getInstance());
    RootCfgDefn.getInstance().registerRelationDefinition(
        RD_TEST_ONE_TO_MANY_PARENT);
  }
  // Create a one-to-many relation for test-parent components.
  static {
    RD_TEST_ONE_TO_ZERO_OR_ONE_PARENT = new OptionalRelationDefinition<TestParentCfgClient, TestParentCfg>(
        RootCfgDefn.getInstance(), "test-one-to-zero-or-one-parent",
        TestParentCfgDefn.getInstance());
    RootCfgDefn.getInstance().registerRelationDefinition(
        RD_TEST_ONE_TO_ZERO_OR_ONE_PARENT);
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfg.java
@@ -28,45 +28,106 @@
import java.util.SortedSet;
import org.opends.server.admin.Configuration;
import org.opends.server.admin.ManagedObjectDefinition;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
/**
 * A sample server-side configuration interface for testing.
 * A server-side interface for querying Test Child settings.
 * <p>
 * A configuration for testing components that are subordinate to a
 * parent component. It re-uses the virtual-attribute configuration
 * LDAP profile.
 */
public interface TestChildCfg extends Configuration {
  /**
   * {@inheritDoc}
   * Get the configuration definition associated with this Test Child.
   *
   * @return Returns the configuration definition associated with this Test Child.
   */
  ManagedObjectDefinition<? extends TestChildCfgClient, ? extends TestChildCfg> definition();
  /**
   * Get the "heartbeat-interval" property.
   * Register to be notified when this Test Child is changed.
   *
   * @return Returns the value of the "heartbeat-interval" property.
   * @param listener
   *          The Test Child configuration change listener.
   */
  long getHeartbeatInterval();
  void addChangeListener(ConfigurationChangeListener<TestChildCfg> listener);
  /**
   * Get the "maximum-length" property.
   * Deregister an existing Test Child configuration change listener.
   *
   * @return Returns the value of the "maximum-length" property.
   * @param listener
   *          The Test Child configuration change listener.
   */
  int getMaximumLength();
  void removeChangeListener(ConfigurationChangeListener<TestChildCfg> listener);
  /**
   * Get the "minimum-length" property.
   * Get the "mandatory-boolean-property" property.
   * <p>
   * A mandatory boolean property.
   *
   * @return Returns the value of the "minimum-length" property.
   * @return Returns the value of the "mandatory-boolean-property" property.
   */
  int getMinimumLength();
  boolean isMandatoryBooleanProperty();
  /**
   * Get the "mandatory-class-property" property.
   * <p>
   * A mandatory Java-class property requiring a component restart.
   *
   * @return Returns the value of the "mandatory-class-property" property.
   */
  String getMandatoryClassProperty();
  /**
   * Get the "mandatory-read-only-attribute-type-property" property.
   * <p>
   * A mandatory read-only attribute type property.
   *
   * @return Returns the value of the "mandatory-read-only-attribute-type-property" property.
   */
  AttributeType getMandatoryReadOnlyAttributeTypeProperty();
  /**
   * Get the "optional-multi-valued-dn-property1" property.
   * <p>
   * An optional multi-valued DN property which inherits its values
   * from optional-multi-valued-dn-property in the parent.
   *
   * @return Returns the values of the "optional-multi-valued-dn-property1" property.
   */
  SortedSet<DN> getOptionalMultiValuedDNProperty1();
  /**
   * Get the "optional-multi-valued-dn-property2" property.
   * <p>
   * An optional multi-valued DN property which inherits its values
   * from optional-multi-valued-dn-property1.
   *
   * @return Returns the values of the "optional-multi-valued-dn-property2" property.
   */
  SortedSet<DN> getOptionalMultiValuedDNProperty2();
}
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgClient.java
@@ -28,81 +28,161 @@
import java.util.Collection;
import java.util.SortedSet;
import org.opends.server.admin.ConfigurationClient;
import org.opends.server.admin.IllegalPropertyValueException;
import org.opends.server.admin.ManagedObjectDefinition;
import org.opends.server.admin.PropertyIsReadOnlyException;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
/**
 * A sample client-side configuration interface for testing.
 * A client-side interface for reading and modifying Test Child
 * settings.
 * <p>
 * A configuration for testing components that are subordinate to a
 * parent component. It re-uses the virtual-attribute configuration
 * LDAP profile.
 */
public interface TestChildCfgClient extends ConfigurationClient {
  /**
   * {@inheritDoc}
   * Get the configuration definition associated with this Test Child.
   *
   * @return Returns the configuration definition associated with this Test Child.
   */
  ManagedObjectDefinition<? extends TestChildCfgClient, ? extends TestChildCfg> definition();
  /**
   * Get the "heartbeat-interval" property.
   * Get the "mandatory-boolean-property" property.
   * <p>
   * A mandatory boolean property.
   *
   * @return Returns the value of the "heartbeat-interval" property.
   * @return Returns the value of the "mandatory-boolean-property" property.
   */
  long getHeartbeatInterval();
  Boolean isMandatoryBooleanProperty();
  /**
   * Set the "heartbeat-interval" property.
   * Set the "mandatory-boolean-property" property.
   * <p>
   * A mandatory boolean property.
   *
   * @param value
   *          The value of the "heartbeat-interval" property.
   * @param value The value of the "mandatory-boolean-property" property.
   * @throws IllegalPropertyValueException
   *           If the new value is invalid.
   */
  void setHeartbeatInterval(Long value) throws IllegalPropertyValueException;
  void setMandatoryBooleanProperty(boolean value) throws IllegalPropertyValueException;
  /**
   * Get the "maximum-length" property.
   * Get the "mandatory-class-property" property.
   * <p>
   * A mandatory Java-class property requiring a component restart.
   *
   * @return Returns the value of the "maximum-length" property.
   * @return Returns the value of the "mandatory-class-property" property.
   */
  int getMaximumLength();
  String getMandatoryClassProperty();
  /**
   * Set the "maximum-length" property.
   * Set the "mandatory-class-property" property.
   * <p>
   * A mandatory Java-class property requiring a component restart.
   *
   * @param value
   *          The value of the "maximum-length" property.
   * @param value The value of the "mandatory-class-property" property.
   * @throws IllegalPropertyValueException
   *           If the new value is invalid.
   */
  void setMaximumLength(Integer value) throws IllegalPropertyValueException;
  void setMandatoryClassProperty(String value) throws IllegalPropertyValueException;
  /**
   * Get the "minimum-length" property.
   * Get the "mandatory-read-only-attribute-type-property" property.
   * <p>
   * A mandatory read-only attribute type property.
   *
   * @return Returns the value of the "minimum-length" property.
   * @return Returns the value of the "mandatory-read-only-attribute-type-property" property.
   */
  int getMinimumLength();
  AttributeType getMandatoryReadOnlyAttributeTypeProperty();
  /**
   * Set the "minimum-length" property.
   * Set the "mandatory-read-only-attribute-type-property" property.
   * <p>
   * A mandatory read-only attribute type property.
   * <p>
   * This property is read-only and can only be modified during
   * creation of a Test Child.
   *
   * @param value
   *          The value of the "minimum-length" property.
   * @param value The value of the "mandatory-read-only-attribute-type-property" property.
   * @throws IllegalPropertyValueException
   *           If the new value is invalid.
   * @throws PropertyIsReadOnlyException
   *           If this Test Child is not being initialized.
   */
  void setMinimumLength(Integer value) throws IllegalPropertyValueException;
  void setMandatoryReadOnlyAttributeTypeProperty(AttributeType value) throws IllegalPropertyValueException, PropertyIsReadOnlyException;
  /**
   * Get the "optional-multi-valued-dn-property1" property.
   * <p>
   * An optional multi-valued DN property which inherits its values
   * from optional-multi-valued-dn-property in the parent.
   *
   * @return Returns the values of the "optional-multi-valued-dn-property1" property.
   */
  SortedSet<DN> getOptionalMultiValuedDNProperty1();
  /**
   * Set the "optional-multi-valued-dn-property1" property.
   * <p>
   * An optional multi-valued DN property which inherits its values
   * from optional-multi-valued-dn-property in the parent.
   *
   * @param values The values of the "optional-multi-valued-dn-property1" property.
   * @throws IllegalPropertyValueException
   *           If one or more of the new values are invalid.
   */
  void setOptionalMultiValuedDNProperty1(Collection<DN> values) throws IllegalPropertyValueException;
  /**
   * Get the "optional-multi-valued-dn-property2" property.
   * <p>
   * An optional multi-valued DN property which inherits its values
   * from optional-multi-valued-dn-property1.
   *
   * @return Returns the values of the "optional-multi-valued-dn-property2" property.
   */
  SortedSet<DN> getOptionalMultiValuedDNProperty2();
  /**
   * Set the "optional-multi-valued-dn-property2" property.
   * <p>
   * An optional multi-valued DN property which inherits its values
   * from optional-multi-valued-dn-property1.
   *
   * @param values The values of the "optional-multi-valued-dn-property2" property.
   * @throws IllegalPropertyValueException
   *           If one or more of the new values are invalid.
   */
  void setOptionalMultiValuedDNProperty2(Collection<DN> values) throws IllegalPropertyValueException;
}
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java
@@ -28,80 +28,145 @@
import java.util.Collection;
import java.util.SortedSet;
import org.opends.server.admin.AdministratorAction;
import org.opends.server.admin.AttributeTypePropertyDefinition;
import org.opends.server.admin.BooleanPropertyDefinition;
import org.opends.server.admin.ClassPropertyDefinition;
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ConcurrentModificationException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.MissingMandatoryPropertiesException;
import org.opends.server.admin.client.OperationRejectedException;
import org.opends.server.admin.DefaultBehaviorProvider;
import org.opends.server.admin.DefinedDefaultBehaviorProvider;
import org.opends.server.admin.DNPropertyDefinition;
import org.opends.server.admin.ManagedObjectAlreadyExistsException;
import org.opends.server.admin.ManagedObjectDefinition;
import org.opends.server.admin.PropertyIsReadOnlyException;
import org.opends.server.admin.PropertyOption;
import org.opends.server.admin.PropertyProvider;
import org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.server.ServerManagedObject;
import org.opends.server.admin.UndefinedDefaultBehaviorProvider;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
/**
 * A sample configuration definition class for testing.
 * An interface for querying the Test Child managed object definition
 * meta information.
 * <p>
 * A configuration for testing components that are subordinate to a
 * parent component. It re-uses the virtual-attribute configuration
 * LDAP profile.
 */
public final class TestChildCfgDefn extends
    ManagedObjectDefinition<TestChildCfgClient, TestChildCfg> {
public final class TestChildCfgDefn extends ManagedObjectDefinition<TestChildCfgClient, TestChildCfg> {
  // The singleton configuration definition instance.
  private static final TestChildCfgDefn INSTANCE = new TestChildCfgDefn();
  // The "maximum-length" property definition.
  private static final IntegerPropertyDefinition PD_MAXIMUM_LENGTH;
  // The "minimum-length" property definition.
  private static final IntegerPropertyDefinition PD_MINIMUM_LENGTH;
  // The "heartbeat-interval" property definition.
  private static final DurationPropertyDefinition PD_HEARTBEAT_INTERVAL;
  // The "mandatory-boolean-property" property definition.
  private static final BooleanPropertyDefinition PD_MANDATORY_BOOLEAN_PROPERTY;
  // Build the "maximum-length" property definition.
  // The "mandatory-class-property" property definition.
  private static final ClassPropertyDefinition PD_MANDATORY_CLASS_PROPERTY;
  // The "mandatory-read-only-attribute-type-property" property definition.
  private static final AttributeTypePropertyDefinition PD_MANDATORY_READ_ONLY_ATTRIBUTE_TYPE_PROPERTY;
  // The "optional-multi-valued-dn-property1" property definition.
  private static final DNPropertyDefinition PD_OPTIONAL_MULTI_VALUED_DN_PROPERTY1;
  // The "optional-multi-valued-dn-property2" property definition.
  private static final DNPropertyDefinition PD_OPTIONAL_MULTI_VALUED_DN_PROPERTY2;
  // Build the "mandatory-boolean-property" property definition.
  static {
    IntegerPropertyDefinition.Builder builder = IntegerPropertyDefinition
        .createBuilder(INSTANCE, "maximum-length");
    DefaultBehaviorProvider<Integer> provider = new RelativeInheritedDefaultBehaviorProvider<Integer>(
        TestParentCfgDefn.getInstance(), "maximum-length", 1);
    builder.setDefaultBehaviorProvider(provider);
    builder.setLowerLimit(0);
    PD_MAXIMUM_LENGTH = builder.getInstance();
    INSTANCE.registerPropertyDefinition(PD_MAXIMUM_LENGTH);
      BooleanPropertyDefinition.Builder builder = BooleanPropertyDefinition.createBuilder(INSTANCE, "mandatory-boolean-property");
      builder.setOption(PropertyOption.MANDATORY);
      builder.setAdministratorAction(new AdministratorAction(AdministratorAction.Type.NONE, INSTANCE, "mandatory-boolean-property"));
      builder.setDefaultBehaviorProvider(new UndefinedDefaultBehaviorProvider<Boolean>());
      PD_MANDATORY_BOOLEAN_PROPERTY = builder.getInstance();
      INSTANCE.registerPropertyDefinition(PD_MANDATORY_BOOLEAN_PROPERTY);
  }
  // Build the "minimum-length" property definition.
  // Build the "mandatory-class-property" property definition.
  static {
    IntegerPropertyDefinition.Builder builder = IntegerPropertyDefinition
        .createBuilder(INSTANCE, "minimum-length");
    DefaultBehaviorProvider<Integer> provider = new AbsoluteInheritedDefaultBehaviorProvider<Integer>(
        ManagedObjectPath.valueOf("/relation=test-parent+name=test parent 2"),
        "minimum-length");
    builder.setDefaultBehaviorProvider(provider);
    builder.setLowerLimit(0);
    PD_MINIMUM_LENGTH = builder.getInstance();
    INSTANCE.registerPropertyDefinition(PD_MINIMUM_LENGTH);
      ClassPropertyDefinition.Builder builder = ClassPropertyDefinition.createBuilder(INSTANCE, "mandatory-class-property");
      builder.setOption(PropertyOption.MANDATORY);
      builder.setAdministratorAction(new AdministratorAction(AdministratorAction.Type.COMPONENT_RESTART, INSTANCE, "mandatory-class-property"));
      DefaultBehaviorProvider<String> provider = new DefinedDefaultBehaviorProvider<String>("org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
      builder.setDefaultBehaviorProvider(provider);
      builder.addInstanceOf("org.opends.server.api.VirtualAttributeProvider");
      PD_MANDATORY_CLASS_PROPERTY = builder.getInstance();
      INSTANCE.registerPropertyDefinition(PD_MANDATORY_CLASS_PROPERTY);
  }
  // Build the "heartbeat-interval" property definition.
  // Build the "mandatory-read-only-attribute-type-property" property definition.
  static {
    DurationPropertyDefinition.Builder builder = DurationPropertyDefinition
        .createBuilder(INSTANCE, "heartbeat-interval");
    DefaultBehaviorProvider<Long> provider = new DefinedDefaultBehaviorProvider<Long>(
        "1000ms");
    builder.setDefaultBehaviorProvider(provider);
    builder.setAllowUnlimited(false);
    builder.setBaseUnit("ms");
    builder.setLowerLimit("100");
    PD_HEARTBEAT_INTERVAL = builder.getInstance();
    INSTANCE.registerPropertyDefinition(PD_HEARTBEAT_INTERVAL);
      AttributeTypePropertyDefinition.Builder builder = AttributeTypePropertyDefinition.createBuilder(INSTANCE, "mandatory-read-only-attribute-type-property");
      builder.setOption(PropertyOption.READ_ONLY);
      builder.setOption(PropertyOption.MANDATORY);
      builder.setAdministratorAction(new AdministratorAction(AdministratorAction.Type.NONE, INSTANCE, "mandatory-read-only-attribute-type-property"));
      builder.setDefaultBehaviorProvider(new UndefinedDefaultBehaviorProvider<AttributeType>());
      PD_MANDATORY_READ_ONLY_ATTRIBUTE_TYPE_PROPERTY = builder.getInstance();
      INSTANCE.registerPropertyDefinition(PD_MANDATORY_READ_ONLY_ATTRIBUTE_TYPE_PROPERTY);
  }
  // Build the "optional-multi-valued-dn-property1" property definition.
  static {
      DNPropertyDefinition.Builder builder = DNPropertyDefinition.createBuilder(INSTANCE, "optional-multi-valued-dn-property1");
      builder.setOption(PropertyOption.MULTI_VALUED);
      builder.setAdministratorAction(new AdministratorAction(AdministratorAction.Type.NONE, INSTANCE, "optional-multi-valued-dn-property1"));
      DefaultBehaviorProvider<DN> provider = new RelativeInheritedDefaultBehaviorProvider<DN>(TestParentCfgDefn.getInstance(), "optional-multi-valued-dn-property", 1);
      builder.setDefaultBehaviorProvider(provider);
      PD_OPTIONAL_MULTI_VALUED_DN_PROPERTY1 = builder.getInstance();
      INSTANCE.registerPropertyDefinition(PD_OPTIONAL_MULTI_VALUED_DN_PROPERTY1);
  }
  // Build the "optional-multi-valued-dn-property2" property definition.
  static {
      DNPropertyDefinition.Builder builder = DNPropertyDefinition.createBuilder(INSTANCE, "optional-multi-valued-dn-property2");
      builder.setOption(PropertyOption.MULTI_VALUED);
      builder.setAdministratorAction(new AdministratorAction(AdministratorAction.Type.NONE, INSTANCE, "optional-multi-valued-dn-property2"));
      DefaultBehaviorProvider<DN> provider = new RelativeInheritedDefaultBehaviorProvider<DN>(TestChildCfgDefn.getInstance(), "optional-multi-valued-dn-property1", 0);
      builder.setDefaultBehaviorProvider(provider);
      PD_OPTIONAL_MULTI_VALUED_DN_PROPERTY2 = builder.getInstance();
      INSTANCE.registerPropertyDefinition(PD_OPTIONAL_MULTI_VALUED_DN_PROPERTY2);
  }
  /**
   * Get the definition singleton.
   * Get the Test Child configuration definition singleton.
   *
   * @return Returns the definition singleton.
   * @return Returns the Test Child configuration definition
   *         singleton.
   */
  public static TestChildCfgDefn getInstance() {
    return INSTANCE;
@@ -148,34 +213,68 @@
  /**
   * Get the "heartbeat-interval" property definition.
   * Get the "mandatory-boolean-property" property definition.
   * <p>
   * A mandatory boolean property.
   *
   * @return Returns the "heartbeat-interval" property definition.
   * @return Returns the "mandatory-boolean-property" property definition.
   */
  public DurationPropertyDefinition getHeartbeatIntervalPropertyDefinition() {
    return PD_HEARTBEAT_INTERVAL;
  public BooleanPropertyDefinition getMandatoryBooleanPropertyPropertyDefinition() {
    return PD_MANDATORY_BOOLEAN_PROPERTY;
  }
  /**
   * Get the "maximum-length" property definition.
   * Get the "mandatory-class-property" property definition.
   * <p>
   * A mandatory Java-class property requiring a component restart.
   *
   * @return Returns the "maximum-length" property definition.
   * @return Returns the "mandatory-class-property" property definition.
   */
  public IntegerPropertyDefinition getMaximumLengthPropertyDefinition() {
    return PD_MAXIMUM_LENGTH;
  public ClassPropertyDefinition getMandatoryClassPropertyPropertyDefinition() {
    return PD_MANDATORY_CLASS_PROPERTY;
  }
  /**
   * Get the "minimum-length" property definition.
   * Get the "mandatory-read-only-attribute-type-property" property definition.
   * <p>
   * A mandatory read-only attribute type property.
   *
   * @return Returns the "minimum-length" property definition.
   * @return Returns the "mandatory-read-only-attribute-type-property" property definition.
   */
  public IntegerPropertyDefinition getMinimumLengthPropertyDefinition() {
    return PD_MINIMUM_LENGTH;
  public AttributeTypePropertyDefinition getMandatoryReadOnlyAttributeTypePropertyPropertyDefinition() {
    return PD_MANDATORY_READ_ONLY_ATTRIBUTE_TYPE_PROPERTY;
  }
  /**
   * Get the "optional-multi-valued-dn-property1" property definition.
   * <p>
   * An optional multi-valued DN property which inherits its values
   * from optional-multi-valued-dn-property in the parent.
   *
   * @return Returns the "optional-multi-valued-dn-property1" property definition.
   */
  public DNPropertyDefinition getOptionalMultiValuedDNProperty1PropertyDefinition() {
    return PD_OPTIONAL_MULTI_VALUED_DN_PROPERTY1;
  }
  /**
   * Get the "optional-multi-valued-dn-property2" property definition.
   * <p>
   * An optional multi-valued DN property which inherits its values
   * from optional-multi-valued-dn-property1.
   *
   * @return Returns the "optional-multi-valued-dn-property2" property definition.
   */
  public DNPropertyDefinition getOptionalMultiValuedDNProperty2PropertyDefinition() {
    return PD_OPTIONAL_MULTI_VALUED_DN_PROPERTY2;
  }
@@ -183,7 +282,8 @@
  /**
   * Managed object client implementation.
   */
  private static class TestChildCfgClientImpl implements TestChildCfgClient {
  private static class TestChildCfgClientImpl implements
    TestChildCfgClient {
    // Private implementation.
    private ManagedObject<? extends TestChildCfgClient> impl;
@@ -201,9 +301,8 @@
    /**
     * {@inheritDoc}
     */
    public long getHeartbeatInterval() {
      return impl.getPropertyValue(INSTANCE
          .getHeartbeatIntervalPropertyDefinition());
    public Boolean isMandatoryBooleanProperty() {
      return impl.getPropertyValue(INSTANCE.getMandatoryBooleanPropertyPropertyDefinition());
    }
@@ -211,9 +310,8 @@
    /**
     * {@inheritDoc}
     */
    public void setHeartbeatInterval(Long value) {
      impl.setPropertyValue(INSTANCE.getHeartbeatIntervalPropertyDefinition(),
          value);
    public void setMandatoryBooleanProperty(boolean value) {
      impl.setPropertyValue(INSTANCE.getMandatoryBooleanPropertyPropertyDefinition(), value);
    }
@@ -221,9 +319,8 @@
    /**
     * {@inheritDoc}
     */
    public int getMaximumLength() {
      return impl.getPropertyValue(INSTANCE
          .getMaximumLengthPropertyDefinition());
    public String getMandatoryClassProperty() {
      return impl.getPropertyValue(INSTANCE.getMandatoryClassPropertyPropertyDefinition());
    }
@@ -231,9 +328,8 @@
    /**
     * {@inheritDoc}
     */
    public void setMaximumLength(Integer value) {
      impl.setPropertyValue(INSTANCE.getMaximumLengthPropertyDefinition(),
          value);
    public void setMandatoryClassProperty(String value) {
      impl.setPropertyValue(INSTANCE.getMandatoryClassPropertyPropertyDefinition(), value);
    }
@@ -241,9 +337,8 @@
    /**
     * {@inheritDoc}
     */
    public int getMinimumLength() {
      return impl.getPropertyValue(INSTANCE
          .getMinimumLengthPropertyDefinition());
    public AttributeType getMandatoryReadOnlyAttributeTypeProperty() {
      return impl.getPropertyValue(INSTANCE.getMandatoryReadOnlyAttributeTypePropertyPropertyDefinition());
    }
@@ -251,9 +346,44 @@
    /**
     * {@inheritDoc}
     */
    public void setMinimumLength(Integer value) {
      impl.setPropertyValue(INSTANCE.getMinimumLengthPropertyDefinition(),
          value);
    public void setMandatoryReadOnlyAttributeTypeProperty(AttributeType value) throws PropertyIsReadOnlyException {
      impl.setPropertyValue(INSTANCE.getMandatoryReadOnlyAttributeTypePropertyPropertyDefinition(), value);
    }
    /**
     * {@inheritDoc}
     */
    public SortedSet<DN> getOptionalMultiValuedDNProperty1() {
      return impl.getPropertyValues(INSTANCE.getOptionalMultiValuedDNProperty1PropertyDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public void setOptionalMultiValuedDNProperty1(Collection<DN> values) {
      impl.setPropertyValues(INSTANCE.getOptionalMultiValuedDNProperty1PropertyDefinition(), values);
    }
    /**
     * {@inheritDoc}
     */
    public SortedSet<DN> getOptionalMultiValuedDNProperty2() {
      return impl.getPropertyValues(INSTANCE.getOptionalMultiValuedDNProperty2PropertyDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public void setOptionalMultiValuedDNProperty2(Collection<DN> values) {
      impl.setPropertyValues(INSTANCE.getOptionalMultiValuedDNProperty2PropertyDefinition(), values);
    }
@@ -279,12 +409,13 @@
    /**
     * {@inheritDoc}
     */
    public void commit() throws ConcurrentModificationException,
    public void commit() throws ManagedObjectAlreadyExistsException,
        MissingMandatoryPropertiesException, ConcurrentModificationException,
        OperationRejectedException, AuthorizationException,
        CommunicationException, ManagedObjectAlreadyExistsException,
        MissingMandatoryPropertiesException {
        CommunicationException {
      impl.commit();
    }
  }
@@ -292,7 +423,8 @@
  /**
   * Managed object server implementation.
   */
  private static class TestChildCfgServerImpl implements TestChildCfg {
  private static class TestChildCfgServerImpl implements
    TestChildCfg {
    // Private implementation.
    private ServerManagedObject<? extends TestChildCfg> impl;
@@ -300,8 +432,7 @@
    // Private constructor.
    private TestChildCfgServerImpl(
        ServerManagedObject<? extends TestChildCfg> impl) {
    private TestChildCfgServerImpl(ServerManagedObject<? extends TestChildCfg> impl) {
      this.impl = impl;
    }
@@ -310,9 +441,9 @@
    /**
     * {@inheritDoc}
     */
    public long getHeartbeatInterval() {
      return impl.getPropertyValue(INSTANCE
          .getHeartbeatIntervalPropertyDefinition());
    public void addChangeListener(
        ConfigurationChangeListener<TestChildCfg> listener) {
      impl.registerChangeListener(listener);
    }
@@ -320,9 +451,9 @@
    /**
     * {@inheritDoc}
     */
    public int getMaximumLength() {
      return impl.getPropertyValue(INSTANCE
          .getMaximumLengthPropertyDefinition());
    public void removeChangeListener(
        ConfigurationChangeListener<TestChildCfg> listener) {
      impl.deregisterChangeListener(listener);
    }
@@ -330,9 +461,44 @@
    /**
     * {@inheritDoc}
     */
    public int getMinimumLength() {
      return impl.getPropertyValue(INSTANCE
          .getMinimumLengthPropertyDefinition());
    public boolean isMandatoryBooleanProperty() {
      return impl.getPropertyValue(INSTANCE.getMandatoryBooleanPropertyPropertyDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public String getMandatoryClassProperty() {
      return impl.getPropertyValue(INSTANCE.getMandatoryClassPropertyPropertyDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public AttributeType getMandatoryReadOnlyAttributeTypeProperty() {
      return impl.getPropertyValue(INSTANCE.getMandatoryReadOnlyAttributeTypePropertyPropertyDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public SortedSet<DN> getOptionalMultiValuedDNProperty1() {
      return impl.getPropertyValues(INSTANCE.getOptionalMultiValuedDNProperty1PropertyDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public SortedSet<DN> getOptionalMultiValuedDNProperty2() {
      return impl.getPropertyValues(INSTANCE.getOptionalMultiValuedDNProperty2PropertyDefinition());
    }
@@ -361,6 +527,6 @@
    public DN dn() {
      return impl.getDN();
    }
  }
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildConfiguration.xml
New file
@@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
  ! 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.
  ! -->
<adm:managed-object name="test-child" plural-name="test-children"
  package="org.opends.server.admin.std"
  xmlns:adm="http://www.opends.org/admin"
  xmlns:ldap="http://www.opends.org/admin-ldap">
  <adm:synopsis>
    A configuration for testing components that are subordinate to a
    parent component. It re-uses the virtual-attribute configuration
    LDAP profile.
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.91</ldap:oid>
      <ldap:name>ds-cfg-virtual-attribute</ldap:name>
      <ldap:superior>top</ldap:superior>
    </ldap:object-class>
  </adm:profile>
  <adm:property name="mandatory-boolean-property" mandatory="true">
    <adm:synopsis>A mandatory boolean property.</adm:synopsis>
    <adm:syntax>
      <adm:boolean />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.326</ldap:oid>
        <ldap:name>ds-cfg-virtual-attribute-enabled</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="mandatory-class-property" mandatory="true">
    <adm:synopsis>
      A mandatory Java-class property requiring a component restart.
    </adm:synopsis>
    <adm:requires-admin-action>
      <adm:component-restart />
    </adm:requires-admin-action>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          org.opends.server.extensions.UserDefinedVirtualAttributeProvider
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:java-class>
        <adm:instance-of>
          org.opends.server.api.VirtualAttributeProvider
        </adm:instance-of>
      </adm:java-class>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.325</ldap:oid>
        <ldap:name>ds-cfg-virtual-attribute-class</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="mandatory-read-only-attribute-type-property"
    mandatory="true" read-only="true">
    <adm:synopsis>
      A mandatory read-only attribute type property.
    </adm:synopsis>
    <adm:syntax>
      <adm:attribute-type />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.327</ldap:oid>
        <ldap:name>ds-cfg-virtual-attribute-type</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="optional-multi-valued-dn-property1"
    multi-valued="true">
    <adm:synopsis>
      An optional multi-valued DN property which inherits its values
      from optional-multi-valued-dn-property in the parent.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:inherited>
        <adm:relative property-name="optional-multi-valued-dn-property"
          offset="1" managed-object-name="test-parent" />
      </adm:inherited>
    </adm:default-behavior>
    <adm:syntax>
      <adm:dn />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.328</ldap:oid>
        <ldap:name>ds-cfg-virtual-attribute-base-dn</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="optional-multi-valued-dn-property2"
    multi-valued="true">
    <adm:synopsis>
      An optional multi-valued DN property which inherits its values
      from optional-multi-valued-dn-property1.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:inherited>
        <adm:relative property-name="optional-multi-valued-dn-property1"
          offset="0" managed-object-name="test-child" />
      </adm:inherited>
    </adm:default-behavior>
    <adm:syntax>
      <adm:dn />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.329</ldap:oid>
        <ldap:name>ds-cfg-virtual-attribute-group-dn</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfg.java
@@ -28,34 +28,229 @@
import java.util.SortedSet;
import org.opends.server.admin.Configuration;
import org.opends.server.admin.ManagedObjectDefinition;
import org.opends.server.admin.server.ConfigurationAddListener;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.server.ConfigurationDeleteListener;
import org.opends.server.config.ConfigException;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
/**
 * A sample server-side configuration interface for testing.
 * A server-side interface for querying Test Parent settings.
 * <p>
 * A configuration for testing components that have child components.
 * It re-uses the virtual-attribute configuration LDAP profile.
 */
public interface TestParentCfg extends Configuration {
  /**
   * {@inheritDoc}
   * Get the configuration definition associated with this Test Parent.
   *
   * @return Returns the configuration definition associated with this Test Parent.
   */
  ManagedObjectDefinition<? extends TestParentCfgClient, ? extends TestParentCfg> definition();
  /**
   * Get the "maximum-length" property.
   * Register to be notified when this Test Parent is changed.
   *
   * @return Returns the value of the "maximum-length" property.
   * @param listener
   *          The Test Parent configuration change listener.
   */
  int getMaximumLength();
  void addChangeListener(ConfigurationChangeListener<TestParentCfg> listener);
  /**
   * Get the "minimum-length" property.
   * Deregister an existing Test Parent configuration change listener.
   *
   * @return Returns the value of the "minimum-length" property.
   * @param listener
   *          The Test Parent configuration change listener.
   */
  int getMinimumLength();
  void removeChangeListener(ConfigurationChangeListener<TestParentCfg> listener);
  /**
   * Get the "mandatory-boolean-property" property.
   * <p>
   * A mandatory boolean property.
   *
   * @return Returns the value of the "mandatory-boolean-property" property.
   */
  boolean isMandatoryBooleanProperty();
  /**
   * Get the "mandatory-class-property" property.
   * <p>
   * A mandatory Java-class property requiring a component restart.
   *
   * @return Returns the value of the "mandatory-class-property" property.
   */
  String getMandatoryClassProperty();
  /**
   * Get the "mandatory-read-only-attribute-type-property" property.
   * <p>
   * A mandatory read-only attribute type property.
   *
   * @return Returns the value of the "mandatory-read-only-attribute-type-property" property.
   */
  AttributeType getMandatoryReadOnlyAttributeTypeProperty();
  /**
   * Get the "optional-multi-valued-dn-property" property.
   * <p>
   * An optional multi-valued DN property with a defined default
   * behavior.
   *
   * @return Returns the values of the "optional-multi-valued-dn-property" property.
   */
  SortedSet<DN> getOptionalMultiValuedDNProperty();
  /**
   * Lists the Test Children.
   *
   * @return Returns an array containing the names of the
   *         Test Children.
   */
  String[] listTestChildren();
  /**
   * Gets the named Test Child.
   *
   * @param name
   *          The name of the Test Child to retrieve.
   * @return Returns the named Test Child.
   * @throws ConfigException
   *           If the Test Child could not be found or it
   *           could not be successfully decoded.
   */
  TestChildCfg getTestChild(String name) throws ConfigException;
  /**
   * Registers to be notified when new Test Children are added.
   *
   * @param listener
   *          The Test Child configuration add listener.
   * @throws ConfigException
   *          If the add listener could not be registered.
   */
  void addTestChildAddListener(ConfigurationAddListener<TestChildCfg> listener) throws ConfigException;
  /**
   * Deregisters an existing Test Child configuration add listener.
   *
   * @param listener
   *          The Test Child configuration add listener.
   */
  void removeTestChildAddListener(ConfigurationAddListener<TestChildCfg> listener);
  /**
   * Registers to be notified when existing Test Children are deleted.
   *
   * @param listener
   *          The Test Child configuration delete listener.
   * @throws ConfigException
   *          If the delete listener could not be registered.
   */
  void addTestChildDeleteListener(ConfigurationDeleteListener<TestChildCfg> listener) throws ConfigException;
  /**
   * Deregisters an existing Test Child configuration delete listener.
   *
   * @param listener
   *          The Test Child configuration delete listener.
   */
  void removeTestChildDeleteListener(ConfigurationDeleteListener<TestChildCfg> listener);
  /**
   * Determines whether or not the Optional Test Child exists.
   *
   * @return Returns <true> if the Optional Test Child exists.
   */
  boolean hasOptionalTestChild();
  /**
   * Gets the Optional Test Child if it is present.
   *
   * @return Returns the Optional Test Child if it is present.
   * @throws ConfigException
   *           If the Optional Test Child does not exist or it could not
   *           be successfully decoded.
   */
  TestChildCfg getOptionalTestChild() throws ConfigException;
  /**
   * Registers to be notified when the Optional Test Child is added.
   *
   * @param listener
   *          The Optional Test Child configuration add listener.
   * @throws ConfigException
   *          If the add listener could not be registered.
   */
  void addOptionalTestChildAddListener(ConfigurationAddListener<TestChildCfg> listener) throws ConfigException;
  /**
   * Deregisters an existing Optional Test Child configuration add listener.
   *
   * @param listener
   *          The Optional Test Child configuration add listener.
   */
  void removeOptionalTestChildAddListener(ConfigurationAddListener<TestChildCfg> listener);
  /**
   * Registers to be notified the Optional Test Child is deleted.
   *
   * @param listener
   *          The Optional Test Child configuration delete listener.
   * @throws ConfigException
   *          If the delete listener could not be registered.
   */
  void addOptionalChildTestDeleteListener(ConfigurationDeleteListener<TestChildCfg> listener) throws ConfigException;
  /**
   * Deregisters an existing Optional Test Child configuration delete listener.
   *
   * @param listener
   *          The Optional Test Child configuration delete listener.
   */
  void removeOptionalTestChildDeleteListener(ConfigurationDeleteListener<TestChildCfg> listener);
}
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgClient.java
@@ -29,39 +29,155 @@
import java.util.Collection;
import org.opends.server.admin.ConfigurationClient;
import org.opends.server.admin.ManagedObjectDefinition;
import java.util.SortedSet;
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ConcurrentModificationException;
import org.opends.server.admin.client.ManagedObjectDecodingException;
import org.opends.server.admin.client.OperationRejectedException;
import org.opends.server.admin.ConfigurationClient;
import org.opends.server.admin.DefaultBehaviorException;
import org.opends.server.admin.DefinitionDecodingException;
import org.opends.server.admin.IllegalPropertyValueException;
import org.opends.server.admin.ManagedObjectDefinition;
import org.opends.server.admin.ManagedObjectNotFoundException;
import org.opends.server.admin.PropertyIsReadOnlyException;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
/**
 * A sample client-side configuration interface for testing.
 * A client-side interface for reading and modifying Test Parent
 * settings.
 * <p>
 * A configuration for testing components that have child components.
 * It re-uses the virtual-attribute configuration LDAP profile.
 */
public interface TestParentCfgClient extends ConfigurationClient {
  /**
   * {@inheritDoc}
   * Get the configuration definition associated with this Test Parent.
   *
   * @return Returns the configuration definition associated with this Test Parent.
   */
  ManagedObjectDefinition<? extends TestParentCfgClient, ? extends TestParentCfg> definition();
  /**
   * Lists the test children.
   * Get the "mandatory-boolean-property" property.
   * <p>
   * A mandatory boolean property.
   *
   * @return Returns an array containing the names of the test
   *         children.
   * @return Returns the value of the "mandatory-boolean-property" property.
   */
  Boolean isMandatoryBooleanProperty();
  /**
   * Set the "mandatory-boolean-property" property.
   * <p>
   * A mandatory boolean property.
   *
   * @param value The value of the "mandatory-boolean-property" property.
   * @throws IllegalPropertyValueException
   *           If the new value is invalid.
   */
  void setMandatoryBooleanProperty(boolean value) throws IllegalPropertyValueException;
  /**
   * Get the "mandatory-class-property" property.
   * <p>
   * A mandatory Java-class property requiring a component restart.
   *
   * @return Returns the value of the "mandatory-class-property" property.
   */
  String getMandatoryClassProperty();
  /**
   * Set the "mandatory-class-property" property.
   * <p>
   * A mandatory Java-class property requiring a component restart.
   *
   * @param value The value of the "mandatory-class-property" property.
   * @throws IllegalPropertyValueException
   *           If the new value is invalid.
   */
  void setMandatoryClassProperty(String value) throws IllegalPropertyValueException;
  /**
   * Get the "mandatory-read-only-attribute-type-property" property.
   * <p>
   * A mandatory read-only attribute type property.
   *
   * @return Returns the value of the "mandatory-read-only-attribute-type-property" property.
   */
  AttributeType getMandatoryReadOnlyAttributeTypeProperty();
  /**
   * Set the "mandatory-read-only-attribute-type-property" property.
   * <p>
   * A mandatory read-only attribute type property.
   * <p>
   * This property is read-only and can only be modified during
   * creation of a Test Parent.
   *
   * @param value The value of the "mandatory-read-only-attribute-type-property" property.
   * @throws IllegalPropertyValueException
   *           If the new value is invalid.
   * @throws PropertyIsReadOnlyException
   *           If this Test Parent is not being initialized.
   */
  void setMandatoryReadOnlyAttributeTypeProperty(AttributeType value) throws IllegalPropertyValueException, PropertyIsReadOnlyException;
  /**
   * Get the "optional-multi-valued-dn-property" property.
   * <p>
   * An optional multi-valued DN property with a defined default
   * behavior.
   *
   * @return Returns the values of the "optional-multi-valued-dn-property" property.
   */
  SortedSet<DN> getOptionalMultiValuedDNProperty();
  /**
   * Set the "optional-multi-valued-dn-property" property.
   * <p>
   * An optional multi-valued DN property with a defined default
   * behavior.
   *
   * @param values The values of the "optional-multi-valued-dn-property" property.
   * @throws IllegalPropertyValueException
   *           If one or more of the new values are invalid.
   */
  void setOptionalMultiValuedDNProperty(Collection<DN> values) throws IllegalPropertyValueException;
  /**
   * Lists the Test Children.
   *
   * @return Returns an array containing the names of the Test
   *         Children.
   * @throws ConcurrentModificationException
   *           If this test parent has been removed from the server by
   *           If this Test Parent has been removed from the server by
   *           another client.
   * @throws AuthorizationException
   *           If the server refuses to list the test children because
   *           If the server refuses to list the Test Children because
   *           the client does not have the correct privileges.
   * @throws CommunicationException
   *           If the client cannot contact the server due to an
@@ -73,25 +189,26 @@
  /**
   * Gets the named test child.
   * Gets the named Test Child.
   *
   * @param name
   *          The name of the test child to retrieve.
   * @return Returns the named test child.
   *           The name of the Test Child to retrieve.
   * @return Returns the named Test Child.
   * @throws DefinitionDecodingException
   *           If the named test child was found but its type could
   *           not be determined.
   *           If the named Test Child was found but its type
   *           could not be determined.
   * @throws ManagedObjectDecodingException
   *           If the named test child was found but one or more of
   *           its properties could not be decoded.
   *           If the named Test Child was found but one or
   *           more of its properties could not be decoded.
   * @throws ManagedObjectNotFoundException
   *           If the named test child was not found on the server.
   *           If the named Test Child was not found on the
   *           server.
   * @throws ConcurrentModificationException
   *           If this test parent has been removed from the server by
   *           If this Test Parent has been removed from the server by
   *           another client.
   * @throws AuthorizationException
   *           If the server refuses to retrieve the named test child
   *           because the client does not have the correct
   *           If the server refuses to retrieve the named Multiple
   *           Children because the client does not have the correct
   *           privileges.
   * @throws CommunicationException
   *           If the client cannot contact the server due to an
@@ -105,93 +222,151 @@
  /**
   * Creates a new test child.
   * Creates a new Test Child. The new Test Child will
   * initially not contain any property values (including mandatory
   * properties). Once the Test Child has been configured it can
   * be added to the server using the {@link #commit()} method.
   *
   * @param <C>
   *          The type of the test child being added.
   *          The type of the Test Child being created.
   * @param d
   *          The definition of the test child to be created.
   *          The definition of the Test Child to be created.
   * @param name
   *          The name of the new test child.
   *          The name of the new Test Child.
   * @param exceptions
   *          An optional collection in which to place any {@link
   *          DefaultBehaviorException}s that occurred whilst
   *          attempting to determine the default values of the test
   *          child. This argument can be <code>null<code>.
   * @return Returns a new test child instance representing the test
   *         child that was created.
   *          attempting to determine the default values of the
   *          Test Child. This argument can be <code>null<code>.
   * @return Returns a new Test Child configuration instance.
   */
  <C extends TestChildCfgClient> C createTestChild(
      ManagedObjectDefinition<C, ?> d, String name,
      Collection<DefaultBehaviorException> exceptions);
      ManagedObjectDefinition<C, ?> d, String name, Collection<DefaultBehaviorException> exceptions);
  /**
   * Removes the named test child.
   * Removes the named Test Child.
   *
   * @param name
   *          The name of the test child to remove.
   *          The name of the Test Child to remove.
   * @throws ManagedObjectNotFoundException
   *           If the test child does not exist.
   *           If the Test Child does not exist.
   * @throws OperationRejectedException
   *           If the server refuses to remove the test child due to
   *           some server-side constraint which cannot be satisfied
   *           (for example, if it is referenced by another managed
   *           object).
   *           If the server refuses to remove the Test Child
   *           due to some server-side constraint which cannot be
   *           satisfied (for example, if it is referenced by another
   *           managed object).
   * @throws ConcurrentModificationException
   *           If this test parent has been removed from the server by
   *           If this Test Parent has been removed from the server by
   *           another client.
   * @throws AuthorizationException
   *           If the server refuses to remove the test child because
   *           If the server refuses to remove the Test Child
   *           because the client does not have the correct privileges.
   * @throws CommunicationException
   *           If the client cannot contact the server due to an
   *           underlying communication problem.
   */
  void removeTestChild(String name)
      throws ManagedObjectNotFoundException, OperationRejectedException,
      ConcurrentModificationException, AuthorizationException,
      CommunicationException;
  /**
   * Determines whether or not the Optional Test Child exists.
   *
   * @return Returns <true> if the Optional Test Child exists.
   * @throws ConcurrentModificationException
   *           If this Test Parent has been removed from the server by
   *           another client.
   * @throws AuthorizationException
   *           If the server refuses to make the determination because
   *           the client does not have the correct privileges.
   * @throws CommunicationException
   *           If the client cannot contact the server due to an
   *           underlying communication problem.
   */
  void removeTestChild(String name) throws ManagedObjectNotFoundException,
      OperationRejectedException, ConcurrentModificationException,
  boolean hasOptionalTestChild() throws ConcurrentModificationException,
      AuthorizationException, CommunicationException;
  /**
   * Get the "maximum-length" property.
   * Gets the Optional Test Child if it is present.
   *
   * @return Returns the value of the "maximum-length" property.
   * @return Returns the Optional Test Child if it is present.
   * @throws DefinitionDecodingException
   *           If the Optional Test Child was found but its type could not
   *           be determined.
   * @throws ManagedObjectDecodingException
   *           If the Optional Test Child was found but one or more of its
   *           properties could not be decoded.
   * @throws ManagedObjectNotFoundException
   *           If the Optional Test Child is not present.
   * @throws ConcurrentModificationException
   *           If this Test Parent has been removed from the server by
   *           another client.
   * @throws AuthorizationException
   *           If the server refuses to retrieve the Optional Test Child
   *           because the client does not have the correct privileges.
   * @throws CommunicationException
   *           If the client cannot contact the server due to an
   *           underlying communication problem.
   */
  int getMaximumLength();
  TestChildCfgClient getOptionalChild()
      throws DefinitionDecodingException, ManagedObjectDecodingException,
      ManagedObjectNotFoundException, ConcurrentModificationException,
      AuthorizationException, CommunicationException;
  /**
   * Set the "maximum-length" property.
   * Creates a new Optional Test Child. The new Optional Test Child will
   * initially not contain any property values (including mandatory
   * properties). Once the Optional Test Child has been configured it can be
   * added to the server using the {@link #commit()} method.
   *
   * @param value
   *          The value of the "maximum-length" property.
   * @throws IllegalPropertyValueException
   *           If the new value is invalid.
   * @param <C>
   *          The type of the Optional Test Child being created.
   * @param d
   *          The definition of the Optional Test Child to be created.
   * @param exceptions
   *          An optional collection in which to place any {@link
   *          DefaultBehaviorException}s that occurred whilst
   *          attempting to determine the default values of the
   *          Optional Test Child. This argument can be <code>null<code>.
   * @return Returns a new Optional Test Child configuration instance.
   */
  void setMaximumLength(Integer value) throws IllegalPropertyValueException;
  <C extends TestChildCfgClient> C createOptionalTestChild(
      ManagedObjectDefinition<C, ?> d, Collection<DefaultBehaviorException> exceptions);
  /**
   * Get the "minimum-length" property.
   * Removes the Optional Test Child if it exists.
   *
   * @return Returns the value of the "minimum-length" property.
   * @throws ManagedObjectNotFoundException
   *           If the Optional Test Child does not exist.
   * @throws OperationRejectedException
   *           If the server refuses to remove the Optional Test Child due
   *           to some server-side constraint which cannot be satisfied
   *           (for example, if it is referenced by another managed
   *           object).
   * @throws ConcurrentModificationException
   *           If this Test Parent has been removed from the server by
   *           another client.
   * @throws AuthorizationException
   *           If the server refuses to remove the Optional Test Child
   *           because the client does not have the correct privileges.
   * @throws CommunicationException
   *           If the client cannot contact the server due to an
   *           underlying communication problem.
   */
  int getMinimumLength();
  void removeOptionalTestChild()
      throws ManagedObjectNotFoundException, OperationRejectedException,
      ConcurrentModificationException, AuthorizationException,
      CommunicationException;
  /**
   * Set the "minimum-length" property.
   *
   * @param value
   *          The value of the "minimum-length" property.
   * @throws IllegalPropertyValueException
   *           If the new value is invalid.
   */
  void setMinimumLength(Integer value) throws IllegalPropertyValueException;
}
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java
@@ -29,7 +29,11 @@
import java.util.Collection;
import java.util.SortedSet;
import org.opends.server.admin.AdministratorAction;
import org.opends.server.admin.AttributeTypePropertyDefinition;
import org.opends.server.admin.BooleanPropertyDefinition;
import org.opends.server.admin.ClassPropertyDefinition;
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ConcurrentModificationException;
@@ -37,79 +41,149 @@
import org.opends.server.admin.client.ManagedObjectDecodingException;
import org.opends.server.admin.client.MissingMandatoryPropertiesException;
import org.opends.server.admin.client.OperationRejectedException;
import org.opends.server.admin.DefaultBehaviorException;
import org.opends.server.admin.DefaultBehaviorProvider;
import org.opends.server.admin.DefinedDefaultBehaviorProvider;
import org.opends.server.admin.DefinitionDecodingException;
import org.opends.server.admin.DNPropertyDefinition;
import org.opends.server.admin.InstantiableRelationDefinition;
import org.opends.server.admin.ManagedObjectAlreadyExistsException;
import org.opends.server.admin.ManagedObjectDefinition;
import org.opends.server.admin.ManagedObjectNotFoundException;
import org.opends.server.admin.OptionalRelationDefinition;
import org.opends.server.admin.PropertyIsReadOnlyException;
import org.opends.server.admin.PropertyOption;
import org.opends.server.admin.PropertyProvider;
import org.opends.server.admin.server.ConfigurationAddListener;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.server.ConfigurationDeleteListener;
import org.opends.server.admin.server.ServerManagedObject;
import org.opends.server.admin.std.meta.RootCfgDefn;
import org.opends.server.admin.UndefinedDefaultBehaviorProvider;
import org.opends.server.config.ConfigException;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
/**
 * A sample configuration definition class for testing.
 * An interface for querying the Test Parent managed object definition
 * meta information.
 * <p>
 * A configuration for testing components that have child components.
 * It re-uses the virtual-attribute configuration LDAP profile.
 */
public final class TestParentCfgDefn extends
    ManagedObjectDefinition<TestParentCfgClient, TestParentCfg> {
public final class TestParentCfgDefn extends ManagedObjectDefinition<TestParentCfgClient, TestParentCfg> {
  // The singleton configuration definition instance.
  private static final TestParentCfgDefn INSTANCE = new TestParentCfgDefn();
  /**
   * The relation between this definition and the root.
   */
  public static final InstantiableRelationDefinition<TestParentCfgClient, TestParentCfg> RD_TEST_PARENT;
  // The "mandatory-boolean-property" property definition.
  private static final BooleanPropertyDefinition PD_MANDATORY_BOOLEAN_PROPERTY;
  // The "mandatory-class-property" property definition.
  private static final ClassPropertyDefinition PD_MANDATORY_CLASS_PROPERTY;
  // The "mandatory-read-only-attribute-type-property" property definition.
  private static final AttributeTypePropertyDefinition PD_MANDATORY_READ_ONLY_ATTRIBUTE_TYPE_PROPERTY;
  // The "optional-multi-valued-dn-property" property definition.
  private static final DNPropertyDefinition PD_OPTIONAL_MULTI_VALUED_DN_PROPERTY;
  // The "test-children" relation definition.
  private static final InstantiableRelationDefinition<TestChildCfgClient, TestChildCfg> RD_TEST_CHILDREN;
  // The "maximum-length" property definition.
  private static final IntegerPropertyDefinition PD_MAXIMUM_LENGTH;
  // The "minimum-length" property definition.
  private static final IntegerPropertyDefinition PD_MINIMUM_LENGTH;
  // Build the "maximum-length" property definition.
  // The "optional-test-child" relation definition.
  private static final OptionalRelationDefinition<TestChildCfgClient, TestChildCfg> RD_OPTIONAL_TEST_CHILD;
  // Build the "mandatory-boolean-property" property definition.
  static {
    IntegerPropertyDefinition.Builder builder = IntegerPropertyDefinition
        .createBuilder(INSTANCE, "maximum-length");
    DefaultBehaviorProvider<Integer> provider = new DefinedDefaultBehaviorProvider<Integer>(
        "456");
    builder.setDefaultBehaviorProvider(provider);
    builder.setLowerLimit(0);
    PD_MAXIMUM_LENGTH = builder.getInstance();
    INSTANCE.registerPropertyDefinition(PD_MAXIMUM_LENGTH);
      BooleanPropertyDefinition.Builder builder = BooleanPropertyDefinition.createBuilder(INSTANCE, "mandatory-boolean-property");
      builder.setOption(PropertyOption.MANDATORY);
      builder.setAdministratorAction(new AdministratorAction(AdministratorAction.Type.NONE, INSTANCE, "mandatory-boolean-property"));
      builder.setDefaultBehaviorProvider(new UndefinedDefaultBehaviorProvider<Boolean>());
      PD_MANDATORY_BOOLEAN_PROPERTY = builder.getInstance();
      INSTANCE.registerPropertyDefinition(PD_MANDATORY_BOOLEAN_PROPERTY);
  }
  // Build the "minimum-length" property definition.
  // Build the "mandatory-class-property" property definition.
  static {
    IntegerPropertyDefinition.Builder builder = IntegerPropertyDefinition
        .createBuilder(INSTANCE, "minimum-length");
    DefaultBehaviorProvider<Integer> provider = new DefinedDefaultBehaviorProvider<Integer>(
        "123");
    builder.setDefaultBehaviorProvider(provider);
    builder.setLowerLimit(0);
    PD_MINIMUM_LENGTH = builder.getInstance();
    INSTANCE.registerPropertyDefinition(PD_MINIMUM_LENGTH);
      ClassPropertyDefinition.Builder builder = ClassPropertyDefinition.createBuilder(INSTANCE, "mandatory-class-property");
      builder.setOption(PropertyOption.MANDATORY);
      builder.setAdministratorAction(new AdministratorAction(AdministratorAction.Type.COMPONENT_RESTART, INSTANCE, "mandatory-class-property"));
      DefaultBehaviorProvider<String> provider = new DefinedDefaultBehaviorProvider<String>("org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
      builder.setDefaultBehaviorProvider(provider);
      builder.addInstanceOf("org.opends.server.api.VirtualAttributeProvider");
      PD_MANDATORY_CLASS_PROPERTY = builder.getInstance();
      INSTANCE.registerPropertyDefinition(PD_MANDATORY_CLASS_PROPERTY);
  }
  // Register this as a relation against the root configuration.
  // Build the "mandatory-read-only-attribute-type-property" property definition.
  static {
    RD_TEST_PARENT = new InstantiableRelationDefinition<TestParentCfgClient, TestParentCfg>(
        INSTANCE, "test-parent", "test-parents", INSTANCE);
    RootCfgDefn.getInstance().registerRelationDefinition(RD_TEST_PARENT);
      AttributeTypePropertyDefinition.Builder builder = AttributeTypePropertyDefinition.createBuilder(INSTANCE, "mandatory-read-only-attribute-type-property");
      builder.setOption(PropertyOption.READ_ONLY);
      builder.setOption(PropertyOption.MANDATORY);
      builder.setAdministratorAction(new AdministratorAction(AdministratorAction.Type.NONE, INSTANCE, "mandatory-read-only-attribute-type-property"));
      builder.setDefaultBehaviorProvider(new UndefinedDefaultBehaviorProvider<AttributeType>());
      PD_MANDATORY_READ_ONLY_ATTRIBUTE_TYPE_PROPERTY = builder.getInstance();
      INSTANCE.registerPropertyDefinition(PD_MANDATORY_READ_ONLY_ATTRIBUTE_TYPE_PROPERTY);
  }
  // Build the "optional-multi-valued-dn-property" property definition.
  static {
      DNPropertyDefinition.Builder builder = DNPropertyDefinition.createBuilder(INSTANCE, "optional-multi-valued-dn-property");
      builder.setOption(PropertyOption.MULTI_VALUED);
      builder.setAdministratorAction(new AdministratorAction(AdministratorAction.Type.NONE, INSTANCE, "optional-multi-valued-dn-property"));
      DefaultBehaviorProvider<DN> provider = new DefinedDefaultBehaviorProvider<DN>("dc=domain1,dc=com", "dc=domain2,dc=com", "dc=domain3,dc=com");
      builder.setDefaultBehaviorProvider(provider);
      PD_OPTIONAL_MULTI_VALUED_DN_PROPERTY = builder.getInstance();
      INSTANCE.registerPropertyDefinition(PD_OPTIONAL_MULTI_VALUED_DN_PROPERTY);
  }
  // Build the "test-children" relation definition.
  static {
    RD_TEST_CHILDREN = new InstantiableRelationDefinition<TestChildCfgClient, TestChildCfg>(
        INSTANCE, "test-child", "test-children", TestChildCfgDefn.getInstance());
        INSTANCE, "multiple-children", "test-children", TestChildCfgDefn.getInstance());
    INSTANCE.registerRelationDefinition(RD_TEST_CHILDREN);
  }
  // Build the "optional-test-child" relation definition.
  static {
    RD_OPTIONAL_TEST_CHILD = new OptionalRelationDefinition<TestChildCfgClient, TestChildCfg>(
        INSTANCE, "optional-test-child", TestChildCfgDefn.getInstance());
    INSTANCE.registerRelationDefinition(RD_OPTIONAL_TEST_CHILD);
  }
  /**
   * Get the definition singleton.
   * Get the Test Parent configuration definition singleton.
   *
   * @return Returns the definition singleton.
   * @return Returns the Test Parent configuration definition
   *         singleton.
   */
  public static TestParentCfgDefn getInstance() {
    return INSTANCE;
@@ -127,39 +201,6 @@
  /**
   * Get the "maximum-length" property definition.
   *
   * @return Returns the "maximum-length" property definition.
   */
  public IntegerPropertyDefinition getMaximumLengthPropertyDefinition() {
    return PD_MAXIMUM_LENGTH;
  }
  /**
   * Get the "minimum-length" property definition.
   *
   * @return Returns the "minimum-length" property definition.
   */
  public IntegerPropertyDefinition getMinimumLengthPropertyDefinition() {
    return PD_MINIMUM_LENGTH;
  }
  /**
   * Get the "test-children" relation definition.
   *
   * @return Returns the "test-children" relation definition.
   */
  public InstantiableRelationDefinition<TestChildCfgClient, TestChildCfg> getTestChildrenRelationDefinition() {
    return RD_TEST_CHILDREN;
  }
  /**
   * {@inheritDoc}
   */
  public TestParentCfgClient createClientConfiguration(
@@ -189,9 +230,85 @@
  /**
   * Get the "mandatory-boolean-property" property definition.
   * <p>
   * A mandatory boolean property.
   *
   * @return Returns the "mandatory-boolean-property" property definition.
   */
  public BooleanPropertyDefinition getMandatoryBooleanPropertyPropertyDefinition() {
    return PD_MANDATORY_BOOLEAN_PROPERTY;
  }
  /**
   * Get the "mandatory-class-property" property definition.
   * <p>
   * A mandatory Java-class property requiring a component restart.
   *
   * @return Returns the "mandatory-class-property" property definition.
   */
  public ClassPropertyDefinition getMandatoryClassPropertyPropertyDefinition() {
    return PD_MANDATORY_CLASS_PROPERTY;
  }
  /**
   * Get the "mandatory-read-only-attribute-type-property" property definition.
   * <p>
   * A mandatory read-only attribute type property.
   *
   * @return Returns the "mandatory-read-only-attribute-type-property" property definition.
   */
  public AttributeTypePropertyDefinition getMandatoryReadOnlyAttributeTypePropertyPropertyDefinition() {
    return PD_MANDATORY_READ_ONLY_ATTRIBUTE_TYPE_PROPERTY;
  }
  /**
   * Get the "optional-multi-valued-dn-property" property definition.
   * <p>
   * An optional multi-valued DN property with a defined default
   * behavior.
   *
   * @return Returns the "optional-multi-valued-dn-property" property definition.
   */
  public DNPropertyDefinition getOptionalMultiValuedDNPropertyPropertyDefinition() {
    return PD_OPTIONAL_MULTI_VALUED_DN_PROPERTY;
  }
  /**
   * Get the "test-children" relation definition.
   *
   * @return Returns the "test-children" relation definition.
   */
  public InstantiableRelationDefinition<TestChildCfgClient,TestChildCfg> getTestChildrenRelationDefinition() {
    return RD_TEST_CHILDREN;
  }
  /**
   * Get the "optional-test-child" relation definition.
   *
   * @return Returns the "optional-test-child" relation definition.
   */
  public OptionalRelationDefinition<TestChildCfgClient,TestChildCfg> getOptionalTestChildRelationDefinition() {
    return RD_OPTIONAL_TEST_CHILD;
  }
  /**
   * Managed object client implementation.
   */
  private static class TestParentCfgClientImpl implements TestParentCfgClient {
  private static class TestParentCfgClientImpl implements
    TestParentCfgClient {
    // Private implementation.
    private ManagedObject<? extends TestParentCfgClient> impl;
@@ -209,9 +326,8 @@
    /**
     * {@inheritDoc}
     */
    public int getMaximumLength() {
      return impl.getPropertyValue(INSTANCE
          .getMaximumLengthPropertyDefinition());
    public Boolean isMandatoryBooleanProperty() {
      return impl.getPropertyValue(INSTANCE.getMandatoryBooleanPropertyPropertyDefinition());
    }
@@ -219,9 +335,8 @@
    /**
     * {@inheritDoc}
     */
    public void setMaximumLength(Integer value) {
      impl.setPropertyValue(INSTANCE.getMaximumLengthPropertyDefinition(),
          value);
    public void setMandatoryBooleanProperty(boolean value) {
      impl.setPropertyValue(INSTANCE.getMandatoryBooleanPropertyPropertyDefinition(), value);
    }
@@ -229,9 +344,8 @@
    /**
     * {@inheritDoc}
     */
    public int getMinimumLength() {
      return impl.getPropertyValue(INSTANCE
          .getMinimumLengthPropertyDefinition());
    public String getMandatoryClassProperty() {
      return impl.getPropertyValue(INSTANCE.getMandatoryClassPropertyPropertyDefinition());
    }
@@ -239,9 +353,130 @@
    /**
     * {@inheritDoc}
     */
    public void setMinimumLength(Integer value) {
      impl.setPropertyValue(INSTANCE.getMinimumLengthPropertyDefinition(),
          value);
    public void setMandatoryClassProperty(String value) {
      impl.setPropertyValue(INSTANCE.getMandatoryClassPropertyPropertyDefinition(), value);
    }
    /**
     * {@inheritDoc}
     */
    public AttributeType getMandatoryReadOnlyAttributeTypeProperty() {
      return impl.getPropertyValue(INSTANCE.getMandatoryReadOnlyAttributeTypePropertyPropertyDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public void setMandatoryReadOnlyAttributeTypeProperty(AttributeType value) throws PropertyIsReadOnlyException {
      impl.setPropertyValue(INSTANCE.getMandatoryReadOnlyAttributeTypePropertyPropertyDefinition(), value);
    }
    /**
     * {@inheritDoc}
     */
    public SortedSet<DN> getOptionalMultiValuedDNProperty() {
      return impl.getPropertyValues(INSTANCE.getOptionalMultiValuedDNPropertyPropertyDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public void setOptionalMultiValuedDNProperty(Collection<DN> values) {
      impl.setPropertyValues(INSTANCE.getOptionalMultiValuedDNPropertyPropertyDefinition(), values);
    }
    /**
     * {@inheritDoc}
     */
    public String[] listTestChildren() throws ConcurrentModificationException,
        AuthorizationException, CommunicationException {
      return impl.listChildren(INSTANCE.getTestChildrenRelationDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public TestChildCfgClient getTestChild(String name)
        throws DefinitionDecodingException, ManagedObjectDecodingException,
        ManagedObjectNotFoundException, ConcurrentModificationException,
        AuthorizationException, CommunicationException {
      return impl.getChild(INSTANCE.getTestChildrenRelationDefinition(), name).getConfiguration();
    }
    /**
     * {@inheritDoc}
     */
    public <M extends TestChildCfgClient> M createTestChild(
        ManagedObjectDefinition<M, ?> d, String name, Collection<DefaultBehaviorException> exceptions) {
      return impl.createChild(INSTANCE.getTestChildrenRelationDefinition(), d, name, exceptions).getConfiguration();
    }
    /**
     * {@inheritDoc}
     */
    public void removeTestChild(String name)
        throws ManagedObjectNotFoundException, ConcurrentModificationException,
        OperationRejectedException, AuthorizationException, CommunicationException {
      impl.removeChild(INSTANCE.getTestChildrenRelationDefinition(), name);
    }
    /**
     * {@inheritDoc}
     */
    public boolean hasOptionalTestChild() throws ConcurrentModificationException,
        AuthorizationException, CommunicationException {
      return impl.hasChild(INSTANCE.getOptionalTestChildRelationDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public TestChildCfgClient getOptionalChild()
        throws DefinitionDecodingException, ManagedObjectDecodingException,
        ManagedObjectNotFoundException, ConcurrentModificationException,
        AuthorizationException, CommunicationException {
      return impl.getChild(INSTANCE.getOptionalTestChildRelationDefinition()).getConfiguration();
    }
    /**
     * {@inheritDoc}
     */
    public <M extends TestChildCfgClient> M createOptionalTestChild(
        ManagedObjectDefinition<M, ?> d, Collection<DefaultBehaviorException> exceptions) {
      return impl.createChild(INSTANCE.getOptionalTestChildRelationDefinition(), d, exceptions).getConfiguration();
    }
    /**
     * {@inheritDoc}
     */
    public void removeOptionalTestChild()
        throws ManagedObjectNotFoundException, ConcurrentModificationException,
        OperationRejectedException, AuthorizationException, CommunicationException {
      impl.removeChild(INSTANCE.getOptionalTestChildRelationDefinition());
    }
@@ -267,58 +502,11 @@
    /**
     * {@inheritDoc}
     */
    public void commit() throws ConcurrentModificationException,
    public void commit() throws ManagedObjectAlreadyExistsException,
        MissingMandatoryPropertiesException, ConcurrentModificationException,
        OperationRejectedException, AuthorizationException,
        CommunicationException, ManagedObjectAlreadyExistsException,
        MissingMandatoryPropertiesException {
      impl.commit();
    }
    /**
     * {@inheritDoc}
     */
    public <C extends TestChildCfgClient> C createTestChild(
        ManagedObjectDefinition<C, ?> d, String name,
        Collection<DefaultBehaviorException> exceptions) {
      return impl.createChild(INSTANCE.getTestChildrenRelationDefinition(), d,
          name, exceptions).getConfiguration();
    }
    /**
     * {@inheritDoc}
     */
    public TestChildCfgClient getTestChild(String name)
        throws DefinitionDecodingException, ManagedObjectDecodingException,
        ManagedObjectNotFoundException, ConcurrentModificationException,
        AuthorizationException, CommunicationException {
      return impl.getChild(INSTANCE.getTestChildrenRelationDefinition(), name)
          .getConfiguration();
    }
    /**
     * {@inheritDoc}
     */
    public String[] listTestChildren() throws ConcurrentModificationException,
        AuthorizationException, CommunicationException {
      return impl.listChildren(INSTANCE.getTestChildrenRelationDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public void removeTestChild(String name)
        throws ManagedObjectNotFoundException, OperationRejectedException,
        ConcurrentModificationException, AuthorizationException,
        CommunicationException {
      impl.removeChild(INSTANCE.getTestChildrenRelationDefinition(), name);
      impl.commit();
    }
  }
@@ -328,7 +516,8 @@
  /**
   * Managed object server implementation.
   */
  private static class TestParentCfgServerImpl implements TestParentCfg {
  private static class TestParentCfgServerImpl implements
    TestParentCfg {
    // Private implementation.
    private ServerManagedObject<? extends TestParentCfg> impl;
@@ -336,8 +525,7 @@
    // Private constructor.
    private TestParentCfgServerImpl(
        ServerManagedObject<? extends TestParentCfg> impl) {
    private TestParentCfgServerImpl(ServerManagedObject<? extends TestParentCfg> impl) {
      this.impl = impl;
    }
@@ -346,9 +534,9 @@
    /**
     * {@inheritDoc}
     */
    public int getMaximumLength() {
      return impl.getPropertyValue(INSTANCE
          .getMaximumLengthPropertyDefinition());
    public void addChangeListener(
        ConfigurationChangeListener<TestParentCfg> listener) {
      impl.registerChangeListener(listener);
    }
@@ -356,9 +544,161 @@
    /**
     * {@inheritDoc}
     */
    public int getMinimumLength() {
      return impl.getPropertyValue(INSTANCE
          .getMinimumLengthPropertyDefinition());
    public void removeChangeListener(
        ConfigurationChangeListener<TestParentCfg> listener) {
      impl.deregisterChangeListener(listener);
    }
    /**
     * {@inheritDoc}
     */
    public boolean isMandatoryBooleanProperty() {
      return impl.getPropertyValue(INSTANCE.getMandatoryBooleanPropertyPropertyDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public String getMandatoryClassProperty() {
      return impl.getPropertyValue(INSTANCE.getMandatoryClassPropertyPropertyDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public AttributeType getMandatoryReadOnlyAttributeTypeProperty() {
      return impl.getPropertyValue(INSTANCE.getMandatoryReadOnlyAttributeTypePropertyPropertyDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public SortedSet<DN> getOptionalMultiValuedDNProperty() {
      return impl.getPropertyValues(INSTANCE.getOptionalMultiValuedDNPropertyPropertyDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public String[] listTestChildren() {
      return impl.listChildren(INSTANCE.getTestChildrenRelationDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public TestChildCfg getTestChild(String name) throws ConfigException {
      return impl.getChild(INSTANCE.getTestChildrenRelationDefinition(), name).getConfiguration();
    }
    /**
     * {@inheritDoc}
     */
    public void addTestChildAddListener(
        ConfigurationAddListener<TestChildCfg> listener) throws ConfigException {
      impl.registerAddListener(INSTANCE.getTestChildrenRelationDefinition(), listener);
    }
    /**
     * {@inheritDoc}
     */
    public void removeTestChildAddListener(
        ConfigurationAddListener<TestChildCfg> listener) {
      impl.deregisterAddListener(INSTANCE.getTestChildrenRelationDefinition(), listener);
    }
    /**
     * {@inheritDoc}
     */
    public void addTestChildDeleteListener(
        ConfigurationDeleteListener<TestChildCfg> listener) throws ConfigException {
      impl.registerDeleteListener(INSTANCE.getTestChildrenRelationDefinition(), listener);
    }
    /**
     * {@inheritDoc}
     */
    public void removeTestChildDeleteListener(
        ConfigurationDeleteListener<TestChildCfg> listener) {
      impl.deregisterDeleteListener(INSTANCE.getTestChildrenRelationDefinition(), listener);
    }
    /**
     * {@inheritDoc}
     */
    public boolean hasOptionalTestChild() {
      return impl.hasChild(INSTANCE.getOptionalTestChildRelationDefinition());
    }
    /**
     * {@inheritDoc}
     */
    public TestChildCfg getOptionalTestChild() throws ConfigException {
      return impl.getChild(INSTANCE.getOptionalTestChildRelationDefinition()).getConfiguration();
    }
    /**
     * {@inheritDoc}
     */
    public void addOptionalTestChildAddListener(
        ConfigurationAddListener<TestChildCfg> listener) throws ConfigException {
      impl.registerAddListener(INSTANCE.getOptionalTestChildRelationDefinition(), listener);
    }
    /**
     * {@inheritDoc}
     */
    public void removeOptionalTestChildAddListener(
        ConfigurationAddListener<TestChildCfg> listener) {
      impl.deregisterAddListener(INSTANCE.getOptionalTestChildRelationDefinition(), listener);
    }
    /**
     * {@inheritDoc}
     */
    public void addOptionalChildTestDeleteListener(
        ConfigurationDeleteListener<TestChildCfg> listener) throws ConfigException {
      impl.registerDeleteListener(INSTANCE.getOptionalTestChildRelationDefinition(), listener);
    }
    /**
     * {@inheritDoc}
     */
    public void removeOptionalTestChildDeleteListener(
        ConfigurationDeleteListener<TestChildCfg> listener) {
      impl.deregisterDeleteListener(INSTANCE.getOptionalTestChildRelationDefinition(), listener);
    }
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentConfiguration.xml
New file
@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
  ! 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.
  ! -->
<adm:managed-object name="test-parent" plural-name="test-parents"
  package="org.opends.server.admin.std"
  xmlns:adm="http://www.opends.org/admin"
  xmlns:ldap="http://www.opends.org/admin-ldap">
  <adm:synopsis>
    A configuration for testing components that have child components.
    It re-uses the virtual-attribute configuration LDAP profile.
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.91</ldap:oid>
      <ldap:name>ds-cfg-virtual-attribute</ldap:name>
      <ldap:superior>top</ldap:superior>
    </ldap:object-class>
  </adm:profile>
  <adm:relation name="test-child">
    <adm:one-to-many />
    <adm:profile name="ldap">
      <ldap:rdn-sequence>cn=multiple children</ldap:rdn-sequence>
    </adm:profile>
  </adm:relation>
  <adm:relation name="optional-test-child"
    managed-object-name="test-child">
    <adm:one-to-zero-or-one />
    <adm:profile name="ldap">
      <ldap:rdn-sequence>cn=optional child</ldap:rdn-sequence>
    </adm:profile>
  </adm:relation>
  <adm:property name="mandatory-boolean-property" mandatory="true">
    <adm:synopsis>A mandatory boolean property.</adm:synopsis>
    <adm:syntax>
      <adm:boolean />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.326</ldap:oid>
        <ldap:name>ds-cfg-virtual-attribute-enabled</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="mandatory-class-property" mandatory="true">
    <adm:synopsis>
      A mandatory Java-class property requiring a component restart.
    </adm:synopsis>
    <adm:requires-admin-action>
      <adm:component-restart />
    </adm:requires-admin-action>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          org.opends.server.extensions.UserDefinedVirtualAttributeProvider
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:java-class>
        <adm:instance-of>
          org.opends.server.api.VirtualAttributeProvider
        </adm:instance-of>
      </adm:java-class>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.325</ldap:oid>
        <ldap:name>ds-cfg-virtual-attribute-class</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="mandatory-read-only-attribute-type-property"
    mandatory="true" read-only="true">
    <adm:synopsis>
      A mandatory read-only attribute type property.
    </adm:synopsis>
    <adm:syntax>
      <adm:attribute-type />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.327</ldap:oid>
        <ldap:name>ds-cfg-virtual-attribute-type</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="optional-multi-valued-dn-property"
    multi-valued="true">
    <adm:synopsis>
      An optional multi-valued DN property with a defined default
      behavior.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>dc=domain1,dc=com</adm:value>
        <adm:value>dc=domain2,dc=com</adm:value>
        <adm:value>dc=domain3,dc=com</adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:dn />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.328</ldap:oid>
        <ldap:name>ds-cfg-virtual-attribute-base-dn</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/LDAPClientTest.java
@@ -28,7 +28,10 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.SortedSet;
import javax.naming.NamingException;
import javax.naming.OperationNotSupportedException;
@@ -38,6 +41,7 @@
import org.opends.server.TestCaseUtils;
import org.opends.server.admin.AdminTestCase;
import org.opends.server.admin.DefinitionDecodingException;
import org.opends.server.admin.LDAPProfile;
import org.opends.server.admin.ManagedObjectAlreadyExistsException;
import org.opends.server.admin.ManagedObjectNotFoundException;
import org.opends.server.admin.MockLDAPProfile;
@@ -53,7 +57,10 @@
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.client.OperationRejectedException;
import org.opends.server.admin.std.client.RootCfgClient;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.DN;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -67,25 +74,112 @@
  // Test LDIF.
  private static final String[] TEST_LDIF = new String[] {
      "dn: cn=test-parents", "objectclass: top", "objectclass: ds-cfg-branch",
      "cn: test-parents", "", "dn: cn=test parent 1, cn=test-parents",
      "objectclass: top", "objectclass: ds-cfg-test-parent",
      "cn: test parent 1", "", "dn: cn=test parent 2,cn=test-parents",
      "objectclass: top", "objectclass: ds-cfg-test-parent",
      "cn: test parent 2", "ds-cfg-minimum-length: 10000",
      "ds-cfg-maximum-length: 20000", "",
      "dn:cn=test-children,cn=test parent 1,cn=test-parents",
      "objectclass: top", "objectclass: ds-cfg-branch", "cn: test-children",
      "", "dn:cn=test-children,cn=test parent 2,cn=test-parents",
      "objectclass: top", "objectclass: ds-cfg-branch", "cn: test-children",
      // Base entries.
      "dn: cn=config",
      "objectclass: top",
      "objectclass: ds-cfg-branch",
      "cn: config",
      "",
      "dn: cn=test child 1,cn=test-children,cn=test parent 1,cn=test-parents",
      "objectclass: top", "objectclass: ds-cfg-test-child", "cn: test child 1",
      "dn: cn=test parents,cn=config",
      "objectclass: top",
      "objectclass: ds-cfg-branch",
      "cn: test-parents",
      "",
      "dn: cn=test child 2,cn=test-children,cn=test parent 1,cn=test-parents",
      "objectclass: top", "objectclass: ds-cfg-test-child", "cn: test child 2",
      "ds-cfg-heartbeat-interval: 12345s", "ds-cfg-minimum-length: 11111",
      "ds-cfg-maximum-length: 22222", "" };
      // Parent 1 - uses default values for
      // optional-multi-valued-dn-property.
      "dn: cn=test parent 1,cn=test parents,cn=config",
      "objectclass: top",
      "objectclass: ds-cfg-virtual-attribute",
      "cn: test parent 1",
      "ds-cfg-virtual-attribute-enabled: true",
      "ds-cfg-virtual-attribute-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
      "ds-cfg-virtual-attribute-type: description",
      "",
      // Parent 2 - overrides default values for
      // optional-multi-valued-dn-property.
      "dn: cn=test parent 2,cn=test parents,cn=config",
      "objectclass: top",
      "objectclass: ds-cfg-virtual-attribute",
      "cn: test parent 2",
      "ds-cfg-virtual-attribute-enabled: true",
      "ds-cfg-virtual-attribute-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
      "ds-cfg-virtual-attribute-type: description",
      "ds-cfg-virtual-attribute-base-dn: dc=default value p2v1,dc=com",
      "ds-cfg-virtual-attribute-base-dn: dc=default value p2v2,dc=com",
      "",
      // Parent 3 - overrides default values for
      // optional-multi-valued-dn-property.
      "dn: cn=test parent 3,cn=test parents,cn=config",
      "objectclass: top",
      "objectclass: ds-cfg-virtual-attribute",
      "cn: test parent 3",
      "ds-cfg-virtual-attribute-enabled: true",
      "ds-cfg-virtual-attribute-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
      "ds-cfg-virtual-attribute-type: description",
      "ds-cfg-virtual-attribute-base-dn: dc=default value p3v1,dc=com",
      "ds-cfg-virtual-attribute-base-dn: dc=default value p3v2,dc=com",
      "",
      // Child base entries.
      "dn:cn=test children,cn=test parent 1,cn=test parents,cn=config",
      "objectclass: top",
      "objectclass: ds-cfg-branch",
      "cn: multiple children",
      "",
      "dn:cn=test children,cn=test parent 2,cn=test parents,cn=config",
      "objectclass: top",
      "objectclass: ds-cfg-branch",
      "cn: multiple children",
      "",
      // Child 1 inherits defaults for both
      // optional-multi-valued-dn-property1 and
      // optional-multi-valued-dn-property2.
      "dn: cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config",
      "objectclass: top",
      "objectclass: ds-cfg-virtual-attribute",
      "cn: test child 1",
      "ds-cfg-virtual-attribute-enabled: true",
      "ds-cfg-virtual-attribute-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
      "ds-cfg-virtual-attribute-type: description",
      "",
      // Child 2 inherits defaults for
      // optional-multi-valued-dn-property2.
      "dn: cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config",
      "objectclass: top",
      "objectclass: ds-cfg-virtual-attribute",
      "cn: test child 2",
      "ds-cfg-virtual-attribute-enabled: true",
      "ds-cfg-virtual-attribute-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
      "ds-cfg-virtual-attribute-type: description",
      "ds-cfg-virtual-attribute-base-dn: dc=default value c2v1,dc=com",
      "ds-cfg-virtual-attribute-base-dn: dc=default value c2v2,dc=com",
      "",
      // Child 3 overrides defaults for
      // optional-multi-valued-dn-property1 and
      // optional-multi-valued-dn-property2.
      "dn: cn=test child 3,cn=test children,cn=test parent 1,cn=test parents,cn=config",
      "objectclass: top",
      "objectclass: ds-cfg-virtual-attribute",
      "cn: test child 3",
      "ds-cfg-virtual-attribute-enabled: true",
      "ds-cfg-virtual-attribute-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
      "ds-cfg-virtual-attribute-type: description",
      "ds-cfg-virtual-attribute-base-dn: dc=default value c3v1,dc=com",
      "ds-cfg-virtual-attribute-base-dn: dc=default value c3v2,dc=com",
      "ds-cfg-virtual-attribute-group-dn: dc=default value c3v3,dc=com",
      "ds-cfg-virtual-attribute-group-dn: dc=default value c3v4,dc=com",
      "",
      // Child 4 inherits overridden defaults for both
      // optional-multi-valued-dn-property1 and
      // optional-multi-valued-dn-property2.
      "dn: cn=test child 1,cn=test children,cn=test parent 2,cn=test parents,cn=config",
      "objectclass: top",
      "objectclass: ds-cfg-virtual-attribute",
      "cn: test child 1",
      "ds-cfg-virtual-attribute-enabled: true",
      "ds-cfg-virtual-attribute-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
      "ds-cfg-virtual-attribute-type: description",
      ""
  };
@@ -98,18 +192,31 @@
  @DataProvider(name = "createManagedObjectExceptions")
  public Object[][] createManagedObjectExceptions() {
    return new Object[][] {
        { new javax.naming.CommunicationException(),
            CommunicationException.class },
        { new javax.naming.ServiceUnavailableException(),
            CommunicationException.class },
        { new javax.naming.CannotProceedException(),
            CommunicationException.class },
        { new javax.naming.NameAlreadyBoundException(),
            ManagedObjectAlreadyExistsException.class },
        { new javax.naming.NoPermissionException(),
            AuthorizationException.class },
        { new OperationNotSupportedException(),
            OperationRejectedException.class } };
        {
            new javax.naming.CommunicationException(),
            CommunicationException.class
        },
        {
            new javax.naming.ServiceUnavailableException(),
            CommunicationException.class
        },
        {
            new javax.naming.CannotProceedException(),
            CommunicationException.class
        },
        {
            new javax.naming.NameAlreadyBoundException(),
            ManagedObjectAlreadyExistsException.class
        },
        {
            new javax.naming.NoPermissionException(),
            AuthorizationException.class
        },
        {
            new OperationNotSupportedException(),
            OperationRejectedException.class
        }
    };
  }
@@ -123,17 +230,30 @@
  @DataProvider(name = "getManagedObjectExceptions")
  public Object[][] getManagedObjectExceptions() {
    return new Object[][] {
        { new javax.naming.CommunicationException(),
            CommunicationException.class },
        { new javax.naming.ServiceUnavailableException(),
            CommunicationException.class },
        { new javax.naming.CannotProceedException(),
            CommunicationException.class },
        { new javax.naming.NameNotFoundException(),
            ManagedObjectNotFoundException.class },
        { new javax.naming.NoPermissionException(),
            AuthorizationException.class },
        { new OperationNotSupportedException(), CommunicationException.class } };
        {
            new javax.naming.CommunicationException(),
            CommunicationException.class
        },
        {
            new javax.naming.ServiceUnavailableException(),
            CommunicationException.class
        },
        {
            new javax.naming.CannotProceedException(),
            CommunicationException.class
        },
        {
            new javax.naming.NameNotFoundException(),
            ManagedObjectNotFoundException.class
        },
        {
            new javax.naming.NoPermissionException(),
            AuthorizationException.class
        },
        {
            new OperationNotSupportedException(), CommunicationException.class
        }
    };
  }
@@ -149,6 +269,17 @@
    // This test suite depends on having the schema available, so
    // we'll start the server.
    TestCaseUtils.startServer();
    LDAPProfile.getInstance().pushWrapper(new MockLDAPProfile());
  }
  /**
   * Tears down test environment.
   */
  @AfterClass
  public void tearDown() {
    LDAPProfile.getInstance().popWrapper();
  }
@@ -162,46 +293,22 @@
  @Test
  public void testCreateChildManagedObject() throws Exception {
    CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
        "cn=test child 3,cn=test-children,cn=test parent 1,cn=test-parents");
        "cn=test child new,cn=test children,cn=test parent 1,cn=test parents,cn=config");
    c.importLDIF(TEST_LDIF);
    c.addExpectedAttribute("cn", "test child 3");
    c.addExpectedAttribute("objectclass", "top", "ds-cfg-test-child");
    c.addExpectedAttribute("cn", "test child new");
    c.addExpectedAttribute("objectclass", "top", "ds-cfg-virtual-attribute");
    c.addExpectedAttribute("ds-cfg-virtual-attribute-enabled", "true");
    c.addExpectedAttribute("ds-cfg-virtual-attribute-class",
        "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
    c.addExpectedAttribute("ds-cfg-virtual-attribute-type", "description");
    // LDAP encoding uses base unit.
    c.addExpectedAttribute("ds-cfg-heartbeat-interval", "10000ms");
    ManagementContext ctx = LDAPManagementContext.createFromContext(c,
        new MockLDAPProfile());
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
    TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn
        .getInstance(), "test child 3", null);
    child.setHeartbeatInterval(10000L);
    child.commit();
    c.assertEntryIsCreated();
  }
  /**
   * Tests creation of a child managed object.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testCreateChildManagedObjectDefault() throws Exception {
    CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
        "cn=test child 3,cn=test-children,cn=test parent 1,cn=test-parents");
    c.importLDIF(TEST_LDIF);
    c.addExpectedAttribute("cn", "test child 3");
    c.addExpectedAttribute("objectclass", "top", "ds-cfg-test-child");
    ManagementContext ctx = LDAPManagementContext.createFromContext(c,
        new MockLDAPProfile());
    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
    TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn
        .getInstance(), "test child 3", null);
        .getInstance(), "test child new", null);
    child.setMandatoryBooleanProperty(true);
    child.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer
        .getAttributeType("description"));
    child.commit();
    c.assertEntryIsCreated();
@@ -234,10 +341,12 @@
    };
    c.importLDIF(TEST_LDIF);
    ManagementContext ctx = LDAPManagementContext.createFromContext(c,
        new MockLDAPProfile());
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    try {
      TestParentCfgClient parent = createTestParent(ctx, "test parent 3");
      TestParentCfgClient parent = createTestParent(ctx, "test parent new");
      parent.setMandatoryBooleanProperty(true);
      parent.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer
          .getAttributeType("description"));
      parent.commit();
    } catch (Exception e) {
      Assert.assertEquals(e.getClass(), expected);
@@ -255,41 +364,20 @@
  @Test
  public void testCreateTopLevelManagedObject() throws Exception {
    CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
        "cn=test parent 3,cn=test-parents");
        "cn=test parent new,cn=test parents,cn=config");
    c.importLDIF(TEST_LDIF);
    c.addExpectedAttribute("cn", "test parent 3");
    c.addExpectedAttribute("objectclass", "top", "ds-cfg-test-parent");
    c.addExpectedAttribute("ds-cfg-maximum-length", "54321");
    c.addExpectedAttribute("ds-cfg-minimum-length", "12345");
    c.addExpectedAttribute("cn", "test parent new");
    c.addExpectedAttribute("objectclass", "top", "ds-cfg-virtual-attribute");
    c.addExpectedAttribute("ds-cfg-virtual-attribute-enabled", "true");
    c.addExpectedAttribute("ds-cfg-virtual-attribute-class",
        "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
    c.addExpectedAttribute("ds-cfg-virtual-attribute-type", "description");
    ManagementContext ctx = LDAPManagementContext.createFromContext(c,
        new MockLDAPProfile());
    TestParentCfgClient parent = createTestParent(ctx, "test parent 3");
    parent.setMaximumLength(54321);
    parent.setMinimumLength(12345);
    parent.commit();
    c.assertEntryIsCreated();
  }
  /**
   * Tests creation of a top-level managed object.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testCreateTopLevelManagedObjectDefault() throws Exception {
    CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
        "cn=test parent 3,cn=test-parents");
    c.importLDIF(TEST_LDIF);
    c.addExpectedAttribute("cn", "test parent 3");
    c.addExpectedAttribute("objectclass", "top", "ds-cfg-test-parent");
    ManagementContext ctx = LDAPManagementContext.createFromContext(c,
        new MockLDAPProfile());
    TestParentCfgClient parent = createTestParent(ctx, "test parent 3");
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    TestParentCfgClient parent = createTestParent(ctx, "test parent new");
    parent.setMandatoryBooleanProperty(true);
    parent.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer
        .getAttributeType("description"));
    parent.commit();
    c.assertEntryIsCreated();
  }
@@ -305,12 +393,20 @@
   */
  @Test
  public void testGetChildManagedObject() throws Exception {
    ManagementContext ctx = getManagementContext(TEST_LDIF);
    MockLDAPConnection c = new MockLDAPConnection();
    c.importLDIF(TEST_LDIF);
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
    TestChildCfgClient child = parent.getTestChild("test child 2");
    Assert.assertEquals(child.getHeartbeatInterval(), 12345000);
    Assert.assertEquals(child.getMinimumLength(), 11111);
    Assert.assertEquals(child.getMaximumLength(), 22222);
    TestChildCfgClient child = parent.getTestChild("test child 3");
    Assert.assertEquals(child.isMandatoryBooleanProperty(), Boolean.TRUE);
    Assert.assertEquals(child.getMandatoryClassProperty(),
        "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
    Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(),
        DirectoryServer.getAttributeType("description"));
    assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(),
        "dc=default value c3v1,dc=com", "dc=default value c3v2,dc=com");
    assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(),
        "dc=default value c3v3,dc=com", "dc=default value c3v4,dc=com");
  }
@@ -323,18 +419,26 @@
   */
  @Test
  public void testGetChildManagedObjectDefault() throws Exception {
    ManagementContext ctx = getManagementContext(TEST_LDIF);
    MockLDAPConnection c = new MockLDAPConnection();
    c.importLDIF(TEST_LDIF);
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
    TestChildCfgClient child = parent.getTestChild("test child 1");
    Assert.assertEquals(child.getHeartbeatInterval(), 1000);
    Assert.assertEquals(child.getMinimumLength(), 10000);
    Assert.assertEquals(child.getMaximumLength(), 456);
    Assert.assertEquals(child.isMandatoryBooleanProperty(), Boolean.TRUE);
    Assert.assertEquals(child.getMandatoryClassProperty(),
        "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
    Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(),
        DirectoryServer.getAttributeType("description"));
    assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(),
        "dc=domain1,dc=com", "dc=domain2,dc=com", "dc=domain3,dc=com");
    assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(),
        "dc=domain1,dc=com", "dc=domain2,dc=com", "dc=domain3,dc=com");
  }
  /**
   * Tests retrieval of a top-level managed object using fails when an
   * Tests retrieval of a top-level managed object fails when an
   * underlying NamingException occurs.
   *
   * @param cause
@@ -358,8 +462,7 @@
    };
    c.importLDIF(TEST_LDIF);
    ManagementContext ctx = LDAPManagementContext.createFromContext(c,
        new MockLDAPProfile());
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    try {
      getTestParent(ctx, "test parent 2");
    } catch (Exception e) {
@@ -378,10 +481,17 @@
   */
  @Test
  public void testGetTopLevelManagedObject() throws Exception {
    ManagementContext ctx = getManagementContext(TEST_LDIF);
    MockLDAPConnection c = new MockLDAPConnection();
    c.importLDIF(TEST_LDIF);
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    TestParentCfgClient parent = getTestParent(ctx, "test parent 2");
    Assert.assertEquals(parent.getMinimumLength(), 10000);
    Assert.assertEquals(parent.getMaximumLength(), 20000);
    Assert.assertEquals(parent.isMandatoryBooleanProperty(), Boolean.TRUE);
    Assert.assertEquals(parent.getMandatoryClassProperty(),
        "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
    Assert.assertEquals(parent.getMandatoryReadOnlyAttributeTypeProperty(),
        DirectoryServer.getAttributeType("description"));
    assertDNSetEquals(parent.getOptionalMultiValuedDNProperty(),
        "dc=default value p2v1,dc=com", "dc=default value p2v2,dc=com");
  }
@@ -395,183 +505,17 @@
   */
  @Test
  public void testGetTopLevelManagedObjectDefault() throws Exception {
    ManagementContext ctx = getManagementContext(TEST_LDIF);
    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
    Assert.assertEquals(parent.getMinimumLength(), 123);
    Assert.assertEquals(parent.getMaximumLength(), 456);
  }
  /**
   * Tests listing of child managed objects.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testListChildManagedObjects() throws Exception {
    ManagementContext ctx = getManagementContext(TEST_LDIF);
    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
    String[] actual = parent.listTestChildren();
    String[] expected = new String[] { "test child 1", "test child 2" };
    Assert.assertEqualsNoOrder(actual, expected);
  }
  /**
   * Tests listing of child managed objects when their are not any.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testListChildManagedObjectsEmpty() throws Exception {
    ManagementContext ctx = getManagementContext(TEST_LDIF);
    TestParentCfgClient parent = getTestParent(ctx, "test parent 2");
    String[] actual = parent.listTestChildren();
    String[] expected = new String[] {};
    Assert.assertEqualsNoOrder(actual, expected);
  }
  /**
   * Tests listing of top level managed objects.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testListTopLevelManagedObjects() throws Exception {
    ManagementContext ctx = getManagementContext(TEST_LDIF);
    String[] actual = listTestParents(ctx);
    String[] expected = new String[] { "test parent 1", "test parent 2" };
    Assert.assertEqualsNoOrder(actual, expected);
  }
  /**
   * Tests listing of top level managed objects when their are not
   * any.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testListTopLevelManagedObjectsEmpty() throws Exception {
    ManagementContext ctx = getManagementContext();
    String[] actual = listTestParents(ctx);
    String[] expected = new String[] {};
    Assert.assertEqualsNoOrder(actual, expected);
  }
  /**
   * Tests modification of a child managed object.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testModifyChildManagedObjectResetToDefault() throws Exception {
    ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
        "cn=test child 2,cn=test-children,cn=test parent 1,cn=test-parents");
    MockLDAPConnection c = new MockLDAPConnection();
    c.importLDIF(TEST_LDIF);
    c.addExpectedModification("ds-cfg-heartbeat-interval");
    ManagementContext ctx = LDAPManagementContext.createFromContext(c,
        new MockLDAPProfile());
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
    TestChildCfgClient child = parent.getTestChild("test child 2");
    child.setHeartbeatInterval(null);
    child.commit();
    Assert.assertTrue(c.isEntryModified());
  }
  /**
   * Tests modification of a top-level managed object.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testModifyTopLevelManagedObjectNoChanges() throws Exception {
    ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
        "cn=test parent 1,cn=test-parents");
    c.importLDIF(TEST_LDIF);
    ManagementContext ctx = LDAPManagementContext.createFromContext(c,
        new MockLDAPProfile());
    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
    parent.commit();
    Assert.assertFalse(c.isEntryModified());
  }
  /**
   * Tests modification of a top-level managed object.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testModifyTopLevelManagedObjectWithChanges() throws Exception {
    ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
        "cn=test parent 1,cn=test-parents");
    c.importLDIF(TEST_LDIF);
    c.addExpectedModification("ds-cfg-maximum-length", "54321");
    c.addExpectedModification("ds-cfg-minimum-length", "12345");
    ManagementContext ctx = LDAPManagementContext.createFromContext(c,
        new MockLDAPProfile());
    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
    parent.setMaximumLength(54321);
    parent.setMinimumLength(12345);
    parent.commit();
    Assert.assertTrue(c.isEntryModified());
  }
  /**
   * Tests removal of a child managed object.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testRemoveChildManagedObject() throws Exception {
    DeleteSubtreeMockLDAPConnection c = new DeleteSubtreeMockLDAPConnection(
        "cn=test child 1,cn=test-children,cn=test parent 1,cn=test-parents");
    c.importLDIF(TEST_LDIF);
    ManagementContext ctx = LDAPManagementContext.createFromContext(c,
        new MockLDAPProfile());
    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
    parent.removeTestChild("test child 1");
    c.assertSubtreeIsDeleted();
  }
  /**
   * Tests removal of a top-level managed object.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testRemoveTopLevelManagedObject() throws Exception {
    DeleteSubtreeMockLDAPConnection c = new DeleteSubtreeMockLDAPConnection(
        "cn=test parent 1,cn=test-parents");
    c.importLDIF(TEST_LDIF);
    ManagementContext ctx = LDAPManagementContext.createFromContext(c,
        new MockLDAPProfile());
    removeTestParent(ctx, "test parent 1");
    c.assertSubtreeIsDeleted();
    Assert.assertEquals(parent.isMandatoryBooleanProperty(), Boolean.TRUE);
    Assert.assertEquals(parent.getMandatoryClassProperty(),
        "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
    Assert.assertEquals(parent.getMandatoryReadOnlyAttributeTypeProperty(),
        DirectoryServer.getAttributeType("description"));
    assertDNSetEquals(parent.getOptionalMultiValuedDNProperty(),
        "dc=domain1,dc=com", "dc=domain2,dc=com", "dc=domain3,dc=com");
  }
@@ -585,24 +529,35 @@
  @Test
  public void testInheritedDefaultValues1() throws Exception {
    CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
        "cn=test child 3,cn=test-children,cn=test parent 1,cn=test-parents");
        "cn=test child new,cn=test children,cn=test parent 1,cn=test parents,cn=config");
    c.importLDIF(TEST_LDIF);
    c.addExpectedAttribute("cn", "test child 3");
    c.addExpectedAttribute("objectclass", "top", "ds-cfg-test-child");
    c.addExpectedAttribute("cn", "test child new");
    c.addExpectedAttribute("objectclass", "top", "ds-cfg-virtual-attribute");
    c.addExpectedAttribute("ds-cfg-virtual-attribute-enabled", "true");
    c.addExpectedAttribute("ds-cfg-virtual-attribute-class",
        "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
    c.addExpectedAttribute("ds-cfg-virtual-attribute-type", "description");
    ManagementContext ctx = LDAPManagementContext.createFromContext(c,
        new MockLDAPProfile());
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
    TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn
        .getInstance(), "test child 3", null);
        .getInstance(), "test child new", null);
    // Inherits from parent (test parent 1).
    Assert.assertEquals(child.getMinimumLength(), 10000);
    // Inherits from test parent 2.
    Assert.assertEquals(child.getMaximumLength(), 456);
    // Check pre-commit values.
    Assert.assertEquals(child.isMandatoryBooleanProperty(), null);
    Assert.assertEquals(child.getMandatoryClassProperty(),
        "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
    Assert
        .assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), null);
    assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(),
        "dc=domain1,dc=com", "dc=domain2,dc=com", "dc=domain3,dc=com");
    assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(),
        "dc=domain1,dc=com", "dc=domain2,dc=com", "dc=domain3,dc=com");
    // Check that the default values are not committed.
    child.setMandatoryBooleanProperty(true);
    child.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer
        .getAttributeType("description"));
    child.commit();
    c.assertEntryIsCreated();
@@ -619,24 +574,35 @@
  @Test
  public void testInheritedDefaultValues2() throws Exception {
    CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
        "cn=test child 3,cn=test-children,cn=test parent 2,cn=test-parents");
        "cn=test child new,cn=test children,cn=test parent 2,cn=test parents,cn=config");
    c.importLDIF(TEST_LDIF);
    c.addExpectedAttribute("cn", "test child 3");
    c.addExpectedAttribute("objectclass", "top", "ds-cfg-test-child");
    c.addExpectedAttribute("cn", "test child new");
    c.addExpectedAttribute("objectclass", "top", "ds-cfg-virtual-attribute");
    c.addExpectedAttribute("ds-cfg-virtual-attribute-enabled", "true");
    c.addExpectedAttribute("ds-cfg-virtual-attribute-class",
        "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
    c.addExpectedAttribute("ds-cfg-virtual-attribute-type", "description");
    ManagementContext ctx = LDAPManagementContext.createFromContext(c,
        new MockLDAPProfile());
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    TestParentCfgClient parent = getTestParent(ctx, "test parent 2");
    TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn
        .getInstance(), "test child 3", null);
        .getInstance(), "test child new", null);
    // Inherits from parent (test parent 2).
    Assert.assertEquals(child.getMinimumLength(), 10000);
    // Inherits from test parent 2.
    Assert.assertEquals(child.getMaximumLength(), 20000);
    // Check pre-commit values.
    Assert.assertEquals(child.isMandatoryBooleanProperty(), null);
    Assert.assertEquals(child.getMandatoryClassProperty(),
        "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
    Assert
        .assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), null);
    assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(),
        "dc=default value p2v1,dc=com", "dc=default value p2v2,dc=com");
    assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(),
        "dc=default value p2v1,dc=com", "dc=default value p2v2,dc=com");
    // Check that the default values are not committed.
    child.setMandatoryBooleanProperty(true);
    child.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer
        .getAttributeType("description"));
    child.commit();
    c.assertEntryIsCreated();
@@ -644,6 +610,202 @@
  /**
   * Tests listing of child managed objects.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testListChildManagedObjects() throws Exception {
    MockLDAPConnection c = new MockLDAPConnection();
    c.importLDIF(TEST_LDIF);
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
    String[] actual = parent.listTestChildren();
    String[] expected = new String[] {
        "test child 1", "test child 2", "test child 3"
    };
    Assert.assertEqualsNoOrder(actual, expected);
  }
  /**
   * Tests listing of child managed objects when their are not any.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testListChildManagedObjectsEmpty() throws Exception {
    MockLDAPConnection c = new MockLDAPConnection();
    c.importLDIF(TEST_LDIF);
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    TestParentCfgClient parent = getTestParent(ctx, "test parent 3");
    String[] actual = parent.listTestChildren();
    String[] expected = new String[] {};
    Assert.assertEqualsNoOrder(actual, expected);
  }
  /**
   * Tests listing of top level managed objects.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testListTopLevelManagedObjects() throws Exception {
    MockLDAPConnection c = new MockLDAPConnection();
    c.importLDIF(TEST_LDIF);
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    String[] actual = listTestParents(ctx);
    String[] expected = new String[] {
        "test parent 1", "test parent 2", "test parent 3"
    };
    Assert.assertEqualsNoOrder(actual, expected);
  }
  /**
   * Tests listing of top level managed objects when their are not
   * any.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testListTopLevelManagedObjectsEmpty() throws Exception {
    String[] ldif = {};
    MockLDAPConnection c = new MockLDAPConnection();
    c.importLDIF(ldif);
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    String[] actual = listTestParents(ctx);
    String[] expected = new String[] {};
    Assert.assertEqualsNoOrder(actual, expected);
  }
  /**
   * Tests modification of a child managed object.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testModifyChildManagedObjectResetToDefault() throws Exception {
    ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
        "cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config");
    c.importLDIF(TEST_LDIF);
    c.addExpectedModification("ds-cfg-virtual-attribute-base-dn");
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
    TestChildCfgClient child = parent.getTestChild("test child 2");
    child.setOptionalMultiValuedDNProperty1(Collections.<DN> emptySet());
    child.commit();
    Assert.assertTrue(c.isEntryModified());
  }
  /**
   * Tests modification of a top-level managed object.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testModifyTopLevelManagedObjectNoChanges() throws Exception {
    ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
        "cn=test parent 1,cn=test parents,cn=config");
    c.importLDIF(TEST_LDIF);
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
    parent.commit();
    Assert.assertFalse(c.isEntryModified());
  }
  /**
   * Tests modification of a top-level managed object.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testModifyTopLevelManagedObjectWithChanges() throws Exception {
    ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
        "cn=test parent 1,cn=test parents,cn=config");
    c.importLDIF(TEST_LDIF);
    c.addExpectedModification("ds-cfg-virtual-attribute-enabled", "false");
    c.addExpectedModification("ds-cfg-virtual-attribute-base-dn",
        "dc=mod1,dc=com", "dc=mod2,dc=com");
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
    parent.setMandatoryBooleanProperty(false);
    parent.setOptionalMultiValuedDNProperty(Arrays.asList(DN
        .decode("dc=mod1,dc=com"), DN.decode("dc=mod2,dc=com")));
    parent.commit();
    Assert.assertTrue(c.isEntryModified());
  }
  /**
   * Tests removal of a child managed object.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testRemoveChildManagedObject() throws Exception {
    DeleteSubtreeMockLDAPConnection c = new DeleteSubtreeMockLDAPConnection(
        "cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config");
    c.importLDIF(TEST_LDIF);
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
    parent.removeTestChild("test child 1");
    c.assertSubtreeIsDeleted();
  }
  /**
   * Tests removal of a top-level managed object.
   *
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test
  public void testRemoveTopLevelManagedObject() throws Exception {
    DeleteSubtreeMockLDAPConnection c = new DeleteSubtreeMockLDAPConnection(
        "cn=test parent 1,cn=test parents,cn=config");
    c.importLDIF(TEST_LDIF);
    ManagementContext ctx = LDAPManagementContext.createFromContext(c);
    removeTestParent(ctx, "test parent 1");
    c.assertSubtreeIsDeleted();
  }
  // Asserts that the actual set of DNs contains the expected values.
  private void assertDNSetEquals(SortedSet<DN> actual, String... expected) {
    String[] actualStrings = new String[actual.size()];
    int i = 0;
    for (DN dn : actual) {
      actualStrings[i] = dn.toString();
      i++;
    }
    Assert.assertEqualsNoOrder(actualStrings, expected);
  }
  // Create the named test parent managed object.
  private TestParentCfgClient createTestParent(ManagementContext context,
      String name) throws ManagedObjectDecodingException,
@@ -652,21 +814,13 @@
      CommunicationException {
    ManagedObject<RootCfgClient> root = context
        .getRootConfigurationManagedObject();
    return root.createChild(TestParentCfgDefn.RD_TEST_PARENT,
    return root.createChild(
        org.opends.server.admin.TestCfg.RD_TEST_ONE_TO_MANY_PARENT,
        TestParentCfgDefn.getInstance(), name, null).getConfiguration();
  }
  // Creates a management context using the provided LDIF.
  private ManagementContext getManagementContext(String... ldif) {
    MockLDAPConnection c = new MockLDAPConnection();
    c.importLDIF(ldif);
    return LDAPManagementContext.createFromContext(c, new MockLDAPProfile());
  }
  // Retrieve the named test parent managed object.
  private TestParentCfgClient getTestParent(ManagementContext context,
      String name) throws DefinitionDecodingException,
@@ -675,7 +829,8 @@
      CommunicationException {
    ManagedObject<RootCfgClient> root = context
        .getRootConfigurationManagedObject();
    return root.getChild(TestParentCfgDefn.RD_TEST_PARENT, name)
    return root.getChild(
        org.opends.server.admin.TestCfg.RD_TEST_ONE_TO_MANY_PARENT, name)
        .getConfiguration();
  }
@@ -687,7 +842,8 @@
      CommunicationException {
    ManagedObject<RootCfgClient> root = context
        .getRootConfigurationManagedObject();
    return root.listChildren(TestParentCfgDefn.RD_TEST_PARENT);
    return root
        .listChildren(org.opends.server.admin.TestCfg.RD_TEST_ONE_TO_MANY_PARENT);
  }
@@ -699,6 +855,7 @@
      CommunicationException {
    ManagedObject<RootCfgClient> root = context
        .getRootConfigurationManagedObject();
    root.removeChild(TestParentCfgDefn.RD_TEST_PARENT, name);
    root.removeChild(
        org.opends.server.admin.TestCfg.RD_TEST_ONE_TO_MANY_PARENT, name);
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/DNBuilderTest.java
@@ -28,25 +28,24 @@
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.*;
import org.opends.server.TestCaseUtils;
import org.opends.server.admin.AdminTestCase;
import org.opends.server.admin.Configuration;
import org.opends.server.admin.ConfigurationClient;
import org.opends.server.admin.InstantiableRelationDefinition;
import org.opends.server.admin.LDAPProfile;
import org.opends.server.admin.ManagedObjectPath;
import org.opends.server.admin.MockLDAPProfile;
import org.opends.server.admin.OptionalRelationDefinition;
import org.opends.server.admin.RelationDefinition;
import org.opends.server.admin.SingletonRelationDefinition;
import org.opends.server.admin.TestCfg;
import org.opends.server.admin.TestChildCfg;
import org.opends.server.admin.TestChildCfgClient;
import org.opends.server.admin.TestChildCfgDefn;
import org.opends.server.admin.TestParentCfg;
import org.opends.server.admin.TestParentCfgClient;
import org.opends.server.admin.TestParentCfgDefn;
import org.opends.server.admin.std.meta.RootCfgDefn;
import org.opends.server.types.DN;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@@ -68,6 +67,17 @@
    // This test suite depends on having the schema available, so
    // we'll start the server.
    TestCaseUtils.startServer();
    LDAPProfile.getInstance().pushWrapper(new MockLDAPProfile());
  }
  /**
   * Tears down test environment.
   */
  @AfterClass
  public void tearDown() {
    LDAPProfile.getInstance().popWrapper();
  }
@@ -82,25 +92,19 @@
  @Test
  public void testCreateOneToMany() throws Exception {
    // First create the path.
    ManagedObjectPath<? extends ConfigurationClient, ? extends Configuration> path = ManagedObjectPath.emptyPath();
    ManagedObjectPath<? extends ConfigurationClient, ? extends Configuration> path = ManagedObjectPath
        .emptyPath();
    InstantiableRelationDefinition<TestParentCfgClient, TestParentCfg> r1 = new InstantiableRelationDefinition<TestParentCfgClient, TestParentCfg>(
        RootCfgDefn.getInstance(), "test-parent", "test-parents",
        TestParentCfgDefn.getInstance());
    InstantiableRelationDefinition<TestChildCfgClient, TestChildCfg> r2 = new InstantiableRelationDefinition<TestChildCfgClient, TestChildCfg>(
        TestParentCfgDefn.getInstance(), "test-child",
        "test-children", TestChildCfgDefn.getInstance());
    path = path.child(r1, "test-parent-1");
    path = path.child(r2, "test-child-1");
    path = path.child(TestCfg.RD_TEST_ONE_TO_MANY_PARENT, "test-parent-1");
    path = path.child(TestParentCfgDefn.getInstance()
        .getTestChildrenRelationDefinition(), "test-child-1");
    // Now serialize it.
    DNBuilder builder = new DNBuilder(new MockLDAPProfile());
    DNBuilder builder = new DNBuilder();
    path.serialize(builder);
    DN actual = builder.getInstance();
    DN expected = DN
        .decode("cn=test-child-1,cn=test-children,cn=test-parent-1,cn=test-parents");
        .decode("cn=test-child-1,cn=test children,cn=test-parent-1,cn=test parents,cn=config");
    assertEquals(actual, expected);
  }
@@ -117,27 +121,44 @@
  @Test
  public void testCreateOneToOne() throws Exception {
    // First create the path.
    ManagedObjectPath<? extends ConfigurationClient, ? extends Configuration> path = ManagedObjectPath.emptyPath();
    ManagedObjectPath<? extends ConfigurationClient, ? extends Configuration> path = ManagedObjectPath
        .emptyPath();
    InstantiableRelationDefinition<TestParentCfgClient, TestParentCfg> r1 = new InstantiableRelationDefinition<TestParentCfgClient, TestParentCfg>(
        RootCfgDefn.getInstance(), "test-parent", "test-parents",
        TestParentCfgDefn.getInstance());
    SingletonRelationDefinition<TestChildCfgClient, TestChildCfg> r2 = new SingletonRelationDefinition<TestChildCfgClient, TestChildCfg>(
    final SingletonRelationDefinition<TestChildCfgClient, TestChildCfg> r2 = new SingletonRelationDefinition<TestChildCfgClient, TestChildCfg>(
        TestParentCfgDefn.getInstance(), "singleton-test-child",
        TestChildCfgDefn.getInstance());
    LDAPProfile.Wrapper wrapper = new LDAPProfile.Wrapper() {
    path = path.child(r1, "test-parent-1");
      /**
       * {@inheritDoc}
       */
      @Override
      public String getRelationRDNSequence(RelationDefinition<?, ?> r) {
        if (r == r2) {
          return "cn=singleton-test-child";
        } else {
          return null;
        }
      }
    };
    path = path.child(TestCfg.RD_TEST_ONE_TO_MANY_PARENT, "test-parent-1");
    path = path.child(r2);
    // Now serialize it.
    DNBuilder builder = new DNBuilder(new MockLDAPProfile());
    path.serialize(builder);
    DN actual = builder.getInstance();
    DN expected = DN
        .decode("cn=singleton-test-child,cn=test-parent-1,cn=test-parents");
    LDAPProfile.getInstance().pushWrapper(wrapper);
    try {
      DNBuilder builder = new DNBuilder();
      path.serialize(builder);
      DN actual = builder.getInstance();
      DN expected = DN
          .decode("cn=singleton-test-child,cn=test-parent-1,cn=test parents,cn=config");
    assertEquals(actual, expected);
      assertEquals(actual, expected);
    } finally {
      LDAPProfile.getInstance().popWrapper();
    }
  }
@@ -152,25 +173,19 @@
  @Test
  public void testCreateOneToZeroOrOne() throws Exception {
    // First create the path.
    ManagedObjectPath<? extends ConfigurationClient, ? extends Configuration> path = ManagedObjectPath.emptyPath();
    ManagedObjectPath<? extends ConfigurationClient, ? extends Configuration> path = ManagedObjectPath
        .emptyPath();
    InstantiableRelationDefinition<TestParentCfgClient, TestParentCfg> r1 = new InstantiableRelationDefinition<TestParentCfgClient, TestParentCfg>(
        RootCfgDefn.getInstance(), "test-parent", "test-parents",
        TestParentCfgDefn.getInstance());
    OptionalRelationDefinition<TestChildCfgClient, TestChildCfg> r2 = new OptionalRelationDefinition<TestChildCfgClient, TestChildCfg>(
        TestParentCfgDefn.getInstance(), "optional-test-child",
        TestChildCfgDefn.getInstance());
    path = path.child(r1, "test-parent-1");
    path = path.child(r2);
    path = path.child(TestCfg.RD_TEST_ONE_TO_MANY_PARENT, "test-parent-1");
    path = path.child(TestParentCfgDefn.getInstance()
        .getOptionalTestChildRelationDefinition());
    // Now serialize it.
    DNBuilder builder = new DNBuilder(new MockLDAPProfile());
    DNBuilder builder = new DNBuilder();
    path.serialize(builder);
    DN actual = builder.getInstance();
    DN expected = DN
        .decode("cn=optional-test-child,cn=test-parent-1,cn=test-parents");
        .decode("cn=optional test child,cn=test-parent-1,cn=test parents,cn=config");
    assertEquals(actual, expected);
  }
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/ListenerTest.java
New file
@@ -0,0 +1,547 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.server.admin.server;
import static org.testng.Assert.*;
import java.util.List;
import org.opends.server.TestCaseUtils;
import org.opends.server.admin.AdminTestCase;
import org.opends.server.admin.LDAPProfile;
import org.opends.server.admin.MockLDAPProfile;
import org.opends.server.admin.TestCfg;
import org.opends.server.admin.TestParentCfg;
import org.opends.server.admin.std.server.RootCfg;
import org.opends.server.api.ConfigAddListener;
import org.opends.server.api.ConfigDeleteListener;
import org.opends.server.config.ConfigEntry;
import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DN;
import org.opends.server.types.ResultCode;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
 * Test cases for listener registration.
 */
public final class ListenerTest extends AdminTestCase {
  // Add listener implementation.
  private static final class TestParentAddListener implements
      ConfigurationAddListener<TestParentCfg> {
    /**
     * {@inheritDoc}
     */
    public ConfigChangeResult applyConfigurationAdd(TestParentCfg configuration) {
      // No implementation required.
      return null;
    }
    /**
     * {@inheritDoc}
     */
    public boolean isConfigurationAddAcceptable(TestParentCfg configuration,
        List<String> unacceptableReasons) {
      // No implementation required.
      return false;
    }
  }
  // Delete listener implementation.
  private static final class TestParentDeleteListener implements
      ConfigurationDeleteListener<TestParentCfg> {
    /**
     * {@inheritDoc}
     */
    public ConfigChangeResult applyConfigurationDelete(
        TestParentCfg configuration) {
      // No implementation required.
      return null;
    }
    /**
     * {@inheritDoc}
     */
    public boolean isConfigurationDeleteAcceptable(TestParentCfg configuration,
        List<String> unacceptableReasons) {
      // No implementation required.
      return false;
    }
  }
  /**
   * Sets up tests
   *
   * @throws Exception
   *           If the server could not be initialized.
   */
  @BeforeClass
  public void setUp() throws Exception {
    // This test suite depends on having the schema available, so
    // we'll start the server.
    TestCaseUtils.startServer();
    LDAPProfile.getInstance().pushWrapper(new MockLDAPProfile());
  }
  /**
   * Tears down test environment.
   */
  @AfterClass
  public void tearDown() {
    LDAPProfile.getInstance().popWrapper();
  }
  /**
   * Checks that a ConfigAddListenerAdaptor is delayed when its
   * associated instantiable relation entry does not exist.
   *
   * @throws Exception
   *           If an unexpected exception occurred.
   */
  @Test
  public void testConfigAddListenerAdaptorInstantiableDelayed()
      throws Exception {
    ServerManagementContext ctx = ServerManagementContext.getInstance();
    ServerManagedObject<RootCfg> root = ctx.getRootConfigurationManagedObject();
    ConfigurationAddListener<TestParentCfg> listener = new TestParentAddListener();
    root.registerAddListener(TestCfg.RD_TEST_ONE_TO_MANY_PARENT, listener);
    // Make sure that the relation entry does not exist.
    DN relationDN = DN.decode("cn=test parents,cn=config");
    ConfigEntry configEntry = DirectoryServer.getConfigEntry(relationDN);
    assertNull(configEntry, "Relation entry " + relationDN + " already exists");
    // Make sure that the listener was delayed and registered against
    // the parent.
    DN parentDN = DN.decode("cn=config");
    configEntry = DirectoryServer.getConfigEntry(parentDN);
    assertNotNull(configEntry, "Relation parent entry " + parentDN
        + " does not exist");
    boolean isFound = false;
    for (ConfigAddListener l : configEntry.getAddListeners()) {
      if (l instanceof DelayedConfigAddListener) {
        DelayedConfigAddListener dl = (DelayedConfigAddListener) l;
        ConfigAddListener tmp = dl.getDelayedAddListener();
        if (tmp instanceof ConfigAddListenerAdaptor) {
          ConfigAddListenerAdaptor al = (ConfigAddListenerAdaptor) tmp;
          if (al.getConfigurationAddListener() == listener) {
            isFound = true;
          }
        }
      }
    }
    if (!isFound) {
      fail("Unable to locate delayed listener in entry " + parentDN);
    }
    // Now make sure that the delayed listener is removed from the
    // parent and the add listener register against the relation entry
    // when it is created.
    String[] entry = new String[] {
        "dn: cn=test parents,cn=config",
        "objectclass: top",
        "objectclass: ds-cfg-branch",
        "cn: test-parents"
    };
    TestCaseUtils.addEntry(entry);
    // Check the delayed listener is removed.
    for (ConfigAddListener l : configEntry.getAddListeners()) {
      if (l instanceof DelayedConfigAddListener) {
        DelayedConfigAddListener dl = (DelayedConfigAddListener) l;
        ConfigAddListener tmp = dl.getDelayedAddListener();
        if (tmp instanceof ConfigAddListenerAdaptor) {
          ConfigAddListenerAdaptor al = (ConfigAddListenerAdaptor) tmp;
          if (al.getConfigurationAddListener() == listener) {
            fail("Delayed listener still exists in entry " + parentDN
                + " when it should have been removed");
            // Clean up.
            configEntry.deregisterAddListener(dl);
          }
        }
      }
    }
    // Check the add listener is registered.
    configEntry = DirectoryServer.getConfigEntry(relationDN);
    assertNotNull(configEntry, "Relation entry " + relationDN
        + " does not exist");
    isFound = false;
    for (ConfigAddListener l : configEntry.getAddListeners()) {
      if (l instanceof ConfigAddListenerAdaptor) {
        ConfigAddListenerAdaptor al = (ConfigAddListenerAdaptor) l;
        if (al.getConfigurationAddListener() == listener) {
          isFound = true;
          // Clean up.
          configEntry.deregisterAddListener(al);
        }
      }
    }
    if (!isFound) {
      fail("Unable to locate listener adaptor in entry " + relationDN);
    }
    // Remove the test entry.
    InternalClientConnection conn = InternalClientConnection
        .getRootConnection();
    DeleteOperation deleteOperation = conn.processDelete(relationDN);
    assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
  }
  /**
   * Checks that a ConfigAddListenerAdaptor is not delayed when its
   * associated instantiable relation entry already exists.
   *
   * @throws Exception
   *           If an unexpected exception occurred.
   */
  @Test
  public void testConfigAddListenerAdaptorInstantiableImmediate()
      throws Exception {
    ServerManagementContext ctx = ServerManagementContext.getInstance();
    ServerManagedObject<RootCfg> root = ctx.getRootConfigurationManagedObject();
    ConfigurationAddListener<TestParentCfg> listener = new TestParentAddListener();
    root.registerAddListener(TestCfg.RD_TEST_ONE_TO_MANY_PARENT, listener);
    // Add the relation entry.
    String[] entry = new String[] {
        "dn: cn=test parents,cn=config",
        "objectclass: top",
        "objectclass: ds-cfg-branch",
        "cn: test-parents"
    };
    TestCaseUtils.addEntry(entry);
    // Make sure that the relation entry exist.
    DN relationDN = DN.decode("cn=test parents,cn=config");
    ConfigEntry configEntry = DirectoryServer.getConfigEntry(relationDN);
    assertNotNull(configEntry, "Relation entry " + relationDN
        + " does not exist");
    // Check the add listener is registered.
    boolean isFound = false;
    for (ConfigAddListener l : configEntry.getAddListeners()) {
      if (l instanceof ConfigAddListenerAdaptor) {
        ConfigAddListenerAdaptor al = (ConfigAddListenerAdaptor) l;
        if (al.getConfigurationAddListener() == listener) {
          isFound = true;
          // Clean up.
          configEntry.deregisterAddListener(al);
        }
      }
    }
    if (!isFound) {
      fail("Unable to locate listener adaptor in entry " + relationDN);
    }
    // Remove the test entry.
    InternalClientConnection conn = InternalClientConnection
        .getRootConnection();
    DeleteOperation deleteOperation = conn.processDelete(relationDN);
    assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
  }
  /**
   * Checks that a ConfigAddListenerAdaptor is registered for optional
   * relations.
   *
   * @throws Exception
   *           If an unexpected exception occurred.
   */
  @Test
  public void testConfigAddListenerAdaptorOptional() throws Exception {
    ServerManagementContext ctx = ServerManagementContext.getInstance();
    ServerManagedObject<RootCfg> root = ctx.getRootConfigurationManagedObject();
    ConfigurationAddListener<TestParentCfg> listener = new TestParentAddListener();
    root.registerAddListener(TestCfg.RD_TEST_ONE_TO_ZERO_OR_ONE_PARENT,
        listener);
    // Make sure that the relation entry exists.
    DN relationDN = DN.decode("cn=config");
    ConfigEntry configEntry = DirectoryServer.getConfigEntry(relationDN);
    assertNotNull(configEntry, "Relation entry " + relationDN
        + " does not exist");
    // Check the add listener is registered.
    boolean isFound = false;
    for (ConfigAddListener l : configEntry.getAddListeners()) {
      if (l instanceof ConfigAddListenerAdaptor) {
        ConfigAddListenerAdaptor al = (ConfigAddListenerAdaptor) l;
        if (al.getConfigurationAddListener() == listener) {
          isFound = true;
          // Clean up.
          configEntry.deregisterAddListener(al);
        }
      }
    }
    if (!isFound) {
      fail("Unable to locate listener adaptor in entry " + relationDN);
    }
  }
  /**
   * Checks that a ConfigDeleteListenerAdaptor is delayed when its
   * associated instantiable relation entry does not exist.
   *
   * @throws Exception
   *           If an unexpected exception occurred.
   */
  @Test
  public void testConfigDeleteListenerAdaptorInstantiableDelayed()
      throws Exception {
    ServerManagementContext ctx = ServerManagementContext.getInstance();
    ServerManagedObject<RootCfg> root = ctx.getRootConfigurationManagedObject();
    ConfigurationDeleteListener<TestParentCfg> listener = new TestParentDeleteListener();
    root.registerDeleteListener(TestCfg.RD_TEST_ONE_TO_MANY_PARENT, listener);
    // Make sure that the relation entry does not exist.
    DN relationDN = DN.decode("cn=test parents,cn=config");
    ConfigEntry configEntry = DirectoryServer.getConfigEntry(relationDN);
    assertNull(configEntry, "Relation entry " + relationDN + " already exists");
    // Make sure that the listener was delayed and registered against
    // the parent.
    DN parentDN = DN.decode("cn=config");
    configEntry = DirectoryServer.getConfigEntry(parentDN);
    assertNotNull(configEntry, "Relation parent entry " + parentDN
        + " does not exist");
    boolean isFound = false;
    for (ConfigAddListener l : configEntry.getAddListeners()) {
      if (l instanceof DelayedConfigAddListener) {
        DelayedConfigAddListener dl = (DelayedConfigAddListener) l;
        ConfigDeleteListener tmp = dl.getDelayedDeleteListener();
        if (tmp instanceof ConfigDeleteListenerAdaptor) {
          ConfigDeleteListenerAdaptor al = (ConfigDeleteListenerAdaptor) tmp;
          if (al.getConfigurationDeleteListener() == listener) {
            isFound = true;
          }
        }
      }
    }
    if (!isFound) {
      fail("Unable to locate delayed listener in entry " + parentDN);
    }
    // Now make sure that the delayed listener is removed from the
    // parent and the add listener register against the relation entry
    // when it is created.
    String[] entry = new String[] {
        "dn: cn=test parents,cn=config",
        "objectclass: top",
        "objectclass: ds-cfg-branch",
        "cn: test-parents"
    };
    TestCaseUtils.addEntry(entry);
    // Check the delayed listener is removed.
    for (ConfigAddListener l : configEntry.getAddListeners()) {
      if (l instanceof DelayedConfigAddListener) {
        DelayedConfigAddListener dl = (DelayedConfigAddListener) l;
        ConfigDeleteListener tmp = dl.getDelayedDeleteListener();
        if (tmp instanceof ConfigDeleteListenerAdaptor) {
          ConfigDeleteListenerAdaptor al = (ConfigDeleteListenerAdaptor) tmp;
          if (al.getConfigurationDeleteListener() == listener) {
            fail("Delayed listener still exists in entry " + parentDN
                + " when it should have been removed");
            // Clean up.
            configEntry.deregisterAddListener(dl);
          }
        }
      }
    }
    // Check the add listener is registered.
    configEntry = DirectoryServer.getConfigEntry(relationDN);
    assertNotNull(configEntry, "Relation entry " + relationDN
        + " does not exist");
    isFound = false;
    for (ConfigDeleteListener l : configEntry.getDeleteListeners()) {
      if (l instanceof ConfigDeleteListenerAdaptor) {
        ConfigDeleteListenerAdaptor al = (ConfigDeleteListenerAdaptor) l;
        if (al.getConfigurationDeleteListener() == listener) {
          isFound = true;
          // Clean up.
          configEntry.deregisterDeleteListener(al);
        }
      }
    }
    if (!isFound) {
      fail("Unable to locate listener adaptor in entry " + relationDN);
    }
    // Remove the test entry.
    InternalClientConnection conn = InternalClientConnection
        .getRootConnection();
    DeleteOperation deleteOperation = conn.processDelete(relationDN);
    assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
  }
  /**
   * Checks that a ConfigDeleteListenerAdaptor is not delayed when its
   * associated instantiable relation entry already exists.
   *
   * @throws Exception
   *           If an unexpected exception occurred.
   */
  @Test
  public void testConfigDeleteListenerAdaptorInstantiableImmediate()
      throws Exception {
    ServerManagementContext ctx = ServerManagementContext.getInstance();
    ServerManagedObject<RootCfg> root = ctx.getRootConfigurationManagedObject();
    ConfigurationDeleteListener<TestParentCfg> listener = new TestParentDeleteListener();
    root.registerDeleteListener(TestCfg.RD_TEST_ONE_TO_MANY_PARENT, listener);
    // Add the relation entry.
    String[] entry = new String[] {
        "dn: cn=test parents,cn=config",
        "objectclass: top",
        "objectclass: ds-cfg-branch",
        "cn: test-parents"
    };
    TestCaseUtils.addEntry(entry);
    // Make sure that the relation entry exist.
    DN relationDN = DN.decode("cn=test parents,cn=config");
    ConfigEntry configEntry = DirectoryServer.getConfigEntry(relationDN);
    assertNotNull(configEntry, "Relation entry " + relationDN
        + " does not exist");
    // Check the add listener is registered.
    boolean isFound = false;
    for (ConfigDeleteListener l : configEntry.getDeleteListeners()) {
      if (l instanceof ConfigDeleteListenerAdaptor) {
        ConfigDeleteListenerAdaptor al = (ConfigDeleteListenerAdaptor) l;
        if (al.getConfigurationDeleteListener() == listener) {
          isFound = true;
          // Clean up.
          configEntry.deregisterDeleteListener(al);
        }
      }
    }
    if (!isFound) {
      fail("Unable to locate listener adaptor in entry " + relationDN);
    }
    // Remove the test entry.
    InternalClientConnection conn = InternalClientConnection
        .getRootConnection();
    DeleteOperation deleteOperation = conn.processDelete(relationDN);
    assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
  }
  /**
   * Checks that a ConfigDeleteListenerAdaptor is registered for
   * optional relations.
   *
   * @throws Exception
   *           If an unexpected exception occurred.
   */
  @Test
  public void testConfigDeleteListenerAdaptorOptional() throws Exception {
    ServerManagementContext ctx = ServerManagementContext.getInstance();
    ServerManagedObject<RootCfg> root = ctx.getRootConfigurationManagedObject();
    ConfigurationDeleteListener<TestParentCfg> listener = new TestParentDeleteListener();
    root.registerDeleteListener(TestCfg.RD_TEST_ONE_TO_ZERO_OR_ONE_PARENT,
        listener);
    // Make sure that the relation entry exists.
    DN relationDN = DN.decode("cn=config");
    ConfigEntry configEntry = DirectoryServer.getConfigEntry(relationDN);
    assertNotNull(configEntry, "Relation entry " + relationDN
        + " does not exist");
    // Check the add listener is registered.
    boolean isFound = false;
    for (ConfigDeleteListener l : configEntry.getDeleteListeners()) {
      if (l instanceof ConfigDeleteListenerAdaptor) {
        ConfigDeleteListenerAdaptor al = (ConfigDeleteListenerAdaptor) l;
        if (al.getConfigurationDeleteListener() == listener) {
          isFound = true;
          // Clean up.
          configEntry.deregisterDeleteListener(al);
        }
      }
    }
    if (!isFound) {
      fail("Unable to locate listener adaptor in entry " + relationDN);
    }
  }
}