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("', $path, '"), "', $property-name, '");
')" />
+ select="concat('"', $path, '", "', $property-name, '");
')" />
<xsl:value-of
select="' builder.setDefaultBehaviorProvider(provider);
'" />
</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("',
- normalize-space(@parent-path), '"));
')" />
+ select="concat(' builder.setParentPath("',
+ normalize-space(@parent-path), '");
')" />
<xsl:value-of
select="concat(' builder.setRelationDefinition("',
normalize-space(@relation-name), '");
')" />
- <xsl:value-of select="' builder.setManagedObjectDefinition('" />
- <xsl:call-template name="get-definition-type" />
- <xsl:value-of select="'.getInstance());
'" />
<xsl:if test="@source-enabled-property-name">
<xsl:value-of
select="concat(' builder.setSourceEnabledPropertyName("',
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