From 5d6e9428fedead57a9c9438cebe58b485ff476d2 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Fri, 14 Sep 2007 10:22:17 +0000
Subject: [PATCH] Avoid managed object definition initialization dependency problems. Using features like inherited default values and aggregation properties it is quite straightforward to encounter initialization dependency problems. For example: the global configuration will contain an aggregation property which references the default password policy. This aggregation definition is defined using a managed object path which, when decoded, contains a reference to the root configuration and its "password-policy" relation. This is what happens during initialization of the root configuration:

---
 opends/src/server/org/opends/server/admin/ClassLoaderProvider.java                            |  118 +++++++----
 opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/AggregationTest.java |   10 
 opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java                |   17 +
 opends/resource/admin/property-types/aggregation.xsl                                          |   13 -
 opends/src/server/org/opends/server/admin/AggregationPropertyDefinition.java                  |  210 +++++++++-----------
 opends/src/server/org/opends/server/admin/DefaultBehaviorProvider.java                        |   67 ++++-
 opends/src/server/org/opends/server/admin/UndefinedDefaultBehaviorProvider.java               |    2 
 opends/src/server/org/opends/server/admin/PropertyDefinition.java                             |   17 +
 opends/src/server/org/opends/server/admin/DefinedDefaultBehaviorProvider.java                 |    2 
 opends/resource/admin/metaMO.xsl                                                              |    2 
 opends/src/messages/messages/admin.properties                                                 |   21 ++
 opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java       |   43 ++-
 opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java       |    6 
 opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestCfg.java                |   18 +
 opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java       |    5 
 opends/src/server/org/opends/server/admin/AliasDefaultBehaviorProvider.java                   |    2 
 16 files changed, 325 insertions(+), 228 deletions(-)

diff --git a/opends/resource/admin/metaMO.xsl b/opends/resource/admin/metaMO.xsl
index d11b125..cb1f445 100644
--- a/opends/resource/admin/metaMO.xsl
+++ b/opends/resource/admin/metaMO.xsl
@@ -699,7 +699,7 @@
         <xsl:variable name="path"
           select="adm:default-behavior/adm:inherited/adm:absolute/@path" />
         <xsl:value-of
-          select="concat('ManagedObjectPath.valueOf(&quot;', $path, '&quot;), &quot;', $property-name, '&quot;);&#xa;')" />
+          select="concat('&quot;', $path, '&quot;, &quot;', $property-name, '&quot;);&#xa;')" />
         <xsl:value-of
           select="'      builder.setDefaultBehaviorProvider(provider);&#xa;'" />
       </xsl:when>
diff --git a/opends/resource/admin/property-types/aggregation.xsl b/opends/resource/admin/property-types/aggregation.xsl
index 2927e6f..be85934 100644
--- a/opends/resource/admin/property-types/aggregation.xsl
+++ b/opends/resource/admin/property-types/aggregation.xsl
@@ -41,15 +41,9 @@
       <xsl:value-of select="'.server.'" />
       <xsl:call-template name="get-server-type" />
     </xsl:element>
-    <xsl:element name="import">
-      <xsl:call-template name="get-definition-package" />
-      <xsl:value-of select="'.meta.'" />
-      <xsl:call-template name="get-definition-type" />
-    </xsl:element>
     <xsl:if test="../../@multi-valued = 'true'">
       <import>java.util.TreeSet</import>
     </xsl:if>
-    <import>org.opends.server.admin.ManagedObjectPath</import>
     <import>org.opends.server.admin.AggregationPropertyDefinition</import>
   </xsl:template>
   <xsl:template match="adm:aggregation" mode="java-value-type">
@@ -91,14 +85,11 @@
       </xsl:message>
     </xsl:if>
     <xsl:value-of
-      select="concat('      builder.setParentPath(ManagedObjectPath.valueOf(&quot;',
-                     normalize-space(@parent-path), '&quot;));&#xa;')" />
+      select="concat('      builder.setParentPath(&quot;',
+                     normalize-space(@parent-path), '&quot;);&#xa;')" />
     <xsl:value-of
       select="concat('      builder.setRelationDefinition(&quot;',
                      normalize-space(@relation-name), '&quot;);&#xa;')" />
-    <xsl:value-of select="'      builder.setManagedObjectDefinition('" />
-    <xsl:call-template name="get-definition-type" />
-    <xsl:value-of select="'.getInstance());&#xa;'" />
     <xsl:if test="@source-enabled-property-name">
       <xsl:value-of
         select="concat('      builder.setSourceEnabledPropertyName(&quot;',
diff --git a/opends/src/messages/messages/admin.properties b/opends/src/messages/messages/admin.properties
index 3b03a62..c58a1f8 100644
--- a/opends/src/messages/messages/admin.properties
+++ b/opends/src/messages/messages/admin.properties
@@ -274,4 +274,23 @@
 SEVERE_ERR_SERVER_REFINT_CANNOT_DISABLE_118=The %s in entry "%s" \
  cannot be disabled because it is referenced by the "%s" property \
  of the %s in entry "%s"
-
+FATAL_ERR_CANNOT_INITIALIZE_ADMIN_FRAMEWORK_119=The administration \
+ framework could not be initialized due to the following exception: %s
+SEVERE_ERR_CLASS_LOADER_CANNOT_READ_MANIFEST_FILE_120=An unexpected \
+ error occurred while reading the manifest file: %s
+SEVERE_ERR_CLASS_LOADER_CANNOT_LOAD_CLASS_121=An error occurred while \
+ attempting to load class "%s": %s 
+SEVERE_ERR_CLASS_LOADER_CANNOT_FIND_GET_INSTANCE_METHOD_122=Unable to \
+ to find the getInstance() method in the managed object definition \
+ class "%s": %s
+SEVERE_ERR_CLASS_LOADER_CANNOT_INVOKE_GET_INSTANCE_METHOD_123=Unable to \
+ to invoke the getInstance() method in the managed object definition \
+ class "%s": %s
+SEVERE_ERR_CLASS_LOADER_CANNOT_INITIALIZE_DEFN_124=Unable initialize the \
+ "%s" managed object definition in class "%s": %s
+SEVERE_ERR_CLASS_LOADER_CANNOT_LOAD_EXTENSION_125=The extension "%s" \
+ with manifest file %s cannot be loaded because an unexpected error \
+ occurred while trying to initialize it: %s
+FATAL_ERR_CLASS_LOADER_CANNOT_LOAD_CORE_126=The core administration \
+ classes could not be loaded from manifest file %s because an unexpected \
+ error occurred: %s
diff --git a/opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java b/opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java
index e0f961c..178342a 100644
--- a/opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java
+++ b/opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java
@@ -30,18 +30,22 @@
 
 /**
  * A default behavior provider which retrieves default values from a
- * managed object in an abolute location. It should be used by
+ * managed object in an absolute location. It should be used by
  * properties which inherit their default value(s) from properties
  * held in an other managed object.
  *
  * @param <T>
  *          The type of values represented by this provider.
  */
-public final class AbsoluteInheritedDefaultBehaviorProvider<T> implements
+public final class AbsoluteInheritedDefaultBehaviorProvider<T> extends
     DefaultBehaviorProvider<T> {
 
   // The absolute path to the managed object containing the property.
-  private final ManagedObjectPath<?, ?> path;
+  private ManagedObjectPath<?, ?> path = null;
+
+  // The string representation of the managed object path specifying
+  // the absolute location of the managed object.
+  private final String pathString;
 
   // The name of the property containing the inherited default values.
   private final String propertyName;
@@ -52,24 +56,16 @@
    * Create an absolute inherited default behavior provider associated
    * with the managed object at the specified absolute location.
    *
-   * @param path
-   *          The absolute location of the managed object.
+   * @param pathString
+   *          The string representation of the managed object path
+   *          specifying the absolute location of the managed object.
    * @param propertyName
    *          The name of the property containing the inherited
    *          default values.
-   * @throws IllegalArgumentException
-   *           If the named property is associated with the managed
-   *           object definition identified by the path.
-   * @throws ClassCastException
-   *           If the named property does not have the same type of
-   *           property values as this default behavior provider.
    */
-  @SuppressWarnings("unchecked")
-  public AbsoluteInheritedDefaultBehaviorProvider(ManagedObjectPath path,
-      String propertyName) throws IllegalArgumentException, ClassCastException {
-    // We do not decode the property name now because the property
-    // might not have been constructed at this point.
-    this.path = path;
+  public AbsoluteInheritedDefaultBehaviorProvider(String pathString,
+      String propertyName) {
+    this.pathString = pathString;
     this.propertyName = propertyName;
   }
 
@@ -111,7 +107,7 @@
 
 
   /**
-   * Get the name of the property containing the inherited default
+   * Gets the name of the property containing the inherited default
    * values.
    *
    * @return Returns the name of the property containing the inherited
@@ -121,4 +117,15 @@
     return propertyName;
   }
 
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected void initialize() throws Exception {
+    // Decode the path.
+    path = ManagedObjectPath.valueOf(pathString);
+  }
+
 }
diff --git a/opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java b/opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java
index 881e140..67e8249 100644
--- a/opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java
+++ b/opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java
@@ -713,6 +713,23 @@
 
 
   /**
+   * Initializes all of the property definitions associated with this
+   * managed object definition.
+   *
+   * @throws Exception
+   *           If this managed object definition could not be
+   *           initialized.
+   */
+  protected final void initialize() throws Exception {
+    for (PropertyDefinition<?> pd : getAllPropertyDefinitions()) {
+      pd.initialize();
+      pd.getDefaultBehaviorProvider().initialize();
+    }
+  }
+
+
+
+  /**
    * Register a constraint with the managed object definition.
    * <p>
    * This method <b>must not</b> be called by applications.
diff --git a/opends/src/server/org/opends/server/admin/AggregationPropertyDefinition.java b/opends/src/server/org/opends/server/admin/AggregationPropertyDefinition.java
index 2c7f1d0..94038e1 100644
--- a/opends/src/server/org/opends/server/admin/AggregationPropertyDefinition.java
+++ b/opends/src/server/org/opends/server/admin/AggregationPropertyDefinition.java
@@ -113,12 +113,9 @@
       <C extends ConfigurationClient, S extends Configuration>
       extends AbstractBuilder<String, AggregationPropertyDefinition<C, S>> {
 
-    // The type of referenced managed objects.
-    private AbstractManagedObjectDefinition<?, ?> cd = null;
-
-    // The name of the managed object which is the parent of the
-    // aggregated managed objects.
-    private ManagedObjectPath<?, ?> p = null;
+    // The string representation of the managed object path specifying
+    // the parent of the aggregated managed objects.
+    private String parentPathString = null;
 
     // The name of a relation in the parent managed object which
     // contains the aggregated managed objects.
@@ -145,35 +142,19 @@
 
 
     /**
-     * Sets the definition of the type of referenced managed objects.
-     * <p>
-     * This must be defined before the property definition can be
-     * built.
-     *
-     * @param d
-     *          The definition of the type of referenced managed
-     *          objects.
-     */
-    public final void setManagedObjectDefinition(
-        AbstractManagedObjectDefinition<C, S> d) {
-      this.cd = d;
-    }
-
-
-
-    /**
      * Sets the name of the managed object which is the parent of the
      * aggregated managed objects.
      * <p>
      * This must be defined before the property definition can be
      * built.
      *
-     * @param p
-     *          The name of the managed object which is the parent of
-     *          the aggregated managed objects.
+     * @param pathString
+     *          The string representation of the managed object path
+     *          specifying the parent of the aggregated managed
+     *          objects.
      */
-    public final void setParentPath(ManagedObjectPath<?, ?> p) {
-      this.p = p;
+    public final void setParentPath(String pathString) {
+      this.parentPathString = pathString;
     }
 
 
@@ -236,14 +217,13 @@
     /**
      * {@inheritDoc}
      */
-    @SuppressWarnings("unchecked")
     @Override
     protected AggregationPropertyDefinition<C, S> buildInstance(
         AbstractManagedObjectDefinition<?, ?> d, String propertyName,
         EnumSet<PropertyOption> options, AdministratorAction adminAction,
         DefaultBehaviorProvider<String> defaultBehavior) {
       // Make sure that the parent path has been defined.
-      if (p == null) {
+      if (parentPathString == null) {
         throw new IllegalStateException("Parent path undefined");
       }
 
@@ -252,29 +232,6 @@
         throw new IllegalStateException("Relation definition undefined");
       }
 
-      // Make sure that the managed object definition has been
-      // defined.
-      if (cd == null) {
-        throw new IllegalStateException("Managed object definition undefined");
-      }
-
-      // Make sure that the relation definition is a member of the
-      // parent path's definition.
-      AbstractManagedObjectDefinition<?, ?> parent = p
-          .getManagedObjectDefinition();
-      RelationDefinition<?, ?> rd = parent.getRelationDefinition(rdName);
-
-      // Make sure the relation refers to the child type.
-      AbstractManagedObjectDefinition<?, ?> dTmp = rd.getChildDefinition();
-      if (dTmp != cd) {
-        throw new IllegalStateException("Relation definition \"" + rd.getName()
-            + "\" does not refer to definition " + d.getName());
-      }
-
-      // Force the relation to the correct type.
-      InstantiableRelationDefinition<C, S> relation =
-        (InstantiableRelationDefinition<C, S>) rd;
-
       // Make sure that if a source property is specified then a
       // target property is also specified.
       if (sourceEnabledPropertyName != null
@@ -284,8 +241,8 @@
       }
 
       return new AggregationPropertyDefinition<C, S>(d, propertyName, options,
-          adminAction, defaultBehavior, p, relation, sourceEnabledPropertyName,
-          targetEnabledPropertyName);
+          adminAction, defaultBehavior, parentPathString, rdName,
+          sourceEnabledPropertyName, targetEnabledPropertyName);
     }
 
   }
@@ -397,6 +354,9 @@
       // isConfigurationDeleteAcceptable() call-back should have
       // trapped this.
       if (configuration.dn().equals(dn)) {
+        // This should not happen - the
+        // isConfigurationDeleteAcceptable() call-back should have
+        // trapped this.
         throw new IllegalStateException("Attempting to delete a referenced "
             + configuration.definition().getUserFriendlyName());
       } else {
@@ -642,7 +602,7 @@
    * @return Returns the new aggregation property definition builder.
    */
   public static <C extends ConfigurationClient, S extends Configuration>
-      Builder<C, S> createBuilder(
+  Builder<C, S> createBuilder(
       AbstractManagedObjectDefinition<?, ?> d, String propertyName) {
     return new Builder<C, S>(d, propertyName);
   }
@@ -650,31 +610,45 @@
   // The active server-side referential integrity change listeners
   // associated with this property.
   private final Map<DN, List<ReferentialIntegrityChangeListener>>
-      changeListeners =
-        new HashMap<DN, List<ReferentialIntegrityChangeListener>>();
+    changeListeners =
+      new HashMap<DN, List<ReferentialIntegrityChangeListener>>();
 
   // The active server-side referential integrity delete listeners
   // associated with this property.
   private final Map<DN, List<ReferentialIntegrityDeleteListener>>
-      deleteListeners =
-        new HashMap<DN, List<ReferentialIntegrityDeleteListener>>();
+    deleteListeners =
+      new HashMap<DN, List<ReferentialIntegrityDeleteListener>>();
 
   // The name of the managed object which is the parent of the
   // aggregated managed objects.
-  private final ManagedObjectPath<?, ?> parentPath;
+  private ManagedObjectPath<?, ?> parentPath;
+
+  // The string representation of the managed object path specifying
+  // the parent of the aggregated managed objects.
+  private final String parentPathString;
+
+  // The name of a relation in the parent managed object which
+  // contains the aggregated managed objects.
+  private final String rdName;
 
   // The relation in the parent managed object which contains the
   // aggregated managed objects.
-  private final InstantiableRelationDefinition<C, S> relationDefinition;
+  private InstantiableRelationDefinition<C, S> relationDefinition;
 
-  // The optional name of a boolean "enabled" property in this managed
-  // object. When this property is true, the enabled property in the
-  // aggregated managed object must also be true.
+  // The decoded source property definition.
+  private BooleanPropertyDefinition sourceEnabledProperty;
+
+  // The optional name of a boolean "enabled" property in this
+  // managed object. When this property is true, the enabled
+  // property in the aggregated managed object must also be true.
   private final String sourceEnabledPropertyName;
 
+  // The decoded target property definition.
+  private BooleanPropertyDefinition targetEnabledProperty;
+
   // The optional name of a boolean "enabled" property in the
-  // aggregated managed object. This property must not be false while
-  // the aggregated managed object is referenced.
+  // aggregated managed object. This property must not be false
+  // while the aggregated managed object is referenced.
   private final String targetEnabledPropertyName;
 
 
@@ -683,14 +657,13 @@
   private AggregationPropertyDefinition(
       AbstractManagedObjectDefinition<?, ?> d, String propertyName,
       EnumSet<PropertyOption> options, AdministratorAction adminAction,
-      DefaultBehaviorProvider<String> defaultBehavior,
-      ManagedObjectPath<?, ?> parentPath,
-      InstantiableRelationDefinition<C, S> relationDefinition,
-      String sourceEnabledPropertyName, String targetEnabledPropertyName) {
+      DefaultBehaviorProvider<String> defaultBehavior, String parentPathString,
+      String rdName, String sourceEnabledPropertyName,
+      String targetEnabledPropertyName) {
     super(d, String.class, propertyName, options, adminAction, defaultBehavior);
 
-    this.parentPath = parentPath;
-    this.relationDefinition = relationDefinition;
+    this.parentPathString = parentPathString;
+    this.rdName = rdName;
     this.sourceEnabledPropertyName = sourceEnabledPropertyName;
     this.targetEnabledPropertyName = targetEnabledPropertyName;
   }
@@ -821,27 +794,9 @@
    * @return Returns the optional boolean "enabled" property in this
    *         managed object, or <code>null</code> if none is
    *         defined.
-   * @throws IllegalArgumentException
-   *           If the named property does not exist in this property's
-   *           associated managed object definition.
-   * @throws ClassCastException
-   *           If the named property does exist but is not a
-   *           {@link BooleanPropertyDefinition}.
    */
-  public final BooleanPropertyDefinition getSourceEnabledPropertyDefinition()
-      throws IllegalArgumentException, ClassCastException {
-    if (sourceEnabledPropertyName == null) {
-      return null;
-    }
-
-    AbstractManagedObjectDefinition<?, ?> d = getManagedObjectDefinition();
-
-    PropertyDefinition<?> pd;
-    pd = d.getPropertyDefinition(sourceEnabledPropertyName);
-
-    // Runtime cast is required to workaround a
-    // bug in JDK versions prior to 1.5.0_08.
-    return BooleanPropertyDefinition.class.cast(pd);
+  public final BooleanPropertyDefinition getSourceEnabledPropertyDefinition() {
+    return sourceEnabledProperty;
   }
 
 
@@ -854,28 +809,9 @@
    * @return Returns the optional boolean "enabled" property in the
    *         aggregated managed object, or <code>null</code> if none
    *         is defined.
-   * @throws IllegalArgumentException
-   *           If the named property does not exist in the aggregated
-   *           managed object's definition.
-   * @throws ClassCastException
-   *           If the named property does exist but is not a
-   *           {@link BooleanPropertyDefinition}.
    */
-  public final BooleanPropertyDefinition getTargetEnabledPropertyDefinition()
-      throws IllegalArgumentException, ClassCastException {
-    if (targetEnabledPropertyName == null) {
-      return null;
-    }
-
-    AbstractManagedObjectDefinition<?, ?> d;
-    PropertyDefinition<?> pd;
-
-    d = relationDefinition.getChildDefinition();
-    pd = d.getPropertyDefinition(targetEnabledPropertyName);
-
-    // Runtime cast is required to workaround a
-    // bug in JDK versions prior to 1.5.0_08.
-    return BooleanPropertyDefinition.class.cast(pd);
+  public final BooleanPropertyDefinition getTargetEnabledPropertyDefinition() {
+    return targetEnabledProperty;
   }
 
 
@@ -935,4 +871,50 @@
     }
   }
 
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @SuppressWarnings("unchecked")
+  @Override
+  protected void initialize() throws Exception {
+    // Decode the path.
+    parentPath = ManagedObjectPath.valueOf(parentPathString);
+
+    // Decode the relation definition.
+    AbstractManagedObjectDefinition<?, ?> parent = parentPath
+        .getManagedObjectDefinition();
+    RelationDefinition<?, ?> rd = parent.getRelationDefinition(rdName);
+    relationDefinition = (InstantiableRelationDefinition<C, S>) rd;
+
+    // Now decode the property definitions.
+    if (sourceEnabledPropertyName == null) {
+      sourceEnabledProperty = null;
+    } else {
+      AbstractManagedObjectDefinition<?, ?> d = getManagedObjectDefinition();
+
+      PropertyDefinition<?> pd;
+      pd = d.getPropertyDefinition(sourceEnabledPropertyName);
+
+      // Runtime cast is required to workaround a
+      // bug in JDK versions prior to 1.5.0_08.
+      sourceEnabledProperty = BooleanPropertyDefinition.class.cast(pd);
+    }
+
+    if (targetEnabledPropertyName == null) {
+      targetEnabledProperty = null;
+    } else {
+      AbstractManagedObjectDefinition<?, ?> d;
+      PropertyDefinition<?> pd;
+
+      d = relationDefinition.getChildDefinition();
+      pd = d.getPropertyDefinition(targetEnabledPropertyName);
+
+      // Runtime cast is required to workaround a
+      // bug in JDK versions prior to 1.5.0_08.
+      targetEnabledProperty = BooleanPropertyDefinition.class.cast(pd);
+    }
+  }
+
 }
diff --git a/opends/src/server/org/opends/server/admin/AliasDefaultBehaviorProvider.java b/opends/src/server/org/opends/server/admin/AliasDefaultBehaviorProvider.java
index 03bfd3a..cc8ad78 100644
--- a/opends/src/server/org/opends/server/admin/AliasDefaultBehaviorProvider.java
+++ b/opends/src/server/org/opends/server/admin/AliasDefaultBehaviorProvider.java
@@ -42,7 +42,7 @@
  * @param <T>
  *          The type of values represented by this provider.
  */
-public final class AliasDefaultBehaviorProvider<T> implements
+public final class AliasDefaultBehaviorProvider<T> extends
     DefaultBehaviorProvider<T> {
 
   // The managed object definition associated with this default
diff --git a/opends/src/server/org/opends/server/admin/ClassLoaderProvider.java b/opends/src/server/org/opends/server/admin/ClassLoaderProvider.java
index 2de3b1d..4dcd284 100644
--- a/opends/src/server/org/opends/server/admin/ClassLoaderProvider.java
+++ b/opends/src/server/org/opends/server/admin/ClassLoaderProvider.java
@@ -25,15 +25,13 @@
  *      Portions Copyright 2007 Sun Microsystems, Inc.
  */
 package org.opends.server.admin;
-import org.opends.messages.Message;
 
 
 
-import static org.opends.server.loggers.ErrorLogger.logError;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import org.opends.server.loggers.debug.DebugTracer;
 import static org.opends.messages.AdminMessages.*;
-import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
+import static org.opends.server.loggers.ErrorLogger.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.util.StaticUtils.*;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -41,6 +39,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
@@ -52,8 +51,10 @@
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 
+import org.opends.messages.Message;
 import org.opends.server.admin.std.meta.RootCfgDefn;
 import org.opends.server.core.DirectoryServer;
+import org.opends.server.loggers.debug.DebugTracer;
 import org.opends.server.types.DebugLogLevel;
 import org.opends.server.types.InitializationException;
 import org.opends.server.util.Validator;
@@ -474,21 +475,13 @@
 
     try {
       loadDefinitionClasses(is);
-    } catch (IOException e) {
+    } catch (InitializationException e) {
       if (debugEnabled()) {
         TRACER.debugCaught(DebugLogLevel.ERROR, e);
       }
 
-      Message message = ERR_ADMIN_CANNOT_READ_CORE_MANIFEST.get(
-          CORE_MANIFEST, stackTraceToSingleLineString(e));
-      throw new InitializationException(message);
-    } catch (Exception e) {
-      if (debugEnabled()) {
-        TRACER.debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      Message message = ERR_ADMIN_CANNOT_LOAD_CLASS_FROM_CORE_MANIFEST.get(
-          CORE_MANIFEST, stackTraceToSingleLineString(e));
+      Message message = ERR_CLASS_LOADER_CANNOT_LOAD_CORE.get(CORE_MANIFEST,
+          stackTraceToSingleLineString(e));
       throw new InitializationException(message);
     }
   }
@@ -519,31 +512,21 @@
           TRACER.debugCaught(DebugLogLevel.ERROR, e);
         }
 
-        Message message = ERR_ADMIN_CANNOT_READ_EXTENSION_MANIFEST.
-            get(EXTENSION_MANIFEST, jarFile.getName(),
-                stackTraceToSingleLineString(e));
+        Message message = ERR_ADMIN_CANNOT_READ_EXTENSION_MANIFEST.get(
+            EXTENSION_MANIFEST, jarFile.getName(),
+            stackTraceToSingleLineString(e));
         throw new InitializationException(message);
       }
 
       try {
         loadDefinitionClasses(is);
-      } catch (IOException e) {
+      } catch (InitializationException e) {
         if (debugEnabled()) {
           TRACER.debugCaught(DebugLogLevel.ERROR, e);
         }
 
-        Message message = ERR_ADMIN_CANNOT_READ_EXTENSION_MANIFEST.
-            get(EXTENSION_MANIFEST, jarFile.getName(),
-                stackTraceToSingleLineString(e));
-        throw new InitializationException(message);
-      } catch (Exception e) {
-        if (debugEnabled()) {
-          TRACER.debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        Message message = ERR_ADMIN_CANNOT_LOAD_CLASS_FROM_EXTENSION_MANIFEST.
-            get(EXTENSION_MANIFEST, jarFile.getName(),
-                stackTraceToSingleLineString(e));
+        Message message = ERR_CLASS_LOADER_CANNOT_LOAD_EXTENSION.get(jarFile
+            .getName(), EXTENSION_MANIFEST, stackTraceToSingleLineString(e));
         throw new InitializationException(message);
       }
     }
@@ -557,24 +540,25 @@
    *
    * @param is
    *          The manifest file input stream.
-   * @throws IOException
-   *           If an IO error occurred whilst reading the manifest
-   *           file.
-   * @throws ClassNotFoundException
-   *           If an IO error occurred whilst reading the manifest
-   *           file.
-   * @throws LinkageError
-   *           If the linkage fails.
-   * @throws ExceptionInInitializerError
-   *           If the initialization provoked by this method fails.
+   * @throws InitializationException
+   *           If the definition classes could not be loaded and
+   *           initialized.
    */
   private void loadDefinitionClasses(InputStream is)
-      throws IOException, ClassNotFoundException, LinkageError,
-      ExceptionInInitializerError {
+      throws InitializationException {
     BufferedReader reader = new BufferedReader(new InputStreamReader(
         is));
+    List<AbstractManagedObjectDefinition<?, ?>> definitions =
+      new LinkedList<AbstractManagedObjectDefinition<?,?>>();
     while (true) {
-      String className = reader.readLine();
+      String className;
+      try {
+        className = reader.readLine();
+      } catch (IOException e) {
+        Message msg = ERR_CLASS_LOADER_CANNOT_READ_MANIFEST_FILE.get(String
+            .valueOf(e.getMessage()));
+        throw new InitializationException(msg, e);
+      }
 
       // Break out when the end of the manifest is reached.
       if (className == null) {
@@ -594,8 +578,48 @@
 
       TRACER.debugMessage(DebugLogLevel.INFO, "Loading class " + className);
 
-      // Use the underlying loader.
-      Class.forName(className, true, loader);
+      // Load the class and get an instance of it if it is a definition.
+      Class<?> theClass;
+      try {
+        theClass = Class.forName(className, true, loader);
+      } catch (Exception e) {
+        Message msg = ERR_CLASS_LOADER_CANNOT_LOAD_CLASS.get(className, String
+            .valueOf(e.getMessage()));
+        throw new InitializationException(msg, e);
+      }
+      if (AbstractManagedObjectDefinition.class.isAssignableFrom(theClass)) {
+        // We need to instantiate it using its getInstance() static method.
+        Method method;
+        try {
+          method = theClass.getMethod("getInstance");
+        } catch (Exception e) {
+          Message msg = ERR_CLASS_LOADER_CANNOT_FIND_GET_INSTANCE_METHOD.get(
+              className, String.valueOf(e.getMessage()));
+          throw new InitializationException(msg, e);
+        }
+
+        // Get the definition instance.
+        AbstractManagedObjectDefinition<?, ?> d;
+        try {
+          d = (AbstractManagedObjectDefinition<?, ?>) method.invoke(null);
+        } catch (Exception e) {
+          Message msg = ERR_CLASS_LOADER_CANNOT_INVOKE_GET_INSTANCE_METHOD.get(
+              className, String.valueOf(e.getMessage()));
+          throw new InitializationException(msg, e);
+        }
+        definitions.add(d);
+      }
+    }
+
+    // Initialize any definitions that were loaded.
+    for (AbstractManagedObjectDefinition<?, ?> d : definitions) {
+      try {
+        d.initialize();
+      } catch (Exception e) {
+        Message msg = ERR_CLASS_LOADER_CANNOT_INITIALIZE_DEFN.get(d.getName(),
+            d.getClass().getName(), String.valueOf(e.getMessage()));
+        throw new InitializationException(msg, e);
+      }
     }
   }
 
diff --git a/opends/src/server/org/opends/server/admin/DefaultBehaviorProvider.java b/opends/src/server/org/opends/server/admin/DefaultBehaviorProvider.java
index 565f7d1..a9aef47 100644
--- a/opends/src/server/org/opends/server/admin/DefaultBehaviorProvider.java
+++ b/opends/src/server/org/opends/server/admin/DefaultBehaviorProvider.java
@@ -29,31 +29,43 @@
 
 
 /**
- * An interface for determining the default behavior of a property. A property
- * exhibits default behavior when it has no values defined. There are four
- * different types of default behavior:
+ * An interface for determining the default behavior of a property. A
+ * property exhibits default behavior when it has no values defined.
+ * There are four different types of default behavior:
  * <ol>
- * <li>there is no default behavior - e.g. leaving a "description" unset has
- * no side-effects. This default behavior is represented using the
- * {@link UndefinedDefaultBehaviorProvider} implementation
- * <li>the property defaults to one or more real values of the property. This
- * default behavior is represented using the
+ * <li>there is no default behavior - e.g. leaving a "description"
+ * unset has no side-effects. This default behavior is represented
+ * using the {@link UndefinedDefaultBehaviorProvider} implementation
+ * <li>the property defaults to one or more real values of the
+ * property. This default behavior is represented using the
  * {@link DefinedDefaultBehaviorProvider} implementation
  * <li>the property defaults to some special behavior that cannot be
- * represented using real property values. This default behavior is represented
- * using the {@link AliasDefaultBehaviorProvider} implementation
- * <li>the property inherits its values from property held in another managed
- * object (e.g. the parent managed object). This default behavior is
- * represented using the {@link AbsoluteInheritedDefaultBehaviorProvider} and
+ * represented using real property values. This default behavior is
+ * represented using the {@link AliasDefaultBehaviorProvider}
+ * implementation
+ * <li>the property inherits its values from property held in another
+ * managed object (e.g. the parent managed object). This default
+ * behavior is represented using the
+ * {@link AbsoluteInheritedDefaultBehaviorProvider} and
  * {@link RelativeInheritedDefaultBehaviorProvider} implementations.
  * </ol>
- * An application can perform actions based on the type of the default behavior
- * by implementing the {@link DefaultBehaviorProviderVisitor} interface.
+ * An application can perform actions based on the type of the default
+ * behavior by implementing the {@link DefaultBehaviorProviderVisitor}
+ * interface.
  *
  * @param <T>
  *          The type of values represented by this provider.
  */
-public interface DefaultBehaviorProvider<T> {
+public abstract class DefaultBehaviorProvider<T> {
+
+  /**
+   * Creates a new default behavior provider.
+   */
+  protected DefaultBehaviorProvider() {
+    // No implementation required.
+  }
+
+
 
   /**
    * Apply a visitor to this default behavior provider.
@@ -61,13 +73,32 @@
    * @param <R>
    *          The return type of the visitor's methods.
    * @param <P>
-   *          The type of the additional parameters to the visitor's methods.
+   *          The type of the additional parameters to the visitor's
+   *          methods.
    * @param v
    *          The default behavior visitor.
    * @param p
    *          Optional additional visitor parameter.
    * @return Returns a result as specified by the visitor.
    */
-  <R, P> R accept(DefaultBehaviorProviderVisitor<T, R, P> v, P p);
+  public abstract <R, P>
+  R accept(DefaultBehaviorProviderVisitor<T, R, P> v, P p);
+
+
+
+  /**
+   * Performs any run-time initialization required by this default
+   * behavior provider. This may include resolving managed object
+   * paths and property names.
+   * <p>
+   * The default implementation is to do nothing.
+   *
+   * @throws Exception
+   *           If this default behavior provider could not be
+   *           initialized.
+   */
+  protected void initialize() throws Exception {
+    // Default implementation is to do nothing.
+  }
 
 }
diff --git a/opends/src/server/org/opends/server/admin/DefinedDefaultBehaviorProvider.java b/opends/src/server/org/opends/server/admin/DefinedDefaultBehaviorProvider.java
index a55be34..4f2fcbe 100644
--- a/opends/src/server/org/opends/server/admin/DefinedDefaultBehaviorProvider.java
+++ b/opends/src/server/org/opends/server/admin/DefinedDefaultBehaviorProvider.java
@@ -42,7 +42,7 @@
  * @param <T>
  *          The type of values represented by this provider.
  */
-public final class DefinedDefaultBehaviorProvider<T> implements
+public final class DefinedDefaultBehaviorProvider<T> extends
     DefaultBehaviorProvider<T> {
 
   // The collection of default values.
diff --git a/opends/src/server/org/opends/server/admin/PropertyDefinition.java b/opends/src/server/org/opends/server/admin/PropertyDefinition.java
index fe7c856..dec0715 100644
--- a/opends/src/server/org/opends/server/admin/PropertyDefinition.java
+++ b/opends/src/server/org/opends/server/admin/PropertyDefinition.java
@@ -26,7 +26,6 @@
  */
 
 package org.opends.server.admin;
-import org.opends.messages.Message;
 
 
 
@@ -38,6 +37,8 @@
 import java.util.MissingResourceException;
 import java.util.Set;
 
+import org.opends.messages.Message;
+
 
 
 /**
@@ -661,4 +662,18 @@
    */
   public abstract void validateValue(T value)
       throws IllegalPropertyValueException;
+
+
+
+  /**
+   * Performs any run-time initialization required by this property
+   * definition. This may include resolving managed object paths and
+   * property names.
+   *
+   * @throws Exception
+   *           If this property definition could not be initialized.
+   */
+  protected void initialize() throws Exception {
+    // No implementation required.
+  }
 }
diff --git a/opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java b/opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java
index 0749254..0f9ca55 100644
--- a/opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java
+++ b/opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java
@@ -37,7 +37,7 @@
  * @param <T>
  *          The type of values represented by this provider.
  */
-public final class RelativeInheritedDefaultBehaviorProvider<T> implements
+public final class RelativeInheritedDefaultBehaviorProvider<T> extends
     DefaultBehaviorProvider<T> {
 
   // The type of managed object expected at the relative offset.
@@ -69,7 +69,6 @@
    * @throws IllegalArgumentException
    *           If the offset is less than 0.
    */
-  @SuppressWarnings("unchecked")
   public RelativeInheritedDefaultBehaviorProvider(
       AbstractManagedObjectDefinition<?, ?> d, String propertyName, int offset)
       throws IllegalArgumentException {
@@ -126,7 +125,7 @@
 
 
   /**
-   * Get the name of the property containing the inherited default
+   * Gets the name of the property containing the inherited default
    * values.
    *
    * @return Returns the name of the property containing the inherited
@@ -148,5 +147,4 @@
   public int getRelativeOffset() {
     return offset;
   }
-
 }
diff --git a/opends/src/server/org/opends/server/admin/UndefinedDefaultBehaviorProvider.java b/opends/src/server/org/opends/server/admin/UndefinedDefaultBehaviorProvider.java
index 0235c99..3768341 100644
--- a/opends/src/server/org/opends/server/admin/UndefinedDefaultBehaviorProvider.java
+++ b/opends/src/server/org/opends/server/admin/UndefinedDefaultBehaviorProvider.java
@@ -37,7 +37,7 @@
  * @param <T>
  *          The type of values represented by this provider.
  */
-public final class UndefinedDefaultBehaviorProvider<T> implements
+public final class UndefinedDefaultBehaviorProvider<T> extends
     DefaultBehaviorProvider<T> {
 
   /**
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestCfg.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestCfg.java
index 82c1a1a..4d4d0cb 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestCfg.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestCfg.java
@@ -127,6 +127,7 @@
 
       // Register the test parent resource bundle.
       TestParentCfgDefn d = TestParentCfgDefn.getInstance();
+      d.initialize();
       String baseName = d.getClass().getName();
       ResourceBundle resourceBundle = ResourceBundle.getBundle(baseName);
       ManagedObjectDefinitionI18NResource.getInstance().setResourceBundle(d,
@@ -139,6 +140,7 @@
 
       // Register the test child resource bundle.
       TestChildCfgDefn d = TestChildCfgDefn.getInstance();
+      d.initialize();
       String baseName = d.getClass().getName();
       ResourceBundle resourceBundle = ResourceBundle.getBundle(baseName);
       ManagedObjectDefinitionI18NResource.getInstance().setResourceBundle(d,
@@ -216,6 +218,22 @@
 
 
   /**
+   * Initializes a property definition and its default behavior.
+   *
+   * @param pd
+   *          The property definition to be initialized.
+   * @throws Exception
+   *           If the property definition could not be initialized.
+   */
+  public static void initializePropertyDefinition(PropertyDefinition<?> pd)
+      throws Exception {
+    pd.initialize();
+    pd.getDefaultBehaviorProvider().initialize();
+  }
+
+
+
+  /**
    * Adds a constraint temporarily with test child definition.
    *
    * @param constraint
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java
index 44dafc4..77af453 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java
@@ -39,7 +39,6 @@
 import org.opends.server.admin.DefinedDefaultBehaviorProvider;
 import org.opends.server.admin.ManagedObjectAlreadyExistsException;
 import org.opends.server.admin.ManagedObjectDefinition;
-import org.opends.server.admin.ManagedObjectPath;
 import org.opends.server.admin.PropertyIsReadOnlyException;
 import org.opends.server.admin.PropertyOption;
 import org.opends.server.admin.PropertyProvider;
@@ -53,7 +52,6 @@
 import org.opends.server.admin.client.MissingMandatoryPropertiesException;
 import org.opends.server.admin.client.OperationRejectedException;
 import org.opends.server.admin.TestChildCfgClient;
-import org.opends.server.admin.std.meta.ConnectionHandlerCfgDefn;
 import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.admin.std.server.ConnectionHandlerCfg;
 import org.opends.server.admin.server.ServerManagedObject;
@@ -114,9 +112,8 @@
       builder.setOption(PropertyOption.MULTI_VALUED);
       builder.setAdministratorAction(new AdministratorAction(AdministratorAction.Type.NONE, INSTANCE, "aggregation-property"));
       builder.setDefaultBehaviorProvider(new UndefinedDefaultBehaviorProvider<String>());
-      builder.setParentPath(ManagedObjectPath.valueOf("/"));
+      builder.setParentPath("/");
       builder.setRelationDefinition("connection-handler");
-      builder.setManagedObjectDefinition(ConnectionHandlerCfgDefn.getInstance());
       PD_AGGREGATION_PROPERTY = builder.getInstance();
       INSTANCE.registerPropertyDefinition(PD_AGGREGATION_PROPERTY);
       INSTANCE.registerConstraint(PD_AGGREGATION_PROPERTY);
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/AggregationTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/AggregationTest.java
index 502eeb2..e5ad1e0 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/AggregationTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/AggregationTest.java
@@ -43,7 +43,6 @@
 import org.opends.server.admin.AggregationPropertyDefinition;
 import org.opends.server.admin.IllegalPropertyValueStringException;
 import org.opends.server.admin.ManagedObjectNotFoundException;
-import org.opends.server.admin.ManagedObjectPath;
 import org.opends.server.admin.PropertyException;
 import org.opends.server.admin.PropertyOption;
 import org.opends.server.admin.TestCfg;
@@ -56,7 +55,6 @@
 import org.opends.server.admin.std.client.ConnectionHandlerCfgClient;
 import org.opends.server.admin.std.client.LDAPConnectionHandlerCfgClient;
 import org.opends.server.admin.std.client.RootCfgClient;
-import org.opends.server.admin.std.meta.ConnectionHandlerCfgDefn;
 import org.opends.server.admin.std.meta.LDAPConnectionHandlerCfgDefn;
 import org.opends.server.admin.std.server.ConnectionHandlerCfg;
 import org.opends.server.admin.std.server.RootCfg;
@@ -306,11 +304,11 @@
         AdministratorAction.Type.NONE, d, "aggregation-property"));
     builder
         .setDefaultBehaviorProvider(new UndefinedDefaultBehaviorProvider<String>());
-    builder.setParentPath(ManagedObjectPath.valueOf("/"));
+    builder.setParentPath("/");
     builder.setRelationDefinition("connection-handler");
-    builder.setManagedObjectDefinition(ConnectionHandlerCfgDefn.getInstance());
     builder.setTargetEnabledPropertyName("enabled");
     aggregationPropertyDefinitionTargetMustBeEnabled = builder.getInstance();
+    TestCfg.initializePropertyDefinition(aggregationPropertyDefinitionTargetMustBeEnabled);
 
     builder = AggregationPropertyDefinition.createBuilder(d,
         "aggregation-property");
@@ -319,13 +317,13 @@
         AdministratorAction.Type.NONE, d, "aggregation-property"));
     builder
         .setDefaultBehaviorProvider(new UndefinedDefaultBehaviorProvider<String>());
-    builder.setParentPath(ManagedObjectPath.valueOf("/"));
+    builder.setParentPath("/");
     builder.setRelationDefinition("connection-handler");
-    builder.setManagedObjectDefinition(ConnectionHandlerCfgDefn.getInstance());
     builder.setTargetEnabledPropertyName("enabled");
     builder.setSourceEnabledPropertyName("mandatory-boolean-property");
     aggregationPropertyDefinitionTargetAndSourceMustBeEnabled = builder
         .getInstance();
+    TestCfg.initializePropertyDefinition(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled);
   }
 
 

--
Gitblit v1.10.0