From feb5d90ec016c99712f19c5485cf7633cd38f111 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Fri, 23 Mar 2007 14:26:04 +0000
Subject: [PATCH] Merge admin framework from config-prototype-branch onto trunk.

---
 opends/src/server/org/opends/server/core/PluginConfigManager.java | 1271 +++++++++++++++++++--------------------------------------
 1 files changed, 434 insertions(+), 837 deletions(-)

diff --git a/opends/src/server/org/opends/server/core/PluginConfigManager.java b/opends/src/server/org/opends/server/core/PluginConfigManager.java
index 43bd420..50c7afa 100644
--- a/opends/src/server/org/opends/server/core/PluginConfigManager.java
+++ b/opends/src/server/org/opends/server/core/PluginConfigManager.java
@@ -28,17 +28,24 @@
 
 
 
+import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.locks.ReentrantLock;
 
+import org.opends.server.admin.ClassPropertyDefinition;
+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.ServerManagementContext;
+import org.opends.server.admin.std.meta.PluginCfgDefn;
+import org.opends.server.admin.std.server.PluginCfg;
+import org.opends.server.admin.std.server.RootCfg;
 import org.opends.server.api.ClientConnection;
-import org.opends.server.api.ConfigAddListener;
-import org.opends.server.api.ConfigChangeListener;
-import org.opends.server.api.ConfigDeleteListener;
 import org.opends.server.api.plugin.DirectoryServerPlugin;
 import org.opends.server.api.plugin.IntermediateResponsePluginResult;
 import org.opends.server.api.plugin.LDIFPluginResult;
@@ -52,11 +59,7 @@
 import org.opends.server.api.plugin.SearchEntryPluginResult;
 import org.opends.server.api.plugin.SearchReferencePluginResult;
 import org.opends.server.api.plugin.StartupPluginResult;
-import org.opends.server.config.BooleanConfigAttribute;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
-import org.opends.server.config.MultiChoiceConfigAttribute;
-import org.opends.server.config.StringConfigAttribute;
 import org.opends.server.types.ConfigChangeResult;
 import org.opends.server.types.DisconnectReason;
 import org.opends.server.types.DN;
@@ -68,11 +71,9 @@
 import org.opends.server.types.LDIFExportConfig;
 import org.opends.server.types.LDIFImportConfig;
 import org.opends.server.types.ResultCode;
-import org.opends.server.types.SearchFilter;
 import org.opends.server.types.SearchResultEntry;
 import org.opends.server.types.SearchResultReference;
 
-import static org.opends.server.config.ConfigConstants.*;
 import static org.opends.server.loggers.debug.DebugLogger.debugCaught;
 import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
 import org.opends.server.types.DebugLogLevel;
@@ -92,11 +93,10 @@
  * also provides methods for invoking all the plugins of a given type.
  */
 public class PluginConfigManager
-       implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener
+       implements ConfigurationAddListener<PluginCfg>,
+                  ConfigurationDeleteListener<PluginCfg>,
+                  ConfigurationChangeListener<PluginCfg>
 {
-
-
-
   // Arrays for holding the plugins of each type.
   private DirectoryServerPlugin[] startupPlugins;
   private DirectoryServerPlugin[] shutdownPlugins;
@@ -147,7 +147,9 @@
 
   // The mapping between the DN of a plugin entry and the plugin instance loaded
   // from that entry.
-  private ConcurrentHashMap<DN,DirectoryServerPlugin> registeredPlugins;
+  private ConcurrentHashMap<DN,
+               DirectoryServerPlugin<? extends PluginCfg>>
+                    registeredPlugins;
 
   // The lock that will provide threadsafe access to the sets of registered
   // plugins.
@@ -208,7 +210,8 @@
     searchResultReferencePlugins = new DirectoryServerPlugin[0];
     intermediateResponsePlugins  = new DirectoryServerPlugin[0];
     registeredPlugins            =
-         new ConcurrentHashMap<DN,DirectoryServerPlugin>();
+         new ConcurrentHashMap<DN,
+                  DirectoryServerPlugin<? extends PluginCfg>>();
   }
 
 
@@ -238,298 +241,186 @@
     registeredPlugins.clear();
 
 
-    // Get the configuration entry that is the root of all the plugins in the
-    // server.
-    ConfigEntry pluginRoot;
+    // Get the root configuration object.
+    ServerManagementContext managementContext =
+         ServerManagementContext.getInstance();
+    RootCfg rootConfiguration =
+         managementContext.getRootConfiguration();
+
+
+    // Register as an add and delete listener with the root configuration so we
+    // can be notified if any plugin entries are added or removed.
+    rootConfiguration.addPluginAddListener(this);
+    rootConfiguration.addPluginDeleteListener(this);
+
+
+    //Initialize the existing plugins.
+    for (String pluginName : rootConfiguration.listPlugins())
+    {
+      PluginCfg pluginConfiguration =
+           rootConfiguration.getPlugin(pluginName);
+
+      if (! pluginConfiguration.isEnabled())
+      {
+        continue;
+      }
+
+      // Create a set of plugin types for the plugin.
+      HashSet<PluginType> initTypes = new HashSet<PluginType>();
+      for (PluginCfgDefn.PluginType pluginType :
+           pluginConfiguration.getPluginType())
+      {
+        PluginType t = getPluginType(pluginType);
+        if ((pluginTypes == null) || pluginTypes.contains(t))
+        {
+          initTypes.add(t);
+        }
+      }
+
+      if (initTypes.isEmpty())
+      {
+        continue;
+      }
+
+      pluginConfiguration.addChangeListener(this);
+
+      try
+      {
+        DirectoryServerPlugin<? extends PluginCfg> plugin =
+             loadPlugin(pluginConfiguration.getPluginClass(), initTypes,
+                        pluginConfiguration);
+        registerPlugin(plugin, pluginConfiguration.dn(), initTypes);
+      }
+      catch (InitializationException ie)
+      {
+        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
+                 ie.getMessage(), ie.getMessageID());
+        continue;
+      }
+    }
+  }
+
+
+
+  /**
+   * Loads the specified class, instantiates it as a plugin, and optionally
+   * initializes that plugin.
+   *
+   * @param  className      The fully-qualified name of the plugin class to
+   *                        load, instantiate, and initialize.
+   * @param  pluginTypes    The set of plugin types for the plugins to
+   *                        initialize, or {@code null} to initialize all types
+   *                        of plugins defined in the server configuration.  In
+   *                        general, this should only be non-null for cases in
+   *                        which the server is running in a special mode that
+   *                        only uses a minimal set of plugins (e.g., LDIF
+   *                        import or export).
+   * @param  configuration  The configuration to use to initialize the plugin,
+   *                        or {@code null} if the plugin should not be
+   *                        initialized.
+   *
+   * @return  The possibly initialized plugin.
+   *
+   * @throws  InitializationException  If a problem occurred while attempting to
+   *                                   initialize the plugin.
+   */
+  private DirectoryServerPlugin<? extends PluginCfg>
+               loadPlugin(String className, Set<PluginType> pluginTypes,
+                          PluginCfg configuration)
+          throws InitializationException
+  {
     try
     {
-      DN pluginRootDN = DN.decode(DN_PLUGIN_BASE);
-      pluginRoot = DirectoryServer.getConfigEntry(pluginRootDN);
+      PluginCfgDefn definition =
+           PluginCfgDefn.getInstance();
+      ClassPropertyDefinition propertyDefinition =
+           definition.getPluginClassPropertyDefinition();
+      Class<? extends DirectoryServerPlugin> pluginClass =
+           propertyDefinition.loadClass(className, DirectoryServerPlugin.class);
+      DirectoryServerPlugin<? extends PluginCfg> plugin =
+           (DirectoryServerPlugin<? extends PluginCfg>)
+           pluginClass.newInstance();
+
+      if (configuration != null)
+      {
+        Method method =
+             plugin.getClass().getMethod("initializePlugin", Set.class,
+                  configuration.definition().getServerConfigurationClass());
+        method.invoke(plugin, pluginTypes, configuration);
+      }
+
+      return plugin;
     }
     catch (Exception e)
     {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int    msgID   = MSGID_CONFIG_PLUGIN_CANNOT_GET_CONFIG_BASE;
-      String message = getMessage(msgID, stackTraceToSingleLineString(e));
-      throw new ConfigException(msgID, message, e);
+      int msgID = MSGID_CONFIG_PLUGIN_CANNOT_INITIALIZE;
+      String message = getMessage(msgID, className,
+                                  String.valueOf(configuration.dn()),
+                                  stackTraceToSingleLineString(e));
+      throw new InitializationException(msgID, message, e);
     }
+  }
 
 
-    // If the configuration root entry is null, then assume it doesn't exist.
-    // In that case, then fail.  At least that entry must exist in the
-    // configuration, even if there are no plugins defined below it.
-    if (pluginRoot == null)
+
+  /**
+   * Gets the OpenDS plugin type object that corresponds to the configuration
+   * counterpart.
+   *
+   * @param  configPluginType  The configuration plugin type for which to
+   *                           retrieve the OpenDS plugin type.
+   */
+  private PluginType getPluginType(PluginCfgDefn.PluginType
+                                        configPluginType)
+  {
+    switch (configPluginType)
     {
-      int    msgID   = MSGID_CONFIG_PLUGIN_BASE_DOES_NOT_EXIST;
-      String message = getMessage(msgID);
-      throw new ConfigException(msgID, message);
-    }
-
-
-    // Register add and delete listeners for the base entry so that we can be
-    // notified of added or removed plugins.
-    pluginRoot.registerAddListener(this);
-    pluginRoot.registerDeleteListener(this);
-
-
-    // Iterate through the set of immediate children below the plugin config
-    // root.
-parsePluginEntry:
-    for (ConfigEntry entry : pluginRoot.getChildren().values())
-    {
-      DN entryDN = entry.getDN();
-
-
-      // Register as a change listener for this backend entry so that we will
-      // be notified of any changes that may be made to it.
-      entry.registerChangeListener(this);
-
-
-      // Check to see if this entry appears to contain a plugin configuration.
-      // If not, then log a warning and skip it.
-      try
-      {
-        SearchFilter filter =
-             SearchFilter.createFilterFromString("(objectClass=" +
-                                                 OC_PLUGIN + ")");
-        if (! filter.matchesEntry(entry.getEntry()))
-        {
-          int msgID = MSGID_CONFIG_PLUGIN_ENTRY_DOES_NOT_HAVE_PLUGIN_CONFIG;
-          String message = getMessage(msgID, String.valueOf(entryDN));
-          logError(ErrorLogCategory.CONFIGURATION,
-                   ErrorLogSeverity.SEVERE_WARNING, message, msgID);
-          continue;
-        }
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        int msgID = MSGID_CONFIG_PLUGIN_ERROR_INTERACTING_WITH_PLUGIN_ENTRY;
-        String message = getMessage(msgID, String.valueOf(entryDN),
-                                    stackTraceToSingleLineString(e));
-          logError(ErrorLogCategory.CONFIGURATION,
-                   ErrorLogSeverity.SEVERE_WARNING, message, msgID);
-          continue;
-      }
-
-
-      // See if the entry contains an attribute that indicates whether the
-      // plugin should be enabled.  If it does not, or if it is not set to
-      // "true", then skip it.
-      int msgID = MSGID_CONFIG_PLUGIN_ATTR_DESCRIPTION_ENABLED;
-      BooleanConfigAttribute enabledStub =
-           new BooleanConfigAttribute(ATTR_PLUGIN_ENABLED, getMessage(msgID),
-                                      false);
-      try
-      {
-        BooleanConfigAttribute enabledAttr =
-             (BooleanConfigAttribute) entry.getConfigAttribute(enabledStub);
-        if (enabledAttr == null)
-        {
-          // The attribute is not present, so this plugin will be disabled.
-          // Log a message and continue.
-          msgID = MSGID_CONFIG_PLUGIN_NO_ENABLED_ATTR;
-          String message = getMessage(msgID, String.valueOf(entryDN));
-          logError(ErrorLogCategory.CONFIGURATION,
-                   ErrorLogSeverity.SEVERE_WARNING, message, msgID);
-          continue;
-        }
-        else if (! enabledAttr.activeValue())
-        {
-          // The plugin is explicitly disabled.  Log a mild warning and
-          // continue.
-          msgID = MSGID_CONFIG_PLUGIN_DISABLED;
-          String message = getMessage(msgID, String.valueOf(entryDN));
-          logError(ErrorLogCategory.CONFIGURATION,
-                   ErrorLogSeverity.INFORMATIONAL, message, msgID);
-          continue;
-        }
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        msgID = MSGID_CONFIG_PLUGIN_UNABLE_TO_DETERMINE_ENABLED_STATE;
-        String message = getMessage(msgID, String.valueOf(entryDN),
-                                    stackTraceToSingleLineString(e));
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 message, msgID);
-        continue;
-      }
-
-
-      // Get the set of plugin types for this entry.  There must be at least one
-      // plugin type specified, and all plugin type names must be valid.
-      HashSet<PluginType> types = new HashSet<PluginType>();
-      msgID = MSGID_CONFIG_PLUGIN_ATTR_DESCRIPTION_PLUGIN_TYPE;
-      MultiChoiceConfigAttribute typesStub =
-           new MultiChoiceConfigAttribute(ATTR_PLUGIN_TYPE, getMessage(msgID),
-                                          true, true, true,
-                                          PluginType.getPluginTypeNames());
-      try
-      {
-        MultiChoiceConfigAttribute typesAttr =
-             (MultiChoiceConfigAttribute) entry.getConfigAttribute(typesStub);
-        if ((typesAttr == null) || typesAttr.activeValues().isEmpty())
-        {
-          msgID = MSGID_CONFIG_PLUGIN_NO_PLUGIN_TYPES;
-          String message = getMessage(msgID, String.valueOf(entryDN));
-          logError(ErrorLogCategory.CONFIGURATION,
-                   ErrorLogSeverity.SEVERE_ERROR, message, msgID);
-          continue;
-        }
-        else
-        {
-          for (String s : typesAttr.activeValues())
-          {
-            PluginType t = PluginType.forName(s.toLowerCase());
-            if (t == null)
-            {
-              msgID = MSGID_CONFIG_PLUGIN_INVALID_PLUGIN_TYPE;
-              String message = getMessage(msgID, String.valueOf(entryDN), s);
-              logError(ErrorLogCategory.CONFIGURATION,
-                       ErrorLogSeverity.SEVERE_ERROR, message, msgID);
-              continue parsePluginEntry;
-            }
-            else
-            {
-              if ((pluginTypes == null) || pluginTypes.contains(t))
-              {
-                types.add(t);
-              }
-            }
-          }
-
-          if (types.isEmpty())
-          {
-            // This means that the plugin doesn't have any of the types that
-            // we are interested in so we don't need to initialize it.
-            continue;
-          }
-        }
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        msgID = MSGID_CONFIG_PLUGIN_CANNOT_GET_PLUGIN_TYPES;
-        String message = getMessage(msgID, String.valueOf(entryDN),
-                                    stackTraceToSingleLineString(e));
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 message, msgID);
-        continue;
-      }
-
-
-      // FIXME -- We need configuration attributes that can be used to define
-      // the order in which plugins are loaded and/or executed.
-
-
-      // See if the entry contains an attribute that specifies the class name
-      // for the plugin implementation.  If it does, then load it and make sure
-      // that it's a valid plugin implementation.  If there is no such
-      // attribute, the specified class cannot be loaded, or it does not contain
-      // a valid plugin implementation, then log an error and skip it.
-      String className;
-      msgID = MSGID_CONFIG_PLUGIN_ATTR_DESCRIPTION_CLASS;
-      StringConfigAttribute classStub =
-           new StringConfigAttribute(ATTR_PLUGIN_CLASS, getMessage(msgID),
-                                     true, false, true);
-      try
-      {
-        StringConfigAttribute classAttr =
-             (StringConfigAttribute) entry.getConfigAttribute(classStub);
-        if (classAttr == null)
-        {
-          msgID = MSGID_CONFIG_PLUGIN_NO_CLASS_ATTR;
-          String message = getMessage(msgID, String.valueOf(entryDN));
-          logError(ErrorLogCategory.CONFIGURATION,
-                   ErrorLogSeverity.SEVERE_ERROR, message, msgID);
-          continue;
-        }
-        else
-        {
-          className = classAttr.activeValue();
-        }
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        msgID = MSGID_CONFIG_PLUGIN_CANNOT_GET_CLASS;
-        String message = getMessage(msgID, String.valueOf(entryDN),
-                                    stackTraceToSingleLineString(e));
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 message, msgID);
-        continue;
-      }
-
-      DirectoryServerPlugin plugin;
-      try
-      {
-        // FIXME --Should we use a custom class loader for this?
-        Class pluginClass = Class.forName(className);
-        plugin = (DirectoryServerPlugin) pluginClass.newInstance();
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        msgID = MSGID_CONFIG_PLUGIN_CANNOT_INSTANTIATE;
-        String message = getMessage(msgID, String.valueOf(className),
-                                    String.valueOf(entryDN),
-                                    stackTraceToSingleLineString(e));
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 message, msgID);
-        continue;
-      }
-
-
-      // Perform the necessary initialization for the plugin entry.
-      try
-      {
-        plugin.initializeInternal(entryDN, types);
-        plugin.initializePlugin(types, entry);
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        msgID = MSGID_CONFIG_PLUGIN_CANNOT_INITIALIZE;
-        String message = getMessage(msgID, String.valueOf(className),
-                                    String.valueOf(entryDN),
-                                    stackTraceToSingleLineString(e));
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 message, msgID);
-        continue;
-      }
-
-
-      // Register the plugin with the server.
-      registerPlugin(plugin, entryDN, types);
+      case STARTUP:                return PluginType.STARTUP;
+      case SHUTDOWN:               return PluginType.SHUTDOWN;
+      case POSTCONNECT:            return PluginType.POST_CONNECT;
+      case POSTDISCONNECT:         return PluginType.POST_DISCONNECT;
+      case LDIFIMPORT:             return PluginType.LDIF_IMPORT;
+      case LDIFEXPORT:             return PluginType.LDIF_EXPORT;
+      case PREPARSEABANDON:        return PluginType.PRE_PARSE_ABANDON;
+      case PREPARSEADD:            return PluginType.PRE_PARSE_ADD;
+      case PREPARSEBIND:           return PluginType.PRE_PARSE_BIND;
+      case PREPARSECOMPARE:        return PluginType.PRE_PARSE_COMPARE;
+      case PREPARSEDELETE:         return PluginType.PRE_PARSE_DELETE;
+      case PREPARSEEXTENDED:       return PluginType.PRE_PARSE_EXTENDED;
+      case PREPARSEMODIFY:         return PluginType.PRE_PARSE_MODIFY;
+      case PREPARSEMODIFYDN:       return PluginType.PRE_PARSE_MODIFY_DN;
+      case PREPARSESEARCH:         return PluginType.PRE_PARSE_SEARCH;
+      case PREPARSEUNBIND:         return PluginType.PRE_PARSE_UNBIND;
+      case PREOPERATIONADD:        return PluginType.PRE_OPERATION_ADD;
+      case PREOPERATIONBIND:       return PluginType.PRE_OPERATION_BIND;
+      case PREOPERATIONCOMPARE:    return PluginType.PRE_OPERATION_COMPARE;
+      case PREOPERATIONDELETE:     return PluginType.PRE_OPERATION_DELETE;
+      case PREOPERATIONEXTENDED:   return PluginType.PRE_OPERATION_EXTENDED;
+      case PREOPERATIONMODIFY:     return PluginType.PRE_OPERATION_MODIFY;
+      case PREOPERATIONMODIFYDN:   return PluginType.PRE_OPERATION_MODIFY_DN;
+      case PREOPERATIONSEARCH:     return PluginType.PRE_OPERATION_SEARCH;
+      case POSTOPERATIONABANDON:   return PluginType.POST_OPERATION_ABANDON;
+      case POSTOPERATIONADD:       return PluginType.POST_OPERATION_ADD;
+      case POSTOPERATIONBIND:      return PluginType.POST_OPERATION_BIND;
+      case POSTOPERATIONCOMPARE:   return PluginType.POST_OPERATION_COMPARE;
+      case POSTOPERATIONDELETE:    return PluginType.POST_OPERATION_DELETE;
+      case POSTOPERATIONEXTENDED:  return PluginType.POST_OPERATION_EXTENDED;
+      case POSTOPERATIONMODIFY:    return PluginType.POST_OPERATION_MODIFY;
+      case POSTOPERATIONMODIFYDN:  return PluginType.POST_OPERATION_MODIFY_DN;
+      case POSTOPERATIONSEARCH:    return PluginType.POST_OPERATION_SEARCH;
+      case POSTOPERATIONUNBIND:    return PluginType.POST_OPERATION_UNBIND;
+      case POSTRESPONSEADD:        return PluginType.POST_RESPONSE_ADD;
+      case POSTRESPONSEBIND:       return PluginType.POST_RESPONSE_BIND;
+      case POSTRESPONSECOMPARE:    return PluginType.POST_RESPONSE_COMPARE;
+      case POSTRESPONSEDELETE:     return PluginType.POST_RESPONSE_DELETE;
+      case POSTRESPONSEEXTENDED:   return PluginType.POST_RESPONSE_EXTENDED;
+      case POSTRESPONSEMODIFY:     return PluginType.POST_RESPONSE_MODIFY;
+      case POSTRESPONSEMODIFYDN:   return PluginType.POST_RESPONSE_MODIFY_DN;
+      case POSTRESPONSESEARCH:     return PluginType.POST_RESPONSE_SEARCH;
+      case SEARCHRESULTENTRY:      return PluginType.SEARCH_RESULT_ENTRY;
+      case SEARCHRESULTREFERENCE:  return PluginType.SEARCH_RESULT_REFERENCE;
+      case INTERMEDIATERESPONSE:   return PluginType.INTERMEDIATE_RESPONSE;
+      default:                     return null;
     }
   }
 
@@ -544,7 +435,7 @@
 
     try
     {
-      Iterator<DirectoryServerPlugin> iterator =
+      Iterator<DirectoryServerPlugin<? extends PluginCfg>> iterator =
            registeredPlugins.values().iterator();
       while (iterator.hasNext())
       {
@@ -578,7 +469,9 @@
    * @return  The set of plugins that have been registered with the Directory
    *          Server.
    */
-  public ConcurrentHashMap<DN,DirectoryServerPlugin> getRegisteredPlugins()
+  public ConcurrentHashMap<DN,
+              DirectoryServerPlugin<? extends PluginCfg>>
+                   getRegisteredPlugins()
   {
     return registeredPlugins;
   }
@@ -602,540 +495,6 @@
 
 
   /**
-   * Indicates whether the configuration entry that will result from a proposed
-   * modification is acceptable to this change listener.
-   *
-   * @param  configEntry         The configuration entry that will result from
-   *                             the requested update.
-   * @param  unacceptableReason  A buffer to which this method can append a
-   *                             human-readable message explaining why the
-   *                             proposed change is not acceptable.
-   *
-   * @return  <CODE>true</CODE> if the proposed entry contains an acceptable
-   *          configuration, or <CODE>false</CODE> if it does not.
-   */
-  public boolean configChangeIsAcceptable(ConfigEntry configEntry,
-                                          StringBuilder unacceptableReason)
-  {
-    // Make sure that the entry has an appropriate objectclass for a plugin.
-    if (! configEntry.hasObjectClass(OC_PLUGIN))
-    {
-      int    msgID   = MSGID_CONFIG_PLUGIN_ENTRY_DOES_NOT_HAVE_PLUGIN_CONFIG;
-      String message = getMessage(msgID, configEntry.getDN().toString());
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // Make sure that the entry specifies the plugin class name.
-    StringConfigAttribute classNameAttr;
-    try
-    {
-      StringConfigAttribute classStub =
-           new StringConfigAttribute(ATTR_PLUGIN_CLASS,
-                    getMessage(MSGID_CONFIG_PLUGIN_ATTR_DESCRIPTION_CLASS),
-                    true, false, true);
-      classNameAttr = (StringConfigAttribute)
-                      configEntry.getConfigAttribute(classStub);
-
-      if (classNameAttr == null)
-      {
-        int    msgID   = MSGID_CONFIG_PLUGIN_NO_CLASS_ATTR;
-        String message = getMessage(msgID, configEntry.getDN().toString());
-        unacceptableReason.append(message);
-        return false;
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int    msgID   = MSGID_CONFIG_PLUGIN_CANNOT_GET_CLASS;
-      String message = getMessage(msgID, configEntry.getDN().toString(),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-    Class pluginClass;
-    try
-    {
-      // FIXME -- Should this be done with a custom class loader?
-      pluginClass = Class.forName(classNameAttr.pendingValue());
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_PLUGIN_CANNOT_GET_CLASS;
-      String message = getMessage(msgID, configEntry.getDN().toString(),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-    try
-    {
-      DirectoryServerPlugin plugin =
-           (DirectoryServerPlugin) pluginClass.newInstance();
-    }
-    catch(Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int    msgID   = MSGID_CONFIG_PLUGIN_CANNOT_INSTANTIATE;
-      String message = getMessage(msgID, pluginClass.getName(),
-                                  String.valueOf(configEntry.getDN()),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // See if this plugin should be enabled.
-    BooleanConfigAttribute enabledAttr;
-    try
-    {
-      BooleanConfigAttribute enabledStub =
-           new BooleanConfigAttribute(ATTR_PLUGIN_ENABLED,
-                    getMessage(MSGID_CONFIG_PLUGIN_ATTR_DESCRIPTION_ENABLED),
-                               false);
-      enabledAttr = (BooleanConfigAttribute)
-                    configEntry.getConfigAttribute(enabledStub);
-
-      if (enabledAttr == null)
-      {
-        int    msgID   = MSGID_CONFIG_PLUGIN_NO_ENABLED_ATTR;
-        String message = getMessage(msgID, configEntry.getDN().toString());
-        unacceptableReason.append(message);
-        return false;
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int    msgID   = MSGID_CONFIG_PLUGIN_UNABLE_TO_DETERMINE_ENABLED_STATE;
-      String message = getMessage(msgID, configEntry.getDN().toString(),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // See the plugin types specified for this plugin and make sure that they
-    // are valid.
-    MultiChoiceConfigAttribute typesAttr;
-    try
-    {
-      MultiChoiceConfigAttribute typesStub =
-           new MultiChoiceConfigAttribute(ATTR_PLUGIN_TYPE,
-                getMessage(MSGID_CONFIG_PLUGIN_ATTR_DESCRIPTION_PLUGIN_TYPE),
-                true, true, true, PluginType.getPluginTypeNames());
-      typesAttr = (MultiChoiceConfigAttribute)
-                  configEntry.getConfigAttribute(typesStub);
-
-      if (typesAttr == null)
-      {
-        int    msgID   = MSGID_CONFIG_PLUGIN_NO_PLUGIN_TYPES;
-        String message = getMessage(msgID, String.valueOf(configEntry.getDN()));
-        unacceptableReason.append(message);
-        return false;
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int    msgID   = MSGID_CONFIG_PLUGIN_CANNOT_GET_PLUGIN_TYPES;
-      String message = getMessage(msgID, configEntry.getDN().toString(),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // If we've gotten here then the plugin entry appears to be acceptable.
-    return true;
-  }
-
-
-
-  /**
-   * Attempts to apply a new configuration to this Directory Server component
-   * based on the provided changed entry.
-   *
-   * @param  configEntry  The configuration entry that containing the updated
-   *                      configuration for this component.
-   *
-   * @return  Information about the result of processing the configuration
-   *          change.
-   */
-  public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry)
-  {
-    DN                configEntryDN       = configEntry.getDN();
-    ResultCode        resultCode          = ResultCode.SUCCESS;
-    boolean           adminActionRequired = false;
-    ArrayList<String> messages            = new ArrayList<String>();
-
-
-    // Make sure that the entry has an appropriate objectclass for a plugin.
-    if (! configEntry.hasObjectClass(OC_PLUGIN))
-    {
-      int    msgID   = MSGID_CONFIG_PLUGIN_ENTRY_DOES_NOT_HAVE_PLUGIN_CONFIG;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-      resultCode = ResultCode.UNWILLING_TO_PERFORM;
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // Get the corresponding plugin if it is active.
-    DirectoryServerPlugin plugin = registeredPlugins.get(configEntryDN);
-
-
-    // See if this plugin should be enabled or disabled.
-    boolean needsEnabled = false;
-    BooleanConfigAttribute enabledAttr;
-    try
-    {
-      BooleanConfigAttribute enabledStub =
-           new BooleanConfigAttribute(ATTR_PLUGIN_ENABLED,
-                    getMessage(MSGID_CONFIG_PLUGIN_ATTR_DESCRIPTION_ENABLED),
-                               false);
-      enabledAttr = (BooleanConfigAttribute)
-                    configEntry.getConfigAttribute(enabledStub);
-
-      if (enabledAttr == null)
-      {
-        int msgID = MSGID_CONFIG_PLUGIN_NO_ENABLED_ATTR;
-        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-        resultCode = ResultCode.UNWILLING_TO_PERFORM;
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-
-      if (enabledAttr.activeValue())
-      {
-        if (plugin == null)
-        {
-          needsEnabled = true;
-        }
-        else
-        {
-          // The plugin is already active, so no action is required.
-        }
-      }
-      else
-      {
-        if (plugin == null)
-        {
-          // The plugin is already disabled, so no action is required and we
-          // can short-circuit out of this processing.
-          return new ConfigChangeResult(resultCode, adminActionRequired,
-                                        messages);
-        }
-        else
-        {
-          // The plugin is active, so it needs to be disabled.  Do this and
-          // return that we were successful.
-          deregisterPlugin(configEntryDN);
-          plugin.finalizePlugin();
-          return new ConfigChangeResult(resultCode, adminActionRequired,
-                                        messages);
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_PLUGIN_UNABLE_TO_DETERMINE_ENABLED_STATE;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              String.valueOf(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // Make sure that the entry specifies the set of plugin types.  If it has
-    // changed, then we will not try to dynamically apply it.
-    HashSet<PluginType> pluginTypes = new HashSet<PluginType>();
-    try
-    {
-      MultiChoiceConfigAttribute typesStub =
-           new MultiChoiceConfigAttribute(ATTR_PLUGIN_TYPE,
-                getMessage(MSGID_CONFIG_PLUGIN_ATTR_DESCRIPTION_PLUGIN_TYPE),
-                true, true, true, PluginType.getPluginTypeNames());
-      MultiChoiceConfigAttribute typesAttr =
-           (MultiChoiceConfigAttribute)
-           configEntry.getConfigAttribute(typesStub);
-      if (typesAttr == null)
-      {
-        int msgID = MSGID_CONFIG_PLUGIN_NO_PLUGIN_TYPES;
-        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-      else
-      {
-        for (String s : typesAttr.activeValues())
-        {
-          PluginType t = PluginType.forName(s.toLowerCase());
-          if (t == null)
-          {
-            int msgID = MSGID_CONFIG_PLUGIN_INVALID_PLUGIN_TYPE;
-            messages.add(getMessage(msgID, String.valueOf(configEntryDN), s));
-            resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
-            return new ConfigChangeResult(resultCode, adminActionRequired,
-                                          messages);
-          }
-          else
-          {
-            pluginTypes.add(t);
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_PLUGIN_CANNOT_GET_PLUGIN_TYPES;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              String.valueOf(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // Make sure that the entry specifies the plugin class name.  If it has
-    // changed, then we will not try to dynamically apply it.
-    String className;
-    try
-    {
-      StringConfigAttribute classStub =
-           new StringConfigAttribute(ATTR_PLUGIN_CLASS,
-                    getMessage(MSGID_CONFIG_PLUGIN_ATTR_DESCRIPTION_CLASS),
-                    true, false, true);
-      StringConfigAttribute classNameAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
-
-      if (classNameAttr == null)
-      {
-        int msgID = MSGID_CONFIG_PLUGIN_NO_CLASS_ATTR;
-        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-
-      className = classNameAttr.pendingValue();
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_PLUGIN_CANNOT_GET_CLASS;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              String.valueOf(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    boolean classChanged = false;
-    String  oldClassName = null;
-    if (plugin != null)
-    {
-      oldClassName = plugin.getClass().getName();
-      classChanged = (! className.equals(oldClassName));
-    }
-
-
-    if (classChanged)
-    {
-      // This will not be applied dynamically.  Add a message to the response
-      // and indicate that admin action is required.
-      adminActionRequired = true;
-      messages.add(getMessage(MSGID_CONFIG_PLUGIN_CLASS_ACTION_REQUIRED,
-                              String.valueOf(oldClassName),
-                              String.valueOf(className),
-                              String.valueOf(configEntryDN)));
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    if (needsEnabled)
-    {
-      try
-      {
-        // FIXME -- Should this be done with a dynamic class loader?
-        Class pluginClass = Class.forName(className);
-        plugin = (DirectoryServerPlugin) pluginClass.newInstance();
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        int msgID = MSGID_CONFIG_PLUGIN_CANNOT_INSTANTIATE;
-        messages.add(getMessage(msgID, className,
-                                String.valueOf(configEntryDN),
-                                String.valueOf(e)));
-        resultCode = DirectoryServer.getServerErrorResultCode();
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-
-      try
-      {
-        plugin.initializeInternal(configEntryDN, pluginTypes);
-        plugin.initializePlugin(pluginTypes, configEntry);
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        int msgID = MSGID_CONFIG_PLUGIN_CANNOT_INITIALIZE;
-        messages.add(getMessage(msgID, className,
-                                String.valueOf(configEntryDN),
-                                String.valueOf(e)));
-        resultCode = DirectoryServer.getServerErrorResultCode();
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-
-
-      registerPlugin(plugin, configEntryDN, pluginTypes);
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // If we've gotten here, then there haven't been any changes to anything
-    // that we care about.
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-  }
-
-
-
-  /**
-   * Indicates whether the configuration entry that will result from a proposed
-   * add is acceptable to this add listener.
-   *
-   * @param  configEntry         The configuration entry that will result from
-   *                             the requested add.
-   * @param  unacceptableReason  A buffer to which this method can append a
-   *                             human-readable message explaining why the
-   *                             proposed entry is not acceptable.
-   *
-   * @return  <CODE>true</CODE> if the proposed entry contains an acceptable
-   *          configuration, or <CODE>false</CODE> if it does not.
-   */
-  public boolean configAddIsAcceptable(ConfigEntry configEntry,
-                                       StringBuilder unacceptableReason)
-  {
-    // NYI
-    return false;
-  }
-
-
-
-  /**
-   * Attempts to apply a new configuration based on the provided added entry.
-   *
-   * @param  configEntry  The new configuration entry that contains the
-   *                      configuration to apply.
-   *
-   * @return  Information about the result of processing the configuration
-   *          change.
-   */
-  public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry)
-  {
-    ResultCode        resultCode          = ResultCode.SUCCESS;
-    boolean           adminActionRequired = false;
-    ArrayList<String> messages            = new ArrayList<String>();
-
-
-    // NYI
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-  }
-
-
-
-  /**
-   * Indicates whether it is acceptable to remove the provided configuration
-   * entry.
-   *
-   * @param  configEntry         The configuration entry that will be removed
-   *                             from the configuration.
-   * @param  unacceptableReason  A buffer to which this method can append a
-   *                             human-readable message explaining why the
-   *                             proposed delete is not acceptable.
-   *
-   * @return  <CODE>true</CODE> if the proposed entry may be removed from the
-   *          configuration, or <CODE>false</CODE> if not.
-   */
-  public boolean configDeleteIsAcceptable(ConfigEntry configEntry,
-                                          StringBuilder unacceptableReason)
-  {
-    // NYI
-    return false;
-  }
-
-
-
-  /**
-   * Attempts to apply a new configuration based on the provided deleted entry.
-   *
-   * @param  configEntry  The new configuration entry that has been deleted.
-   *
-   * @return  Information about the result of processing the configuration
-   *          change.
-   */
-  public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry)
-  {
-    ResultCode        resultCode          = ResultCode.SUCCESS;
-    boolean           adminActionRequired = false;
-    ArrayList<String> messages            = new ArrayList<String>();
-
-
-    // NYI
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-  }
-
-
-
-  /**
    * Registers the provided plugin with this plugin config manager and ensures
    * that it will be invoked in the specified ways.
    *
@@ -1145,8 +504,9 @@
    * @param  pluginTypes    The plugin types that will be used to control the
    *                        points at which the provided plugin is invoked.
    */
-  private void registerPlugin(DirectoryServerPlugin plugin, DN pluginEntryDN,
-                              HashSet<PluginType> pluginTypes)
+  private void registerPlugin(
+                    DirectoryServerPlugin<? extends PluginCfg> plugin,
+                    DN pluginEntryDN, Set<PluginType> pluginTypes)
   {
     pluginLock.lock();
 
@@ -1368,9 +728,10 @@
   {
     pluginLock.lock();
 
+    DirectoryServerPlugin<? extends PluginCfg> plugin;
     try
     {
-      DirectoryServerPlugin plugin = registeredPlugins.remove(configEntryDN);
+      plugin = registeredPlugins.remove(configEntryDN);
       if (plugin == null)
       {
         return;
@@ -1556,6 +917,8 @@
     {
       pluginLock.unlock();
     }
+
+    plugin.finalizePlugin();
   }
 
 
@@ -5118,5 +4481,239 @@
 
     return result;
   }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationAddAcceptable(PluginCfg configuration,
+                                              List<String> unacceptableReasons)
+  {
+    if (configuration.isEnabled())
+    {
+      // Create a set of plugin types for the plugin.
+      HashSet<PluginType> pluginTypes = new HashSet<PluginType>();
+      for (PluginCfgDefn.PluginType pluginType :
+           configuration.getPluginType())
+      {
+        pluginTypes.add(getPluginType(pluginType));
+      }
+
+      // Get the name of the class and make sure we can instantiate it as a
+      // plugin.
+      String className = configuration.getPluginClass();
+      try
+      {
+        loadPlugin(className, pluginTypes, null);
+      }
+      catch (InitializationException ie)
+      {
+        unacceptableReasons.add(ie.getMessage());
+        return false;
+      }
+    }
+
+    // If we've gotten here, then it's fine.
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationAdd(
+                                 PluginCfg configuration)
+  {
+    ResultCode        resultCode          = ResultCode.SUCCESS;
+    boolean           adminActionRequired = false;
+    ArrayList<String> messages            = new ArrayList<String>();
+
+    configuration.addChangeListener(this);
+
+    if (! configuration.isEnabled())
+    {
+      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+    }
+
+    // Create a set of plugin types for the plugin.
+    HashSet<PluginType> pluginTypes = new HashSet<PluginType>();
+    for (PluginCfgDefn.PluginType pluginType :
+         configuration.getPluginType())
+    {
+      pluginTypes.add(getPluginType(pluginType));
+    }
+
+    // Get the name of the class and make sure we can instantiate it as a
+    // plugin.
+    DirectoryServerPlugin<? extends PluginCfg> plugin = null;
+    String className = configuration.getPluginClass();
+    try
+    {
+      plugin = loadPlugin(className, pluginTypes, configuration);
+    }
+    catch (InitializationException ie)
+    {
+      if (resultCode == ResultCode.SUCCESS)
+      {
+        resultCode = DirectoryServer.getServerErrorResultCode();
+      }
+
+      messages.add(ie.getMessage());
+    }
+
+    if (resultCode == ResultCode.SUCCESS)
+    {
+      registerPlugin(plugin, configuration.dn(), pluginTypes);
+    }
+
+    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationDeleteAcceptable(
+                      PluginCfg configuration,
+                      List<String> unacceptableReasons)
+  {
+    // We will always allow plugins to be removed.
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationDelete(
+                                 PluginCfg configuration)
+  {
+    ResultCode        resultCode          = ResultCode.SUCCESS;
+    boolean           adminActionRequired = false;
+    ArrayList<String> messages            = new ArrayList<String>();
+
+    deregisterPlugin(configuration.dn());
+
+    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationChangeAcceptable(
+                      PluginCfg configuration,
+                      List<String> unacceptableReasons)
+  {
+    if (configuration.isEnabled())
+    {
+      // Create a set of plugin types for the plugin.
+      HashSet<PluginType> pluginTypes = new HashSet<PluginType>();
+      for (PluginCfgDefn.PluginType pluginType :
+           configuration.getPluginType())
+      {
+        pluginTypes.add(getPluginType(pluginType));
+      }
+
+      // Get the name of the class and make sure we can instantiate it as a
+      // plugin.
+      String className = configuration.getPluginClass();
+      try
+      {
+        loadPlugin(className, pluginTypes, null);
+      }
+      catch (InitializationException ie)
+      {
+        unacceptableReasons.add(ie.getMessage());
+        return false;
+      }
+    }
+
+    // If we've gotten here, then it's fine.
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationChange(
+                                 PluginCfg configuration)
+  {
+    ResultCode        resultCode          = ResultCode.SUCCESS;
+    boolean           adminActionRequired = false;
+    ArrayList<String> messages            = new ArrayList<String>();
+
+
+    // Get the existing plugin if it's already enabled.
+    DirectoryServerPlugin existingPlugin =
+         registeredPlugins.get(configuration.dn());
+
+
+    // If the new configuration has the plugin disabled, then deregister it if
+    // it is enabled, or do nothing if it's already disabled.
+    if (! configuration.isEnabled())
+    {
+      if (existingPlugin != null)
+      {
+        deregisterPlugin(configuration.dn());
+      }
+
+      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+    }
+
+
+    // Get the class for the identity mapper.  If the mapper is already enabled,
+    // then we shouldn't do anything with it although if the class has changed
+    // then we'll at least need to indicate that administrative action is
+    // required.  If the mapper is disabled, then instantiate the class and
+    // initialize and register it as an identity mapper.
+    String className = configuration.getPluginClass();
+    if (existingPlugin != null)
+    {
+      if (! className.equals(existingPlugin.getClass().getName()))
+      {
+        adminActionRequired = true;
+      }
+
+      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+    }
+
+    // Create a set of plugin types for the plugin.
+    HashSet<PluginType> pluginTypes = new HashSet<PluginType>();
+    for (PluginCfgDefn.PluginType pluginType :
+         configuration.getPluginType())
+    {
+      pluginTypes.add(getPluginType(pluginType));
+    }
+
+    DirectoryServerPlugin<? extends PluginCfg> plugin = null;
+    try
+    {
+      plugin = loadPlugin(className, pluginTypes, configuration);
+    }
+    catch (InitializationException ie)
+    {
+      if (resultCode == ResultCode.SUCCESS)
+      {
+        resultCode = DirectoryServer.getServerErrorResultCode();
+      }
+
+      messages.add(ie.getMessage());
+    }
+
+    if (resultCode == ResultCode.SUCCESS)
+    {
+      registerPlugin(plugin, configuration.dn(), pluginTypes);
+    }
+
+    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+  }
 }
 

--
Gitblit v1.10.0