From c5e1bceb1bcb9f1f36d5b5f568ac5fd3b73d9c2c Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Fri, 13 Dec 2013 14:07:45 +0000
Subject: [PATCH] Checkpoint commit for OPENDJ-1235 : Migrate configuration framework

---
 opendj-admin/src/test/java/org/opends/server/admin/TestTopCfgDefnTest.java                           |  115 
 opendj-admin/src/test/java/org/opends/server/admin/TestChildCfgDefn.properties                       |    9 
 opendj-admin/src/test/java/org/opends/server/admin/TestParentCfgDefn.properties                      |   12 
 opendj-admin/src/test/java/org/opends/server/admin/BooleanPropertyDefinitionTest.java                |   87 
 opendj-admin/src/test/java/org/opends/server/admin/DurationUnitTest.java                             |   90 
 opendj-admin/src/test/java/org/opends/server/admin/MockLDAPProfile.java                              |  148 +
 opendj-admin/src/test/java/org/opends/server/admin/StringPropertyDefinitionTest.java                 |   84 
 opendj-admin/src/test/java/org/opends/server/admin/AbstractManagedObjectDefinitionTest.java          |  209 +
 opendj-admin/src/test/java/org/opends/server/admin/IntegerPropertyDefinitionTest.java                |  241 ++
 opendj-admin/src/test/java/org/opends/server/admin/SizeUnitTest.java                                 |  279 ++
 opendj-admin/src/main/java/org/opends/server/admin/ManagedObjectDefinitionI18NResource.java          |  534 ++--
 opendj-admin/src/test/java/org/opends/server/admin/TestChildCfg.java                                 |  125 +
 opendj-admin/src/test/java/org/opends/server/admin/AdminTestCase.java                                |   39 
 opendj-admin/src/test/java/org/opends/server/admin/TestParentCfg.java                                |  216 +
 opendj-admin/src/test/java/org/opends/server/admin/EnumPropertyDefinitionTest.java                   |  143 +
 opendj-admin/src/main/java/org/opends/server/core/DirectoryServer.java                               |   69 
 opendj-admin/src/test/java/org/opends/server/admin/ClassPropertyDefinitionTest.java                  |  153 +
 opendj-admin/src/test/java/org/opends/server/admin/AggregationPropertyDefinitionTest.java            |   81 
 opendj-admin/src/test/java/org/opends/server/admin/AttributeTypePropertyDefinitionTest.java          |  105 
 opendj-admin/src/main/java/org/opends/server/admin/TopCfgDefn.java                                   |   63 
 opendj-admin/src/test/java/org/opends/server/admin/TestParentCfgClient.java                          |  300 ++
 opendj-admin/src/test/java/org/opends/server/admin/ValidateConfigDefinitionsTest.java                |  220 +
 opendj-admin/src/test/java/org/opends/server/admin/TestChildCfgDefn.java                             |  474 ++++
 opendj-admin/pom.xml                                                                                 |   53 
 opendj-admin/src/test/java/org/opends/server/admin/TestCfg.java                                      |  222 +
 opendj-admin/src/test/java/org/opends/server/admin/DurationPropertyDefinitionTest.java               |  359 +++
 opendj-admin/src/test/java/org/opends/server/admin/DNPropertyDefinitionTest.java                     |  135 +
 opendj-admin/src/test/java/org/opends/server/admin/TestParentCfgDefn.java                            |  568 ++++
 opendj-admin/src/test/java/org/opends/server/admin/TestParentConfiguration.xml                       |  134 +
 opendj-admin/src/test/java/org/opends/server/admin/ManagedObjectDefinitionI18NResourceTest.java      |   58 
 opendj-admin/src/test/java/org/opends/server/admin/SizePropertyDefinitionTest.java                   |  260 ++
 opendj-admin/src/main/java/org/opends/server/admin/LDAPProfile.java                                  |  632 ++--
 opendj-admin/src/test/java/org/opends/server/admin/TestChildCfgClient.java                           |  193 +
 opendj-admin/src/test/java/org/opends/server/admin/LDAPProfileTest.java                              |   54 
 opendj-admin/src/test/java/org/opends/server/admin/ManagedObjectPathTest.java                        |  242 ++
 opendj-admin/src/test/java/org/opends/server/admin/RelativeInheritedDefaultBehaviorProviderTest.java |   99 
 opendj-admin/src/test/java/org/opends/server/admin/TestChildConfiguration.xml                        |  161 +
 37 files changed, 6,267 insertions(+), 699 deletions(-)

diff --git a/opendj-admin/pom.xml b/opendj-admin/pom.xml
index ef20cf6..522299e 100644
--- a/opendj-admin/pom.xml
+++ b/opendj-admin/pom.xml
@@ -64,11 +64,12 @@
       com.sun.security.auth*;resolution:=optional,
       *
     </opendj.osgi.import>
-    <xmlDefinitionsBaseDir>${basedir}/src/main/resources/definitions</xmlDefinitionsBaseDir>
+    <mainResourcesDir>${basedir}/src/main/resources</mainResourcesDir>
+    <xmlDefinitionsBaseDir>${mainResourcesDir}/definitions</xmlDefinitionsBaseDir>
     <xmlDefinitionsDir>${xmlDefinitionsBaseDir}/org/forgerock/opendj/admin</xmlDefinitionsDir>
     <adminPackage>org/forgerock/opendj/admin</adminPackage>
     <generatedSourcesDir>${project.build.directory}/generated-sources/admin/${adminPackage}</generatedSourcesDir>
-    <xslDir>${basedir}/src/main/resources/stylesheets</xslDir>
+    <xslDir>${mainResourcesDir}/stylesheets</xslDir>
 
     <!-- properties used to generate DynamicConstant class -->
     <serverProductName>OpenDJ</serverProductName>
@@ -182,7 +183,8 @@
           </execution>
         </executions>
       </plugin>
-      <!-- Generate core administration components. -->
+      <!-- Validate core components XML definition files 
+           and generate the components. -->
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>xml-maven-plugin</artifactId>
@@ -388,10 +390,36 @@
                     </parameter>
                   </parameters>
                 </transformationSet>
-                <!-- Generate I18N messages for core administration components. -->
+                <!-- Generate manifest file for core administration components. -->
                 <transformationSet>
                   <dir>${xmlDefinitionsDir}</dir>
-                  <outputDir>${project.build.outputDirectory}/admin/messages/${adminPackage}/meta</outputDir>
+                  <outputDir>${project.build.directory}/tmp</outputDir>
+                  <stylesheet>${xslDir}/manifestMO.xsl</stylesheet>
+                  <excludes>
+                    <exclude>Package.xml</exclude>
+                  </excludes>
+                  <fileMappers>
+                    <fileMapper
+                      implementation="org.codehaus.plexus.components.io.filemappers.FileExtensionMapper">
+                      <targetExtension>.manifest</targetExtension>
+                    </fileMapper>
+                  </fileMappers>
+                </transformationSet>
+              </transformationSets>
+            </configuration>
+          </execution>
+          <execution>
+            <id>generate-core-properties</id>
+            <phase>generate-resources</phase>
+            <goals>
+              <goal>transform</goal>
+            </goals>
+            <configuration>
+              <transformationSets>
+               <!-- Generate I18N messages for core administration components. -->
+                <transformationSet>
+                  <dir>${xmlDefinitionsDir}</dir>
+                  <outputDir>${mainResourcesDir}/admin/messages/${adminPackage}/meta</outputDir>
                   <stylesheet>${xslDir}/messagesMO.xsl</stylesheet>
                   <excludes>
                     <exclude>Package.xml</exclude>
@@ -410,21 +438,6 @@
                     </parameter>
                   </parameters>
                 </transformationSet>
-                <!-- Generate manifest file for core administration components. -->
-                <transformationSet>
-                  <dir>${xmlDefinitionsDir}</dir>
-                  <outputDir>${project.build.directory}/tmp</outputDir>
-                  <stylesheet>${xslDir}/manifestMO.xsl</stylesheet>
-                  <excludes>
-                    <exclude>Package.xml</exclude>
-                  </excludes>
-                  <fileMappers>
-                    <fileMapper
-                      implementation="org.codehaus.plexus.components.io.filemappers.FileExtensionMapper">
-                      <targetExtension>.manifest</targetExtension>
-                    </fileMapper>
-                  </fileMappers>
-                </transformationSet>
               </transformationSets>
             </configuration>
           </execution>
diff --git a/opendj-admin/src/main/java/org/opends/server/admin/LDAPProfile.java b/opendj-admin/src/main/java/org/opends/server/admin/LDAPProfile.java
index 027b896..3dba061 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/LDAPProfile.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/LDAPProfile.java
@@ -27,8 +27,6 @@
 
 package org.opends.server.admin;
 
-
-
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.LinkedList;
@@ -37,387 +35,329 @@
 import java.util.NoSuchElementException;
 import java.util.Set;
 
-
-
 /**
- * This class is used to map configuration elements to their LDAP
- * schema names.
+ * This class is used to map configuration elements to their LDAP schema names.
  * <p>
- * It is possible to augment the core LDAP profile with additional
- * profile mappings at run-time using instances of {@link Wrapper}.
- * This is useful for unit tests which need to add and remove mock
- * components.
+ * It is possible to augment the core LDAP profile with additional profile
+ * mappings at run-time using instances of {@link Wrapper}. This is useful for
+ * unit tests which need to add and remove mock components.
  */
 public final class LDAPProfile {
 
-  /**
-   * LDAP profile wrappers can be used to provide temporary LDAP
-   * profile information for components which do not have LDAP profile
-   * property files. These components are typically "mock" components
-   * used in unit-tests.
-   */
-  public static abstract class Wrapper {
-
     /**
-     * Default constructor.
+     * LDAP profile wrappers can be used to provide temporary LDAP profile
+     * information for components which do not have LDAP profile property files.
+     * These components are typically "mock" components used in unit-tests.
      */
-    protected Wrapper() {
-      // No implementation required.
+    public static abstract class Wrapper {
+
+        /**
+         * Default constructor.
+         */
+        protected Wrapper() {
+            // No implementation required.
+        }
+
+        /**
+         * Get the name of the LDAP attribute associated with the specified
+         * property definition.
+         * <p>
+         * The default implementation of this method is to return
+         * <code>null</code>.
+         *
+         * @param d
+         *            The managed object definition.
+         * @param pd
+         *            The property definition.
+         * @return Returns the name of the LDAP attribute associated with the
+         *         specified property definition, or <code>null</code> if the
+         *         property definition is not handled by this LDAP profile
+         *         wrapper.
+         */
+        public String getAttributeName(AbstractManagedObjectDefinition<?, ?> d, PropertyDefinition<?> pd) {
+            return null;
+        }
+
+        /**
+         * Gets the LDAP RDN attribute type for child entries of an instantiable
+         * relation.
+         * <p>
+         * The default implementation of this method is to return
+         * <code>null</code>.
+         *
+         * @param r
+         *            The instantiable relation.
+         * @return Returns the LDAP RDN attribute type for child entries of an
+         *         instantiable relation, or <code>null</code> if the
+         *         instantiable relation is not handled by this LDAP profile
+         *         wrapper.
+         */
+        public String getRelationChildRDNType(InstantiableRelationDefinition<?, ?> r) {
+            return null;
+        }
+
+        /**
+         * Gets the LDAP RDN attribute type for child entries of an set
+         * relation.
+         * <p>
+         * The default implementation of this method is to return
+         * <code>null</code>.
+         *
+         * @param r
+         *            The set relation.
+         * @return Returns the LDAP RDN attribute type for child entries of an
+         *         set relation, or <code>null</code> if the set relation is not
+         *         handled by this LDAP profile wrapper.
+         */
+        public String getRelationChildRDNType(SetRelationDefinition<?, ?> r) {
+            return null;
+        }
+
+        /**
+         * Get the principle object class associated with the specified
+         * definition.
+         * <p>
+         * The default implementation of this method is to return
+         * <code>null</code>.
+         *
+         * @param d
+         *            The managed object definition.
+         * @return Returns the principle object class associated with the
+         *         specified definition, or <code>null</code> if the managed
+         *         object definition is not handled by this LDAP profile
+         *         wrapper.
+         */
+        public String getObjectClass(AbstractManagedObjectDefinition<?, ?> d) {
+            return null;
+        }
+
+        /**
+         * Get an LDAP RDN sequence associatied with a relation.
+         * <p>
+         * The default implementation of this method is to return
+         * <code>null</code>.
+         *
+         * @param r
+         *            The relation.
+         * @return Returns the LDAP RDN sequence associatied with a relation, or
+         *         <code>null</code> if the relation is not handled by this LDAP
+         *         profile wrapper.
+         */
+        public String getRelationRDNSequence(RelationDefinition<?, ?> r) {
+            return null;
+        }
     }
 
-
+    // The singleton instance.
+    private static final LDAPProfile INSTANCE = new LDAPProfile();
 
     /**
-     * Get the name of the LDAP attribute associated with the
-     * specified property definition.
-     * <p>
-     * The default implementation of this method is to return
-     * <code>null</code>.
+     * Get the global LDAP profile instance.
      *
-     * @param d
-     *          The managed object definition.
-     * @param pd
-     *          The property definition.
-     * @return Returns the name of the LDAP attribute associated with
-     *         the specified property definition, or <code>null</code>
-     *         if the property definition is not handled by this LDAP
-     *         profile wrapper.
+     * @return Returns the global LDAP profile instance.
      */
-    public String getAttributeName(AbstractManagedObjectDefinition<?, ?> d,
-        PropertyDefinition<?> pd) {
-      return null;
+    public static LDAPProfile getInstance() {
+        return INSTANCE;
     }
 
+    // The list of profile wrappers.
+    private final LinkedList<Wrapper> profiles = new LinkedList<Wrapper>();;
 
+    // The LDAP profile property table.
+    private final ManagedObjectDefinitionResource resource = ManagedObjectDefinitionResource.createForProfile("ldap");
 
-    /**
-     * Gets the LDAP RDN attribute type for child entries of an
-     * instantiable relation.
-     * <p>
-     * The default implementation of this method is to return
-     * <code>null</code>.
-     *
-     * @param r
-     *          The instantiable relation.
-     * @return Returns the LDAP RDN attribute type for child entries
-     *         of an instantiable relation, or <code>null</code> if
-     *         the instantiable relation is not handled by this LDAP
-     *         profile wrapper.
-     */
-    public String getRelationChildRDNType(
-        InstantiableRelationDefinition<?, ?> r) {
-      return null;
+    // Prevent construction.
+    private LDAPProfile() {
+        // No implementation required.
     }
 
-
-
     /**
-     * Gets the LDAP RDN attribute type for child entries of an set
-     * relation.
-     * <p>
-     * The default implementation of this method is to return
-     * <code>null</code>.
-     *
-     * @param r
-     *          The set relation.
-     * @return Returns the LDAP RDN attribute type for child entries of
-     *         an set relation, or <code>null</code> if the set relation
-     *         is not handled by this LDAP profile wrapper.
-     */
-    public String getRelationChildRDNType(SetRelationDefinition<?, ?> r)
-    {
-      return null;
-    }
-
-
-
-    /**
-     * Get the principle object class associated with the specified
+     * Get the name of the LDAP attribute associated with the specified property
      * definition.
-     * <p>
-     * The default implementation of this method is to return
-     * <code>null</code>.
      *
      * @param d
-     *          The managed object definition.
-     * @return Returns the principle object class associated with the
-     *         specified definition, or <code>null</code> if the
-     *         managed object definition is not handled by this LDAP
-     *         profile wrapper.
+     *            The managed object definition.
+     * @param pd
+     *            The property definition.
+     * @return Returns the name of the LDAP attribute associated with the
+     *         specified property definition.
+     * @throws MissingResourceException
+     *             If the LDAP profile properties file associated with the
+     *             provided managed object definition could not be loaded.
      */
-    public String getObjectClass(AbstractManagedObjectDefinition<?, ?> d) {
-      return null;
+    public String getAttributeName(AbstractManagedObjectDefinition<?, ?> d, PropertyDefinition<?> pd)
+            throws MissingResourceException {
+        for (Wrapper profile : profiles) {
+            String attributeName = profile.getAttributeName(d, pd);
+            if (attributeName != null) {
+                return attributeName;
+            }
+        }
+        return resource.getString(d, "attribute." + pd.getName());
     }
 
+    /**
+     * Gets the LDAP RDN attribute type for child entries of an instantiable
+     * relation.
+     *
+     * @param r
+     *            The instantiable relation.
+     * @return Returns the LDAP RDN attribute type for child entries of an
+     *         instantiable relation.
+     * @throws MissingResourceException
+     *             If the LDAP profile properties file associated with the
+     *             provided managed object definition could not be loaded.
+     */
+    public String getRelationChildRDNType(InstantiableRelationDefinition<?, ?> r) throws MissingResourceException {
+        if (r.getNamingPropertyDefinition() != null) {
+            // Use the attribute associated with the naming property.
+            return getAttributeName(r.getChildDefinition(), r.getNamingPropertyDefinition());
+        } else {
+            for (Wrapper profile : profiles) {
+                String rdnType = profile.getRelationChildRDNType(r);
+                if (rdnType != null) {
+                    return rdnType;
+                }
+            }
+            return resource.getString(r.getParentDefinition(), "naming-attribute." + r.getName());
+        }
+    }
 
+    /**
+     * Gets the LDAP object classes associated with an instantiable or set
+     * relation branch. The branch is the parent entry of child managed objects.
+     *
+     * @param r
+     *            The instantiable or set relation.
+     * @return Returns the LDAP object classes associated with an instantiable
+     *         or set relation branch.
+     */
+    public List<String> getRelationObjectClasses(RelationDefinition<?, ?> r) {
+        return Arrays.asList(new String[] { "top", "ds-cfg-branch" });
+    }
+
+    /**
+     * Gets the LDAP RDN attribute type for child entries of an set relation.
+     *
+     * @param r
+     *            The set relation.
+     * @return Returns the LDAP RDN attribute type for child entries of an set
+     *         relation.
+     * @throws MissingResourceException
+     *             If the LDAP profile properties file associated with the
+     *             provided managed object definition could not be loaded.
+     */
+    public String getRelationChildRDNType(SetRelationDefinition<?, ?> r) throws MissingResourceException {
+        for (Wrapper profile : profiles) {
+            String rdnType = profile.getRelationChildRDNType(r);
+            if (rdnType != null) {
+                return rdnType;
+            }
+        }
+        return resource.getString(r.getParentDefinition(), "naming-attribute." + r.getName());
+    }
+
+    /**
+     * Get the principle object class associated with the specified definition.
+     *
+     * @param d
+     *            The managed object definition.
+     * @return Returns the principle object class associated with the specified
+     *         definition.
+     * @throws MissingResourceException
+     *             If the LDAP profile properties file associated with the
+     *             provided managed object definition could not be loaded.
+     */
+    public String getObjectClass(AbstractManagedObjectDefinition<?, ?> d) throws MissingResourceException {
+        if (d.isTop()) {
+            return "top";
+        }
+
+        for (Wrapper profile : profiles) {
+            String objectClass = profile.getObjectClass(d);
+            if (objectClass != null) {
+                return objectClass;
+            }
+        }
+        return resource.getString(d, "objectclass");
+    }
+
+    /**
+     * Get all the object classes associated with the specified definition.
+     * <p>
+     * The returned list is ordered such that the uppermost object classes
+     * appear first (e.g. top).
+     *
+     * @param d
+     *            The managed object definition.
+     * @return Returns all the object classes associated with the specified
+     *         definition.
+     * @throws MissingResourceException
+     *             If the LDAP profile properties file associated with the
+     *             provided managed object definition could not be loaded.
+     */
+    public List<String> getObjectClasses(AbstractManagedObjectDefinition<?, ?> d) throws MissingResourceException {
+        LinkedList<String> objectClasses = new LinkedList<String>();
+        Set<String> s = new HashSet<String>();
+
+        // Add the object classes from the parent hierarchy.
+        while (d != null) {
+            String oc = getObjectClass(d);
+            if (!s.contains(oc)) {
+                objectClasses.addFirst(oc);
+                s.add(oc);
+            }
+            d = d.getParent();
+        }
+
+        if (!s.contains("top")) {
+            objectClasses.addFirst("top");
+        }
+
+        return objectClasses;
+    }
 
     /**
      * Get an LDAP RDN sequence associatied with a relation.
-     * <p>
-     * The default implementation of this method is to return
-     * <code>null</code>.
      *
      * @param r
-     *          The relation.
-     * @return Returns the LDAP RDN sequence associatied with a
-     *         relation, or <code>null</code> if the relation is not
-     *         handled by this LDAP profile wrapper.
+     *            The relation.
+     * @return Returns the LDAP RDN sequence associatied with a relation.
+     * @throws MissingResourceException
+     *             If the LDAP profile properties file associated with the
+     *             provided managed object definition could not be loaded.
      */
-    public String getRelationRDNSequence(RelationDefinition<?, ?> r) {
-      return null;
-    }
-  }
-
-  // The singleton instance.
-  private static final LDAPProfile INSTANCE = new LDAPProfile();
-
-
-
-  /**
-   * Get the global LDAP profile instance.
-   *
-   * @return Returns the global LDAP profile instance.
-   */
-  public static LDAPProfile getInstance() {
-    return INSTANCE;
-  }
-
-  // The list of profile wrappers.
-  private final LinkedList<Wrapper> profiles = new LinkedList<Wrapper>();;
-
-  // The LDAP profile property table.
-  private final ManagedObjectDefinitionResource resource =
-    ManagedObjectDefinitionResource.createForProfile("ldap");
-
-
-
-  // Prevent construction.
-  private LDAPProfile() {
-    // No implementation required.
-  }
-
-
-
-  /**
-   * Get the name of the LDAP attribute associated with the specified
-   * property definition.
-   *
-   * @param d
-   *          The managed object definition.
-   * @param pd
-   *          The property definition.
-   * @return Returns the name of the LDAP attribute associated with
-   *         the specified property definition.
-   * @throws MissingResourceException
-   *           If the LDAP profile properties file associated with the
-   *           provided managed object definition could not be loaded.
-   */
-  public String getAttributeName(AbstractManagedObjectDefinition<?, ?> d,
-      PropertyDefinition<?> pd) throws MissingResourceException {
-    for (Wrapper profile : profiles) {
-      String attributeName = profile.getAttributeName(d, pd);
-      if (attributeName != null) {
-        return attributeName;
-      }
-    }
-    return resource.getString(d, "attribute." + pd.getName());
-  }
-
-
-
-  /**
-   * Gets the LDAP RDN attribute type for child entries of an
-   * instantiable relation.
-   *
-   * @param r
-   *          The instantiable relation.
-   * @return Returns the LDAP RDN attribute type for child entries of
-   *         an instantiable relation.
-   * @throws MissingResourceException
-   *           If the LDAP profile properties file associated with the
-   *           provided managed object definition could not be loaded.
-   */
-  public String getRelationChildRDNType(
-      InstantiableRelationDefinition<?, ?> r) throws MissingResourceException {
-    if (r.getNamingPropertyDefinition() != null) {
-      // Use the attribute associated with the naming property.
-      return getAttributeName(r.getChildDefinition(), r
-          .getNamingPropertyDefinition());
-    } else {
-      for (Wrapper profile : profiles) {
-        String rdnType = profile.getRelationChildRDNType(r);
-        if (rdnType != null) {
-          return rdnType;
+    public String getRelationRDNSequence(RelationDefinition<?, ?> r) throws MissingResourceException {
+        for (Wrapper profile : profiles) {
+            String rdnSequence = profile.getRelationRDNSequence(r);
+            if (rdnSequence != null) {
+                return rdnSequence;
+            }
         }
-      }
-      return resource.getString(r.getParentDefinition(), "naming-attribute."
-          + r.getName());
-    }
-  }
-
-
-
-  /**
-   * Gets the LDAP object classes associated with an instantiable or set
-   * relation branch. The branch is the parent entry of child managed
-   * objects.
-   *
-   * @param r
-   *          The instantiable or set relation.
-   * @return Returns the LDAP object classes associated with an
-   *         instantiable or set relation branch.
-   */
-  public List<String> getRelationObjectClasses(
-      RelationDefinition<?, ?> r) {
-    return Arrays.asList(new String[] { "top", "ds-cfg-branch" });
-  }
-
-
-
-  /**
-   * Gets the LDAP RDN attribute type for child entries of an set
-   * relation.
-   *
-   * @param r
-   *          The set relation.
-   * @return Returns the LDAP RDN attribute type for child entries of an
-   *         set relation.
-   * @throws MissingResourceException
-   *           If the LDAP profile properties file associated with the
-   *           provided managed object definition could not be loaded.
-   */
-  public String getRelationChildRDNType(SetRelationDefinition<?, ?> r)
-      throws MissingResourceException
-  {
-    for (Wrapper profile : profiles)
-    {
-      String rdnType = profile.getRelationChildRDNType(r);
-      if (rdnType != null)
-      {
-        return rdnType;
-      }
-    }
-    return resource.getString(r.getParentDefinition(),
-        "naming-attribute." + r.getName());
-  }
-
-
-
-  /**
-   * Get the principle object class associated with the specified
-   * definition.
-   *
-   * @param d
-   *          The managed object definition.
-   * @return Returns the principle object class associated with the
-   *         specified definition.
-   * @throws MissingResourceException
-   *           If the LDAP profile properties file associated with the
-   *           provided managed object definition could not be loaded.
-   */
-  public String getObjectClass(AbstractManagedObjectDefinition<?, ?> d)
-      throws MissingResourceException {
-    if (d.isTop()) {
-      return "top";
+        return resource.getString(r.getParentDefinition(), "rdn." + r.getName());
     }
 
-    for (Wrapper profile : profiles) {
-      String objectClass = profile.getObjectClass(d);
-      if (objectClass != null) {
-        return objectClass;
-      }
-    }
-    return resource.getString(d, "objectclass");
-  }
-
-
-
-  /**
-   * Get all the object classes associated with the specified
-   * definition.
-   * <p>
-   * The returned list is ordered such that the uppermost object
-   * classes appear first (e.g. top).
-   *
-   * @param d
-   *          The managed object definition.
-   * @return Returns all the object classes associated with the
-   *         specified definition.
-   * @throws MissingResourceException
-   *           If the LDAP profile properties file associated with the
-   *           provided managed object definition could not be loaded.
-   */
-  public List<String> getObjectClasses(AbstractManagedObjectDefinition<?, ?> d)
-      throws MissingResourceException {
-    LinkedList<String> objectClasses = new LinkedList<String>();
-    Set<String> s = new HashSet<String>();
-
-    // Add the object classes from the parent hierarchy.
-    while (d != null) {
-      String oc = getObjectClass(d);
-      if (!s.contains(oc)) {
-        objectClasses.addFirst(oc);
-        s.add(oc);
-      }
-      d = d.getParent();
+    /**
+     * Removes the last LDAP profile wrapper added using
+     * {@link #pushWrapper(org.opends.server.admin.LDAPProfile.Wrapper)}.
+     *
+     * @throws NoSuchElementException
+     *             If there are no LDAP profile wrappers.
+     */
+    public void popWrapper() throws NoSuchElementException {
+        profiles.removeFirst();
     }
 
-    if (!s.contains("top")) {
-      objectClasses.addFirst("top");
+    /**
+     * Decorates the core LDAP profile with the provided LDAP profile wrapper.
+     * All profile requests will be directed to the provided wrapper before
+     * being forwarded onto the core profile if the request could not be
+     * satisfied.
+     *
+     * @param wrapper
+     *            The LDAP profile wrapper.
+     */
+    public void pushWrapper(Wrapper wrapper) {
+        profiles.addFirst(wrapper);
     }
-
-    return objectClasses;
-  }
-
-
-
-  /**
-   * Get an LDAP RDN sequence associatied with a relation.
-   *
-   * @param r
-   *          The relation.
-   * @return Returns the LDAP RDN sequence associatied with a
-   *         relation.
-   * @throws MissingResourceException
-   *           If the LDAP profile properties file associated with the
-   *           provided managed object definition could not be loaded.
-   */
-  public String getRelationRDNSequence(RelationDefinition<?, ?> r)
-      throws MissingResourceException {
-    for (Wrapper profile : profiles) {
-      String rdnSequence = profile.getRelationRDNSequence(r);
-      if (rdnSequence != null) {
-        return rdnSequence;
-      }
-    }
-    return resource.getString(r.getParentDefinition(), "rdn." + r.getName());
-  }
-
-
-
-  /**
-   * Removes the last LDAP profile wrapper added using
-   * {@link #pushWrapper(org.opends.server.admin.LDAPProfile.Wrapper)}.
-   *
-   * @throws NoSuchElementException
-   *           If there are no LDAP profile wrappers.
-   */
-  public void popWrapper() throws NoSuchElementException {
-    profiles.removeFirst();
-  }
-
-
-
-  /**
-   * Decorates the core LDAP profile with the provided LDAP profile
-   * wrapper. All profile requests will be directed to the provided
-   * wrapper before being forwarded onto the core profile if the
-   * request could not be satisfied.
-   *
-   * @param wrapper
-   *          The LDAP profile wrapper.
-   */
-  public void pushWrapper(Wrapper wrapper) {
-    profiles.addFirst(wrapper);
-  }
 }
diff --git a/opendj-admin/src/main/java/org/opends/server/admin/ManagedObjectDefinitionI18NResource.java b/opendj-admin/src/main/java/org/opends/server/admin/ManagedObjectDefinitionI18NResource.java
index e3e0a3d..7cfe16e 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/ManagedObjectDefinitionI18NResource.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/ManagedObjectDefinitionI18NResource.java
@@ -24,8 +24,8 @@
  *
  *      Copyright 2008 Sun Microsystems, Inc.
  */
-
 package org.opends.server.admin;
+
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
@@ -34,313 +34,263 @@
 
 import org.forgerock.i18n.LocalizableMessage;
 
-
-
 /**
- * A class for retrieving internationalized resource properties
- * associated with a managed object definition.
+ * A class for retrieving internationalized resource properties associated with
+ * a managed object definition.
  * <p>
- * I18N resource properties are not available for the
- * {@link TopCfgDefn}.
+ * I18N resource properties are not available for the {@link TopCfgDefn}.
  */
 public final class ManagedObjectDefinitionI18NResource {
 
-  // Application-wide set of instances.
-  private static final Map<String, ManagedObjectDefinitionI18NResource>
-    INSTANCES = new HashMap<String, ManagedObjectDefinitionI18NResource>();
+    // Application-wide set of instances.
+    private static final Map<String, ManagedObjectDefinitionI18NResource> INSTANCES =
+            new HashMap<String, ManagedObjectDefinitionI18NResource>();
 
-
-
-  /**
-   * Gets the internationalized resource instance which can be used to
-   * retrieve the localized descriptions for the managed objects and
-   * their associated properties and relations.
-   *
-   * @return Returns the I18N resource instance.
-   */
-  public static ManagedObjectDefinitionI18NResource getInstance() {
-    return getInstance("admin.messages");
-  }
-
-
-
-  /**
-   * Gets the internationalized resource instance for the named
-   * profile.
-   *
-   * @param profile
-   *          The name of the profile.
-   * @return Returns the I18N resource instance for the named profile.
-   */
-  public static ManagedObjectDefinitionI18NResource getInstanceForProfile(
-      String profile) {
-    return getInstance("admin.profiles." + profile);
-  }
-
-
-
-  // Get a resource instance creating it if necessary.
-  private synchronized static ManagedObjectDefinitionI18NResource getInstance(
-      String prefix) {
-    ManagedObjectDefinitionI18NResource instance = INSTANCES
-        .get(prefix);
-
-    if (instance == null) {
-      instance = new ManagedObjectDefinitionI18NResource(prefix);
-      INSTANCES.put(prefix, instance);
+    /**
+     * Gets the internationalized resource instance which can be used to
+     * retrieve the localized descriptions for the managed objects and their
+     * associated properties and relations.
+     *
+     * @return Returns the I18N resource instance.
+     */
+    public static ManagedObjectDefinitionI18NResource getInstance() {
+        return getInstance("admin.messages");
     }
 
-    return instance;
-  }
-
-
-
-  // Mapping from definition to locale-based resource bundle.
-  private final Map<AbstractManagedObjectDefinition<?, ?>,
-    Map<Locale, ResourceBundle>> resources;
-
-
-
-  // The resource name prefix.
-  private final String prefix;
-
-
-
-  // Private constructor.
-  private ManagedObjectDefinitionI18NResource(String prefix) {
-    this.resources = new HashMap<AbstractManagedObjectDefinition<?, ?>,
-      Map<Locale, ResourceBundle>>();
-    this.prefix = prefix;
-  }
-
-
-
-  /**
-   * Get the internationalized message associated with the specified
-   * key in the default locale.
-   *
-   * @param d
-   *          The managed object definition.
-   * @param key
-   *          The resource key.
-   * @return Returns the internationalized message associated with the
-   *         specified key in the default locale.
-   * @throws MissingResourceException
-   *           If the key was not found.
-   * @throws UnsupportedOperationException
-   *           If the provided managed object definition was the
-   *           {@link TopCfgDefn}.
-   */
-  public LocalizableMessage getMessage(AbstractManagedObjectDefinition<?, ?> d, String key)
-      throws MissingResourceException, UnsupportedOperationException {
-    return getMessage(d, key, Locale.getDefault(), (String[]) null);
-  }
-
-
-
-  /**
-   * Get the internationalized message associated with the specified
-   * key and locale.
-   *
-   * @param d
-   *          The managed object definition.
-   * @param key
-   *          The resource key.
-   * @param locale
-   *          The locale.
-   * @return Returns the internationalized message associated with the
-   *         specified key and locale.
-   * @throws MissingResourceException
-   *           If the key was not found.
-   * @throws UnsupportedOperationException
-   *           If the provided managed object definition was the
-   *           {@link TopCfgDefn}.
-   */
-  public LocalizableMessage getMessage(AbstractManagedObjectDefinition<?, ?> d,
-      String key, Locale locale) throws MissingResourceException,
-      UnsupportedOperationException {
-    return getMessage(d, key, locale, (String[]) null);
-  }
-
-
-
-  /**
-   * Get the parameterized internationalized message associated with
-   * the specified key and locale.
-   *
-   * @param d
-   *          The managed object definition.
-   * @param key
-   *          The resource key.
-   * @param locale
-   *          The locale.
-   * @param args
-   *          Arguments that should be inserted into the retrieved
-   *          message.
-   * @return Returns the internationalized message associated with the
-   *         specified key and locale.
-   * @throws MissingResourceException
-   *           If the key was not found.
-   * @throws UnsupportedOperationException
-   *           If the provided managed object definition was the
-   *           {@link TopCfgDefn}.
-   */
-  public LocalizableMessage getMessage(AbstractManagedObjectDefinition<?, ?> d,
-      String key, Locale locale, String... args)
-      throws MissingResourceException, UnsupportedOperationException {
-    ResourceBundle resource = getResourceBundle(d, locale);
-
-    // TODO: use message framework directly
-    if (args == null) {
-      return LocalizableMessage.raw(resource.getString(key));
-    } else {
-      return LocalizableMessage.raw(resource.getString(key), (Object[]) args);
-    }
-  }
-
-
-
-  /**
-   * Get the parameterized internationalized message associated with
-   * the specified key in the default locale.
-   *
-   * @param d
-   *          The managed object definition.
-   * @param key
-   *          The resource key.
-   * @param args
-   *          Arguments that should be inserted into the retrieved
-   *          message.
-   * @return Returns the internationalized message associated with the
-   *         specified key in the default locale.
-   * @throws MissingResourceException
-   *           If the key was not found.
-   * @throws UnsupportedOperationException
-   *           If the provided managed object definition was the
-   *           {@link TopCfgDefn}.
-   */
-  public LocalizableMessage getMessage(AbstractManagedObjectDefinition<?, ?> d,
-      String key, String... args) throws MissingResourceException,
-      UnsupportedOperationException {
-    return getMessage(d, key, Locale.getDefault(), args);
-  }
-
-
-
-  /**
-   * Forcefully removes any resource bundles associated with the
-   * provided definition and using the default locale.
-   * <p>
-   * This method is intended for internal testing only.
-   *
-   * @param d
-   *          The managed object definition.
-   */
-  synchronized void removeResourceBundle(
-      AbstractManagedObjectDefinition<?, ?> d) {
-    removeResourceBundle(d, Locale.getDefault());
-  }
-
-
-
-  /**
-   * Forcefully removes any resource bundles associated with the
-   * provided definition and locale.
-   * <p>
-   * This method is intended for internal testing only.
-   *
-   * @param d
-   *          The managed object definition.
-   * @param locale
-   *          The locale.
-   */
-  synchronized void removeResourceBundle(
-      AbstractManagedObjectDefinition<?, ?> d, Locale locale) {
-    // Get the locale resource mapping.
-    Map<Locale, ResourceBundle> map = resources.get(d);
-    if (map != null) {
-      map.remove(locale);
-    }
-  }
-
-
-
-  /**
-   * Forcefully adds the provided resource bundle to this I18N
-   * resource for the default locale.
-   * <p>
-   * This method is intended for internal testing only.
-   *
-   * @param d
-   *          The managed object definition.
-   * @param resoureBundle
-   *          The resource bundle to be used.
-   */
-  synchronized void setResourceBundle(AbstractManagedObjectDefinition<?, ?> d,
-      ResourceBundle resoureBundle) {
-    setResourceBundle(d, Locale.getDefault(), resoureBundle);
-  }
-
-
-
-  /**
-   * Forcefully adds the provided resource bundle to this I18N
-   * resource.
-   * <p>
-   * This method is intended for internal testing only.
-   *
-   * @param d
-   *          The managed object definition.
-   * @param locale
-   *          The locale.
-   * @param resoureBundle
-   *          The resource bundle to be used.
-   */
-  synchronized void setResourceBundle(AbstractManagedObjectDefinition<?, ?> d,
-      Locale locale, ResourceBundle resoureBundle) {
-    // First get the locale-resource mapping, creating it if
-    // necessary.
-    Map<Locale, ResourceBundle> map = resources.get(d);
-    if (map == null) {
-      map = new HashMap<Locale, ResourceBundle>();
-      resources.put(d, map);
+    /**
+     * Gets the internationalized resource instance for the named profile.
+     *
+     * @param profile
+     *            The name of the profile.
+     * @return Returns the I18N resource instance for the named profile.
+     */
+    public static ManagedObjectDefinitionI18NResource getInstanceForProfile(String profile) {
+        return getInstance("admin.profiles." + profile);
     }
 
-    // Add the resource bundle.
-    map.put(locale, resoureBundle);
-  }
+    // Get a resource instance creating it if necessary.
+    private synchronized static ManagedObjectDefinitionI18NResource getInstance(String prefix) {
+        ManagedObjectDefinitionI18NResource instance = INSTANCES.get(prefix);
 
+        if (instance == null) {
+            instance = new ManagedObjectDefinitionI18NResource(prefix);
+            INSTANCES.put(prefix, instance);
+        }
 
-
-  // Retrieve the resource bundle associated with a managed object and
-  // locale, lazily loading it if necessary.
-  private synchronized ResourceBundle getResourceBundle(
-      AbstractManagedObjectDefinition<?, ?> d, Locale locale)
-      throws MissingResourceException, UnsupportedOperationException {
-    if (d.isTop()) {
-      throw new UnsupportedOperationException(
-          "I18n resources are not available for the "
-              + "Top configuration definition");
+        return instance;
     }
 
-    // First get the locale-resource mapping, creating it if
-    // necessary.
-    Map<Locale, ResourceBundle> map = resources.get(d);
-    if (map == null) {
-      map = new HashMap<Locale, ResourceBundle>();
-      resources.put(d, map);
+    // Mapping from definition to locale-based resource bundle.
+    private final Map<AbstractManagedObjectDefinition<?, ?>, Map<Locale, ResourceBundle>> resources;
+
+    // The resource name prefix.
+    private final String prefix;
+
+    // Private constructor.
+    private ManagedObjectDefinitionI18NResource(String prefix) {
+        this.resources = new HashMap<AbstractManagedObjectDefinition<?, ?>, Map<Locale, ResourceBundle>>();
+        this.prefix = prefix;
     }
 
-    // Now get the resource based on the locale, loading it if
-    // necessary.
-    ResourceBundle resourceBundle = map.get(locale);
-    if (resourceBundle == null) {
-      String baseName = prefix + "." + d.getClass().getName();
-      resourceBundle = ResourceBundle.getBundle(baseName, locale,
-          ClassLoaderProvider.getInstance().getClassLoader());
-      map.put(locale, resourceBundle);
+    /**
+     * Get the internationalized message associated with the specified key in
+     * the default locale.
+     *
+     * @param d
+     *            The managed object definition.
+     * @param key
+     *            The resource key.
+     * @return Returns the internationalized message associated with the
+     *         specified key in the default locale.
+     * @throws MissingResourceException
+     *             If the key was not found.
+     * @throws UnsupportedOperationException
+     *             If the provided managed object definition was the
+     *             {@link TopCfgDefn}.
+     */
+    public LocalizableMessage getMessage(AbstractManagedObjectDefinition<?, ?> d, String key)
+            throws MissingResourceException, UnsupportedOperationException {
+        return getMessage(d, key, Locale.getDefault(), (String[]) null);
     }
 
-    return resourceBundle;
-  }
+    /**
+     * Get the internationalized message associated with the specified key and
+     * locale.
+     *
+     * @param d
+     *            The managed object definition.
+     * @param key
+     *            The resource key.
+     * @param locale
+     *            The locale.
+     * @return Returns the internationalized message associated with the
+     *         specified key and locale.
+     * @throws MissingResourceException
+     *             If the key was not found.
+     * @throws UnsupportedOperationException
+     *             If the provided managed object definition was the
+     *             {@link TopCfgDefn}.
+     */
+    public LocalizableMessage getMessage(AbstractManagedObjectDefinition<?, ?> d, String key, Locale locale)
+            throws MissingResourceException, UnsupportedOperationException {
+        return getMessage(d, key, locale, (String[]) null);
+    }
+
+    /**
+     * Get the parameterized internationalized message associated with the
+     * specified key and locale.
+     *
+     * @param d
+     *            The managed object definition.
+     * @param key
+     *            The resource key.
+     * @param locale
+     *            The locale.
+     * @param args
+     *            Arguments that should be inserted into the retrieved message.
+     * @return Returns the internationalized message associated with the
+     *         specified key and locale.
+     * @throws MissingResourceException
+     *             If the key was not found.
+     * @throws UnsupportedOperationException
+     *             If the provided managed object definition was the
+     *             {@link TopCfgDefn}.
+     */
+    public LocalizableMessage getMessage(AbstractManagedObjectDefinition<?, ?> d, String key, Locale locale,
+            String... args) throws MissingResourceException, UnsupportedOperationException {
+        ResourceBundle resource = getResourceBundle(d, locale);
+
+        // TODO: use message framework directly
+        if (args == null) {
+            return LocalizableMessage.raw(resource.getString(key));
+        } else {
+            return LocalizableMessage.raw(resource.getString(key), (Object[]) args);
+        }
+    }
+
+    /**
+     * Get the parameterized internationalized message associated with the
+     * specified key in the default locale.
+     *
+     * @param d
+     *            The managed object definition.
+     * @param key
+     *            The resource key.
+     * @param args
+     *            Arguments that should be inserted into the retrieved message.
+     * @return Returns the internationalized message associated with the
+     *         specified key in the default locale.
+     * @throws MissingResourceException
+     *             If the key was not found.
+     * @throws UnsupportedOperationException
+     *             If the provided managed object definition was the
+     *             {@link TopCfgDefn}.
+     */
+    public LocalizableMessage getMessage(AbstractManagedObjectDefinition<?, ?> d, String key, String... args)
+            throws MissingResourceException, UnsupportedOperationException {
+        return getMessage(d, key, Locale.getDefault(), args);
+    }
+
+    /**
+     * Forcefully removes any resource bundles associated with the provided
+     * definition and using the default locale.
+     * <p>
+     * This method is intended for internal testing only.
+     *
+     * @param d
+     *            The managed object definition.
+     */
+    synchronized void removeResourceBundle(AbstractManagedObjectDefinition<?, ?> d) {
+        removeResourceBundle(d, Locale.getDefault());
+    }
+
+    /**
+     * Forcefully removes any resource bundles associated with the provided
+     * definition and locale.
+     * <p>
+     * This method is intended for internal testing only.
+     *
+     * @param d
+     *            The managed object definition.
+     * @param locale
+     *            The locale.
+     */
+    synchronized void removeResourceBundle(AbstractManagedObjectDefinition<?, ?> d, Locale locale) {
+        // Get the locale resource mapping.
+        Map<Locale, ResourceBundle> map = resources.get(d);
+        if (map != null) {
+            map.remove(locale);
+        }
+    }
+
+    /**
+     * Forcefully adds the provided resource bundle to this I18N resource for
+     * the default locale.
+     * <p>
+     * This method is intended for internal testing only.
+     *
+     * @param d
+     *            The managed object definition.
+     * @param resoureBundle
+     *            The resource bundle to be used.
+     */
+    synchronized void setResourceBundle(AbstractManagedObjectDefinition<?, ?> d, ResourceBundle resoureBundle) {
+        setResourceBundle(d, Locale.getDefault(), resoureBundle);
+    }
+
+    /**
+     * Forcefully adds the provided resource bundle to this I18N resource.
+     * <p>
+     * This method is intended for internal testing only.
+     *
+     * @param d
+     *            The managed object definition.
+     * @param locale
+     *            The locale.
+     * @param resoureBundle
+     *            The resource bundle to be used.
+     */
+    synchronized void setResourceBundle(AbstractManagedObjectDefinition<?, ?> d, Locale locale,
+            ResourceBundle resoureBundle) {
+        // First get the locale-resource mapping, creating it if
+        // necessary.
+        Map<Locale, ResourceBundle> map = resources.get(d);
+        if (map == null) {
+            map = new HashMap<Locale, ResourceBundle>();
+            resources.put(d, map);
+        }
+
+        // Add the resource bundle.
+        map.put(locale, resoureBundle);
+    }
+
+    // Retrieve the resource bundle associated with a managed object and
+    // locale, lazily loading it if necessary.
+    private synchronized ResourceBundle getResourceBundle(AbstractManagedObjectDefinition<?, ?> d, Locale locale)
+            throws MissingResourceException, UnsupportedOperationException {
+        if (d.isTop()) {
+            throw new UnsupportedOperationException("I18n resources are not available for the "
+                    + "Top configuration definition");
+        }
+
+        // First get the locale-resource mapping, creating it if
+        // necessary.
+        Map<Locale, ResourceBundle> map = resources.get(d);
+        if (map == null) {
+            map = new HashMap<Locale, ResourceBundle>();
+            resources.put(d, map);
+        }
+
+        // Now get the resource based on the locale, loading it if
+        // necessary.
+        ResourceBundle resourceBundle = map.get(locale);
+        if (resourceBundle == null) {
+            String baseName = prefix + "." + d.getClass().getName();
+            resourceBundle = ResourceBundle.getBundle(baseName, locale, ClassLoaderProvider.getInstance()
+                    .getClassLoader());
+            map.put(locale, resourceBundle);
+        }
+
+        return resourceBundle;
+    }
 }
diff --git a/opendj-admin/src/main/java/org/opends/server/admin/TopCfgDefn.java b/opendj-admin/src/main/java/org/opends/server/admin/TopCfgDefn.java
index 240b55a..df4daaf 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/TopCfgDefn.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/TopCfgDefn.java
@@ -26,49 +26,40 @@
  */
 package org.opends.server.admin;
 
-
-
 /**
- * Configuration definition <code>TopCfgDefn</code> is the root of
- * the configuration definition hierarchy. Every configuration has
+ * Configuration definition <code>TopCfgDefn</code> is the root of the
+ * configuration definition hierarchy. Every configuration has
  * <code>TopCfgDefn</code> as a superclass.
  * <p>
- * The <code>TopCfgDefn</code> has no properties or relations.
- * However, it can be used to determine all the configuration
- * definitions currently available to the administration framework
- * using the {@link #getAllChildren()}.
+ * The <code>TopCfgDefn</code> has no properties or relations. However, it can
+ * be used to determine all the configuration definitions currently available to
+ * the administration framework using the {@link #getAllChildren()}.
  * <p>
- * <b>NOTE:</b> it is not possible to retrieve I18N related
- * information or profile information for this managed object
- * definition. In particular, calls to the methods
- * {@link #getSynopsis()}, {@link #getDescription()},
- * {@link #getUserFriendlyName()}, and
- * {@link #getUserFriendlyPluralName()} will not work.
+ * <b>NOTE:</b> it is not possible to retrieve I18N related information or
+ * profile information for this managed object definition. In particular, calls
+ * to the methods {@link #getSynopsis()}, {@link #getDescription()},
+ * {@link #getUserFriendlyName()}, and {@link #getUserFriendlyPluralName()} will
+ * not work.
  */
-public final class TopCfgDefn extends
-    AbstractManagedObjectDefinition<ConfigurationClient, Configuration> {
+public final class TopCfgDefn extends AbstractManagedObjectDefinition<ConfigurationClient, Configuration> {
 
-  // The singleton configuration definition instance.
-  private static final TopCfgDefn INSTANCE = new TopCfgDefn();
+    // The singleton configuration definition instance.
+    private static final TopCfgDefn INSTANCE = new TopCfgDefn();
 
+    /**
+     * Get the Top configuration definition singleton.
+     *
+     * @return Returns the Top configuration definition singleton.
+     */
+    public static TopCfgDefn getInstance() {
+        return INSTANCE;
+    }
 
-
-  /**
-   * Get the Top configuration definition singleton.
-   *
-   * @return Returns the Top configuration definition singleton.
-   */
-  public static TopCfgDefn getInstance() {
-    return INSTANCE;
-  }
-
-
-
-  /**
-   * Private constructor.
-   */
-  private TopCfgDefn() {
-    super("top", null);
-  }
+    /**
+     * Private constructor.
+     */
+    private TopCfgDefn() {
+        super("top", null);
+    }
 
 }
diff --git a/opendj-admin/src/main/java/org/opends/server/core/DirectoryServer.java b/opendj-admin/src/main/java/org/opends/server/core/DirectoryServer.java
index a33ca5f..0e97bc7 100644
--- a/opendj-admin/src/main/java/org/opends/server/core/DirectoryServer.java
+++ b/opendj-admin/src/main/java/org/opends/server/core/DirectoryServer.java
@@ -29,16 +29,53 @@
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.opendj.ldap.schema.ObjectClass;
 import org.forgerock.opendj.ldap.schema.Schema;
+import org.forgerock.opendj.ldap.schema.UnknownSchemaElementException;
 import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 
 /**
- * TODO : this is a stub, with default or no implementation
+ * TODO : this is a stub, with some default implementations for some methods,
+ * and no implementation for others.
  */
 public class DirectoryServer {
 
-    public static AttributeType getAttributeType(String name, boolean b) {
-        return Schema.getDefaultSchema().getAttributeType(name);
+    /**
+     * Retrieves the attribute type for the provided lowercase name or OID. It
+     * can optionally return a generated "default" version if the requested
+     * attribute type is not defined in the schema.
+     *
+     * @param lowerName
+     *            The lowercase name or OID for the attribute type to retrieve.
+     * @param returnDefault
+     *            Indicates whether to generate a default version if the
+     *            requested attribute type is not defined in the server schema.
+     * @return The requested attribute type, or <CODE>null</CODE> if there is no
+     *         attribute with the specified type defined in the server schema
+     *         and a default type should not be returned.
+     */
+    public static AttributeType getAttributeType(String lowerName, boolean returnDefault) {
+        if (returnDefault) {
+            return getAttributeType(lowerName);
+        } else {
+            try {
+                return Schema.getDefaultSchema().asStrictSchema().getAttributeType(lowerName);
+            } catch (UnknownSchemaElementException e) {
+                return null;
+            }
+        }
+    }
+
+    /**
+     * Retrieves the attribute type for the provided lowercase name or OID.
+     *
+     * @param lowerName
+     *            The lowercase attribute name or OID for the attribute type to
+     *            retrieve.
+     * @return The requested attribute type, or <CODE>null</CODE> if there is no
+     *         attribute with the specified type defined in the server schema.
+     */
+    public static AttributeType getAttributeType(String lowerName) {
+        return Schema.getDefaultSchema().getAttributeType(lowerName);
     }
 
     public static String getInstanceRoot() {
@@ -49,10 +86,32 @@
         throw new RuntimeException("Not implemented");
     }
 
-    public static ObjectClass getObjectClass(String name) {
-        return Schema.getDefaultSchema().getObjectClass(name);
+    /**
+     * Retrieves the objectclass for the provided lowercase name or OID.
+     *
+     * @param lowerName
+     *            The lowercase name or OID for the objectclass to retrieve.
+     * @return The requested objectclass, or <CODE>null</CODE> if there is no
+     *         such objectclass defined in the server schema.
+     */
+    public static ObjectClass getObjectClass(String lowerName) {
+        try {
+            return Schema.getDefaultSchema().getObjectClass(lowerName);
+        } catch (UnknownSchemaElementException e) {
+            return null;
+        }
     }
 
+    /**
+     * Causes the Directory Server to construct a new objectclass definition
+     * with the provided name and with no required or allowed attributes. This
+     * should only be used if there is no objectclass for the specified name. It
+     * will not register the created objectclass with the Directory Server.
+     *
+     * @param name
+     *            The name to use for the objectclass, as provided by the user.
+     * @return The constructed objectclass definition.
+     */
     public static ObjectClass getDefaultObjectClass(String name) {
         return getObjectClass(name);
     }
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/AbstractManagedObjectDefinitionTest.java b/opendj-admin/src/test/java/org/opends/server/admin/AbstractManagedObjectDefinitionTest.java
new file mode 100644
index 0000000..281bf02
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/AbstractManagedObjectDefinitionTest.java
@@ -0,0 +1,209 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2007-2008 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.admin;
+
+import static org.fest.assertions.Assertions.*;
+import static org.testng.Assert.*;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+@SuppressWarnings({"javadoc", "unchecked", "rawtypes"})
+@Test(singleThreaded = true)
+public class AbstractManagedObjectDefinitionTest extends ConfigTestCase {
+
+    /** A test managed object definition. */
+    private static class ManagedObjectDef extends AbstractManagedObjectDefinition {
+
+        protected ManagedObjectDef(String name, AbstractManagedObjectDefinition parent) {
+            super(name, parent);
+        }
+    }
+
+    private ManagedObjectDef top = new ManagedObjectDef("topmost", null);
+
+    private ManagedObjectDef middle1 = new ManagedObjectDef("middle1", top);
+
+    private ManagedObjectDef middle2 = new ManagedObjectDef("middle2", top);
+
+    private ManagedObjectDef bottom1 = new ManagedObjectDef("bottom1", middle1);
+
+    private ManagedObjectDef bottom2 = new ManagedObjectDef("bottom2", middle1);
+
+    private ManagedObjectDef bottom3 = new ManagedObjectDef("bottom3", middle1);
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        disableClassValidationForProperties();
+        TestCfg.setUp();
+    }
+
+    @AfterClass
+    public void tearDown() {
+        TestCfg.cleanup();
+    }
+
+    @DataProvider(name = "isChildOf")
+    public Object[][] createIsChildOf() {
+        return new Object[][] {
+            // child def, parent def, is child of
+            { top, top, true },
+            { middle1, middle1, true },
+            { bottom1, bottom1, true },
+            { top, middle1, false },
+            { top, bottom1, false },
+            { middle1, top, true },
+            { bottom1, top, true },
+            { bottom1, middle1, true },
+        };
+    }
+
+    @Test(dataProvider = "isChildOf")
+    public void testIsChildOf(ManagedObjectDef childDef, ManagedObjectDef parentDef, boolean expectedIsChildOf) {
+        assertEquals(childDef.isChildOf(parentDef), expectedIsChildOf);
+    }
+
+    @DataProvider(name = "isParentOf")
+    public Object[][] createIsParentOf() {
+        return new Object[][] {
+            // parent def, child def, is parent of
+            { top, top, true },
+            { middle1, middle1, true },
+            { bottom1, bottom1, true },
+            { top, middle1, true },
+            { top, bottom1, true },
+            { middle1, top, false },
+            { bottom1, top, false },
+            { bottom1, middle1, false },
+        };
+    }
+
+    @Test(dataProvider = "isParentOf")
+    public void testIsParentOf(ManagedObjectDef parentDef, ManagedObjectDef childDef, boolean expectedIsParentOf) {
+        assertEquals(parentDef.isParentOf(childDef), expectedIsParentOf);
+    }
+
+    @Test
+    public void testGetAllChildrenOfTop() {
+        Collection<AbstractManagedObjectDefinition> children = top.getAllChildren();
+        assertThat(children).hasSize(5);
+        assertThat(children).containsOnly(middle1, middle2, bottom1, bottom2, bottom3);
+    }
+
+    @Test
+    public void testGetAllChildrenOfMiddle() {
+        Collection<AbstractManagedObjectDefinition> children = middle1.getAllChildren();
+        assertThat(children).hasSize(3);
+        assertThat(children).containsOnly(bottom1, bottom2, bottom3);
+    }
+
+    @Test
+    public void testGetAllChildrenNoChild() {
+        Collection<AbstractManagedObjectDefinition> children = middle2.getAllChildren();
+        assertThat(children).isEmpty();
+    }
+
+    @Test
+    public void testGetChildrenTop() {
+        Collection<AbstractManagedObjectDefinition> children = top.getChildren();
+        assertThat(children).hasSize(2);
+        assertThat(children).containsOnly(middle1, middle2);
+    }
+
+    @Test
+    public void testGetChildrenMiddleNoChild() {
+        Collection<AbstractManagedObjectDefinition> children = middle2.getChildren();
+        assertThat(children).isEmpty();
+    }
+
+    /** Check default value of "class" property provided for parent. */
+    @Test
+    public void testPropertyOverrideParent() {
+        AbstractManagedObjectDefinition<?, ?> def = TestParentCfgDefn.getInstance();
+        PropertyDefinition<?> propertyDef = def.getPropertyDefinition("mandatory-class-property");
+        DefaultBehaviorProvider<?> provider = propertyDef.getDefaultBehaviorProvider();
+        assertEquals(provider.getClass(), DefinedDefaultBehaviorProvider.class);
+
+        DefinedDefaultBehaviorProvider<?> definedProvider = (DefinedDefaultBehaviorProvider<?>) provider;
+        assertEquals(definedProvider.getDefaultValues(),
+                Collections.singleton("org.opends.server.extensions.SomeVirtualAttributeProvider"));
+    }
+
+    /** Check default value of "class" property provided for child. */
+    @Test
+    public void testPropertyOverrideChild() {
+        AbstractManagedObjectDefinition<?, ?> def = TestChildCfgDefn.getInstance();
+        PropertyDefinition<?> propertyDef = def.getPropertyDefinition("mandatory-class-property");
+        DefaultBehaviorProvider<?> provider = propertyDef.getDefaultBehaviorProvider();
+        assertEquals(provider.getClass(), DefinedDefaultBehaviorProvider.class);
+
+        DefinedDefaultBehaviorProvider<?> definedProvider = (DefinedDefaultBehaviorProvider<?>) provider;
+        assertEquals(definedProvider.getDefaultValues(),
+                Collections.singleton("org.opends.server.extensions.UserDefinedVirtualAttributeProvider"));
+    }
+
+    @Test
+    public void testGetReverseRelationDefinitions() {
+        Collection<RelationDefinition<TestParentCfgClient, TestParentCfg>> parentRelDef =
+                TestParentCfgDefn.getInstance().getReverseRelationDefinitions();
+
+        assertThat(parentRelDef).hasSize(2);
+        assertThat(parentRelDef).contains(TestCfg.getTestOneToManyParentRelationDefinition());
+        assertThat(parentRelDef).contains(TestCfg.getTestOneToZeroOrOneParentRelationDefinition());
+
+        Collection<RelationDefinition<TestChildCfgClient, TestChildCfg>> childRelDef = TestChildCfgDefn.getInstance()
+                .getReverseRelationDefinitions();
+
+        assertThat(childRelDef).hasSize(2);
+        assertThat(childRelDef).contains(TestParentCfgDefn.getInstance().getTestChildrenRelationDefinition());
+        assertThat(childRelDef).contains(TestParentCfgDefn.getInstance().getOptionalTestChildRelationDefinition());
+    }
+
+    @Test
+    public void testGetAllReverseRelationDefinitions() {
+        Collection<RelationDefinition<? super TestParentCfgClient, ? super TestParentCfg>> parentRelDef =
+                TestParentCfgDefn.getInstance().getAllReverseRelationDefinitions();
+
+        assertThat(parentRelDef).hasSize(2);
+        assertThat(parentRelDef).contains(TestCfg.getTestOneToManyParentRelationDefinition());
+        assertThat(parentRelDef).contains(TestCfg.getTestOneToZeroOrOneParentRelationDefinition());
+
+        Collection<RelationDefinition<? super TestChildCfgClient, ? super TestChildCfg>> childRelDef =
+                TestChildCfgDefn.getInstance().getAllReverseRelationDefinitions();
+
+        assertThat(childRelDef).hasSize(2);
+        assertThat(childRelDef).contains(TestParentCfgDefn.getInstance().getTestChildrenRelationDefinition());
+        assertThat(childRelDef).contains(TestParentCfgDefn.getInstance().getOptionalTestChildRelationDefinition());
+    }
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/AdminTestCase.java b/opendj-admin/src/test/java/org/opends/server/admin/AdminTestCase.java
new file mode 100644
index 0000000..671b4d5
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/AdminTestCase.java
@@ -0,0 +1,39 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.testng.annotations.Test;
+
+/**
+ * An abstract class that all admin unit tests should extend.
+ */
+@Test(groups = { "precommit", "admin" }, singleThreaded = true)
+public abstract class AdminTestCase extends ConfigTestCase {
+  // No implementation required.
+  // TODO : merge with ConfigTestCase ?
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/AggregationPropertyDefinitionTest.java b/opendj-admin/src/test/java/org/opends/server/admin/AggregationPropertyDefinitionTest.java
new file mode 100644
index 0000000..3d56533
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/AggregationPropertyDefinitionTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.admin;
+
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.forgerock.opendj.ldap.DN;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+@Test(singleThreaded = true)
+public class AggregationPropertyDefinitionTest extends ConfigTestCase {
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        disableClassValidationForProperties();
+        TestCfg.setUp();
+    }
+
+    @AfterClass
+    public void tearDown() {
+        TestCfg.cleanup();
+    }
+
+     /** Tests that the {@link AggregationPropertyDefinition#normalizeValue(String)} works. */
+    @Test
+    public void testNormalizeValue() throws Exception {
+        TestChildCfgDefn definition = TestChildCfgDefn.getInstance();
+        AggregationPropertyDefinition<?, ?> propertyDef = definition.getAggregationPropertyPropertyDefinition();
+        String nvalue = propertyDef.normalizeValue("  LDAP   connection    handler  ");
+        Assert.assertEquals(nvalue, "ldap connection handler");
+    }
+
+    /** Tests that the {@link AggregationPropertyDefinition#getChildDN(String)} works. */
+    @Test
+    public void testGetChildDN() throws Exception {
+        TestChildCfgDefn definition = TestChildCfgDefn.getInstance();
+        AggregationPropertyDefinition<?, ?> propertyDef = definition.getAggregationPropertyPropertyDefinition();
+        DN expected = DN.valueOf("cn=ldap connection handler, cn=connection handlers, cn=config");
+        DN actual = propertyDef.getChildDN("  LDAP  connection handler  ");
+        Assert.assertEquals(actual, expected);
+    }
+
+    @Test
+    public void testGetChildPath() throws Exception {
+        TestChildCfgDefn definition = TestChildCfgDefn.getInstance();
+        AggregationPropertyDefinition<?, ?> propertyDef = definition.getAggregationPropertyPropertyDefinition();
+        ManagedObjectPath<?, ?> path = propertyDef.getChildPath("LDAP connection handler");
+
+        Assert.assertSame(path.getManagedObjectDefinition(), propertyDef.getRelationDefinition().getChildDefinition());
+        Assert.assertSame(path.getRelationDefinition(), propertyDef.getRelationDefinition());
+    }
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/AttributeTypePropertyDefinitionTest.java b/opendj-admin/src/test/java/org/opends/server/admin/AttributeTypePropertyDefinitionTest.java
new file mode 100644
index 0000000..80c35f3
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/AttributeTypePropertyDefinitionTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+import static org.testng.Assert.*;
+
+import org.forgerock.opendj.admin.meta.RootCfgDefn;
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.forgerock.opendj.ldap.schema.Schema;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class AttributeTypePropertyDefinitionTest extends ConfigTestCase {
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        disableClassValidationForProperties();
+    }
+
+    @Test
+    public void testValidateValue() {
+        AttributeTypePropertyDefinition.setCheckSchema(true);
+        AttributeTypePropertyDefinition propertyDef = createPropertyDefinition();
+        propertyDef.validateValue(Schema.getDefaultSchema().getAttributeType("cn"));
+    }
+
+    @DataProvider(name = "valueLegalData")
+    public Object[][] createValidateValueLegalData() {
+        return new Object[][] { { "cn" }, { "o" }, { "ou" } };
+    }
+
+    @Test(dataProvider = "valueLegalData")
+    public void testDecodeValue(String value) {
+        AttributeTypePropertyDefinition.setCheckSchema(true);
+        AttributeTypePropertyDefinition propertyDef = createPropertyDefinition();
+        AttributeType expected = Schema.getDefaultSchema().getAttributeType(value);
+        assertEquals(propertyDef.decodeValue(value), expected);
+    }
+
+    @Test(dataProvider = "valueLegalData")
+    public void testEncodeValue(String value) {
+        AttributeTypePropertyDefinition.setCheckSchema(true);
+        AttributeTypePropertyDefinition propertyDef = createPropertyDefinition();
+        assertEquals(propertyDef.encodeValue(propertyDef.decodeValue(value)), value);
+    }
+
+    @DataProvider(name = "valueIllegalData")
+    public Object[][] createValidateValueIllegalData() {
+        return new Object[][] { { "dummy-type-xxx" } };
+    }
+
+    @Test(dataProvider = "valueIllegalData", expectedExceptions = { IllegalPropertyValueStringException.class })
+    public void testDecodeValueIllegal(String value) {
+        AttributeTypePropertyDefinition.setCheckSchema(true);
+        AttributeTypePropertyDefinition propertyDef = createPropertyDefinition();
+        propertyDef.decodeValue(value);
+    }
+
+    @Test(dataProvider = "valueIllegalData")
+    public void testDecodeValueIllegalNoSchemaCheck(String value) {
+        AttributeTypePropertyDefinition.setCheckSchema(false);
+        AttributeTypePropertyDefinition propertyDef = createPropertyDefinition();
+        AttributeType type = propertyDef.decodeValue(value);
+        assertEquals(type.getNameOrOID(), value);
+
+        // Make sure to turn schema checking back on
+        // so that other tests which depend on it don't fail.
+        AttributeTypePropertyDefinition.setCheckSchema(true);
+    }
+
+    // Create a new definition.
+    private AttributeTypePropertyDefinition createPropertyDefinition() {
+        AttributeTypePropertyDefinition.Builder builder = AttributeTypePropertyDefinition.createBuilder(
+                RootCfgDefn.getInstance(), "test-property");
+        return builder.getInstance();
+    }
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/BooleanPropertyDefinitionTest.java b/opendj-admin/src/test/java/org/opends/server/admin/BooleanPropertyDefinitionTest.java
new file mode 100644
index 0000000..512bbf1
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/BooleanPropertyDefinitionTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+import static org.testng.Assert.*;
+
+import org.forgerock.opendj.admin.meta.RootCfgDefn;
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class BooleanPropertyDefinitionTest extends ConfigTestCase {
+
+    BooleanPropertyDefinition.Builder builder = null;
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        disableClassValidationForProperties();
+        builder = BooleanPropertyDefinition.createBuilder(RootCfgDefn.getInstance(), "test-property");
+    }
+
+    @Test
+    public void testValidateValue() {
+        BooleanPropertyDefinition def = createPropertyDefinition();
+        def.validateValue(Boolean.TRUE);
+    }
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testValidateValueIllegal() {
+        BooleanPropertyDefinition def = createPropertyDefinition();
+        def.validateValue(null);
+    }
+
+    @DataProvider(name = "decodeValueData")
+    public Object[][] createValidateValueData() {
+        return new Object[][] { { "false", Boolean.FALSE }, { "true", Boolean.TRUE } };
+    }
+
+    @Test(dataProvider = "decodeValueData")
+    public void testDecodeValue(String value, Boolean expected) {
+        BooleanPropertyDefinition def = createPropertyDefinition();
+        assertEquals(def.decodeValue(value), expected);
+    }
+
+    @DataProvider(name = "decodeValueDataIllegal")
+    public Object[][] createValidateValueDataIllegal() {
+        return new Object[][] { { null }, { "abc" } };
+    }
+
+    @Test(dataProvider = "decodeValueDataIllegal", expectedExceptions = { NullPointerException.class,
+            IllegalPropertyValueStringException.class })
+    public void testDecodeValueIllegal(String value) {
+        BooleanPropertyDefinition def = createPropertyDefinition();
+        def.decodeValue(value);
+    }
+
+    private BooleanPropertyDefinition createPropertyDefinition() {
+        return builder.getInstance();
+    }
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/ClassPropertyDefinitionTest.java b/opendj-admin/src/test/java/org/opends/server/admin/ClassPropertyDefinitionTest.java
new file mode 100644
index 0000000..e19b651
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/ClassPropertyDefinitionTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ *      Portions copyright 2012 ForgeRock AS.
+ */
+
+package org.opends.server.admin;
+
+import static org.testng.Assert.*;
+
+import java.util.Comparator;
+import java.util.List;
+
+import org.forgerock.opendj.admin.meta.RootCfgDefn;
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class ClassPropertyDefinitionTest extends ConfigTestCase {
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        disableClassValidationForProperties();
+    }
+
+    // Dummy class used in tests.
+    public static final class Dummy {
+        public class X {
+            // no implementation
+        }
+
+        public Comparator<Dummy> comparator() {
+            return new Comparator<ClassPropertyDefinitionTest.Dummy>() {
+                public int compare(Dummy o1, Dummy o2) {
+                    // No implementation required.
+                    return 0;
+                }
+            };
+        }
+    }
+
+    ClassPropertyDefinition.Builder builder = null;
+
+    @DataProvider(name = "validClassNames")
+    public Object[][] createBuilderAddInstanceOfData() {
+        return new Object[][] {
+            { "org.opends.server.admin.ClassPropertyDefinitionTest" },
+            { "org.opends.server.admin.ClassPropertyDefinitionTest$Dummy" },
+            { "org.opends.server.admin.ClassPropertyDefinitionTest$Dummy$X" },
+            { "org.opends.server.admin.ClassPropertyDefinitionTest$Dummy$1" }, };
+    }
+
+    @Test(dataProvider = "validClassNames")
+    public void testBuilderAddInstanceOf(String classNameToAdd) {
+        ClassPropertyDefinition.Builder localBuilder = ClassPropertyDefinition.createBuilder(RootCfgDefn.getInstance(),
+                "test-property");
+        localBuilder.addInstanceOf(classNameToAdd);
+        ClassPropertyDefinition propertyDef = localBuilder.getInstance();
+        List<String> instances = propertyDef.getInstanceOfInterface();
+        assertTrue(instances.contains(classNameToAdd));
+    }
+
+    @DataProvider(name = "invalidClassNames")
+    public Object[][] createBuilderAddInstanceOfDataInvalid() {
+        return new Object[][] {
+            { "1" },
+            { "" },
+            { " " },
+            { "  " },
+            { "abc." },
+            { "abc.123" },
+            { "abc.123$" },
+        };
+    }
+
+    @Test(dataProvider = "invalidClassNames", expectedExceptions = { IllegalArgumentException.class })
+    public void testBuilderAddInstanceInvalid(String className) {
+        ClassPropertyDefinition.Builder localBuilder = ClassPropertyDefinition.createBuilder(RootCfgDefn.getInstance(),
+                "test-property");
+        localBuilder.addInstanceOf(className);
+        ClassPropertyDefinition propertyDef = localBuilder.getInstance();
+        List<String> instances = propertyDef.getInstanceOfInterface();
+        assertTrue(instances.contains(className));
+    }
+
+    /**
+     * @return data for testing with illegal values
+     */
+    @DataProvider(name = "loadClasses")
+    public Object[][] createLoadData() {
+        return new Object[][] {
+            { "java.io.Serializable", "java.lang.String", Object.class, String.class },
+            { "java.io.Serializable", "java.lang.String", String.class, String.class },
+            // abstractclass
+            { "java.lang.Number", "java.lang.Long", Number.class, Long.class }, };
+    }
+
+    @Test(dataProvider = "loadClasses")
+    public <T> void testLoadClass(String interfaceName, String loadClassName, Class<T> instanceOfClass,
+            Class<?> expectedClass) {
+        ClassPropertyDefinition.Builder localBuilder = ClassPropertyDefinition.createBuilder(RootCfgDefn.getInstance(),
+                "test-property");
+        localBuilder.addInstanceOf(interfaceName);
+        ClassPropertyDefinition propertyDef = localBuilder.getInstance();
+        Class<?> clazz = propertyDef.loadClass(loadClassName, instanceOfClass);
+        assertEquals(clazz, expectedClass);
+    }
+
+    @DataProvider(name = "loadClassesIllegal")
+    public Object[][] createLoadDataIllegal() {
+        return new Object[][] {
+            { "java.lang.Runnable", "java.lang.String", Object.class, String.class },
+            { "java.lang.Runnable", "some.bogus.ClassName", Object.class, String.class },
+            { "java.lang.Runnable", "java.lang.String", Number.class, Number.class }, };
+    }
+
+    @SuppressWarnings("unused")
+    @Test(dataProvider = "loadClassesIllegal", expectedExceptions = { IllegalPropertyValueException.class })
+    public <T> void testLoadClassIllegal(String interfaceName, String loadClassName, Class<T> instanceOfClass,
+            Class<?> expectedClass) {
+        ClassPropertyDefinition.Builder localBuilder = ClassPropertyDefinition.createBuilder(RootCfgDefn.getInstance(),
+                "test-property");
+        localBuilder.addInstanceOf(interfaceName);
+        ClassPropertyDefinition propertyDef = localBuilder.getInstance();
+        Class<?> clazz = propertyDef.loadClass(loadClassName, instanceOfClass);
+        assertEquals(clazz, String.class);
+    }
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/DNPropertyDefinitionTest.java b/opendj-admin/src/test/java/org/opends/server/admin/DNPropertyDefinitionTest.java
new file mode 100644
index 0000000..e2703b7
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/DNPropertyDefinitionTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.admin;
+
+import static org.testng.Assert.assertEquals;
+
+import org.forgerock.opendj.admin.meta.RootCfgDefn;
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.forgerock.opendj.ldap.DN;
+import org.opends.server.types.DirectoryException;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class DNPropertyDefinitionTest extends ConfigTestCase {
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        disableClassValidationForProperties();
+    }
+
+    @DataProvider(name = "baseDN")
+    public Object[][] createBuilderSetBaseDN() {
+        return new Object[][] {
+            { null },
+            { "cn=key manager providers, cn=config" } };
+    }
+
+
+    @Test(dataProvider = "baseDN")
+    public void testBuilderSetBaseDN(String baseDN) throws DirectoryException {
+        DNPropertyDefinition.Builder localBuilder = DNPropertyDefinition.createBuilder(RootCfgDefn.getInstance(),
+                "test-property");
+        localBuilder.setBaseDN(baseDN);
+        DNPropertyDefinition propertyDef = localBuilder.getInstance();
+
+        DN actual = propertyDef.getBaseDN();
+        DN expected = baseDN == null ? null : DN.valueOf(baseDN);
+
+        assertEquals(actual, expected);
+    }
+
+    @DataProvider(name = "legalValues")
+    public Object[][] createLegalValues() {
+        return new Object[][] {
+            // base DN, value to validate
+            { null, "cn=config" },
+            { null, "dc=example,dc=com" },
+            { "", "cn=config" },
+            { "cn=config", "cn=key manager providers, cn=config" },
+            { "cn=key manager providers, cn=config", "cn=my provider, cn=key manager providers, cn=config" },
+            };
+    }
+
+    @DataProvider(name = "illegalValues")
+    public Object[][] createIllegalValues() {
+        return new Object[][] {
+            // Above base DN.
+            { "cn=config", "" },
+
+            // Same as base DN.
+            { "cn=config", "cn=config" },
+
+            // Same as base DN.
+            { "cn=key manager providers, cn=config", "cn=key manager providers, cn=config" },
+
+            // Too far beneath base DN.
+            { "cn=config", "cn=my provider, cn=key manager providers, cn=config" },
+
+            // Unrelated to base DN.
+            { "cn=config", "dc=example, dc=com" }, };
+    }
+
+    @Test(dataProvider = "legalValues")
+    public void testValidateLegalValues(String baseDN, String valueToValidate) throws DirectoryException {
+        DNPropertyDefinition.Builder localBuilder = DNPropertyDefinition.createBuilder(RootCfgDefn.getInstance(),
+                "test-property");
+        localBuilder.setBaseDN(baseDN);
+        DNPropertyDefinition propertyDef = localBuilder.getInstance();
+        propertyDef.validateValue(DN.valueOf(valueToValidate));
+    }
+
+    @Test(dataProvider = "illegalValues", expectedExceptions = IllegalPropertyValueException.class)
+    public void testValidateIllegalValues(String baseDN, String valueToValidate) throws DirectoryException {
+        DNPropertyDefinition.Builder localBuilder = DNPropertyDefinition.createBuilder(RootCfgDefn.getInstance(),
+                "test-property");
+        localBuilder.setBaseDN(baseDN);
+        DNPropertyDefinition propertyDef = localBuilder.getInstance();
+        propertyDef.validateValue(DN.valueOf(valueToValidate));
+    }
+
+    @Test(dataProvider = "legalValues")
+    public void testDecodeLegalValues(String baseDN, String valueToValidate) {
+        DNPropertyDefinition.Builder localBuilder = DNPropertyDefinition.createBuilder(RootCfgDefn.getInstance(),
+                "test-property");
+        localBuilder.setBaseDN(baseDN);
+        DNPropertyDefinition propertyDef = localBuilder.getInstance();
+        propertyDef.decodeValue(valueToValidate);
+    }
+
+    @Test(dataProvider = "illegalValues", expectedExceptions = IllegalPropertyValueStringException.class)
+    public void testDecodeIllegalValues(String baseDN, String valueToValidate) {
+        DNPropertyDefinition.Builder localBuilder = DNPropertyDefinition.createBuilder(RootCfgDefn.getInstance(),
+                "test-property");
+        localBuilder.setBaseDN(baseDN);
+        DNPropertyDefinition propertyDef = localBuilder.getInstance();
+        propertyDef.decodeValue(valueToValidate);
+    }
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/DurationPropertyDefinitionTest.java b/opendj-admin/src/test/java/org/opends/server/admin/DurationPropertyDefinitionTest.java
new file mode 100644
index 0000000..8e266b6
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/DurationPropertyDefinitionTest.java
@@ -0,0 +1,359 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.admin;
+
+import static org.fest.assertions.Assertions.*;
+import static org.testng.Assert.*;
+
+import org.forgerock.opendj.admin.meta.RootCfgDefn;
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class DurationPropertyDefinitionTest extends ConfigTestCase {
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        disableClassValidationForProperties();
+    }
+
+    @Test
+    public void testCreateBuilder() {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        assertNotNull(builder);
+    }
+
+    /**
+     * Creates data for testing string-based limit values
+     *
+     * @return data
+     */
+    @DataProvider(name = "longLimitData")
+    Object[][] createLongLimitData() {
+        return new Object[][] {
+                { 1L, 1L },
+        };
+    }
+
+    /**
+     * Creates data for testing limit values
+     *
+     * @return data
+     */
+    @DataProvider(name = "illegalLongLimitData")
+    Object[][] createIllegalLongLimitData() {
+        return new Object[][] {
+             // lower, upper, lower first
+             { -1L, 0L, true },
+             { 0L, -1L, false },
+             { 2L, 1L, true },
+             { 2L, 1L, false } };
+    }
+
+    @DataProvider(name = "stringLimitData")
+    Object[][] createStringLimitData() {
+        return new Object[][] {
+            // unit, limit, expected value
+            { "ms", "123", 123 },
+            { "ms", "123s", 123000 },
+            { "s", "123", 123000 },
+            { "s", "123s", 123000 },
+            { "m", "10", 600000 },
+            { "m", "10s", 10000 } };
+    }
+
+    @Test(dataProvider = "longLimitData")
+    public void testLowerLimitWithLong(long lowerLimit, long expectedValue) {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setLowerLimit(lowerLimit);
+        DurationPropertyDefinition def = buildTestDefinition(builder);
+        assertEquals(def.getLowerLimit(), expectedValue);
+    }
+
+    @Test(dataProvider = "stringLimitData")
+    public void testLowerLimitWithString(String unit, String limitValue, long expected) {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setBaseUnit(DurationUnit.getUnit(unit));
+        builder.setLowerLimit(limitValue);
+        DurationPropertyDefinition def = buildTestDefinition(builder);
+        assertEquals(def.getLowerLimit(), expected);
+    }
+
+    @Test(dataProvider = "longLimitData")
+    public void testUpperLimitWithLong(long upperLimit, long expectedValue) {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setUpperLimit(upperLimit);
+        DurationPropertyDefinition def = buildTestDefinition(builder);
+        assertEquals((long) def.getUpperLimit(), expectedValue);
+    }
+
+    @Test(dataProvider = "illegalLongLimitData", expectedExceptions = IllegalArgumentException.class)
+    public void testIllegalLimitsWithLong(long lowerLimit, long upperLimit, boolean isLowerFirst) {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        if (isLowerFirst) {
+            builder.setLowerLimit(lowerLimit);
+            builder.setUpperLimit(upperLimit);
+        } else {
+            builder.setUpperLimit(upperLimit);
+            builder.setLowerLimit(lowerLimit);
+        }
+    }
+
+    @Test
+    public void testAllowUnlimitedIsTrue() {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        DurationPropertyDefinition def = buildTestDefinition(builder);
+        def.decodeValue("unlimited");
+    }
+
+    @Test(expectedExceptions = IllegalPropertyValueStringException.class)
+    public void testAllowUnlimitedIsFalse() {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(false);
+        DurationPropertyDefinition def = buildTestDefinition(builder);
+        def.decodeValue("unlimited");
+    }
+
+    @Test(expectedExceptions = IllegalPropertyValueException.class)
+    public void testAllowUnlimitedIsFalseNumValue() {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(false);
+        DurationPropertyDefinition def = buildTestDefinition(builder);
+        def.validateValue(-1L);
+    }
+
+    @DataProvider(name = "validateValueData")
+    Object[][] createValidateValueData() {
+        return new Object[][] {
+            // low in ms, high in ms, allow unlimited, value in seconds
+            { 5000L, 10000L, false, 7L },
+            { 5000L, null, true, -1L },
+            { 5000L, 10000L, false, 5L },
+            { 5000L, 10000L, false, 10L },
+            { 5000L, null, false, 10000L }
+        };
+    }
+
+    @Test(dataProvider = "validateValueData")
+    public void testValidateValue(Long lowerLimitInMillis, Long higherLimitInMillis,
+            boolean isAllowUnlimited, Long valueInSeconds) {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setLowerLimit(lowerLimitInMillis);
+        builder.setUpperLimit(higherLimitInMillis);
+        builder.setAllowUnlimited(isAllowUnlimited);
+        DurationPropertyDefinition def = buildTestDefinition(builder);
+        def.validateValue(valueInSeconds);
+    }
+
+    @DataProvider(name = "illegalValidateValueData")
+    Object[][] createIllegalValidateValueData() {
+        return new Object[][] {
+             // low in ms, high in ms, allow unlimited, value in seconds
+            { 5000L, 10000L, false, null },
+            { 5000L, 10000L, false, 1L },
+            { 5000L, 10000L, false, 11L },
+            { 5000L, 10000L, false, -1L } };
+    }
+
+    @Test(dataProvider = "illegalValidateValueData", expectedExceptions = { AssertionError.class,
+            NullPointerException.class, IllegalPropertyValueException.class })
+    public void testValidateValueIllegal(Long lowLimitInMillis, Long highLimitInMillis,
+            boolean isAllowUnlimited, Long valueInSeconds) {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setLowerLimit(lowLimitInMillis);
+        builder.setUpperLimit(highLimitInMillis);
+        builder.setAllowUnlimited(isAllowUnlimited);
+        DurationPropertyDefinition def = buildTestDefinition(builder);
+        def.validateValue(valueInSeconds);
+    }
+
+    @DataProvider(name = "encodeValueData")
+    Object[][] createEncodeValueData() {
+        return new Object[][] {
+            { -1L, "unlimited" },
+            { 0L, "0 s" },
+            { 1L, "1 s" },
+            { 2L, "2 s" },
+            { 999L, "999 s" },
+            { 1000L, "1000 s" },
+            { 1001L, "1001 s" },
+            { 1023L, "1023 s" },
+            { 1024L, "1024 s" },
+            { 1025L, "1025 s" },
+            { 1000L * 1000L, "1000000 s" },
+         };
+    }
+
+    @Test(dataProvider = "encodeValueData")
+    public void testEncodeValue(Long valueToEncode, String expectedValue) {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        DurationPropertyDefinition def = buildTestDefinition(builder);
+        assertEquals(def.encodeValue(valueToEncode), expectedValue);
+    }
+
+    /** Test that accept doesn't throw and exception */
+    @Test
+    public void testAccept() {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        DurationPropertyDefinition def = buildTestDefinition(builder);
+        PropertyDefinitionVisitor<Boolean, Void> v = new PropertyDefinitionVisitor<Boolean, Void>() {
+            public Boolean visitDuration(DurationPropertyDefinition d, Void o) {
+                return true;
+            }
+            @SuppressWarnings("unused")
+            public Boolean visitUnknown(PropertyDefinition<?> d, Void o) throws UnknownPropertyDefinitionException {
+                return false;
+            }
+        };
+
+        assertEquals((boolean) def.accept(v, null), true);
+    }
+
+    /** Make sure toString doesn't barf */
+    @Test
+    public void testToString() {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        DurationPropertyDefinition def = buildTestDefinition(builder);
+        def.toString();
+    }
+
+    /** Make sure toString doesn't barf */
+    @Test
+    public void testToString2() {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setUpperLimit(10L);
+        DurationPropertyDefinition def = buildTestDefinition(builder);
+        def.toString();
+    }
+
+    @Test
+    public void testCompare() {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        DurationPropertyDefinition def = buildTestDefinition(builder);
+        def.compare(1L, 2L);
+    }
+
+    @Test
+    public void testSetDefaultBehaviorProvider() {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        builder.setDefaultBehaviorProvider(new DefaultBehaviorProvider<Long>() {
+            public <R, P> R accept(DefaultBehaviorProviderVisitor<Long, R, P> v, P p) {
+                return null;
+            }
+        });
+    }
+
+    @Test
+    public void testSetPropertyOption() {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setOption(PropertyOption.HIDDEN);
+    }
+
+    @DataProvider(name = "decodeValueData")
+    Object[][] createDecodeValueData() {
+        return new Object[][] {
+            // syntax tests
+            { "unlimited", -1L },
+            { "0h", 0L },
+            { "0.0h", 0L },
+            { "0.00h", 0L },
+            { "0 h", 0L },
+            { "0.00 h", 0L },
+            { "1h", 1L },
+            { "1 h", 1L },
+            { "0ms", 0L },
+            { "1h60m", 2L },
+            { "1d10h", 34L },
+            { "4d600m", 106L },
+
+            // conversion tests
+            { "1 d", 24L }, { "2 d", 48L }, { "0.5 d", 12L } };
+    }
+
+    @Test(dataProvider = "decodeValueData")
+    public void testDecodeValue(String valueToDecode, Long expectedValue) {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        builder.setBaseUnit(DurationUnit.HOURS);
+        builder.setMaximumUnit(DurationUnit.DAYS);
+        DurationPropertyDefinition def = buildTestDefinition(builder);
+
+        assertThat(def.decodeValue(valueToDecode)).isEqualTo(expectedValue);
+    }
+
+    @DataProvider(name = "decodeValueDataIllegal")
+    Object[][] createDecodeValueDataIllegal() {
+        return new Object[][] { { "" }, { "0" }, // no unit
+                { "123" }, // no unit
+                { "a s" },
+                { "1 x" },
+                { "0.h" },
+                { "0. h" },
+                { "1.h" },
+                { "1. h" },
+                { "1.1 h" }, // too granular
+                { "30 m" }, // unit too small violation
+                { "60 m" }, // unit too small violation
+                { "1 w" }, // unit too big violation
+                { "7 w" }, // unit too big violation
+                { "1 x" }, { "1 d" }, // upper limit violation
+                { "2 h" }, // lower limit violation
+                { "-1 h" } // unlimited violation
+        };
+    }
+
+    @Test(dataProvider = "decodeValueDataIllegal", expectedExceptions = { IllegalPropertyValueStringException.class })
+    public void testDecodeValue(String valueToDecode) {
+        DurationPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(false);
+        builder.setBaseUnit(DurationUnit.HOURS);
+        builder.setMaximumUnit(DurationUnit.DAYS);
+        builder.setLowerLimit(5L);
+        builder.setUpperLimit(10L);
+        DurationPropertyDefinition def = buildTestDefinition(builder);
+        def.decodeValue(valueToDecode);
+    }
+
+    private DurationPropertyDefinition.Builder createTestBuilder() {
+        return DurationPropertyDefinition.createBuilder(RootCfgDefn.getInstance(), "test-property-name");
+    }
+
+    private DurationPropertyDefinition buildTestDefinition(DurationPropertyDefinition.Builder builder) {
+        builder.setDefaultBehaviorProvider(new DefinedDefaultBehaviorProvider<Long>("0"));
+        return builder.getInstance();
+    }
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/DurationUnitTest.java b/opendj-admin/src/test/java/org/opends/server/admin/DurationUnitTest.java
new file mode 100644
index 0000000..9730ca8
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/DurationUnitTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.admin;
+
+import static org.opends.server.admin.DurationUnit.*;
+import static org.testng.Assert.*;
+
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.testng.annotations.*;
+
+@SuppressWarnings("javadoc")
+public class DurationUnitTest extends ConfigTestCase {
+
+    @DataProvider(name = "testGetUnitData")
+    public Object[][] createStringToSizeLimitData() {
+        return new Object[][] {
+                { "ms", MILLI_SECONDS },
+                { "milliseconds", MILLI_SECONDS },
+                { "s", SECONDS },
+                { "seconds", SECONDS },
+                { "m", MINUTES },
+                { "minutes", MINUTES },
+                { "h", HOURS },
+                { "hours", HOURS },
+                { "d", DAYS },
+                { "days", DAYS },
+                { "w", WEEKS },
+                { "weeks", WEEKS } };
+    }
+
+    @Test(dataProvider = "testGetUnitData")
+    public void testGetUnit(String unitString, DurationUnit unit) {
+        assertEquals(getUnit(unitString), unit);
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testGetUnitWithIllegalString() {
+        getUnit("xxx");
+    }
+
+    @DataProvider(name = "valueToStringData")
+    public Object[][] createValueToStringData() {
+        return new Object[][] {
+                { 0L, "0 ms" },
+                { 1L, "1 ms" },
+                { 999L, "999 ms" },
+                { 1000L, "1 s" },
+                { 1001L, "1 s 1 ms" },
+                { 59999L, "59 s 999 ms" },
+                { 60000L, "1 m" },
+                { 3599999L, "59 m 59 s 999 ms" },
+                { 3600000L, "1 h" } };
+    }
+
+    @Test(dataProvider = "valueToStringData")
+    public void testToString(long ordinalValue, String expectedString) {
+        assertEquals(DurationUnit.toString(ordinalValue), expectedString);
+    }
+
+    @Test(dataProvider = "valueToStringData")
+    public void testParseValue(long expectedOrdinal, String value) {
+        assertEquals(DurationUnit.parseValue(value), expectedOrdinal);
+    }
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/EnumPropertyDefinitionTest.java b/opendj-admin/src/test/java/org/opends/server/admin/EnumPropertyDefinitionTest.java
new file mode 100644
index 0000000..1e5f0c1
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/EnumPropertyDefinitionTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.admin;
+
+import static org.testng.Assert.*;
+
+import org.forgerock.opendj.admin.meta.RootCfgDefn;
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class EnumPropertyDefinitionTest extends ConfigTestCase {
+
+    private enum TestEnum {
+        ONE, TWO, THREE
+    }
+
+    private EnumPropertyDefinition.Builder<TestEnum> builder = null;
+
+    @BeforeClass
+    public void setUp() {
+        disableClassValidationForProperties();
+        builder = EnumPropertyDefinition.createBuilder(RootCfgDefn.getInstance(), "test-property");
+        builder.setEnumClass(TestEnum.class);
+    }
+
+    @Test
+    public void testCreateBuilder() {
+        assertNotNull(builder);
+    }
+
+    /**
+     * Tests that exception thrown when no enum class specified by builder
+     */
+    @Test
+    public void testBuildInstance() {
+        EnumPropertyDefinition<?> def = builder.getInstance();
+        assertEquals(def.getEnumClass(), TestEnum.class);
+    }
+
+    /**
+     * Tests that exception thrown when no enum class specified by builder
+     */
+    @Test(expectedExceptions = { IllegalStateException.class })
+    public void testBuildInstanceWithoutEnumClassSpecified() {
+        EnumPropertyDefinition.Builder<TestEnum> localBuilder = EnumPropertyDefinition.createBuilder(
+                RootCfgDefn.getInstance(), "test-property");
+        localBuilder.getInstance();
+    }
+
+    /**
+     * Creates data decodeValue test
+     *
+     * @return data
+     */
+    @DataProvider(name = "decodeValueData")
+    Object[][] createDecodeValueData() {
+        return new Object[][] { { "ONE", TestEnum.ONE } };
+    }
+
+    /**
+     * Tests decodeValue()
+     *
+     * @param value
+     *            to decode
+     * @param expectedValue
+     *            enum expected
+     */
+    @Test(dataProvider = "decodeValueData")
+    public void testDecodeValue(String value, TestEnum expectedValue) {
+        EnumPropertyDefinition<?> def = builder.getInstance();
+        assertEquals(def.decodeValue(value), expectedValue);
+    }
+
+    /**
+     * Creates illegal data for decode value test
+     *
+     * @return data
+     */
+    @DataProvider(name = "decodeValueIllegalData")
+    Object[][] createDecodeValueIllegalData() {
+        return new Object[][] { { "xxx" }, { null } };
+    }
+
+    /**
+     * Tests decodeValue()
+     *
+     * @param value
+     *            to decode
+     */
+    @Test(dataProvider = "decodeValueIllegalData", expectedExceptions = { NullPointerException.class,
+            IllegalPropertyValueStringException.class })
+    public void testDecodeValueIllegalData(String value) {
+        EnumPropertyDefinition<?> def = builder.getInstance();
+        def.decodeValue(value);
+    }
+
+    /**
+     * Tests normalization
+     */
+    @Test
+    public void testNormalizeValue() {
+        EnumPropertyDefinition<TestEnum> def = builder.getInstance();
+        assertEquals(def.normalizeValue(TestEnum.ONE), "one");
+    }
+
+    /**
+     * Tests validation
+     */
+    @Test
+    public void testValidateValue() {
+        EnumPropertyDefinition<TestEnum> def = builder.getInstance();
+        def.validateValue(TestEnum.ONE);
+    }
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/IntegerPropertyDefinitionTest.java b/opendj-admin/src/test/java/org/opends/server/admin/IntegerPropertyDefinitionTest.java
new file mode 100644
index 0000000..de3ca4f
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/IntegerPropertyDefinitionTest.java
@@ -0,0 +1,241 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+import static org.testng.Assert.*;
+
+import org.forgerock.opendj.admin.meta.RootCfgDefn;
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class IntegerPropertyDefinitionTest extends ConfigTestCase {
+
+    @BeforeClass
+    public void setUp() {
+        disableClassValidationForProperties();
+    }
+
+    @Test
+    public void testCreateBuilder() {
+        IntegerPropertyDefinition.Builder builder = createTestBuilder();
+        assertNotNull(builder);
+    }
+
+    @DataProvider(name = "limitData")
+    public Object[][] createlimitData() {
+        return new Object[][] { { 1, 1 },
+        // { null, 0 }
+        };
+    }
+
+    @DataProvider(name = "illegalLimitData")
+    public Object[][] createIllegalLimitData() {
+        return new Object[][] {
+             // lower, upper, is lower first ?
+            { -1, 0, true },
+            { 0, -1, false },
+            { 2, 1, true },
+            { 2, 1, false }
+        };
+    }
+
+    @Test(dataProvider = "limitData")
+    public void testLowerLimitWithInteger(int limit, int expectedValue) {
+        IntegerPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setLowerLimit(limit);
+        IntegerPropertyDefinition propertyDef = buildTestDefinition(builder);
+        assert propertyDef.getLowerLimit() == expectedValue;
+    }
+
+    @Test(dataProvider = "limitData")
+    public void testUpperLimitWithInteger(int limit, int expectedValue) {
+        IntegerPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setUpperLimit(limit);
+        IntegerPropertyDefinition propertyDef = buildTestDefinition(builder);
+        assert propertyDef.getUpperLimit().equals(expectedValue);
+    }
+
+    @Test(dataProvider = "illegalLimitData", expectedExceptions = IllegalArgumentException.class)
+    public void testIllegalLimits(int lower, int upper, boolean isLowerFirst) {
+        IntegerPropertyDefinition.Builder builder = createTestBuilder();
+        if (isLowerFirst) {
+            builder.setLowerLimit(lower);
+            builder.setUpperLimit(upper);
+        } else {
+            builder.setUpperLimit(upper);
+            builder.setLowerLimit(lower);
+        }
+    }
+
+    @Test
+    public void testIsAllowUnlimitedTrue() {
+        IntegerPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        IntegerPropertyDefinition propertyDef = buildTestDefinition(builder);
+        propertyDef.decodeValue("unlimited");
+    }
+
+    @Test(expectedExceptions = IllegalPropertyValueStringException.class)
+    public void testIsAllowUnlimitedFalse() {
+        IntegerPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(false);
+        IntegerPropertyDefinition propertyDef = buildTestDefinition(builder);
+        propertyDef.decodeValue("unlimited");
+    }
+
+    @Test(expectedExceptions = IllegalPropertyValueException.class)
+    public void testIsAllowUnlimitedInteger() {
+        IntegerPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(false);
+        IntegerPropertyDefinition propertyDef = buildTestDefinition(builder);
+        propertyDef.validateValue(-1);
+    }
+
+    @DataProvider(name = "validateValueData")
+    public Object[][] createvalidateValueData() {
+        return new Object[][] {
+            // low, high, allow unlimited ?, value to validate
+            { 5, 10, false, 7 },
+            { 5, null, true, -1 },
+            { 5, 10, true, -1 },
+        };
+    }
+
+    @Test(dataProvider = "validateValueData")
+    public void testValidateValue(Integer low, Integer high, boolean allowUnlimited, Integer valueToValidate) {
+        IntegerPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setLowerLimit(low);
+        builder.setUpperLimit(high);
+        builder.setAllowUnlimited(allowUnlimited);
+        IntegerPropertyDefinition propertyDef = buildTestDefinition(builder);
+        propertyDef.validateValue(valueToValidate);
+    }
+
+    @DataProvider(name = "illegalValidateValueData")
+    public Object[][] createIllegalValidateValueData() {
+        return new Object[][] {
+            // low, high, allow unlimited ?, value to validate
+            { 5, 10, false, null },
+            { 5, 10, false, 1 },
+            { 5, 10, false, 11 },
+            { 5, 10, false, -1 },
+            { 5, 10, true, 2 },
+            { 5, 10, true, 11 }
+         };
+    }
+
+    @Test(dataProvider = "illegalValidateValueData", expectedExceptions = { AssertionError.class,
+            NullPointerException.class, IllegalPropertyValueException.class })
+    public void testValidateValueIllegal(Integer low, Integer high, boolean allowUnlimited, Integer value) {
+        IntegerPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setLowerLimit(low);
+        builder.setUpperLimit(high);
+        builder.setAllowUnlimited(allowUnlimited);
+        IntegerPropertyDefinition propertyDef = buildTestDefinition(builder);
+        propertyDef.validateValue(value);
+    }
+
+    @DataProvider(name = "encodeValueData")
+    public Object[][] createEncodeValueData() {
+        return new Object[][] {
+            { -1, "unlimited" },
+            { 1, "1" }, };
+    }
+
+    @Test(dataProvider = "encodeValueData")
+    public void testEncodeValue(Integer value, String expectedValue) {
+        IntegerPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        IntegerPropertyDefinition propertyDef = buildTestDefinition(builder);
+        assertEquals(propertyDef.encodeValue(value), expectedValue);
+    }
+
+    @Test
+    public void testAccept() {
+        IntegerPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        IntegerPropertyDefinition propertyDef = buildTestDefinition(builder);
+        PropertyDefinitionVisitor<Boolean, Void> v = new PropertyDefinitionVisitor<Boolean, Void>() {
+            public Boolean visitInteger(IntegerPropertyDefinition d, Void o) {
+                return true;
+            }
+
+            @SuppressWarnings("unused")
+            public Boolean visitUnknown(PropertyDefinition<?> d, Void o) throws UnknownPropertyDefinitionException {
+                return false;
+            }
+        };
+
+        assertEquals((boolean) propertyDef.accept(v, null), true);
+    }
+
+    @Test
+    public void testToString() {
+        IntegerPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        IntegerPropertyDefinition propertyDef = buildTestDefinition(builder);
+        propertyDef.toString();
+    }
+
+    @Test
+    public void testCompare() {
+        IntegerPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        IntegerPropertyDefinition propertyDef = buildTestDefinition(builder);
+        propertyDef.compare(1, 2);
+    }
+
+    @Test
+    public void testSetDefaultBehaviorProvider() {
+        IntegerPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        builder.setDefaultBehaviorProvider(new DefaultBehaviorProvider<Integer>() {
+            public <R, P> R accept(DefaultBehaviorProviderVisitor<Integer, R, P> v, P p) {
+                return null;
+            }
+        });
+    }
+
+    @Test
+    public void testSetOption() {
+        IntegerPropertyDefinition.Builder builder = createTestBuilder();
+        builder.setOption(PropertyOption.HIDDEN);
+    }
+
+    private IntegerPropertyDefinition.Builder createTestBuilder() {
+        return IntegerPropertyDefinition.createBuilder(RootCfgDefn.getInstance(), "test-property-name");
+    }
+
+    private IntegerPropertyDefinition buildTestDefinition(IntegerPropertyDefinition.Builder builder) {
+        builder.setDefaultBehaviorProvider(new DefinedDefaultBehaviorProvider<Integer>("0"));
+        return builder.getInstance();
+    }
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/LDAPProfileTest.java b/opendj-admin/src/test/java/org/opends/server/admin/LDAPProfileTest.java
new file mode 100644
index 0000000..ee613f9
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/LDAPProfileTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+import static org.testng.Assert.*;
+
+import java.util.List;
+
+import org.forgerock.opendj.admin.meta.GlobalCfgDefn;
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class LDAPProfileTest extends ConfigTestCase {
+
+    @BeforeClass
+    public void setUp() {
+        disableClassValidationForProperties();
+    }
+
+    /** Makes sure the returned list contains "top" */
+    @Test
+    public void testGetObjectClasses() {
+        LDAPProfile ldapProfile = LDAPProfile.getInstance();
+        List<String> objectClasses = ldapProfile.getObjectClasses(GlobalCfgDefn.getInstance());
+        assertTrue(objectClasses.contains("top"));
+    }
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/ManagedObjectDefinitionI18NResourceTest.java b/opendj-admin/src/test/java/org/opends/server/admin/ManagedObjectDefinitionI18NResourceTest.java
new file mode 100644
index 0000000..87fbda7
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/ManagedObjectDefinitionI18NResourceTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+import static org.testng.Assert.*;
+
+import java.util.Locale;
+
+import org.forgerock.opendj.admin.meta.GlobalCfgDefn;
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class ManagedObjectDefinitionI18NResourceTest extends ConfigTestCase {
+
+    ManagedObjectDefinitionI18NResource definitionI18NResource = null;
+
+    @BeforeClass
+    public void setUp() {
+        disableClassValidationForProperties();
+        definitionI18NResource = ManagedObjectDefinitionI18NResource.getInstanceForProfile("ldap");
+    }
+
+    @Test
+    public void testGetMessage() {
+        // Ideally we should test getting messages with arguments
+        // but I couldn't find any existing properties files with
+        // args
+        assertNotNull(definitionI18NResource.getMessage(GlobalCfgDefn.getInstance(), "objectclass",
+                Locale.getDefault()));
+    }
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/ManagedObjectPathTest.java b/opendj-admin/src/test/java/org/opends/server/admin/ManagedObjectPathTest.java
new file mode 100644
index 0000000..0b5fb18
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/ManagedObjectPathTest.java
@@ -0,0 +1,242 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+import static org.testng.Assert.*;
+
+import org.forgerock.opendj.admin.client.ConnectionHandlerCfgClient;
+import org.forgerock.opendj.admin.client.GlobalCfgClient;
+import org.forgerock.opendj.admin.client.LDAPConnectionHandlerCfgClient;
+import org.forgerock.opendj.admin.meta.ConnectionHandlerCfgDefn;
+import org.forgerock.opendj.admin.meta.GlobalCfgDefn;
+import org.forgerock.opendj.admin.meta.LDAPConnectionHandlerCfgDefn;
+import org.forgerock.opendj.admin.meta.ReplicationDomainCfgDefn;
+import org.forgerock.opendj.admin.meta.ReplicationSynchronizationProviderCfgDefn;
+import org.forgerock.opendj.admin.meta.RootCfgDefn;
+import org.forgerock.opendj.admin.server.ConnectionHandlerCfg;
+import org.forgerock.opendj.admin.server.GlobalCfg;
+import org.forgerock.opendj.admin.server.LDAPConnectionHandlerCfg;
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.forgerock.opendj.ldap.DN;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class ManagedObjectPathTest extends ConfigTestCase {
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        disableClassValidationForProperties();
+    }
+
+    @Test
+    public void testEmptyPathIsEmpty() {
+        ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+        assertTrue(path.isEmpty());
+    }
+
+    @Test
+    public void testEmptyPathHasZeroElements() {
+        ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+        assertEquals(path.size(), 0);
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testEmptyPathHasNoParent() {
+        ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+        path.parent();
+    }
+
+    @Test
+    public void testEmptyPathIsRootConfiguration() {
+        ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+        assertEquals(path.getManagedObjectDefinition(), RootCfgDefn.getInstance());
+    }
+
+    @Test
+    public void testEmptyPathHasNoRelation() {
+        ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+        assertEquals(path.getRelationDefinition(), null);
+    }
+
+    @Test
+    public void testEmptyPathHasNoName() {
+        ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+        assertNull(path.getName());
+    }
+
+    @Test
+    public void testEmptyPathString() {
+        ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+        assertEquals(path.toString(), "/");
+    }
+
+    @Test
+    public void testEmptyPathDecode() {
+        ManagedObjectPath<?, ?> path = ManagedObjectPath.valueOf("/");
+        assertEquals(path, ManagedObjectPath.emptyPath());
+    }
+
+    @Test
+    public void testSingletonChild() {
+        ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+        ManagedObjectPath<GlobalCfgClient, GlobalCfg> child = path.child(RootCfgDefn.getInstance()
+                .getGlobalConfigurationRelationDefinition());
+
+        assertFalse(child.isEmpty());
+        assertEquals(child.size(), 1);
+        assertEquals(child.parent(), path);
+        assertNull(child.getName());
+        assertEquals(child.getManagedObjectDefinition(), GlobalCfgDefn.getInstance());
+        assertEquals(child.getRelationDefinition(), RootCfgDefn.getInstance()
+                .getGlobalConfigurationRelationDefinition());
+        assertEquals(child.toString(), "/relation=global-configuration");
+        assertEquals(child, ManagedObjectPath.valueOf("/relation=global-configuration"));
+    }
+
+    @Test
+    public void testInstantiableChild() {
+        ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+        ManagedObjectPath<ConnectionHandlerCfgClient, ConnectionHandlerCfg> child = path.child(RootCfgDefn
+                .getInstance().getConnectionHandlersRelationDefinition(), "LDAP connection handler");
+
+        assertFalse(child.isEmpty());
+        assertEquals(child.size(), 1);
+        assertEquals(child.parent(), path);
+        assertEquals(child.getName(), "LDAP connection handler");
+        assertEquals(child.getManagedObjectDefinition(), ConnectionHandlerCfgDefn.getInstance());
+        assertEquals(child.getRelationDefinition(), RootCfgDefn.getInstance()
+                .getConnectionHandlersRelationDefinition());
+        assertEquals(child.toString(), "/relation=connection-handler+name=LDAP connection handler");
+        assertEquals(child, ManagedObjectPath.valueOf("/relation=connection-handler+name=LDAP connection handler"));
+    }
+
+    @Test
+    public void testInstantiableChildWithSubtype() {
+        ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+        ManagedObjectPath<LDAPConnectionHandlerCfgClient, LDAPConnectionHandlerCfg> child = path.child(RootCfgDefn
+                .getInstance().getConnectionHandlersRelationDefinition(), LDAPConnectionHandlerCfgDefn.getInstance(),
+                "LDAP connection handler");
+
+        assertFalse(child.isEmpty());
+        assertEquals(child.size(), 1);
+        assertEquals(child.parent(), path);
+        assertEquals(child.getManagedObjectDefinition(), LDAPConnectionHandlerCfgDefn.getInstance());
+        assertEquals(child.getRelationDefinition(), RootCfgDefn.getInstance()
+                .getConnectionHandlersRelationDefinition());
+        String childAsString =
+                "/relation=connection-handler+type=ldap-connection-handler+name=LDAP connection handler";
+        assertEquals(child.toString(), childAsString);
+        assertEquals(child, ManagedObjectPath.valueOf(childAsString));
+    }
+
+    @Test
+    public void testInstantiableChildMultipleLevels() {
+        ManagedObjectPath<?, ?> root = ManagedObjectPath.emptyPath();
+        ManagedObjectPath<?, ?> mmr = root.child(RootCfgDefn.getInstance()
+                .getSynchronizationProvidersRelationDefinition(), ReplicationSynchronizationProviderCfgDefn
+                .getInstance(), "MMR");
+        ManagedObjectPath<?, ?> domain = mmr.child(ReplicationSynchronizationProviderCfgDefn.getInstance()
+                .getReplicationDomainsRelationDefinition(), "Domain");
+        assertFalse(domain.isEmpty());
+        assertEquals(domain.size(), 2);
+        assertEquals(domain.parent(), mmr);
+        assertEquals(domain.parent(2), root);
+        assertEquals(domain.getManagedObjectDefinition(), ReplicationDomainCfgDefn.getInstance());
+        assertEquals(domain.getRelationDefinition(), ReplicationSynchronizationProviderCfgDefn.getInstance()
+                .getReplicationDomainsRelationDefinition());
+        String domainAsString = "/relation=synchronization-provider+type=replication-synchronization-provider"
+                + "+name=MMR/relation=replication-domain+name=Domain";
+        assertEquals(domain.toString(), domainAsString);
+        assertEquals(domain, ManagedObjectPath.valueOf(domainAsString));
+    }
+
+    @Test
+    public void testMatchesAndEqualsBehavior() {
+        ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+
+        ManagedObjectPath<ConnectionHandlerCfgClient, ConnectionHandlerCfg> child1 = path.child(RootCfgDefn
+                .getInstance().getConnectionHandlersRelationDefinition(), "LDAP connection handler");
+
+        ManagedObjectPath<LDAPConnectionHandlerCfgClient, LDAPConnectionHandlerCfg> child2 = path.child(RootCfgDefn
+                .getInstance().getConnectionHandlersRelationDefinition(), LDAPConnectionHandlerCfgDefn.getInstance(),
+                "LDAP connection handler");
+
+        ManagedObjectPath<LDAPConnectionHandlerCfgClient, LDAPConnectionHandlerCfg> child3 = path.child(RootCfgDefn
+                .getInstance().getConnectionHandlersRelationDefinition(), LDAPConnectionHandlerCfgDefn.getInstance(),
+                "Another LDAP connection handler");
+
+        // child 1 and child2 matches each other
+        assertTrue(child1.matches(child1));
+        assertTrue(child2.matches(child2));
+        assertTrue(child1.matches(child2));
+        assertTrue(child2.matches(child1));
+
+        // child 1 and child2 are not equal to each other
+        assertTrue(child1.equals(child1));
+        assertTrue(child2.equals(child2));
+        assertFalse(child1.equals(child2));
+        assertFalse(child2.equals(child1));
+
+        // child 1/2 does not match nor equals child3
+        assertFalse(child1.matches(child3));
+        assertFalse(child2.matches(child3));
+        assertFalse(child3.matches(child1));
+        assertFalse(child3.matches(child2));
+
+        assertFalse(child1.equals(child3));
+        assertFalse(child2.equals(child3));
+        assertFalse(child3.equals(child1));
+        assertFalse(child3.equals(child2));
+    }
+
+    @Test
+    public void testToDN() throws Exception {
+        ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+
+        ManagedObjectPath<ConnectionHandlerCfgClient, ConnectionHandlerCfg> child1 = path.child(RootCfgDefn
+                .getInstance().getConnectionHandlersRelationDefinition(), "LDAP connection handler");
+
+        ManagedObjectPath<LDAPConnectionHandlerCfgClient, LDAPConnectionHandlerCfg> child2 = path.child(RootCfgDefn
+                .getInstance().getConnectionHandlersRelationDefinition(), LDAPConnectionHandlerCfgDefn.getInstance(),
+                "LDAP connection handler");
+
+        ManagedObjectPath<LDAPConnectionHandlerCfgClient, LDAPConnectionHandlerCfg> child3 = path.child(RootCfgDefn
+                .getInstance().getConnectionHandlersRelationDefinition(), LDAPConnectionHandlerCfgDefn.getInstance(),
+                "Another LDAP connection handler");
+
+        DN expectedEmpty = DN.rootDN();
+        DN expectedChild1 = DN.valueOf("cn=LDAP connection handler,cn=connection handlers,cn=config");
+        DN expectedChild2 = DN.valueOf("cn=LDAP connection handler,cn=connection handlers,cn=config");
+        DN expectedChild3 = DN.valueOf("cn=Another LDAP connection handler,cn=connection handlers,cn=config");
+
+        assertEquals(path.toDN(), expectedEmpty);
+        assertEquals(child1.toDN(), expectedChild1);
+        assertEquals(child2.toDN(), expectedChild2);
+        assertEquals(child3.toDN(), expectedChild3);
+    }
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/MockLDAPProfile.java b/opendj-admin/src/test/java/org/opends/server/admin/MockLDAPProfile.java
new file mode 100644
index 0000000..3d41520
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/MockLDAPProfile.java
@@ -0,0 +1,148 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008-2010 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+
+
+/**
+ * A mock LDAP profile wrapper for testing purposes.
+ */
+public final class MockLDAPProfile extends LDAPProfile.Wrapper {
+
+  /**
+   * Creates a new mock LDAP profile.
+   */
+  public MockLDAPProfile() {
+    // No implementation required.
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getAttributeName(AbstractManagedObjectDefinition<?, ?> d,
+      PropertyDefinition<?> pd) {
+
+    if (d == TestParentCfgDefn.getInstance()) {
+      TestParentCfgDefn td = TestParentCfgDefn.getInstance();
+
+      if (pd == (PropertyDefinition<?>)td.getMandatoryBooleanPropertyPropertyDefinition()) {
+        return "ds-cfg-enabled";
+      } else if (pd == (PropertyDefinition<?>)td.getMandatoryClassPropertyPropertyDefinition()) {
+        return "ds-cfg-java-class";
+      } else if (pd == (PropertyDefinition<?>)td
+          .getMandatoryReadOnlyAttributeTypePropertyPropertyDefinition()) {
+        return "ds-cfg-attribute-type";
+      } else if (pd == (PropertyDefinition<?>)td.getOptionalMultiValuedDNPropertyPropertyDefinition()) {
+        return "ds-cfg-base-dn";
+      } else {
+        throw new RuntimeException("Unexpected test-parent property"
+            + pd.getName());
+      }
+    } else if (d == TestChildCfgDefn.getInstance()) {
+      TestChildCfgDefn td = TestChildCfgDefn.getInstance();
+
+      if (pd == (PropertyDefinition<?>)td.getMandatoryBooleanPropertyPropertyDefinition()) {
+        return "ds-cfg-enabled";
+      } else if (pd == (PropertyDefinition<?>)td.getMandatoryClassPropertyPropertyDefinition()) {
+        return "ds-cfg-java-class";
+      } else if (pd == (PropertyDefinition<?>)td
+          .getMandatoryReadOnlyAttributeTypePropertyPropertyDefinition()) {
+        return "ds-cfg-attribute-type";
+      } else if (pd == (PropertyDefinition<?>)td.getOptionalMultiValuedDNProperty1PropertyDefinition()) {
+        return "ds-cfg-base-dn";
+      } else if (pd == (PropertyDefinition<?>)td.getOptionalMultiValuedDNProperty2PropertyDefinition()) {
+        return "ds-cfg-group-dn";
+      } else if (pd.getName().equals("aggregation-property")) {
+        return "ds-cfg-rotation-policy";
+      } else {
+        throw new RuntimeException("Unexpected test-child property"
+            + pd.getName());
+      }
+    }
+
+    // Not known.
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getRelationChildRDNType(
+      InstantiableRelationDefinition<?, ?> r) {
+    if (r == TestCfg.getTestOneToManyParentRelationDefinition()
+        || r == TestParentCfgDefn.getInstance()
+            .getTestChildrenRelationDefinition()) {
+      return "cn";
+    } else {
+      return null;
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getObjectClass(AbstractManagedObjectDefinition<?, ?> d) {
+    if (d == TestParentCfgDefn.getInstance()) {
+      return "ds-cfg-test-parent-dummy";
+    } else if (d == TestChildCfgDefn.getInstance()) {
+      return "ds-cfg-test-child-dummy";
+    } else {
+      // Not known.
+      return null;
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getRelationRDNSequence(RelationDefinition<?, ?> r) {
+    if (r == TestCfg.getTestOneToManyParentRelationDefinition()) {
+      return "cn=test parents,cn=config";
+    } else if (r == TestCfg.getTestOneToZeroOrOneParentRelationDefinition()) {
+      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 null;
+    }
+  }
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/RelativeInheritedDefaultBehaviorProviderTest.java b/opendj-admin/src/test/java/org/opends/server/admin/RelativeInheritedDefaultBehaviorProviderTest.java
new file mode 100644
index 0000000..6660b17
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/RelativeInheritedDefaultBehaviorProviderTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.admin;
+
+import static org.testng.Assert.*;
+
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class RelativeInheritedDefaultBehaviorProviderTest extends ConfigTestCase {
+
+    private static final int OFFSET = 0;
+
+    private TestParentCfgDefn parentDefinition;
+
+    private RelativeInheritedDefaultBehaviorProvider<Boolean> defaultBehaviorProvider = null;
+
+    @BeforeClass
+    public void setUp() {
+        disableClassValidationForProperties();
+        parentDefinition = TestParentCfgDefn.getInstance();
+        this.defaultBehaviorProvider = new RelativeInheritedDefaultBehaviorProvider<Boolean>(
+            parentDefinition,
+            parentDefinition.getMandatoryBooleanPropertyPropertyDefinition().getName(),
+            OFFSET);
+    }
+
+    @Test
+    @SuppressWarnings("rawtypes")
+    public void testAccept() {
+        defaultBehaviorProvider.accept(new DefaultBehaviorProviderVisitor<Boolean, Object, Object>() {
+
+            public Object visitAbsoluteInherited(AbsoluteInheritedDefaultBehaviorProvider d, Object o) {
+                return null;
+            }
+
+            public Object visitAlias(AliasDefaultBehaviorProvider d, Object o) {
+                return null;
+            }
+
+            public Object visitDefined(DefinedDefaultBehaviorProvider d, Object o) {
+                return null;
+            }
+
+            public Object visitRelativeInherited(RelativeInheritedDefaultBehaviorProvider d, Object o) {
+                return null;
+            }
+
+            public Object visitUndefined(UndefinedDefaultBehaviorProvider d, Object o) {
+                return null;
+            }
+        }, new Object());
+    }
+
+    @Test
+    public void testGetManagedObjectPath() {
+        assertEquals(defaultBehaviorProvider.getManagedObjectPath(ManagedObjectPath.emptyPath()),
+                ManagedObjectPath.emptyPath());
+    }
+
+    @Test
+    public void testGetPropertyDefinition() {
+        assertEquals(defaultBehaviorProvider.getPropertyName(),
+                parentDefinition.getMandatoryBooleanPropertyPropertyDefinition().getName());
+    }
+
+    @Test
+    public void testGetRelativeOffset() {
+        assertEquals(defaultBehaviorProvider.getRelativeOffset(), OFFSET);
+    }
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/SizePropertyDefinitionTest.java b/opendj-admin/src/test/java/org/opends/server/admin/SizePropertyDefinitionTest.java
new file mode 100644
index 0000000..9418353
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/SizePropertyDefinitionTest.java
@@ -0,0 +1,260 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+import static org.testng.Assert.*;
+
+import org.forgerock.opendj.admin.meta.RootCfgDefn;
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class SizePropertyDefinitionTest extends ConfigTestCase {
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        disableClassValidationForProperties();
+    }
+
+    @Test
+    public void testCreateBuilder() {
+        SizePropertyDefinition.Builder builder = createTestBuilder();
+        assertNotNull(builder);
+    }
+
+    @Test
+    public void testLowerLimit() {
+        SizePropertyDefinition.Builder builder = createTestBuilder();
+        builder.setLowerLimit(1);
+        SizePropertyDefinition propertyDef = buildTestDefinition(builder);
+        assert propertyDef.getLowerLimit() == 1;
+    }
+
+    @DataProvider(name = "stringLimitData")
+    public Object[][] createStringLimitData() {
+        return new Object[][] {
+            { "1 b", 1L },
+        };
+    }
+
+    @DataProvider(name = "illegalLimitData")
+    public Object[][] createIllegalLimitData() {
+        return new Object[][] {
+            // lower, upper, is lower first
+            { -1L, 0L, true },
+            { 0L, -1L, false },
+            { 2L, 1L, true },
+            { 2L, 1L, false } };
+    }
+
+    @Test(dataProvider = "stringLimitData")
+    public void testLowerLimitString(String unitLimit, Long expectedValue) {
+        SizePropertyDefinition.Builder builder = createTestBuilder();
+        builder.setLowerLimit(unitLimit);
+        SizePropertyDefinition propertyDef = buildTestDefinition(builder);
+        assert propertyDef.getLowerLimit() == expectedValue;
+    }
+
+    @Test(dataProvider = "stringLimitData")
+    public void testUpperLimitString(String limit, long expectedValue) {
+        SizePropertyDefinition.Builder builder = createTestBuilder();
+        builder.setUpperLimit(limit);
+        SizePropertyDefinition propertyDef = buildTestDefinition(builder);
+        assert propertyDef.getUpperLimit().equals(expectedValue);
+    }
+
+    @Test(dataProvider = "illegalLimitData", expectedExceptions = IllegalArgumentException.class)
+    public void testIllegalLimits(long lower, long upper, boolean lowerFirst) {
+        SizePropertyDefinition.Builder builder = createTestBuilder();
+        if (lowerFirst) {
+            builder.setLowerLimit(lower);
+            builder.setUpperLimit(upper);
+        } else {
+            builder.setUpperLimit(upper);
+            builder.setLowerLimit(lower);
+        }
+    }
+
+    @Test
+    public void testIsAllowUnlimitedTrue() {
+        SizePropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        SizePropertyDefinition propertyDef = buildTestDefinition(builder);
+        propertyDef.decodeValue("unlimited");
+    }
+
+    @Test(expectedExceptions = IllegalPropertyValueStringException.class)
+    public void testIsAllowUnlimitedFalse() {
+        SizePropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(false);
+        SizePropertyDefinition propertyDef = buildTestDefinition(builder);
+        propertyDef.decodeValue("unlimited");
+    }
+
+    @Test(expectedExceptions = IllegalPropertyValueException.class)
+    public void testIsAllowUnlimitedNumeric() {
+        SizePropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(false);
+        SizePropertyDefinition propertyDef = buildTestDefinition(builder);
+        propertyDef.validateValue(-1L);
+    }
+
+    @DataProvider(name = "validateValueData")
+    public Object[][] createvalidateValueData() {
+        return new Object[][] {
+            // low, high, is allow unlimited, value
+            { 5L, 10L, false, 7L },
+            { 5L, null, true, -1L },
+            { 5L, 10L, true, -1L },
+        };
+    }
+
+    @Test(dataProvider = "validateValueData")
+    public void testValidateValue(Long low, Long high, boolean isAllowUnlimited, Long valueToValidate) {
+        SizePropertyDefinition.Builder builder = createTestBuilder();
+        builder.setLowerLimit(low);
+        builder.setUpperLimit(high);
+        builder.setAllowUnlimited(isAllowUnlimited);
+        SizePropertyDefinition propertyDef = buildTestDefinition(builder);
+        propertyDef.validateValue(valueToValidate);
+    }
+
+    @DataProvider(name = "illegalValidateValueData")
+    public Object[][] createIllegalValidateValueData() {
+        return new Object[][] {
+             // low, high, is allow unlimited, value
+            { 5L, 10L, false, null },
+            { 5L, 10L, false, 1L },
+            { 5L, 10L, false, 11L },
+            { 5L, 10L, false, -1L },
+            { 5L, 10L, true, 2L },
+            { 5L, 10L, true, 11L }
+        };
+    }
+
+    @Test(dataProvider = "illegalValidateValueData", expectedExceptions = { AssertionError.class,
+            NullPointerException.class, IllegalPropertyValueException.class })
+    public void testValidateValueIllegal(Long low, Long high, boolean allowUnlimited, Long valueToValidate) {
+        SizePropertyDefinition.Builder builder = createTestBuilder();
+        builder.setLowerLimit(low);
+        builder.setUpperLimit(high);
+        builder.setAllowUnlimited(allowUnlimited);
+        SizePropertyDefinition propertyDef = buildTestDefinition(builder);
+        propertyDef.validateValue(valueToValidate);
+    }
+
+    @DataProvider(name = "encodeValueData")
+    public Object[][] createEncodeValueData() {
+        return new Object[][] {
+            { -1L, "unlimited" },
+            { 0L, "0 b" },
+            { 1L, "1 b" },
+            { 2L, "2 b" },
+            { 999L, "999 b" },
+            { 1000L, "1 kb" },
+            { 1001L, "1001 b" },
+            { 1023L, "1023 b" },
+            { 1024L, "1 kib" },
+            { 1025L, "1025 b" },
+            { 1000L * 1000L, "1 mb" },
+            { 1000L * 1000L * 1000L, "1 gb" },
+            { 1024L * 1024L * 1024L, "1 gib" },
+            { 1000L * 1000L * 1000L * 1000L, "1 tb" }
+        };
+    }
+
+    @Test(dataProvider = "encodeValueData")
+    public void testEncodeValue(Long value, String expectedValue) {
+        SizePropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        SizePropertyDefinition propertyDef = buildTestDefinition(builder);
+        assertEquals(propertyDef.encodeValue(value), expectedValue);
+    }
+
+    @Test
+    public void testAccept() {
+        SizePropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        SizePropertyDefinition propertyDef = buildTestDefinition(builder);
+        PropertyDefinitionVisitor<Boolean, Void> v = new PropertyDefinitionVisitor<Boolean, Void>() {
+            public Boolean visitSize(SizePropertyDefinition d, Void o) {
+                return true;
+            }
+            @SuppressWarnings("unused")
+            public Boolean visitUnknown(PropertyDefinition<?> d, Void o) throws UnknownPropertyDefinitionException {
+                return false;
+            }
+        };
+
+        assertEquals((boolean) propertyDef.accept(v, null), true);
+    }
+
+    @Test
+    public void testToString() {
+        SizePropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        SizePropertyDefinition propertyDef = buildTestDefinition(builder);
+        propertyDef.toString();
+    }
+
+    @Test
+    public void testCompare() {
+        SizePropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        SizePropertyDefinition propertyDef = buildTestDefinition(builder);
+        assertEquals(propertyDef.compare(1L, 2L), -1);
+    }
+
+    @Test
+    public void testSetDefaultBehaviorProvider() {
+        SizePropertyDefinition.Builder builder = createTestBuilder();
+        builder.setAllowUnlimited(true);
+        builder.setDefaultBehaviorProvider(new DefaultBehaviorProvider<Long>() {
+            public <R, P> R accept(DefaultBehaviorProviderVisitor<Long, R, P> v, P p) {
+                return null;
+            }
+        });
+    }
+
+    @Test
+    public void testSetOption() {
+        SizePropertyDefinition.Builder builder = createTestBuilder();
+        builder.setOption(PropertyOption.HIDDEN);
+    }
+
+    private SizePropertyDefinition.Builder createTestBuilder() {
+        return SizePropertyDefinition.createBuilder(RootCfgDefn.getInstance(), "test-property-name");
+    }
+
+    private SizePropertyDefinition buildTestDefinition(SizePropertyDefinition.Builder builder) {
+        builder.setDefaultBehaviorProvider(new DefinedDefaultBehaviorProvider<Long>("0"));
+        return builder.getInstance();
+    }
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/SizeUnitTest.java b/opendj-admin/src/test/java/org/opends/server/admin/SizeUnitTest.java
new file mode 100644
index 0000000..39966b7
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/SizeUnitTest.java
@@ -0,0 +1,279 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.admin;
+
+import static org.testng.Assert.*;
+
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class SizeUnitTest extends ConfigTestCase {
+
+    @DataProvider(name = "stringToSizeLimitData")
+    public Object[][] createStringToSizeLimitData() {
+        return new Object[][] {
+            { "b", SizeUnit.BYTES },
+            { "kb", SizeUnit.KILO_BYTES },
+            { "kib", SizeUnit.KIBI_BYTES },
+            { "mb", SizeUnit.MEGA_BYTES },
+            { "mib", SizeUnit.MEBI_BYTES },
+            { "gb", SizeUnit.GIGA_BYTES },
+            { "gib", SizeUnit.GIBI_BYTES },
+            { "tb", SizeUnit.TERA_BYTES },
+            { "tib", SizeUnit.TEBI_BYTES } };
+    }
+
+    @Test(dataProvider = "stringToSizeLimitData")
+    public void testGetUnit(String name, SizeUnit expectedUnit) {
+        SizeUnit unit = SizeUnit.getUnit(name);
+        assertEquals(unit, expectedUnit);
+    }
+
+    @DataProvider(name = "parseValueData")
+    public Object[][] createParseValueData() {
+        return new Object[][] {
+            { "1.0 b", 1L },
+            { "1.0 kb", 1000L },
+            { "1.0 kib", 1024L },
+            { "0b", 0L },
+            { "0 b", 0L },
+            { "0 bytes", 0L },
+            { "0kb", 0L },
+            { "0 kilobytes", 0L },
+            { "0 KILOBYTES", 0L },
+            { "0 KB", 0L },
+            { "1b", 1L },
+            { "1 b", 1L },
+            { "1 bytes", 1L },
+            { "1kb", 1000L },
+            { "1 kilobytes", 1000L },
+            { "1 KILOBYTES", 1000L },
+            { "1 KB", 1000L },
+            { "1000b", 1000L },
+            { "1000 b", 1000L },
+            { "1000 bytes", 1000L },
+            { "1000kb", 1000000L },
+            { "1000 kilobytes", 1000000L },
+            { "1000 KILOBYTES", 1000000L },
+            { "1000 KB", 1000000L } };
+    }
+
+    @Test(dataProvider = "parseValueData")
+    public void testParseValue(String valueToParse, long expectedValue) {
+        assertEquals(SizeUnit.parseValue(valueToParse), expectedValue);
+    }
+
+    @DataProvider(name = "parseValueIllegalData")
+    public Object[][] createParseValueIllegalData() {
+        return new Object[][] {
+            { "a.0 b" },
+            { "1.a kb" },
+            { "1.0 xx" },
+            { "" },
+            { "hello" },
+            { "-1" },
+            { "-1b" },
+            { "1" },
+            { "1x" },
+            { "1.1y" }
+         };
+    }
+
+
+    @Test(dataProvider = "parseValueIllegalData", expectedExceptions = NumberFormatException.class)
+    public void testParseValueIllegal(String value) {
+        SizeUnit.parseValue(value);
+    }
+
+    @DataProvider(name = "valuesToKiloBytes")
+    public Object[][] createConversionData() {
+        return new Object[][] {
+            { "1.0 b", 1L },
+            { "1.0 kb", 1000L },
+            { "1.0 kib", 1024L },
+            { "1.0", 1000L },
+            { "1000", 1000000L },
+            { "1MB", 1000000L }
+         };
+    }
+
+    @Test(dataProvider = "valuesToKiloBytes")
+    public void testParseValueWithUnit(String value, long expectedValueInKB) {
+        assertEquals(SizeUnit.parseValue(value, SizeUnit.KILO_BYTES), expectedValueInKB);
+    }
+
+    @DataProvider(name = "parseValueIllegalDataKB")
+    public Object[][] createParseValueIllegalDataKB() {
+        return new Object[][] {
+            { "a.0 b" },
+            { "1.a kb" },
+            { "1.0 xx" },
+            { "" },
+            { "hello" },
+            { "-1" },
+            { "-1b" },
+            { "1x" },
+            { "1.1y" }
+    };
+    }
+
+    @Test(dataProvider = "parseValueIllegalDataKB", expectedExceptions = NumberFormatException.class)
+    public void testParseValueIllegalWithUnit(String value) {
+        SizeUnit.parseValue(value, SizeUnit.KILO_BYTES);
+    }
+
+    @DataProvider(name = "fromBytesTestData")
+    public Object[][] createFromBytesTestData() {
+        return new Object[][] {
+            { SizeUnit.BYTES, 1L, 1D }
+            // TODO: more data
+        };
+    }
+
+    @Test(dataProvider = "fromBytesTestData")
+    public void testFromBytes(SizeUnit unit, long value, double expected) {
+        assertEquals(unit.fromBytes(value), expected);
+    }
+
+    @DataProvider(name = "bestFitUnitExactData")
+    public Object[][] createBestFitExactData() {
+        return new Object[][] {
+            { 0, SizeUnit.BYTES },
+            { 999, SizeUnit.BYTES },
+            { 1000, SizeUnit.KILO_BYTES },
+            { 1024, SizeUnit.KIBI_BYTES },
+            { 1025, SizeUnit.BYTES },
+            { 999999, SizeUnit.BYTES },
+            { 1000000, SizeUnit.MEGA_BYTES },
+            { 1000001, SizeUnit.BYTES } };
+    }
+
+
+    @Test(dataProvider = "bestFitUnitExactData")
+    public void testGetBestFitUnitExact(long valueForWhichBestFitSought, SizeUnit expectedUnit) {
+        assertEquals(SizeUnit.getBestFitUnitExact(valueForWhichBestFitSought), expectedUnit);
+    }
+
+    @DataProvider(name = "bestFitUnitData")
+    public Object[][] createBestFitData() {
+        return new Object[][] {
+            { 0, SizeUnit.BYTES },
+            { 999, SizeUnit.BYTES },
+            { 1000, SizeUnit.KILO_BYTES },
+            { 1024, SizeUnit.KIBI_BYTES },
+            { 1025, SizeUnit.KILO_BYTES },
+            { 999999, SizeUnit.KILO_BYTES },
+            { 1000000, SizeUnit.MEGA_BYTES },
+            { 1000001, SizeUnit.MEGA_BYTES } };
+    }
+
+    @Test(dataProvider = "bestFitUnitData")
+    public void testGetBestFitUnit(long valueForWhichBestFitSought, SizeUnit expectedUnit) {
+        assertEquals(SizeUnit.getBestFitUnit(valueForWhichBestFitSought), expectedUnit);
+    }
+
+    @DataProvider(name = "longNameData")
+    public Object[][] createLongNameData() {
+        return new Object[][] {
+            { SizeUnit.BYTES, "bytes" },
+            { SizeUnit.KILO_BYTES, "kilobytes" },
+            { SizeUnit.KIBI_BYTES, "kibibytes" },
+            { SizeUnit.MEGA_BYTES, "megabytes" },
+            { SizeUnit.MEBI_BYTES, "mebibytes" },
+            { SizeUnit.GIGA_BYTES, "gigabytes" },
+            { SizeUnit.GIBI_BYTES, "gibibytes" },
+            { SizeUnit.TERA_BYTES, "terabytes" },
+            { SizeUnit.TEBI_BYTES, "tebibytes" }
+        };
+    }
+
+    @Test(dataProvider = "longNameData")
+    public void testGetLongName(SizeUnit unit, String expectedName) {
+        assertEquals(unit.getLongName(), expectedName);
+    }
+
+    @DataProvider(name = "shortNameData")
+    public Object[][] createShortNameData() {
+        return new Object[][] {
+            { SizeUnit.BYTES, "b" },
+            { SizeUnit.KILO_BYTES, "kb" },
+            { SizeUnit.KIBI_BYTES, "kib" },
+            { SizeUnit.MEGA_BYTES, "mb" },
+            { SizeUnit.MEBI_BYTES, "mib" },
+            { SizeUnit.GIGA_BYTES, "gb" },
+            { SizeUnit.GIBI_BYTES, "gib" },
+            { SizeUnit.TERA_BYTES, "tb" },
+            { SizeUnit.TEBI_BYTES, "tib" }
+        };
+    }
+
+    @Test(dataProvider = "shortNameData")
+    public void testGetShortName(SizeUnit unit, String expectedShortName) {
+        assertEquals(unit.getShortName(), expectedShortName);
+    }
+
+    @DataProvider(name = "sizeData")
+    public Object[][] createSizeData() {
+        return new Object[][] {
+            { SizeUnit.BYTES, 1L },
+            { SizeUnit.KILO_BYTES, 1000L },
+            { SizeUnit.KIBI_BYTES, 1024L },
+            { SizeUnit.MEGA_BYTES, (long) 1000 * 1000 },
+            { SizeUnit.MEBI_BYTES, (long) 1024 * 1024 },
+            { SizeUnit.GIGA_BYTES, (long) 1000 * 1000 * 1000 },
+            { SizeUnit.GIBI_BYTES, (long) 1024 * 1024 * 1024 },
+            { SizeUnit.TERA_BYTES, (long) 1000 * 1000 * 1000 * 1000 },
+            { SizeUnit.TEBI_BYTES, (long) 1024 * 1024 * 1024 * 1024 }
+        };
+    }
+
+    @Test(dataProvider = "sizeData")
+    public void testGetSize(SizeUnit unit, long expectedSize) {
+        assertEquals(unit.getSize(), expectedSize);
+    }
+
+    @DataProvider(name = "toBytesData")
+    public Object[][] createToBytesData() {
+        return new Object[][] {
+            // unit to test, amount of unit in bytes, expected
+            { SizeUnit.BYTES, 1D, 1L } };
+    }
+
+    @Test(dataProvider = "toBytesData")
+    public void testToBytes(SizeUnit unit, double amountOfUnitInBytes, long expected) {
+        assertEquals(unit.toBytes(amountOfUnitInBytes), expected);
+    }
+
+    @Test(dataProvider = "shortNameData")
+    public void testToString(SizeUnit unit, String expected) {
+        assertEquals(unit.toString(), expected);
+    }
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/StringPropertyDefinitionTest.java b/opendj-admin/src/test/java/org/opends/server/admin/StringPropertyDefinitionTest.java
new file mode 100644
index 0000000..b127f08
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/StringPropertyDefinitionTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+import static org.testng.Assert.*;
+
+import org.forgerock.opendj.admin.meta.RootCfgDefn;
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class StringPropertyDefinitionTest extends ConfigTestCase {
+
+    @BeforeClass
+    public void setUp() {
+        disableClassValidationForProperties();
+    }
+
+    @Test
+    public void testValidateValueNoPattern() {
+        StringPropertyDefinition d = getDefinition(true, null);
+        d.validateValue("abc");
+    }
+
+    @Test
+    public void testValidateValuePatternMatches() {
+        StringPropertyDefinition d = getDefinition(true, "^[a-z]+$");
+        d.validateValue("abc");
+    }
+
+    // TODO : I18N problem
+    @Test(enabled = false, expectedExceptions = IllegalPropertyValueException.class)
+    public void testValidateValuePatternDoesNotMatch() {
+        StringPropertyDefinition d = getDefinition(true, "^[a-z]+$");
+        d.validateValue("abc123");
+    }
+
+    @Test
+    public void testDecodeValuePatternMatches() {
+        StringPropertyDefinition d = getDefinition(true, "^[a-z]+$");
+        assertEquals(d.decodeValue("abc"), "abc");
+    }
+
+    // TODO : I18N problem
+    @Test(enabled = false, expectedExceptions = IllegalPropertyValueStringException.class)
+    public void testDecodeValuePatternDoesNotMatch() {
+        StringPropertyDefinition d = getDefinition(true, "^[a-z]+$");
+        d.decodeValue("abc123");
+    }
+
+    // Create a string property definition.
+    private StringPropertyDefinition getDefinition(boolean isCaseInsensitive, String pattern) {
+        StringPropertyDefinition.Builder builder = StringPropertyDefinition.createBuilder(RootCfgDefn.getInstance(),
+                "test-property");
+        builder.setCaseInsensitive(isCaseInsensitive);
+        builder.setPattern(pattern, "STRING");
+        return builder.getInstance();
+    }
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/TestCfg.java b/opendj-admin/src/test/java/org/opends/server/admin/TestCfg.java
new file mode 100644
index 0000000..db8dfaa
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/TestCfg.java
@@ -0,0 +1,222 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+import java.util.ResourceBundle;
+
+import org.forgerock.opendj.admin.meta.RootCfgDefn;
+
+/**
+ * Common methods for hooking in the test components.
+ */
+public final class TestCfg {
+
+    /**
+     * A one-to-many relation between the root and test-parent components.
+     */
+    private 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.
+     */
+    private static final OptionalRelationDefinition<TestParentCfgClient, TestParentCfg>
+        RD_TEST_ONE_TO_ZERO_OR_ONE_PARENT;
+
+    // Create a one-to-many relation for test-parent components.
+    static {
+        InstantiableRelationDefinition.Builder<TestParentCfgClient, TestParentCfg> builder =
+            new InstantiableRelationDefinition.Builder<TestParentCfgClient, TestParentCfg>(
+                RootCfgDefn.getInstance(), "test-one-to-many-parent", "test-one-to-many-parents",
+                TestParentCfgDefn.getInstance());
+        RD_TEST_ONE_TO_MANY_PARENT = builder.getInstance();
+    }
+
+    // Create a one-to-many relation for test-parent components.
+    static {
+        OptionalRelationDefinition.Builder<TestParentCfgClient, TestParentCfg> builder =
+            new OptionalRelationDefinition.Builder<TestParentCfgClient, TestParentCfg>(
+                RootCfgDefn.getInstance(), "test-one-to-zero-or-one-parent", TestParentCfgDefn.getInstance());
+        RD_TEST_ONE_TO_ZERO_OR_ONE_PARENT = builder.getInstance();
+    }
+
+    //private static ObjectClass TEST_PARENT_OBJECTCLASS = null;
+    //private static ObjectClass TEST_CHILD_OBJECTCLASS = null;
+
+    /**
+     * Registers test parent and child object class definitions and any required
+     * resource bundles.
+     * <p>
+     * Unit tests which call this method <b>must</b> call {@link #cleanup()} on
+     * completion.
+     *
+     * @throws Exception
+     *             If an unexpected error occurred.
+     */
+    public synchronized static void setUp() throws Exception {
+//        SchemaBuilder schemaBuilder = new SchemaBuilder(Schema.getDefaultSchema());
+//        if (TEST_PARENT_OBJECTCLASS == null || TEST_CHILD_OBJECTCLASS == null) {
+//            String def1 = "( 1.3.6.1.4.1.26027.1.2.4455114401 " + "NAME 'ds-cfg-test-parent-dummy' "
+//                    + "SUP top STRUCTURAL " + "MUST ( cn $ ds-cfg-java-class $ "
+//                    + "ds-cfg-enabled $ ds-cfg-attribute-type ) " + "MAY ( ds-cfg-base-dn $ ds-cfg-group-dn $ "
+//                    + "ds-cfg-filter $ ds-cfg-conflict-behavior ) " + "X-ORIGIN 'OpenDS Directory Server' )";
+//            schemaBuilder.addObjectClass(def1, false);
+//
+//            String def2 = "( 1.3.6.1.4.1.26027.1.2.4455114402 " + "NAME 'ds-cfg-test-child-dummy' "
+//                    + "SUP top STRUCTURAL " + "MUST ( cn $ ds-cfg-java-class $ "
+//                    + "ds-cfg-enabled $ ds-cfg-attribute-type ) " + "MAY ( ds-cfg-base-dn $ ds-cfg-group-dn $ "
+//                    + "ds-cfg-filter $ ds-cfg-conflict-behavior $" + "ds-cfg-rotation-policy) "
+//                    + "X-ORIGIN 'OpenDS Directory Server' )";
+//            schemaBuilder.addObjectClass(def2, false);
+//            Schema schema = schemaBuilder.toSchema();
+//            TEST_PARENT_OBJECTCLASS = schema.getObjectClass("ds-cfg-test-parent-dummy");
+//            TEST_CHILD_OBJECTCLASS = schema.getObjectClass("ds-cfg-test-child-dummy");
+//        }
+
+
+        {
+            // Register the test parent resource bundle.
+            TestParentCfgDefn def = TestParentCfgDefn.getInstance();
+            def.initialize();
+            String baseName = def.getClass().getName();
+            ResourceBundle resourceBundle = ResourceBundle.getBundle(baseName);
+            ManagedObjectDefinitionI18NResource.getInstance().setResourceBundle(def, resourceBundle);
+        }
+
+        {
+            // Register the test child resource bundle.
+            TestChildCfgDefn def = TestChildCfgDefn.getInstance();
+            def.initialize();
+            String baseName = def.getClass().getName();
+            ResourceBundle resourceBundle = ResourceBundle.getBundle(baseName);
+            ManagedObjectDefinitionI18NResource.getInstance().setResourceBundle(def, resourceBundle);
+        }
+
+        // Ensure that the relations are registered (do this after things
+        // that can fail and leave tests in a bad state).
+        RootCfgDefn.getInstance().registerRelationDefinition(RD_TEST_ONE_TO_MANY_PARENT);
+        RootCfgDefn.getInstance().registerRelationDefinition(RD_TEST_ONE_TO_ZERO_OR_ONE_PARENT);
+        LDAPProfile.getInstance().pushWrapper(new MockLDAPProfile());
+    }
+
+    /**
+     * Deregisters the test configurations from the administration framework.
+     */
+    public static void cleanup() {
+        LDAPProfile.getInstance().popWrapper();
+
+        AbstractManagedObjectDefinition<?, ?> root = RootCfgDefn.getInstance();
+        root.deregisterRelationDefinition(RD_TEST_ONE_TO_MANY_PARENT);
+        root.deregisterRelationDefinition(RD_TEST_ONE_TO_ZERO_OR_ONE_PARENT);
+
+        TestParentCfgDefn parentDef = TestParentCfgDefn.getInstance();
+        ManagedObjectDefinitionI18NResource.getInstance().removeResourceBundle(parentDef);
+
+        TestChildCfgDefn childDef = TestChildCfgDefn.getInstance();
+        ManagedObjectDefinitionI18NResource.getInstance().removeResourceBundle(childDef);
+    }
+
+    /**
+     * Gets the one-to-many relation between the root and test-parent
+     * components.
+     * <p>
+     * Unit tests which call this method <b>must</b> have already called
+     * {@link #setUp()}.
+     *
+     * @return Returns the one-to-many relation between the root and test-parent
+     *         components.
+     */
+    public static InstantiableRelationDefinition<TestParentCfgClient, TestParentCfg>
+        getTestOneToManyParentRelationDefinition() {
+            return RD_TEST_ONE_TO_MANY_PARENT;
+    }
+
+    /**
+     * Gets the one-to-zero-or-one relation between the root and a test-parent
+     * component.
+     * <p>
+     * Unit tests which call this method <b>must</b> have already called
+     * {@link #setUp()}.
+     *
+     * @return Returns the one-to-zero-or-one relation between the root and a
+     *         test-parent component.
+     */
+    public static OptionalRelationDefinition<TestParentCfgClient, TestParentCfg>
+        getTestOneToZeroOrOneParentRelationDefinition() {
+            return RD_TEST_ONE_TO_ZERO_OR_ONE_PARENT;
+    }
+
+    /**
+     * Initializes a property definition and its default behavior.
+     *
+     * @param propertyDef
+     *            The property definition to be initialized.
+     * @throws Exception
+     *             If the property definition could not be initialized.
+     */
+    public static void initializePropertyDefinition(PropertyDefinition<?> propertyDef) throws Exception {
+        propertyDef.initialize();
+        propertyDef.getDefaultBehaviorProvider().initialize();
+    }
+
+    /**
+     * Adds a constraint temporarily with test child definition.
+     *
+     * @param constraint
+     *            The constraint.
+     */
+    public static void addConstraint(Constraint constraint) {
+        TestChildCfgDefn.getInstance().registerConstraint(constraint);
+    }
+
+    /**
+     * Adds a property definition temporarily with test child definition,
+     * replacing any existing property definition with the same name.
+     *
+     * @param pd
+     *            The property definition.
+     */
+    public static void addPropertyDefinition(PropertyDefinition<?> pd) {
+        TestChildCfgDefn.getInstance().registerPropertyDefinition(pd);
+    }
+
+    /**
+     * Removes a constraint from the test child definition.
+     *
+     * @param constraint
+     *            The constraint.
+     */
+    public static void removeConstraint(Constraint constraint) {
+        TestChildCfgDefn.getInstance().deregisterConstraint(constraint);
+    }
+
+    // Prevent instantiation.
+    private TestCfg() {
+        // No implementation required.
+    }
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/TestChildCfg.java b/opendj-admin/src/test/java/org/opends/server/admin/TestChildCfg.java
new file mode 100644
index 0000000..f0e3d18
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/TestChildCfg.java
@@ -0,0 +1,125 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2007-2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+import java.util.SortedSet;
+
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+
+/**
+ * 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 {
+
+    /**
+     * Get the configuration class associated with this Test Child.
+     *
+     * @return Returns the configuration class associated with this Test Child.
+     */
+    Class<? extends TestChildCfg> configurationClass();
+
+    /**
+     * Register to be notified when this Test Child is changed.
+     *
+     * @param listener
+     *            The Test Child configuration change listener.
+     */
+    void addChangeListener(ConfigurationChangeListener<TestChildCfg> listener);
+
+    /**
+     * Deregister an existing Test Child configuration change listener.
+     *
+     * @param listener
+     *            The Test Child configuration change listener.
+     */
+    void removeChangeListener(ConfigurationChangeListener<TestChildCfg> listener);
+
+    /**
+     * Get the "aggregation-property" property.
+     * <p>
+     * An aggregation property which references connection handlers.
+     *
+     * @return Returns the values of the "aggregation-property" property.
+     */
+    SortedSet<String> getAggregationProperty();
+
+    /**
+     * 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-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();
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/TestChildCfgClient.java b/opendj-admin/src/test/java/org/opends/server/admin/TestChildCfgClient.java
new file mode 100644
index 0000000..c2d7f89
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/TestChildCfgClient.java
@@ -0,0 +1,193 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+import java.util.Collection;
+import java.util.SortedSet;
+
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.schema.AttributeType;
+
+/**
+ * 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 {
+
+    /**
+     * 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 "aggregation-property" property.
+     * <p>
+     * An aggregation property which references connection handlers.
+     *
+     * @return Returns the values of the "aggregation-property" property.
+     */
+    SortedSet<String> getAggregationProperty();
+
+    /**
+     * Set the "aggregation-property" property.
+     * <p>
+     * An aggregation property which references connection handlers.
+     *
+     * @param values
+     *            The values of the "aggregation-property" property.
+     * @throws IllegalPropertyValueException
+     *             If one or more of the new values are invalid.
+     */
+    void setAggregationProperty(Collection<String> values) throws IllegalPropertyValueException;
+
+    /**
+     * Get the "mandatory-boolean-property" property.
+     * <p>
+     * A mandatory boolean property.
+     *
+     * @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 Child.
+     *
+     * @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 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;
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/TestChildCfgDefn.java b/opendj-admin/src/test/java/org/opends/server/admin/TestChildCfgDefn.java
new file mode 100644
index 0000000..c5f87cc
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/TestChildCfgDefn.java
@@ -0,0 +1,474 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2007-2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+import java.util.Collection;
+import java.util.SortedSet;
+
+import org.forgerock.opendj.admin.client.ConnectionHandlerCfgClient;
+import org.forgerock.opendj.admin.server.ConnectionHandlerCfg;
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.ErrorResultException;
+import org.forgerock.opendj.ldap.schema.AttributeType;
+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.server.ConfigurationChangeListener;
+import org.opends.server.admin.server.ServerManagedObject;
+
+/**
+ * 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> {
+
+    // The singleton configuration definition instance.
+    private static final TestChildCfgDefn INSTANCE = new TestChildCfgDefn();
+
+    // The "aggregation-property" property definition.
+    private static final AggregationPropertyDefinition<ConnectionHandlerCfgClient, ConnectionHandlerCfg>
+        PROPDEF_AGGREGATION_PROPERTY;
+
+    // The "mandatory-boolean-property" property definition.
+    private static final BooleanPropertyDefinition PROPDEF_MANDATORY_BOOLEAN_PROPERTY;
+
+    // The "mandatory-class-property" property definition.
+    private static final ClassPropertyDefinition PROPDEF_MANDATORY_CLASS_PROPERTY;
+
+    // The "mandatory-read-only-attribute-type-property" property definition.
+    private static final AttributeTypePropertyDefinition PROPDEF_MANDATORY_READ_ONLY_ATTRIBUTE_TYPE_PROPERTY;
+
+    // The "optional-multi-valued-dn-property1" property definition.
+    private static final DNPropertyDefinition PROPDEF_OPTIONAL_MULTI_VALUED_DN_PROPERTY1;
+
+    // The "optional-multi-valued-dn-property2" property definition.
+    private static final DNPropertyDefinition PROPDEF_OPTIONAL_MULTI_VALUED_DN_PROPERTY2;
+
+    // Build the "aggregation-property" property definition.
+    static {
+        AggregationPropertyDefinition.Builder<ConnectionHandlerCfgClient, ConnectionHandlerCfg> builder =
+                AggregationPropertyDefinition.createBuilder(INSTANCE, "aggregation-property");
+        builder.setOption(PropertyOption.MULTI_VALUED);
+        builder.setAdministratorAction(new AdministratorAction(AdministratorAction.Type.NONE, INSTANCE,
+                "aggregation-property"));
+        builder.setDefaultBehaviorProvider(new UndefinedDefaultBehaviorProvider<String>());
+        builder.setParentPath("/");
+        builder.setRelationDefinition("connection-handler");
+        PROPDEF_AGGREGATION_PROPERTY = builder.getInstance();
+        INSTANCE.registerPropertyDefinition(PROPDEF_AGGREGATION_PROPERTY);
+        INSTANCE.registerConstraint(PROPDEF_AGGREGATION_PROPERTY.getSourceConstraint());
+    }
+
+    // Build the "mandatory-boolean-property" property definition.
+    static {
+        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>());
+        PROPDEF_MANDATORY_BOOLEAN_PROPERTY = builder.getInstance();
+        INSTANCE.registerPropertyDefinition(PROPDEF_MANDATORY_BOOLEAN_PROPERTY);
+    }
+
+    // Build the "mandatory-class-property" property definition.
+    static {
+        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");
+        PROPDEF_MANDATORY_CLASS_PROPERTY = builder.getInstance();
+        INSTANCE.registerPropertyDefinition(PROPDEF_MANDATORY_CLASS_PROPERTY);
+    }
+
+    // Build the "mandatory-read-only-attribute-type-property" property
+    // definition.
+    static {
+        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>());
+        PROPDEF_MANDATORY_READ_ONLY_ATTRIBUTE_TYPE_PROPERTY = builder.getInstance();
+        INSTANCE.registerPropertyDefinition(PROPDEF_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);
+        PROPDEF_OPTIONAL_MULTI_VALUED_DN_PROPERTY1 = builder.getInstance();
+        INSTANCE.registerPropertyDefinition(PROPDEF_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);
+        PROPDEF_OPTIONAL_MULTI_VALUED_DN_PROPERTY2 = builder.getInstance();
+        INSTANCE.registerPropertyDefinition(PROPDEF_OPTIONAL_MULTI_VALUED_DN_PROPERTY2);
+    }
+
+    /**
+     * Get the Test Child configuration definition singleton.
+     *
+     * @return Returns the Test Child configuration definition singleton.
+     */
+    public static TestChildCfgDefn getInstance() {
+        return INSTANCE;
+    }
+
+    /**
+     * Private constructor.
+     */
+    private TestChildCfgDefn() {
+        super("test-child", null);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public TestChildCfgClient createClientConfiguration(ManagedObject<? extends TestChildCfgClient> impl) {
+        return new TestChildCfgClientImpl(impl);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public TestChildCfg createServerConfiguration(ServerManagedObject<? extends TestChildCfg> impl) {
+        return new TestChildCfgServerImpl(impl);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Class<TestChildCfg> getServerConfigurationClass() {
+        return TestChildCfg.class;
+    }
+
+    /**
+     * Get the "aggregation-property" property definition.
+     * <p>
+     * An aggregation property which references connection handlers.
+     *
+     * @return Returns the "aggregation-property" property definition.
+     */
+    public AggregationPropertyDefinition<ConnectionHandlerCfgClient, ConnectionHandlerCfg>
+        getAggregationPropertyPropertyDefinition() {
+            return PROPDEF_AGGREGATION_PROPERTY;
+    }
+
+    /**
+     * Get the "mandatory-boolean-property" property definition.
+     * <p>
+     * A mandatory boolean property.
+     *
+     * @return Returns the "mandatory-boolean-property" property definition.
+     */
+    public BooleanPropertyDefinition getMandatoryBooleanPropertyPropertyDefinition() {
+        return PROPDEF_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 PROPDEF_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 PROPDEF_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 PROPDEF_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 PROPDEF_OPTIONAL_MULTI_VALUED_DN_PROPERTY2;
+    }
+
+    /**
+     * Managed object client implementation.
+     */
+    private static class TestChildCfgClientImpl implements TestChildCfgClient {
+
+        // Private implementation.
+        private ManagedObject<? extends TestChildCfgClient> impl;
+
+        // Private constructor.
+        private TestChildCfgClientImpl(ManagedObject<? extends TestChildCfgClient> impl) {
+            this.impl = impl;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public SortedSet<String> getAggregationProperty() {
+            return impl.getPropertyValues(INSTANCE.getAggregationPropertyPropertyDefinition());
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void setAggregationProperty(Collection<String> values) {
+            impl.setPropertyValues(INSTANCE.getAggregationPropertyPropertyDefinition(), values);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Boolean isMandatoryBooleanProperty() {
+            return impl.getPropertyValue(INSTANCE.getMandatoryBooleanPropertyPropertyDefinition());
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void setMandatoryBooleanProperty(boolean value) {
+            impl.setPropertyValue(INSTANCE.getMandatoryBooleanPropertyPropertyDefinition(), value);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public String getMandatoryClassProperty() {
+            return impl.getPropertyValue(INSTANCE.getMandatoryClassPropertyPropertyDefinition());
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        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> 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);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public ManagedObjectDefinition<? extends TestChildCfgClient, ? extends TestChildCfg> definition() {
+            return INSTANCE;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public PropertyProvider properties() {
+            return impl;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void commit() throws ManagedObjectAlreadyExistsException, MissingMandatoryPropertiesException,
+                ConcurrentModificationException, OperationRejectedException, ErrorResultException {
+            impl.commit();
+        }
+
+    }
+
+    /**
+     * Managed object server implementation.
+     */
+    private static class TestChildCfgServerImpl implements TestChildCfg {
+
+        // Private implementation.
+        private ServerManagedObject<? extends TestChildCfg> impl;
+
+        // Private constructor.
+        private TestChildCfgServerImpl(ServerManagedObject<? extends TestChildCfg> impl) {
+            this.impl = impl;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void addChangeListener(ConfigurationChangeListener<TestChildCfg> listener) {
+            impl.registerChangeListener(listener);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void removeChangeListener(ConfigurationChangeListener<TestChildCfg> listener) {
+            impl.deregisterChangeListener(listener);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public SortedSet<String> getAggregationProperty() {
+            return impl.getPropertyValues(INSTANCE.getAggregationPropertyPropertyDefinition());
+        }
+
+        /**
+         * {@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> getOptionalMultiValuedDNProperty1() {
+            return impl.getPropertyValues(INSTANCE.getOptionalMultiValuedDNProperty1PropertyDefinition());
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public SortedSet<DN> getOptionalMultiValuedDNProperty2() {
+            return impl.getPropertyValues(INSTANCE.getOptionalMultiValuedDNProperty2PropertyDefinition());
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Class<? extends TestChildCfg> configurationClass() {
+            return TestChildCfg.class;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public DN dn() {
+            return impl.getDN();
+        }
+
+    }
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/TestChildCfgDefn.properties b/opendj-admin/src/test/java/org/opends/server/admin/TestChildCfgDefn.properties
new file mode 100644
index 0000000..a5d5ac7
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/TestChildCfgDefn.properties
@@ -0,0 +1,9 @@
+user-friendly-name=Test Child
+user-friendly-plural-name=Test Children
+synopsis=A configuration for testing components that are subordinate to a parent component. It re-uses the virtual-attribute configuration LDAP profile.
+property.aggregation-property.synopsis=An aggregation property which references connection handlers.
+property.mandatory-boolean-property.synopsis=A mandatory boolean property.
+property.mandatory-class-property.synopsis=A mandatory Java-class property requiring a component restart.
+property.mandatory-read-only-attribute-type-property.synopsis=A mandatory read-only attribute type property.
+property.optional-multi-valued-dn-property1.synopsis=An optional multi-valued DN property which inherits its values from optional-multi-valued-dn-property in the parent.
+property.optional-multi-valued-dn-property2.synopsis=An optional multi-valued DN property which inherits its values from optional-multi-valued-dn-property1.
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/TestChildConfiguration.xml b/opendj-admin/src/test/java/org/opends/server/admin/TestChildConfiguration.xml
new file mode 100644
index 0000000..734cd32
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/TestChildConfiguration.xml
@@ -0,0 +1,161 @@
+<?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
+  !
+  !
+  !      Copyright 2008 Sun Microsystems, Inc.
+  ! -->
+<adm:managed-object name="test-child" plural-name="test-children"
+  package="org.opends.server.admin"
+  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.4455114402</ldap:oid>
+      <ldap:name>ds-cfg-test-child-dummy</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-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-java-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-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-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-group-dn</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="aggregation-property" multi-valued="true">
+    <adm:synopsis>
+      An aggregation property which references connection handlers.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:undefined />
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:aggregation parent-path="/"
+        relation-name="connection-handler" />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.332</ldap:oid>
+        <ldap:name>ds-task-initialize-domain-dn</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+</adm:managed-object>
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/TestParentCfg.java b/opendj-admin/src/test/java/org/opends/server/admin/TestParentCfg.java
new file mode 100644
index 0000000..db943cc
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/TestParentCfg.java
@@ -0,0 +1,216 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2007-2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+import java.util.SortedSet;
+
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.schema.AttributeType;
+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;
+
+/**
+ * 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 {
+
+    /**
+     * Get the configuration class associated with this Test Parent.
+     *
+     * @return Returns the configuration class associated with this Test Parent.
+     */
+    Class<? extends TestParentCfg> configurationClass();
+
+    /**
+     * Register to be notified when this Test Parent is changed.
+     *
+     * @param listener
+     *            The Test Parent configuration change listener.
+     */
+    void addChangeListener(ConfigurationChangeListener<TestParentCfg> listener);
+
+    /**
+     * Deregister an existing Test Parent configuration change listener.
+     *
+     * @param listener
+     *            The Test Parent configuration change listener.
+     */
+    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);
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/TestParentCfgClient.java b/opendj-admin/src/test/java/org/opends/server/admin/TestParentCfgClient.java
new file mode 100644
index 0000000..fcb168a
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/TestParentCfgClient.java
@@ -0,0 +1,300 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+import java.util.Collection;
+import java.util.SortedSet;
+
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.ErrorResultException;
+import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.opends.server.admin.client.ConcurrentModificationException;
+import org.opends.server.admin.client.IllegalManagedObjectNameException;
+import org.opends.server.admin.client.ManagedObjectDecodingException;
+import org.opends.server.admin.client.OperationRejectedException;
+
+/**
+ * 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 {
+
+    /**
+     * 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 "mandatory-boolean-property" property.
+     * <p>
+     * A mandatory boolean property.
+     *
+     * @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
+     *             another client.
+     * @throws ErrorResultException
+     *             If an error occurs
+     */
+    String[] listTestChildren() throws ConcurrentModificationException, ErrorResultException;
+
+    /**
+     * Gets the named Test Child.
+     *
+     * @param name
+     *            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.
+     * @throws ManagedObjectDecodingException
+     *             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.
+     * @throws ConcurrentModificationException
+     *             If this Test Parent has been removed from the server by
+     *             another client.
+     * @throws ErrorResultException
+     *             If an error occurs.
+     */
+    TestChildCfgClient getTestChild(String name) throws DefinitionDecodingException, ManagedObjectDecodingException,
+            ManagedObjectNotFoundException, ConcurrentModificationException, ErrorResultException;
+
+    /**
+     * 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 created.
+     * @param d
+     *            The definition of the Test Child to be created.
+     * @param name
+     *            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 configuration instance.
+     * @throws IllegalManagedObjectNameException
+     *             If the name is invalid.
+     */
+    <C extends TestChildCfgClient> C createTestChild(ManagedObjectDefinition<C, ? extends TestChildCfg> d, String name,
+            Collection<DefaultBehaviorException> exceptions) throws IllegalManagedObjectNameException;
+
+    /**
+     * Removes the named Test Child.
+     *
+     * @param name
+     *            The name of the Test Child to remove.
+     * @throws ManagedObjectNotFoundException
+     *             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).
+     * @throws ConcurrentModificationException
+     *             If this Test Parent has been removed from the server by
+     *             another client.
+     * @throws ErrorResultException
+     *          If an errors occurs.
+     */
+    void removeTestChild(String name) throws ManagedObjectNotFoundException, OperationRejectedException,
+            ConcurrentModificationException, ErrorResultException;
+
+    /**
+     * 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 ErrorResultException
+     *          If an errors occurs.
+     */
+    boolean hasOptionalTestChild() throws ConcurrentModificationException, ErrorResultException;
+
+    /**
+     * Gets the Optional Test Child if it is present.
+     *
+     * @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 ErrorResultException
+     *             If an errors occurs.
+     */
+    TestChildCfgClient getOptionalChild() throws DefinitionDecodingException, ManagedObjectDecodingException,
+            ManagedObjectNotFoundException, ConcurrentModificationException, ErrorResultException;
+
+    /**
+     * 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 <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.
+     */
+    <C extends TestChildCfgClient> C createOptionalTestChild(ManagedObjectDefinition<C, ? extends TestChildCfg> d,
+            Collection<DefaultBehaviorException> exceptions);
+
+    /**
+     * Removes the Optional Test Child if it exists.
+     *
+     * @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 ErrorResultException
+     *             If an errors occurs.
+     */
+    void removeOptionalTestChild() throws ManagedObjectNotFoundException, OperationRejectedException,
+            ConcurrentModificationException, ErrorResultException;
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/TestParentCfgDefn.java b/opendj-admin/src/test/java/org/opends/server/admin/TestParentCfgDefn.java
new file mode 100644
index 0000000..0d953ab
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/TestParentCfgDefn.java
@@ -0,0 +1,568 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2007-2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+import java.util.Collection;
+import java.util.SortedSet;
+
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.ErrorResultException;
+import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.opends.server.admin.client.ConcurrentModificationException;
+import org.opends.server.admin.client.IllegalManagedObjectNameException;
+import org.opends.server.admin.client.ManagedObject;
+import org.opends.server.admin.client.ManagedObjectDecodingException;
+import org.opends.server.admin.client.MissingMandatoryPropertiesException;
+import org.opends.server.admin.client.OperationRejectedException;
+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.config.ConfigException;
+
+/**
+ * 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> {
+
+    // The singleton configuration definition instance.
+    private static final TestParentCfgDefn INSTANCE = new TestParentCfgDefn();
+
+    // 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 "optional-test-child" relation definition.
+    private static final OptionalRelationDefinition<TestChildCfgClient, TestChildCfg> RD_OPTIONAL_TEST_CHILD;
+
+    // Build the "mandatory-boolean-property" property definition.
+    static {
+        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 "mandatory-class-property" property definition.
+    static {
+        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.SomeVirtualAttributeProvider");
+        builder.setDefaultBehaviorProvider(provider);
+        builder.addInstanceOf("org.opends.server.api.VirtualAttributeProvider");
+        PD_MANDATORY_CLASS_PROPERTY = builder.getInstance();
+        INSTANCE.registerPropertyDefinition(PD_MANDATORY_CLASS_PROPERTY);
+    }
+
+    // Build the "mandatory-read-only-attribute-type-property" property
+    // definition.
+    static {
+        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 {
+        InstantiableRelationDefinition.Builder<TestChildCfgClient, TestChildCfg> builder =
+            new InstantiableRelationDefinition.Builder<TestChildCfgClient, TestChildCfg>(
+                INSTANCE, "multiple-children", "test-children", TestChildCfgDefn.getInstance());
+        RD_TEST_CHILDREN = builder.getInstance();
+        INSTANCE.registerRelationDefinition(RD_TEST_CHILDREN);
+    }
+
+    // Build the "optional-test-child" relation definition.
+    static {
+        OptionalRelationDefinition.Builder<TestChildCfgClient, TestChildCfg> builder =
+            new OptionalRelationDefinition.Builder<TestChildCfgClient, TestChildCfg>(
+                INSTANCE, "optional-test-child", TestChildCfgDefn.getInstance());
+        RD_OPTIONAL_TEST_CHILD = builder.getInstance();
+        INSTANCE.registerRelationDefinition(RD_OPTIONAL_TEST_CHILD);
+    }
+
+    /**
+     * Get the Test Parent configuration definition singleton.
+     *
+     * @return Returns the Test Parent configuration definition singleton.
+     */
+    public static TestParentCfgDefn getInstance() {
+        return INSTANCE;
+    }
+
+    /**
+     * Private constructor.
+     */
+    private TestParentCfgDefn() {
+        super("test-parent", null);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public TestParentCfgClient createClientConfiguration(ManagedObject<? extends TestParentCfgClient> impl) {
+        return new TestParentCfgClientImpl(impl);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public TestParentCfg createServerConfiguration(ServerManagedObject<? extends TestParentCfg> impl) {
+        return new TestParentCfgServerImpl(impl);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Class<TestParentCfg> getServerConfigurationClass() {
+        return TestParentCfg.class;
+    }
+
+    /**
+     * 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 implementation.
+        private ManagedObject<? extends TestParentCfgClient> impl;
+
+        // Private constructor.
+        private TestParentCfgClientImpl(ManagedObject<? extends TestParentCfgClient> impl) {
+            this.impl = impl;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Boolean isMandatoryBooleanProperty() {
+            return impl.getPropertyValue(INSTANCE.getMandatoryBooleanPropertyPropertyDefinition());
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void setMandatoryBooleanProperty(boolean value) {
+            impl.setPropertyValue(INSTANCE.getMandatoryBooleanPropertyPropertyDefinition(), value);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public String getMandatoryClassProperty() {
+            return impl.getPropertyValue(INSTANCE.getMandatoryClassPropertyPropertyDefinition());
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        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, ErrorResultException {
+            return impl.listChildren(INSTANCE.getTestChildrenRelationDefinition());
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public TestChildCfgClient getTestChild(String name) throws DefinitionDecodingException,
+                ManagedObjectDecodingException, ManagedObjectNotFoundException, ConcurrentModificationException,
+                ErrorResultException {
+            return impl.getChild(INSTANCE.getTestChildrenRelationDefinition(), name).getConfiguration();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public <M extends TestChildCfgClient> M createTestChild(ManagedObjectDefinition<M, ? extends TestChildCfg> d,
+                String name, Collection<DefaultBehaviorException> exceptions) throws IllegalManagedObjectNameException {
+            return impl.createChild(INSTANCE.getTestChildrenRelationDefinition(), d, name, exceptions)
+                    .getConfiguration();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void removeTestChild(String name) throws ManagedObjectNotFoundException,
+                ConcurrentModificationException, OperationRejectedException, ErrorResultException {
+            impl.removeChild(INSTANCE.getTestChildrenRelationDefinition(), name);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public boolean hasOptionalTestChild() throws ConcurrentModificationException, ErrorResultException {
+            return impl.hasChild(INSTANCE.getOptionalTestChildRelationDefinition());
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public TestChildCfgClient getOptionalChild() throws DefinitionDecodingException,
+                ManagedObjectDecodingException, ManagedObjectNotFoundException, ConcurrentModificationException,
+                ErrorResultException {
+            return impl.getChild(INSTANCE.getOptionalTestChildRelationDefinition()).getConfiguration();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public <M extends TestChildCfgClient> M createOptionalTestChild(
+                ManagedObjectDefinition<M, ? extends TestChildCfg> d, Collection<DefaultBehaviorException> exceptions) {
+            return impl.createChild(INSTANCE.getOptionalTestChildRelationDefinition(), d, exceptions)
+                    .getConfiguration();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void removeOptionalTestChild() throws ManagedObjectNotFoundException, ConcurrentModificationException,
+                OperationRejectedException, ErrorResultException {
+            impl.removeChild(INSTANCE.getOptionalTestChildRelationDefinition());
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public ManagedObjectDefinition<? extends TestParentCfgClient, ? extends TestParentCfg> definition() {
+            return INSTANCE;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public PropertyProvider properties() {
+            return impl;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void commit() throws ManagedObjectAlreadyExistsException, MissingMandatoryPropertiesException,
+                ConcurrentModificationException, OperationRejectedException, ErrorResultException {
+            impl.commit();
+        }
+
+    }
+
+    /**
+     * Managed object server implementation.
+     */
+    private static class TestParentCfgServerImpl implements TestParentCfg {
+
+        // Private implementation.
+        private ServerManagedObject<? extends TestParentCfg> impl;
+
+        // Private constructor.
+        private TestParentCfgServerImpl(ServerManagedObject<? extends TestParentCfg> impl) {
+            this.impl = impl;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void addChangeListener(ConfigurationChangeListener<TestParentCfg> listener) {
+            impl.registerChangeListener(listener);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        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);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Class<? extends TestParentCfg> configurationClass() {
+            return TestParentCfg.class;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public DN dn() {
+            return impl.getDN();
+        }
+
+    }
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/TestParentCfgDefn.properties b/opendj-admin/src/test/java/org/opends/server/admin/TestParentCfgDefn.properties
new file mode 100644
index 0000000..2e5c044
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/TestParentCfgDefn.properties
@@ -0,0 +1,12 @@
+user-friendly-name=Test Parent
+user-friendly-plural-name=Test Parents
+synopsis=A configuration for testing components that have child components. It re-uses the virtual-attribute configuration LDAP profile.
+property.mandatory-boolean-property.synopsis=A mandatory boolean property.
+property.mandatory-class-property.synopsis=A mandatory Java-class property requiring a component restart.
+property.mandatory-read-only-attribute-type-property.synopsis=A mandatory read-only attribute type property.
+property.optional-multi-valued-dn-property.synopsis=An optional multi-valued DN property with a defined default behavior.
+relation.optional-test-child.user-friendly-name=Optional Test Child
+relation.optional-test-child.synopsis=A configuration for testing components that are subordinate to a parent component. It re-uses the virtual-attribute configuration LDAP profile.
+relation.test-child.user-friendly-name=Test Child
+relation.test-child.user-friendly-plural-name=Test Children
+relation.test-child.synopsis=A configuration for testing components that are subordinate to a parent component. It re-uses the virtual-attribute configuration LDAP profile.
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/TestParentConfiguration.xml b/opendj-admin/src/test/java/org/opends/server/admin/TestParentConfiguration.xml
new file mode 100644
index 0000000..8192db2
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/TestParentConfiguration.xml
@@ -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
+  !
+  !
+  !      Copyright 2008 Sun Microsystems, Inc.
+  ! -->
+<adm:managed-object name="test-parent" plural-name="test-parents"
+  package="org.opends.server.admin"
+  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.4455114401</ldap:oid>
+      <ldap:name>ds-cfg-test-parent-dummy</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-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-java-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-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-base-dn</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+</adm:managed-object>
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/TestTopCfgDefnTest.java b/opendj-admin/src/test/java/org/opends/server/admin/TestTopCfgDefnTest.java
new file mode 100644
index 0000000..29f0fd3
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/TestTopCfgDefnTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.admin;
+
+import static org.fest.assertions.Assertions.*;
+import static org.testng.Assert.*;
+
+import org.forgerock.opendj.admin.meta.RootCfgDefn;
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+
+@SuppressWarnings("javadoc")
+@Test(singleThreaded = true)
+public class TestTopCfgDefnTest extends ConfigTestCase {
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        disableClassValidationForProperties();
+    }
+
+    @Test
+    public void testGetInstance() {
+        assertNotNull(TopCfgDefn.getInstance());
+    }
+
+    @Test
+    public void testGetName() {
+        assertEquals(TopCfgDefn.getInstance().getName(), "top");
+    }
+
+    @Test
+    public void testGetAllPropertyDefinitionsIsEmpty() {
+        assertTrue(TopCfgDefn.getInstance().getAllPropertyDefinitions().isEmpty());
+    }
+
+    @Test
+    public void testGetAllRelationDefinitionsIsEmpty() {
+        assertTrue(TopCfgDefn.getInstance().getAllRelationDefinitions().isEmpty());
+    }
+
+    @Test
+    public void testGetAllConstraintsIsEmpty() {
+        assertTrue(TopCfgDefn.getInstance().getAllConstraints().isEmpty());
+    }
+
+    @Test
+    public void testGetAllTagsIsEmpty() {
+        assertTrue(TopCfgDefn.getInstance().getAllTags().isEmpty());
+    }
+
+    @Test
+    public void testGetParentReturnNull() {
+        assertNull(TopCfgDefn.getInstance().getParent());
+    }
+
+    @Test
+    public void testIsTop() {
+        assertTrue(TopCfgDefn.getInstance().isTop());
+    }
+
+    @Test(expectedExceptions = UnsupportedOperationException.class)
+    public void testGetSynopsis() {
+        assertNotNull(TopCfgDefn.getInstance().getSynopsis());
+    }
+
+    @Test(expectedExceptions = UnsupportedOperationException.class)
+    public void testGetDescription() {
+        assertNotNull(TopCfgDefn.getInstance().getDescription());
+    }
+
+    @Test(expectedExceptions = UnsupportedOperationException.class)
+    public void testGetUserFriendlyName() {
+        assertNotNull(TopCfgDefn.getInstance().getUserFriendlyName());
+    }
+
+    @Test(expectedExceptions = UnsupportedOperationException.class)
+    public void testGetUserFriendlyPluralName() {
+        assertNotNull(TopCfgDefn.getInstance().getUserFriendlyPluralName());
+    }
+
+    @Test
+    public void testGetAllChildren() {
+        // load RootCfgDef as child of TopCfgDef, and load all children of RootCfgDef as well
+        RootCfgDefn.getInstance();
+        assertThat(TopCfgDefn.getInstance().getAllChildren()).isNotEmpty();
+    }
+
+}
diff --git a/opendj-admin/src/test/java/org/opends/server/admin/ValidateConfigDefinitionsTest.java b/opendj-admin/src/test/java/org/opends/server/admin/ValidateConfigDefinitionsTest.java
new file mode 100644
index 0000000..78efc0e
--- /dev/null
+++ b/opendj-admin/src/test/java/org/opends/server/admin/ValidateConfigDefinitionsTest.java
@@ -0,0 +1,220 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ *      Portions copyright 2011 ForgeRock AS
+ */
+package org.opends.server.admin;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.forgerock.opendj.config.ConfigTestCase;
+import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.forgerock.opendj.ldap.schema.ObjectClass;
+import org.forgerock.opendj.ldap.schema.Schema;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class ValidateConfigDefinitionsTest extends ConfigTestCase {
+
+    private static final String EOL = System.getProperty("line.separator");
+
+    @BeforeClass
+    public void setup() throws Exception {
+        disableClassValidationForProperties();
+        TestCfg.setUp();
+    }
+
+    @AfterClass
+    public void tearDown() {
+        TestCfg.cleanup();
+    }
+
+    @DataProvider
+    Object[][] enumerateManageObjectDefns() throws Exception {
+        TopCfgDefn topCfgDefn = TopCfgDefn.getInstance();
+        List<AbstractManagedObjectDefinition<?, ?>> allCfgDefns =
+                new ArrayList<AbstractManagedObjectDefinition<?, ?>>(topCfgDefn.getAllChildren());
+
+        Object[][] params = new Object[allCfgDefns.size()][];
+        for (int i = 0; i < params.length; i++) {
+            params[i] = new Object[] { allCfgDefns.get(i) };
+        }
+        System.out.println(params.length);
+        return params;
+    }
+
+    // Exceptions to config objects having a different objectclass
+    private static final List<String> CLASS_OBJECT_CLASS_EXCEPTIONS = Arrays.asList(new String[] {
+            "org.opends.server.admin.std.meta.RootCfgDefn", "org.opends.server.admin.std.meta.GlobalCfgDefn", });
+
+    // TODO : does not work because can retrieve object class objects
+    @Test(enabled = false, dataProvider = "enumerateManageObjectDefns")
+    public void validateConfigObjectDefinitions(AbstractManagedObjectDefinition<?, ?> objectDef) {
+        String objName = objectDef.getName();
+        StringBuilder errors = new StringBuilder();
+        Collection<PropertyDefinition<?>> allPropertyDefs = objectDef.getAllPropertyDefinitions();
+
+        LDAPProfile ldapProfile = LDAPProfile.getInstance();
+        String ldapObjectclassName = ldapProfile.getObjectClass(objectDef);
+        if (ldapObjectclassName == null) {
+            errors.append("There is no objectclass definition for configuration object " + objName);
+        } else {
+            String expectedObjectClass = "ds-cfg-" + objName;
+            if (!ldapObjectclassName.equals(expectedObjectClass)
+                    && !CLASS_OBJECT_CLASS_EXCEPTIONS.contains(objectDef.getClass().getName())) {
+                errors.append(
+                        "For config object " + objName + ", the LDAP objectclass must be " + expectedObjectClass
+                                + " instead of " + ldapObjectclassName).append(EOL + EOL);
+            }
+        }
+        ObjectClass configObjectClass = Schema.getDefaultSchema().asNonStrictSchema().
+                getObjectClass(ldapObjectclassName.toLowerCase());
+        ;
+
+        for (PropertyDefinition<?> propDef : allPropertyDefs) {
+            validatePropertyDefinition(objectDef, configObjectClass, propDef, errors);
+        }
+
+        if (errors.length() > 0) {
+            Assert.fail("The configuration definition for " + objectDef.getName() + " has the following problems: "
+                    + EOL + errors.toString());
+        }
+    }
+
+    // Exceptions to properties ending in -class being exactly 'java-class'.
+    private static final List<String> CLASS_PROPERTY_EXCEPTIONS = Arrays.asList(new String[] {
+    // e.g. "prop-name-ending-with-class"
+            });
+
+    // Exceptions to properties ending in -enabled being exactly 'enabled'.
+    private static final List<String> ENABLED_PROPERTY_EXCEPTIONS = Arrays.asList(new String[] {
+            "index-filter-analyzer-enabled", "subordinate-indexes-enabled"
+    // e.g. "prop-name-ending-with-enabled"
+            });
+
+    // Exceptions to properties not starting with the name of their config
+    // object
+    private static final List<String> OBJECT_PREFIX_PROPERTY_EXCEPTIONS = Arrays.asList(new String[] { "backend-id",
+            "plugin-type", "replication-server-id", "network-group-id", "workflow-id", "workflow-element-id",
+            "workflow-element"
+    // e.g. "prop-name-starting-with-object-prefix"
+            });
+
+    private void validatePropertyDefinition(AbstractManagedObjectDefinition<?, ?> objectDef,
+            ObjectClass configObjectClass, PropertyDefinition<?> propDef, StringBuilder errors) {
+        String objName = objectDef.getName();
+        String propName = propDef.getName();
+
+        // We want class properties to be exactly java-class
+        if (propName.endsWith("-class") && !propName.equals("java-class")
+                && !CLASS_PROPERTY_EXCEPTIONS.contains(propName)) {
+            errors.append("The " + propName + " property on config object " + objName
+                    + " should probably be java-class.  If not, then add " + propName
+                    + " to the CLASS_PROPERTY_EXCEPTIONS array in " + ValidateConfigDefinitionsTest.class.getName()
+                    + " to suppress" + " this warning.");
+        }
+
+        // We want enabled properties to be exactly enabled
+        if (propName.endsWith("-enabled") && !ENABLED_PROPERTY_EXCEPTIONS.contains(propName)) {
+            errors.append("The " + propName + " property on config object " + objName
+                    + " should probably be just 'enabled'.  If not, then add " + propName
+                    + " to the ENABLED_PROPERTY_EXCEPTIONS array in " + ValidateConfigDefinitionsTest.class.getName()
+                    + " to suppress" + " this warning.");
+        }
+
+        // It's redundant for properties to be prefixed with the name of their
+        // objecty
+        if (propName.startsWith(objName) && !propName.equals(objName)
+                && !OBJECT_PREFIX_PROPERTY_EXCEPTIONS.contains(propName)) {
+            errors.append("The " + propName + " property on config object " + objName
+                    + " should not be prefixed with the name of the config object because"
+                    + " this is redundant.  If you disagree, then add " + propName
+                    + " to the OBJECT_PREFIX_PROPERTY_EXCEPTIONS array in "
+                    + ValidateConfigDefinitionsTest.class.getName() + " to suppress" + " this warning.");
+        }
+
+        LDAPProfile ldapProfile = LDAPProfile.getInstance();
+        String ldapAttrName = ldapProfile.getAttributeName(objectDef, propDef);
+
+        // LDAP attribute name is consistent with the property name
+        String expectedLdapAttr = "ds-cfg-" + propName;
+        if (!ldapAttrName.equals(expectedLdapAttr)) {
+            errors.append(
+                    "For the " + propName + " property on config object " + objName + ", the LDAP attribute must be "
+                            + expectedLdapAttr + " instead of " + ldapAttrName).append(EOL + EOL);
+        }
+
+        Schema schema = Schema.getDefaultSchema();
+        AttributeType attrType = schema.getAttributeType(ldapAttrName.toLowerCase());
+
+        // LDAP attribute exists
+        if (attrType == null) {
+            errors.append(
+                    propName + " property on config object " + objName + " is declared" + " to use ldap attribute "
+                            + ldapAttrName + ", but this attribute is not in the schema ").append(EOL + EOL);
+        } else {
+
+            // LDAP attribute is multivalued if the property is multivalued
+            if (propDef.hasOption(PropertyOption.MULTI_VALUED) && attrType.isSingleValue()) {
+                errors.append(
+                        propName + " property on config object " + objName + " is declared"
+                                + " as multi-valued, but the corresponding ldap attribute " + ldapAttrName
+                                + " is declared as single-valued.").append(EOL + EOL);
+            }
+
+            if (configObjectClass != null) {
+                // If it's mandatory in the schema, it must be mandatory on the
+                // config property
+                Set<AttributeType> mandatoryAttributes = configObjectClass.getRequiredAttributes();
+                if (mandatoryAttributes.contains(attrType) && !propDef.hasOption(PropertyOption.MANDATORY)) {
+                    errors.append(
+                            propName + " property on config object " + objName + " is not declared"
+                                    + " as mandatory even though the corresponding ldap attribute " + ldapAttrName
+                                    + " is declared as mandatory in the schema.").append(EOL + EOL);
+                }
+
+                Set<AttributeType> allowedAttributes = new HashSet<AttributeType>(mandatoryAttributes);
+                allowedAttributes.addAll(configObjectClass.getOptionalAttributes());
+                if (!allowedAttributes.contains(attrType)) {
+                    errors.append(
+                            propName + " property on config object " + objName + " has"
+                                    + " the corresponding ldap attribute " + ldapAttrName
+                                    + ", but this attribute is not an allowed attribute on the configuration "
+                                    + " object's objectclass " + configObjectClass.getNameOrOID()).append(EOL + EOL);
+                }
+            }
+        }
+    }
+
+}

--
Gitblit v1.10.0