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/ConnectionHandlerConfigManager.java | 1459 +++++++++++++++-------------------------------------------
 1 files changed, 381 insertions(+), 1,078 deletions(-)

diff --git a/opends/src/server/org/opends/server/core/ConnectionHandlerConfigManager.java b/opends/src/server/org/opends/server/core/ConnectionHandlerConfigManager.java
index fc6219a..bc4cff5 100644
--- a/opends/src/server/org/opends/server/core/ConnectionHandlerConfigManager.java
+++ b/opends/src/server/org/opends/server/core/ConnectionHandlerConfigManager.java
@@ -28,1145 +28,448 @@
 
 
 
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.opends.server.api.ConfigAddListener;
-import org.opends.server.api.ConfigChangeListener;
-import org.opends.server.api.ConfigDeleteListener;
-import org.opends.server.api.ConfigurableComponent;
-import org.opends.server.api.ConnectionHandler;
-import org.opends.server.config.BooleanConfigAttribute;
-import org.opends.server.config.ConfigEntry;
-import org.opends.server.config.ConfigException;
-import org.opends.server.config.StringConfigAttribute;
-import org.opends.server.types.ConfigChangeResult;
-import org.opends.server.types.DN;
-import org.opends.server.types.ErrorLogCategory;
-import org.opends.server.types.ErrorLogSeverity;
-import org.opends.server.types.InitializationException;
-import org.opends.server.types.ResultCode;
-import org.opends.server.types.SearchFilter;
-
-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;
-import static org.opends.server.loggers.Error.*;
 import static org.opends.server.messages.ConfigMessages.*;
 import static org.opends.server.messages.CoreMessages.*;
-import static org.opends.server.messages.MessageHandler.*;
-import static org.opends.server.util.StaticUtils.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
 
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+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.*;
+import org.opends.server.admin.std.server.ConnectionHandlerCfg;
+import org.opends.server.admin.std.server.RootCfg;
+import org.opends.server.api.ConnectionHandler;
+import org.opends.server.config.ConfigException;
+import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.DN;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.ResultCode;
 
 
 /**
- * This class defines a utility that will be used to manage the configuration
- * for the set of connection handlers defined in the Directory Server.  It will
- * perform the necessary initialization of those connection handlers when the
- * server is first started, and then will manage any changes to them while the
- * server is running.
+ * This class defines a utility that will be used to manage the
+ * configuration for the set of connection handlers defined in the
+ * Directory Server. It will perform the necessary initialization of
+ * those connection handlers when the server is first started, and
+ * then will manage any changes to them while the server is running.
  */
-public class ConnectionHandlerConfigManager
-       implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener
-{
+public class ConnectionHandlerConfigManager implements
+    ConfigurationAddListener<ConnectionHandlerCfg>,
+    ConfigurationDeleteListener<ConnectionHandlerCfg>,
+    ConfigurationChangeListener<ConnectionHandlerCfg> {
 
-
-
-  // The mapping between configuration entry DNs and their corresponding
-  // connection handler implementations.
-  private ConcurrentHashMap<DN,ConnectionHandler> connectionHandlers;
-
-  // The DN of the associated configuration entry.
-  private DN configEntryDN;
+  // The mapping between configuration entry DNs and their
+  // corresponding connection handler implementations.
+  private ConcurrentHashMap<DN, ConnectionHandler> connectionHandlers;
 
 
 
   /**
    * Creates a new instance of this connection handler config manager.
    */
-  public ConnectionHandlerConfigManager()
-  {
+  public ConnectionHandlerConfigManager() {
     // No implementation is required.
   }
 
 
 
   /**
-   * Initializes the configuration associated with the Directory Server
-   * connection handlers.  This should only be called at Directory Server
-   * startup.
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationAdd(
+      ConnectionHandlerCfg configuration) {
+    // Default result code.
+    ResultCode resultCode = ResultCode.SUCCESS;
+    boolean adminActionRequired = false;
+    ArrayList<String> messages = new ArrayList<String>();
+
+    // Register as a change listener for this connection handler entry
+    // so that we will be notified of any changes that may be made to
+    // it.
+    configuration.addChangeListener(this);
+
+    // Ignore this connection handler if it is disabled.
+    if (configuration.isEnabled()) {
+      // The connection handler needs to be enabled.
+      DN dn = configuration.dn();
+      try {
+        // Attempt to start the connection handler.
+        ConnectionHandler connectionHandler =
+          getConnectionHandler(configuration);
+        connectionHandler.start();
+
+        // Put this connection handler in the hash so that we will be
+        // able to find it if it is altered.
+        connectionHandlers.put(dn, connectionHandler);
+
+        // Register the connection handler with the Directory Server.
+        DirectoryServer.registerConnectionHandler(connectionHandler);
+      } catch (ConfigException e) {
+        if (debugEnabled())
+        {
+          debugCaught(DebugLogLevel.ERROR, e);
+        }
+
+        messages.add(e.getMessage());
+        resultCode = DirectoryServer.getServerErrorResultCode();
+      } catch (Exception e) {
+        if (debugEnabled())
+        {
+          debugCaught(DebugLogLevel.ERROR, e);
+        }
+
+        int msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_INITIALIZE;
+        messages.add(getMessage(msgID, String.valueOf(configuration
+            .getJavaImplementationClass()), String.valueOf(dn),
+            stackTraceToSingleLineString(e)));
+        resultCode = DirectoryServer.getServerErrorResultCode();
+      }
+    }
+
+    // Return the configuration result.
+    return new ConfigChangeResult(resultCode, adminActionRequired,
+        messages);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationChange(
+      ConnectionHandlerCfg configuration) {
+    // Attempt to get the existing connection handler. This will only
+    // succeed if it was enabled.
+    DN dn = configuration.dn();
+    ConnectionHandler connectionHandler = connectionHandlers.get(dn);
+
+    // Default result code.
+    ResultCode resultCode = ResultCode.SUCCESS;
+    boolean adminActionRequired = false;
+    ArrayList<String> messages = new ArrayList<String>();
+
+    // See whether the connection handler should be enabled.
+    if (connectionHandler == null) {
+      if (configuration.isEnabled()) {
+        // The connection handler needs to be enabled.
+        try {
+          // Attempt to start the connection handler.
+          connectionHandler = getConnectionHandler(configuration);
+          connectionHandler.start();
+
+          // Put this connection handler in the hash so that we will
+          // be able to find it if it is altered.
+          connectionHandlers.put(dn, connectionHandler);
+
+          // Register the connection handler with the Directory
+          // Server.
+          DirectoryServer
+              .registerConnectionHandler(connectionHandler);
+        } catch (ConfigException e) {
+          if (debugEnabled())
+          {
+            debugCaught(DebugLogLevel.ERROR, e);
+          }
+
+          messages.add(e.getMessage());
+          resultCode = DirectoryServer.getServerErrorResultCode();
+        } catch (Exception e) {
+          if (debugEnabled())
+          {
+            debugCaught(DebugLogLevel.ERROR, e);
+          }
+
+          int msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_INITIALIZE;
+          messages.add(getMessage(msgID, String.valueOf(configuration
+              .getJavaImplementationClass()), String.valueOf(dn),
+              stackTraceToSingleLineString(e)));
+          resultCode = DirectoryServer.getServerErrorResultCode();
+        }
+      }
+    } else {
+      if (configuration.isEnabled()) {
+        // The connection handler is currently active, so we don't
+        // need to do anything. Changes to the class name cannot be
+        // applied dynamically, so if the class name did change then
+        // indicate that administrative action is required for that
+        // change to take effect.
+        String className = configuration.getJavaImplementationClass();
+        if (!className.equals(connectionHandler.getClass().getName())) {
+          adminActionRequired = true;
+        }
+      } else {
+        // We need to disable the connection handler.
+        DirectoryServer
+            .deregisterConnectionHandler(connectionHandler);
+        connectionHandlers.remove(dn);
+
+        int id = MSGID_CONNHANDLER_CLOSED_BY_DISABLE;
+        connectionHandler.finalizeConnectionHandler(getMessage(id),
+            false);
+      }
+    }
+
+    // Return the configuration result.
+    return new ConfigChangeResult(resultCode, adminActionRequired,
+        messages);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationDelete(
+      ConnectionHandlerCfg configuration) {
+
+    // Default result code.
+    ResultCode resultCode = ResultCode.SUCCESS;
+    boolean adminActionRequired = false;
+
+    // See if the entry is registered as a connection handler. If so,
+    // deregister and stop it. We'll try to leave any established
+    // connections alone if possible.
+    DN dn = configuration.dn();
+    ConnectionHandler connectionHandler = connectionHandlers.get(dn);
+    if (connectionHandler != null) {
+      DirectoryServer.deregisterConnectionHandler(connectionHandler);
+
+      int id = MSGID_CONNHANDLER_CLOSED_BY_DELETE;
+      connectionHandler.finalizeConnectionHandler(getMessage(id),
+          false);
+    }
+
+    return new ConfigChangeResult(resultCode, adminActionRequired);
+  }
+
+
+
+  /**
+   * Initializes the configuration associated with the Directory
+   * Server connection handlers. This should only be called at
+   * Directory Server startup.
    *
-   * @throws  ConfigException  If a critical configuration problem prevents the
-   *                           connection handler initialization from
-   *                           succeeding.
-   *
-   * @throws  InitializationException  If a problem occurs while initializing
-   *                                   the connection handlers that is not
-   *                                   related to the server configuration.
+   * @throws ConfigException
+   *           If a critical configuration problem prevents the
+   *           connection handler initialization from succeeding.
+   * @throws InitializationException
+   *           If a problem occurs while initializing the connection
+   *           handlers that is not related to the server
+   *           configuration.
    */
   public void initializeConnectionHandlerConfig()
-         throws ConfigException, InitializationException
-  {
-    connectionHandlers = new ConcurrentHashMap<DN,ConnectionHandler>();
+      throws ConfigException, InitializationException {
+    connectionHandlers = new ConcurrentHashMap<DN, ConnectionHandler>();
 
+    // Get the root configuration which acts as the parent of all
+    // connection handlers.
+    ServerManagementContext context = ServerManagementContext
+        .getInstance();
+    RootCfg root = context.getRootConfiguration();
 
+    // Register as an add and delete listener so that we can
+    // be notified if new connection handlers are added or existing
+    // connection handlers are removed.
+    root.addConnectionHandlerAddListener(this);
+    root.addConnectionHandlerDeleteListener(this);
 
-    // Get the configuration entry that is at the root of all the connection
-    // handlers in the server.
-    ConfigEntry connectionHandlerRoot;
-    try
-    {
-      configEntryDN         = DN.decode(DN_CONNHANDLER_BASE);
-      connectionHandlerRoot = DirectoryServer.getConfigEntry(configEntryDN);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
+    // Initialize existing connection handles.
+    for (String name : root.listConnectionHandlers()) {
+      ConnectionHandlerCfg config = root
+          .getConnectionHandler(name);
+
+      // Register as a change listener for this connection handler
+      // entry so that we will be notified of any changes that may be
+      // made to it.
+      config.addChangeListener(this);
+
+      // Ignore this connection handler if it is disabled.
+      if (config.isEnabled()) {
+        // Note that we don't want to start the connection handler
+        // because we're still in the startup process. Therefore, we
+        // will not do so and allow the server to start it at the very
+        // end of the initialization process.
+        ConnectionHandler connectionHandler = getConnectionHandler(config);
+
+        // Put this connection handler in the hash so that we will be
+        // able to find it if it is altered.
+        connectionHandlers.put(config.dn(), connectionHandler);
+
+        // Register the connection handler with the Directory Server.
+        DirectoryServer.registerConnectionHandler(connectionHandler);
       }
-
-      int    msgID   = MSGID_CONFIG_CONNHANDLER_CANNOT_GET_CONFIG_BASE;
-      String message = getMessage(msgID, stackTraceToSingleLineString(e));
-      throw new ConfigException(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 connection handlers defined below it.
-    if (connectionHandlerRoot == null)
-    {
-      int    msgID   = MSGID_CONFIG_CONNHANDLER_BASE_DOES_NOT_EXIST;
-      String message = getMessage(msgID);
-      throw new ConfigException(msgID, message);
-    }
-
-
-    // Register as an add and delete listener for the base entry so that we can
-    // be notified if new connection handlers are added or existing connection
-    // handlers are removed.
-    connectionHandlerRoot.registerAddListener(this);
-    connectionHandlerRoot.registerDeleteListener(this);
-
-
-    // Iterate through the set of immediate children below the connection
-    // handler config root.
-    for (ConfigEntry connectionHandlerEntry :
-         connectionHandlerRoot.getChildren().values())
-    {
-      DN connectionHandlerDN = connectionHandlerEntry.getDN();
-
-
-      // Register as a change listener for this connection handler entry so that
-      // we will be notified of any changes that may be made to it.
-      connectionHandlerEntry.registerChangeListener(this);
-
-
-      // Check to see if this entry appears to contain a connection handler
-      // configuration.  If not, log a warning and skip it.
-      if (! connectionHandlerEntry.hasObjectClass(OC_CONNECTION_HANDLER))
-      {
-        int msgID =
-             MSGID_CONFIG_CONNHANDLER_ENTRY_DOES_NOT_HAVE_CONNHANDLER_CONFIG;
-        String message = getMessage(msgID,
-                                    String.valueOf(connectionHandlerDN));
-        logError(ErrorLogCategory.CONFIGURATION,
-                 ErrorLogSeverity.SEVERE_WARNING, message, msgID);
-        continue;
-      }
-
-
-      // See if the entry contains an attribute that indicates whether the
-      // connection handler should be enabled.  If it does not, or if it is not
-      // set to "true", then skip it.
-      int msgID = MSGID_CONFIG_CONNHANDLER_ATTR_DESCRIPTION_ENABLED;
-      BooleanConfigAttribute enabledStub =
-           new BooleanConfigAttribute(ATTR_CONNECTION_HANDLER_ENABLED,
-                                      getMessage(msgID), false);
-      try
-      {
-        BooleanConfigAttribute enabledAttr =
-             (BooleanConfigAttribute)
-             connectionHandlerEntry.getConfigAttribute(enabledStub);
-        if (enabledAttr == null)
-        {
-          // The attribute is not present, so this connection handler will be
-          // disabled.  Log a message and continue.
-          msgID = MSGID_CONFIG_CONNHANDLER_NO_ENABLED_ATTR;
-          String message = getMessage(msgID,
-                                      String.valueOf(connectionHandlerDN));
-          logError(ErrorLogCategory.CONFIGURATION,
-                   ErrorLogSeverity.SEVERE_WARNING, message, msgID);
-          continue;
-        }
-        else if (! enabledAttr.activeValue())
-        {
-          // The connection handler is explicitly disabled.  Log a mild warning
-          // and continue.
-          msgID = MSGID_CONFIG_CONNHANDLER_DISABLED;
-          String message = getMessage(msgID,
-                                      String.valueOf(connectionHandlerDN));
-          logError(ErrorLogCategory.CONFIGURATION,
-                   ErrorLogSeverity.INFORMATIONAL, message, msgID);
-          continue;
-        }
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        msgID = MSGID_CONFIG_CONNHANDLER_UNABLE_TO_DETERMINE_ENABLED_STATE;
-        String message = getMessage(msgID, String.valueOf(connectionHandlerDN),
-                                    stackTraceToSingleLineString(e));
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 message, msgID);
-        continue;
-      }
-
-
-      // See if the entry contains an attribute that specifies the class name
-      // for the connection handler implementation.  If it does, then load it
-      // and make sure that it's a valid connection handler implementation.
-      // If there is no such attribute, the specified class cannot be loaded, or
-      // it does not contain a valid connection handler implementation, then log
-      // an error and skip it.
-      String className;
-      msgID = MSGID_CONFIG_CONNHANDLER_ATTR_DESCRIPTION_CLASS;
-      StringConfigAttribute classStub =
-           new StringConfigAttribute(ATTR_CONNECTION_HANDLER_CLASS,
-                                     getMessage(msgID), true, false, true);
-      try
-      {
-        StringConfigAttribute classAttr =
-             (StringConfigAttribute)
-             connectionHandlerEntry.getConfigAttribute(classStub);
-        if (classAttr == null)
-        {
-          msgID = MSGID_CONFIG_CONNHANDLER_NO_CLASS_ATTR;
-          String message = getMessage(msgID,
-                                      String.valueOf(connectionHandlerDN));
-          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_CONNHANDLER_CANNOT_GET_CLASS;
-        String message = getMessage(msgID, String.valueOf(connectionHandlerDN),
-                                    stackTraceToSingleLineString(e));
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 message, msgID);
-        continue;
-      }
-
-      ConnectionHandler connectionHandler;
-      try
-      {
-        // FIXME -- Should we use a custom class loader for this?
-        Class connectionHandlerClass = Class.forName(className);
-        connectionHandler =
-             (ConnectionHandler) connectionHandlerClass.newInstance();
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_INSTANTIATE;
-        String message = getMessage(msgID, String.valueOf(className),
-                                    String.valueOf(connectionHandlerDN),
-                                    stackTraceToSingleLineString(e));
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 message, msgID);
-        continue;
-      }
-
-
-      // Perform the necessary initialization for the connection handler.
-      try
-      {
-        connectionHandler.initializeConnectionHandler(connectionHandlerEntry);
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_INITIALIZE;
-        String message = getMessage(msgID, String.valueOf(className),
-                                    String.valueOf(connectionHandlerDN),
-                                    stackTraceToSingleLineString(e));
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 message, msgID);
-        continue;
-      }
-
-
-      // Put this connection handler in the hash so that we will be able to find
-      // it if it is altered.
-      connectionHandlers.put(connectionHandlerDN, connectionHandler);
-
-
-      // Register the connection handler with the Directory Server.
-      DirectoryServer.registerConnectionHandler(connectionHandler);
-
-
-      // Note that we don't want to start the connection handler because we're
-      // still in the startup process.  Therefore, we will not do so and allow
-      // the server to start it at the very end of the initialization process.
     }
   }
 
 
 
   /**
-   * 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.
+   * {@inheritDoc}
    */
-  public boolean configChangeIsAcceptable(ConfigEntry configEntry,
-                                          StringBuilder unacceptableReason)
-  {
-    DN connectionHandlerDN = configEntry.getDN();
-
-
-    // Register as a change listener for this connection handler entry so that
-    // we will be notified of any changes that may be made to it.
-    configEntry.registerChangeListener(this);
-
-
-    // Check to see if this entry appears to contain a connection handler
-    // configuration.  If not, then it is unacceptable.
-    try
-    {
-      SearchFilter connectionHandlerFilter =
-           SearchFilter.createFilterFromString("(objectClass=" +
-                                               OC_CONNECTION_HANDLER + ")");
-      if (! connectionHandlerFilter.matchesEntry(
-                                         configEntry.getEntry()))
-      {
-        int msgID =
-             MSGID_CONFIG_CONNHANDLER_ENTRY_DOES_NOT_HAVE_CONNHANDLER_CONFIG;
-        String message = getMessage(msgID,
-                                    String.valueOf(connectionHandlerDN));
-        unacceptableReason.append(message);
-        return false;
-      }
+  public boolean isConfigurationAddAcceptable(
+      ConnectionHandlerCfg configuration,
+      List<String> unacceptableReasons) {
+    if (configuration.isEnabled()) {
+      // It's enabled so always validate the class.
+      return isJavaClassAcceptable(configuration, unacceptableReasons);
+    } else {
+      // It's disabled so ignore it.
+      return true;
     }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID =
-           MSGID_CONFIG_CONNHANDLER_ERROR_INTERACTING_WITH_CONNHANDLER_ENTRY;
-      unacceptableReason.append(getMessage(msgID,
-                                           String.valueOf(connectionHandlerDN),
-                                           stackTraceToSingleLineString(e)));
-      return false;
-    }
-
-
-    // See if the entry contains an attribute that indicates whether the
-    // connection handler should be enabled.  If it does not, then reject it.
-    int msgID = MSGID_CONFIG_CONNHANDLER_ATTR_DESCRIPTION_ENABLED;
-    BooleanConfigAttribute enabledStub =
-         new BooleanConfigAttribute(ATTR_CONNECTION_HANDLER_ENABLED,
-                                    getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute enabledAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(enabledStub);
-      if (enabledAttr == null)
-      {
-        // The attribute is not present, which is not acceptable.
-        msgID = MSGID_CONFIG_CONNHANDLER_NO_ENABLED_ATTR;
-        String message = getMessage(msgID,
-                                    String.valueOf(connectionHandlerDN));
-        unacceptableReason.append(message);
-        return false;
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_CONNHANDLER_UNABLE_TO_DETERMINE_ENABLED_STATE;
-      unacceptableReason.append(getMessage(msgID,
-                                           String.valueOf(connectionHandlerDN),
-                                           stackTraceToSingleLineString(e)));
-      return false;
-    }
-
-
-    // See if the entry contains an attribute that specifies the class name for
-    // the connection handler implementation.  If it does, then load it and make
-    // sure that it's a valid connection handler implementation.  If there is no
-    // such attribute, the specified class cannot be loaded, or it does not
-    // contain a valid connection handler implementation, then it is
-    // unacceptable.
-    String className;
-    msgID = MSGID_CONFIG_CONNHANDLER_ATTR_DESCRIPTION_CLASS;
-    StringConfigAttribute classStub =
-         new StringConfigAttribute(ATTR_CONNECTION_HANDLER_CLASS,
-                                   getMessage(msgID), true, false, true);
-    try
-    {
-      StringConfigAttribute classAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(classStub);
-      if (classAttr == null)
-      {
-        msgID = MSGID_CONFIG_CONNHANDLER_NO_CLASS_ATTR;
-        String message = getMessage(msgID,
-                                    String.valueOf(connectionHandlerDN));
-        unacceptableReason.append(message);
-        return false;
-      }
-      else
-      {
-        className = classAttr.activeValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_GET_CLASS;
-      unacceptableReason.append(getMessage(msgID,
-                                           String.valueOf(connectionHandlerDN),
-                                           stackTraceToSingleLineString(e)));
-      return false;
-    }
-
-    try
-    {
-      // FIXME -- Should we use a custom class loader for this?
-      Class connectionHandlerClass = Class.forName(className);
-      ConnectionHandler connectionHandler =
-           (ConnectionHandler) connectionHandlerClass.newInstance();
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_INSTANTIATE;
-      unacceptableReason.append(getMessage(msgID, String.valueOf(className),
-                                           String.valueOf(connectionHandlerDN),
-                                           stackTraceToSingleLineString(e)));
-      return false;
-    }
-
-
-    // If we've gotten to this point, then it is acceptable as far as we are
-    // concerned.  If it is unacceptable according to the configuration for that
-    // connection handler, then the handler itself will need to make that
-    // determination.
-    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.
+   * {@inheritDoc}
    */
-  public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry)
-  {
-    DN connectionHandlerDN = configEntry.getDN();
-    ConnectionHandler connectionHandler =
-         connectionHandlers.get(connectionHandlerDN);
-
-    ResultCode        resultCode          = ResultCode.SUCCESS;
-    boolean           adminActionRequired = false;
-    ArrayList<String> messages            = new ArrayList<String>();
-
-
-    // Check to see if this entry appears to contain a connection handler
-    // configuration.  If not, then skip it.
-    if (! configEntry.hasObjectClass(OC_CONNECTION_HANDLER))
-    {
-        int msgID =
-             MSGID_CONFIG_CONNHANDLER_ENTRY_DOES_NOT_HAVE_CONNHANDLER_CONFIG;
-        messages.add(getMessage(msgID, String.valueOf(connectionHandlerDN)));
-        resultCode = ResultCode.UNWILLING_TO_PERFORM;
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
+  public boolean isConfigurationChangeAcceptable(
+      ConnectionHandlerCfg configuration,
+      List<String> unacceptableReasons) {
+    if (configuration.isEnabled()) {
+      // It's enabled so always validate the class.
+      return isJavaClassAcceptable(configuration, unacceptableReasons);
+    } else {
+      // It's disabled so ignore it.
+      return true;
     }
-
-
-    // See if the entry contains an attribute that indicates whether the
-    // connection handler should be enabled.
-    boolean needToEnable = false;
-    int msgID = MSGID_CONFIG_CONNHANDLER_ATTR_DESCRIPTION_ENABLED;
-    BooleanConfigAttribute enabledStub =
-         new BooleanConfigAttribute(ATTR_CONNECTION_HANDLER_ENABLED,
-                                    getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute enabledAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(enabledStub);
-      if (enabledAttr == null)
-      {
-        // The attribute is not present.  We won't allow this.
-        msgID = MSGID_CONFIG_CONNHANDLER_NO_ENABLED_ATTR;
-        messages.add(getMessage(msgID, String.valueOf(connectionHandlerDN)));
-        resultCode = ResultCode.UNWILLING_TO_PERFORM;
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-      else if (enabledAttr.activeValue())
-      {
-        // The connection handler is marked as enabled.  See if that is already
-        // true.
-        if (connectionHandler == null)
-        {
-          needToEnable = true;
-        }
-        else
-        {
-          // It's already enabled, so we don't need to do anything.
-        }
-      }
-      else
-      {
-        // The connection handler is marked as disabled.  See if that is already
-        // true.
-        if (connectionHandler != null)
-        {
-          // It isn't disabled, so we will do so now and deregister it from the
-          // server.  We'll try to preserve existing connections if possible.
-          DirectoryServer.deregisterConnectionHandler(connectionHandler);
-          connectionHandlers.remove(connectionHandlerDN);
-
-          int id = MSGID_CONNHANDLER_CLOSED_BY_DISABLE;
-          connectionHandler.finalizeConnectionHandler(getMessage(id), false);
-
-          return new ConfigChangeResult(resultCode, adminActionRequired,
-                                        messages);
-        }
-        else
-        {
-          // It's already disabled, so we don't need to do anything.
-          return new ConfigChangeResult(resultCode, adminActionRequired,
-                                        messages);
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_CONNHANDLER_UNABLE_TO_DETERMINE_ENABLED_STATE;
-      messages.add(getMessage(msgID, String.valueOf(connectionHandlerDN),
-                              stackTraceToSingleLineString(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // See if the entry contains an attribute that specifies the class name
-    // for the connection handler implementation.  If it does, then load it and
-    // make sure that it's a valid connection handler.  If there is no such
-    // attribute, the specified class cannot be loaded, or it does not contain a
-    // valid connection handler implementation, then flag an error and skip it.
-    String className;
-    msgID = MSGID_CONFIG_CONNHANDLER_ATTR_DESCRIPTION_CLASS;
-    StringConfigAttribute classStub =
-         new StringConfigAttribute(ATTR_CONNECTION_HANDLER_CLASS,
-                                   getMessage(msgID), true, false, true);
-    try
-    {
-      StringConfigAttribute classAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
-      if (classAttr == null)
-      {
-        msgID = MSGID_CONFIG_CONNHANDLER_NO_CLASS_ATTR;
-        messages.add(getMessage(msgID, String.valueOf(connectionHandlerDN)));
-        resultCode = ResultCode.UNWILLING_TO_PERFORM;
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-      else
-      {
-        className = classAttr.activeValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_GET_CLASS;
-      messages.add(getMessage(msgID, String.valueOf(connectionHandlerDN),
-                              stackTraceToSingleLineString(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired,
-                                    messages);
-    }
-
-
-    // If the connection handler is currently active, then we don't need to do
-    // anything.  Changes to the class name cannot be applied dynamically, so
-    // if the class name did change then indicate that administrative action
-    // is required for that change to take effect.
-    if (connectionHandler != null)
-    {
-      if (! className.equals(connectionHandler.getClass().getName()))
-      {
-        adminActionRequired = true;
-      }
-
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // If we've gotten here, then that should mean that we need to enable the
-    // connection handler.  Try to do so.
-    if (needToEnable)
-    {
-      try
-      {
-        // FIXME -- Should we use a custom class loader for this?
-        Class handlerClass = Class.forName(className);
-        connectionHandler = (ConnectionHandler) handlerClass.newInstance();
-      }
-      catch (Exception e)
-      {
-        // It is not a valid connection handler class.  This is an error.
-        msgID = MSGID_CONFIG_CONNHANDLER_CLASS_NOT_CONNHANDLER;
-        messages.add(getMessage(msgID, String.valueOf(className),
-                                String.valueOf(connectionHandlerDN)));
-        resultCode = ResultCode.CONSTRAINT_VIOLATION;
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-
-
-      try
-      {
-        connectionHandler.initializeConnectionHandler(configEntry);
-        connectionHandler.start();
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_INITIALIZE;
-        messages.add(getMessage(msgID, String.valueOf(className),
-                                String.valueOf(connectionHandlerDN),
-                                stackTraceToSingleLineString(e)));
-        resultCode = DirectoryServer.getServerErrorResultCode();
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-
-      connectionHandlers.put(connectionHandlerDN, connectionHandler);
-      DirectoryServer.registerConnectionHandler(connectionHandler);
-    }
-
-
-    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.
+   * {@inheritDoc}
    */
-  public boolean configAddIsAcceptable(ConfigEntry configEntry,
-                                       StringBuilder unacceptableReason)
-  {
-    DN connectionHandlerDN = configEntry.getDN();
-
-
-    // Register as a change listener for this connection handler entry so that
-    // we will be notified of any changes that may be made to it.
-    configEntry.registerChangeListener(this);
-
-
-    // Check to see if this entry appears to contain a connection handler
-    // configuration.  If not, then it is unacceptable.
-    try
-    {
-      SearchFilter connectionHandlerFilter =
-           SearchFilter.createFilterFromString("(objectClass=" +
-                                               OC_CONNECTION_HANDLER + ")");
-      if (! connectionHandlerFilter.matchesEntry(
-                                         configEntry.getEntry()))
-      {
-        int msgID =
-             MSGID_CONFIG_CONNHANDLER_ENTRY_DOES_NOT_HAVE_CONNHANDLER_CONFIG;
-        String message = getMessage(msgID,
-                                    String.valueOf(connectionHandlerDN));
-        unacceptableReason.append(message);
-        return false;
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID =
-           MSGID_CONFIG_CONNHANDLER_ERROR_INTERACTING_WITH_CONNHANDLER_ENTRY;
-      unacceptableReason.append(getMessage(msgID,
-                                           String.valueOf(connectionHandlerDN),
-                                           stackTraceToSingleLineString(e)));
-      return false;
-    }
-
-
-    // See if the entry contains an attribute that indicates whether the
-    // connection handler should be enabled.  If it does not, then reject it.
-    int msgID = MSGID_CONFIG_CONNHANDLER_ATTR_DESCRIPTION_ENABLED;
-    BooleanConfigAttribute enabledStub =
-         new BooleanConfigAttribute(ATTR_CONNECTION_HANDLER_ENABLED,
-                                    getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute enabledAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(enabledStub);
-      if (enabledAttr == null)
-      {
-        // The attribute is not present, which is not acceptable.
-        msgID = MSGID_CONFIG_CONNHANDLER_NO_ENABLED_ATTR;
-        String message = getMessage(msgID,
-                                    String.valueOf(connectionHandlerDN));
-        unacceptableReason.append(message);
-        return false;
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_CONNHANDLER_UNABLE_TO_DETERMINE_ENABLED_STATE;
-      unacceptableReason.append(getMessage(msgID,
-                                           String.valueOf(connectionHandlerDN),
-                                           stackTraceToSingleLineString(e)));
-      return false;
-    }
-
-
-    // See if the entry contains an attribute that specifies the class name for
-    // the connection handler implementation.  If it does, then load it and make
-    // sure that it's a valid connection handler implementation.  If there is no
-    // such attribute, the specified class cannot be loaded, or it does not
-    // contain a valid connection handler implementation, then it is
-    // unacceptable.
-    String className;
-    msgID = MSGID_CONFIG_CONNHANDLER_ATTR_DESCRIPTION_CLASS;
-    StringConfigAttribute classStub =
-         new StringConfigAttribute(ATTR_CONNECTION_HANDLER_CLASS,
-                                   getMessage(msgID), true, false, true);
-    try
-    {
-      StringConfigAttribute classAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(classStub);
-      if (classAttr == null)
-      {
-        msgID = MSGID_CONFIG_CONNHANDLER_NO_CLASS_ATTR;
-        String message = getMessage(msgID,
-                                    String.valueOf(connectionHandlerDN));
-        unacceptableReason.append(message);
-        return false;
-      }
-      else
-      {
-        className = classAttr.activeValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_GET_CLASS;
-      unacceptableReason.append(getMessage(msgID,
-                                           String.valueOf(connectionHandlerDN),
-                                           stackTraceToSingleLineString(e)));
-      return false;
-    }
-
-    ConnectionHandler connectionHandler;
-    try
-    {
-      // FIXME -- Should we use a custom class loader for this?
-      Class connectionHandlerClass = Class.forName(className);
-      connectionHandler =
-           (ConnectionHandler) connectionHandlerClass.newInstance();
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_INSTANTIATE;
-      unacceptableReason.append(getMessage(msgID, String.valueOf(className),
-                                           String.valueOf(connectionHandlerDN),
-                                           stackTraceToSingleLineString(e)));
-      return false;
-    }
-
-
-    // If the connection handler is a configurable component, then make sure
-    // that its configuration is valid.
-    if (connectionHandler instanceof ConfigurableComponent)
-    {
-      ConfigurableComponent cc = (ConfigurableComponent) connectionHandler;
-      LinkedList<String> errorMessages = new LinkedList<String>();
-      if (! cc.hasAcceptableConfiguration(configEntry, errorMessages))
-      {
-        if (errorMessages.isEmpty())
-        {
-          msgID = MSGID_CONFIG_CONNHANDLER_UNACCEPTABLE_CONFIG;
-          unacceptableReason.append(getMessage(msgID,
-                                               String.valueOf(configEntryDN)));
-        }
-        else
-        {
-          Iterator<String> iterator = errorMessages.iterator();
-          unacceptableReason.append(iterator.next());
-          while (iterator.hasNext())
-          {
-            unacceptableReason.append("  ");
-            unacceptableReason.append(iterator.next());
-          }
-        }
-
-        return false;
-      }
-    }
-
-
-    // If we've gotten to this point, then it is acceptable as far as we are
-    // concerned.  If it is unacceptable according to the configuration for that
-    // connection handler, then the handler itself will need to make that
-    // determination.
-    return true;
-  }
-
-
-
-  /**
-   * 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)
-  {
-    DN                configEntryDN       = configEntry.getDN();
-    ResultCode        resultCode          = ResultCode.SUCCESS;
-    boolean           adminActionRequired = false;
-    ArrayList<String> messages            = new ArrayList<String>();
-
-
-    // Register as a change listener for this connection handler entry so that
-    // we will be notified of any changes that may be made to it.
-    configEntry.registerChangeListener(this);
-
-
-    // Check to see if this entry appears to contain a connection handler
-    // configuration.  If not, log a warning and skip it.
-    if (! configEntry.hasObjectClass(OC_CONNECTION_HANDLER))
-    {
-      int msgID =
-           MSGID_CONFIG_CONNHANDLER_ENTRY_DOES_NOT_HAVE_CONNHANDLER_CONFIG;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-      resultCode = ResultCode.CONSTRAINT_VIOLATION;
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // See if the entry contains an attribute that indicates whether the
-    // connection handler should be enabled.  If it does not, or if it is not
-    // set to "true", then skip it.
-    int msgID = MSGID_CONFIG_CONNHANDLER_ATTR_DESCRIPTION_ENABLED;
-    BooleanConfigAttribute enabledStub =
-         new BooleanConfigAttribute(ATTR_CONNECTION_HANDLER_ENABLED,
-                                    getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute enabledAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(enabledStub);
-      if (enabledAttr == null)
-      {
-        // The attribute is not present, so this connection handler will be
-        // disabled.  We don't need to do anything else with this entry.
-        msgID = MSGID_CONFIG_CONNHANDLER_NO_ENABLED_ATTR;
-        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-      else if (! enabledAttr.activeValue())
-      {
-        // The connection handler is explicitly disabled.  We don't need to do
-        // anything else with this entry.
-        msgID = MSGID_CONFIG_CONNHANDLER_DISABLED;
-        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_CONNHANDLER_UNABLE_TO_DETERMINE_ENABLED_STATE;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // See if the entry contains an attribute that specifies the class name
-    // for the connection handler implementation.  If it does, then load it
-    // and make sure that it's a valid connection handler implementation.
-    // If there is no such attribute, the specified class cannot be loaded, or
-    // it does not contain a valid connection handler implementation, then log
-    // an error and skip it.
-    String className;
-    msgID = MSGID_CONFIG_CONNHANDLER_ATTR_DESCRIPTION_CLASS;
-    StringConfigAttribute classStub =
-         new StringConfigAttribute(ATTR_CONNECTION_HANDLER_CLASS,
-                                   getMessage(msgID), true, false, true);
-    try
-    {
-      StringConfigAttribute classAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(classStub);
-      if (classAttr == null)
-      {
-        msgID = MSGID_CONFIG_CONNHANDLER_NO_CLASS_ATTR;
-        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-      else
-      {
-        className = classAttr.activeValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_GET_CLASS;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-    ConnectionHandler connectionHandler;
-    try
-    {
-      // FIXME -- Should we use a custom class loader for this?
-      Class connectionHandlerClass = Class.forName(className);
-      connectionHandler =
-           (ConnectionHandler) connectionHandlerClass.newInstance();
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_INSTANTIATE;
-      messages.add(getMessage(msgID, String.valueOf(className),
-                              String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // Perform the necessary initialization for the connection handler.
-    try
-    {
-      connectionHandler.initializeConnectionHandler(configEntry);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_INITIALIZE;
-      messages.add(getMessage(msgID, String.valueOf(className),
-                              String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // Put this connection handler in the hash so that we will be able to find
-    // it if it is altered.
-    connectionHandlers.put(configEntryDN, connectionHandler);
-
-
-    // Register the connection handler with the Directory Server.
-    DirectoryServer.registerConnectionHandler(connectionHandler);
-
-
-    // Since this method should only be called if the directory server is
-    // online, then we will want to actually start the connection handler.  Do
-    // so now.
-    connectionHandler.start();
-
-
-    // At this point, everything should be done so return success.
-    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)
-  {
+  public boolean isConfigurationDeleteAcceptable(
+      ConnectionHandlerCfg configuration,
+      List<String> unacceptableReasons) {
     // A delete should always be acceptable, so just return true.
     return true;
   }
 
 
 
-  /**
-   * 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)
-  {
-    DN         configEntryDN       = configEntry.getDN();
-    ResultCode resultCode          = ResultCode.SUCCESS;
-    boolean    adminActionRequired = false;
+  // Load and initialize the connection handler named in the config.
+  private ConnectionHandler getConnectionHandler(
+      ConnectionHandlerCfg config) throws ConfigException {
+    String className = config.getJavaImplementationClass();
+    ConnectionHandlerCfgDefn d =
+      ConnectionHandlerCfgDefn.getInstance();
+    ClassPropertyDefinition pd = d
+        .getJavaImplementationClassPropertyDefinition();
 
+    // Load the class and cast it to a connection handler.
+    Class<? extends ConnectionHandler> theClass;
+    ConnectionHandler connectionHandler;
 
-    // See if the entry is registered as a connection handler.  If so,
-    // deregister and stop it.  We'll try to leave any established connections
-    // alone if possible.
-    ConnectionHandler connectionHandler =
-         connectionHandlers.get(configEntryDN);
-    if (connectionHandler != null)
-    {
-      DirectoryServer.deregisterConnectionHandler(connectionHandler);
+    try {
+      theClass = pd.loadClass(className, ConnectionHandler.class);
+      connectionHandler = theClass.newInstance();
+    } catch (Exception e) {
+      if (debugEnabled())
+      {
+        debugCaught(DebugLogLevel.ERROR, e);
+      }
 
-      int id = MSGID_CONNHANDLER_CLOSED_BY_DELETE;
-      connectionHandler.finalizeConnectionHandler(getMessage(id), false);
+      int msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_INITIALIZE;
+      String message = getMessage(msgID, String.valueOf(className),
+          String.valueOf(config.dn()),
+          stackTraceToSingleLineString(e));
+      throw new ConfigException(msgID, message, e);
     }
 
+    // Perform the necessary initialization for the connection
+    // handler.
+    try {
+      // Determine the initialization method to use: it must take a
+      // single parameter which is the exact type of the configuration
+      // object.
+      Method method = theClass.getMethod(
+          "initializeConnectionHandler", config.definition()
+              .getServerConfigurationClass());
 
-    return new ConfigChangeResult(resultCode, adminActionRequired);
+      method.invoke(connectionHandler, config);
+    } catch (Exception e) {
+      if (debugEnabled())
+      {
+        debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      int msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_INITIALIZE;
+      String message = getMessage(msgID, String.valueOf(className),
+          String.valueOf(config.dn()),
+          stackTraceToSingleLineString(e));
+      throw new ConfigException(msgID, message, e);
+    }
+
+    // The connection handler has been successfully initialized.
+    return connectionHandler;
+  }
+
+
+
+  // Determines whether or not the new configuration's implementation
+  // class is acceptable.
+  private boolean isJavaClassAcceptable(
+      ConnectionHandlerCfg config,
+      List<String> unacceptableReasons) {
+    String className = config.getJavaImplementationClass();
+    ConnectionHandlerCfgDefn d =
+      ConnectionHandlerCfgDefn.getInstance();
+    ClassPropertyDefinition pd = d
+        .getJavaImplementationClassPropertyDefinition();
+
+    // Load the class and cast it to a connection handler.
+    Class<? extends ConnectionHandler> theClass;
+    try {
+      theClass = pd.loadClass(className, ConnectionHandler.class);
+      theClass.newInstance();
+    } catch (Exception e) {
+      if (debugEnabled())
+      {
+        debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      int msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_INITIALIZE;
+      unacceptableReasons.add(getMessage(msgID, String
+          .valueOf(className), String.valueOf(config.dn()),
+          stackTraceToSingleLineString(e)));
+      return false;
+    }
+
+    // Perform the necessary initialization for the connection
+    // handler.
+    try {
+      // Determine the initialization method to use: it must take a
+      // single parameter which is the exact type of the configuration
+      // object.
+      theClass.getMethod("initializeConnectionHandler", config.definition()
+          .getServerConfigurationClass());
+    } catch (Exception e) {
+      if (debugEnabled())
+      {
+        debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      int msgID = MSGID_CONFIG_CONNHANDLER_CANNOT_INITIALIZE;
+      unacceptableReasons.add(getMessage(msgID, String
+          .valueOf(className), String.valueOf(config.dn()),
+          stackTraceToSingleLineString(e)));
+      return false;
+    }
+
+    // The class is valid as far as we can tell.
+    return true;
   }
 }
-

--
Gitblit v1.10.0