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/protocols/ldap/LDAPConnectionHandler.java | 4327 +++++++++++-----------------------------------------------
 1 files changed, 842 insertions(+), 3,485 deletions(-)

diff --git a/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java b/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
index 554f2dd..1ea5d8e 100644
--- a/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
+++ b/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
@@ -28,48 +28,49 @@
 
 
 
+import static org.opends.server.loggers.Access.logConnect;
+import static org.opends.server.loggers.Error.logError;
+import static org.opends.server.loggers.debug.DebugLogger.debugCaught;
+import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
+import static org.opends.server.messages.MessageHandler.getMessage;
+import static org.opends.server.messages.ProtocolMessages.*;
+import static org.opends.server.util.ServerConstants.*;
+import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
+
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
-import java.net.UnknownHostException;
 import java.nio.channels.SelectionKey;
 import java.nio.channels.Selector;
 import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Set;
 
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.server.LDAPConnectionHandlerCfg;
 import org.opends.server.api.AlertGenerator;
 import org.opends.server.api.ClientConnection;
-import org.opends.server.api.ConfigurableComponent;
 import org.opends.server.api.ConnectionHandler;
 import org.opends.server.api.ConnectionSecurityProvider;
 import org.opends.server.api.KeyManagerProvider;
+import org.opends.server.api.ServerShutdownListener;
 import org.opends.server.api.TrustManagerProvider;
 import org.opends.server.api.plugin.PostConnectPluginResult;
+import org.opends.server.config.ConfigException;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.PluginConfigManager;
-import org.opends.server.config.BooleanConfigAttribute;
-import org.opends.server.config.ConfigAttribute;
-import org.opends.server.config.ConfigEntry;
-import org.opends.server.config.ConfigException;
-import org.opends.server.config.DNConfigAttribute;
-import org.opends.server.config.IntegerConfigAttribute;
-import org.opends.server.config.IntegerWithUnitConfigAttribute;
-import org.opends.server.config.MultiChoiceConfigAttribute;
-import org.opends.server.config.StringConfigAttribute;
 import org.opends.server.extensions.NullConnectionSecurityProvider;
 import org.opends.server.extensions.TLSConnectionSecurityProvider;
 import org.opends.server.types.AddressMask;
 import org.opends.server.types.ConfigChangeResult;
-import org.opends.server.types.DisconnectReason;
 import org.opends.server.types.DN;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DisconnectReason;
 import org.opends.server.types.ErrorLogCategory;
 import org.opends.server.types.ErrorLogSeverity;
 import org.opends.server.types.HostPort;
@@ -77,176 +78,71 @@
 import org.opends.server.types.ResultCode;
 import org.opends.server.types.SSLClientAuthPolicy;
 
-import static org.opends.server.config.ConfigConstants.*;
-import static org.opends.server.loggers.Access.*;
-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.MessageHandler.*;
-import static org.opends.server.messages.ProtocolMessages.*;
-import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
-
 
 
 /**
- * This class defines a connection handler that will be used for communicating
- * with clients over LDAP.  It is actually implemented in two parts:  as a
- * connection handler and one or more request handlers.  The connection handler
- * is responsible for accepting new connections and registering each of them
- * with a request handler.  The request handlers then are responsible for
- * reading requests from the clients and parsing them as operations.  A single
- * request handler may be used, but having multiple handlers might provide
+ * This class defines a connection handler that will be used for
+ * communicating with clients over LDAP. It is actually implemented in
+ * two parts: as a connection handler and one or more request
+ * handlers. The connection handler is responsible for accepting new
+ * connections and registering each of them with a request handler.
+ * The request handlers then are responsible for reading requests from
+ * the clients and parsing them as operations. A single request
+ * handler may be used, but having multiple handlers might provide
  * better performance in a multi-CPU system.
  */
-public class LDAPConnectionHandler
-       extends ConnectionHandler
-       implements ConfigurableComponent, AlertGenerator
-{
+public final class LDAPConnectionHandler extends
+    ConnectionHandler<LDAPConnectionHandlerCfg> implements
+    ConfigurationChangeListener<LDAPConnectionHandlerCfg>,
+    ServerShutdownListener, AlertGenerator {
+
   /**
    * The fully-qualified name of this class.
    */
   private static final String CLASS_NAME =
-       "org.opends.server.protocols.ldap.LDAPConnectionHandler";
+    "org.opends.server.protocols.ldap.LDAPConnectionHandler";
 
+  // The current configuration state.
+  private LDAPConnectionHandlerCfg currentConfig;
 
-
-  /**
-   * The hash map that holds the units that may be provided in conjunction with
-   * the maximum request size.
-   */
-  private static final HashMap<String,Double> SIZE_UNITS =
-       new HashMap<String,Double>();
-
-  static
-  {
-    SIZE_UNITS.put(SIZE_UNIT_BYTES_ABBR, 1D);
-    SIZE_UNITS.put(SIZE_UNIT_BYTES_FULL, 1D);
-    SIZE_UNITS.put(SIZE_UNIT_KILOBYTES_ABBR, 1000D);
-    SIZE_UNITS.put(SIZE_UNIT_KILOBYTES_FULL, 1000D);
-    SIZE_UNITS.put(SIZE_UNIT_MEGABYTES_ABBR, 1000000D);
-    SIZE_UNITS.put(SIZE_UNIT_MEGABYTES_FULL, 1000000D);
-    SIZE_UNITS.put(SIZE_UNIT_GIGABYTES_ABBR, 1000000000D);
-    SIZE_UNITS.put(SIZE_UNIT_GIGABYTES_FULL, 1000000000D);
-    SIZE_UNITS.put(SIZE_UNIT_KIBIBYTES_ABBR, 1024D);
-    SIZE_UNITS.put(SIZE_UNIT_KIBIBYTES_FULL, 1024D);
-    SIZE_UNITS.put(SIZE_UNIT_MEBIBYTES_ABBR, (double) (1024 * 1024));
-    SIZE_UNITS.put(SIZE_UNIT_MEBIBYTES_FULL, (double) (1024 * 1024));
-    SIZE_UNITS.put(SIZE_UNIT_GIBIBYTES_ABBR, (double) (1024 * 1024 * 1024));
-    SIZE_UNITS.put(SIZE_UNIT_GIBIBYTES_FULL, (double) (1024 * 1024 * 1024));
-  }
-
-
-
-  /**
-   * The maximum value that may be specified for the max request size
-   * configuration attribute.
-   */
-  private static final int MAX_REQUEST_SIZE_LIMIT = 2147483647;
-
-
-
-  // The set of clients that are explicitly allowed access to the server.
-  private AddressMask[] allowedClients;
-
-  // The set of clients that have been explicitly denied access to the server.
-  private AddressMask[] deniedClients;
-
-  // Indicates whether to allow LDAPv2 clients.
-  private boolean allowLDAPv2;
-
-  // Indicates whether to allow the reuse address socket option.
-  private boolean allowReuseAddress;
-
-  // Indicates whether to allow startTLS extended operations on this connection.
-  private boolean allowStartTLS;
-
-  // Indicates whether this connection handler is enabled.
-  private boolean enabled;
-
-  // Indicates whether usage statistics should be maintained.
-  private boolean keepStats;
-
-  // Indicates whether the server should send an LDAP notice of disconnection
-  // message to a client if a connection is rejected.
-  private boolean sendRejectionNotice;
-
-  // Indicates whether the Directory Server is in the process of shutting down.
-  private boolean shutdownRequested;
-
-  // Indicates whether to use TCP keepalive messages for new connections.
-  private boolean useKeepAlive;
-
-  // Indicates whether to use SSL to communicate with the clients.
-  private boolean useSSL;
-
-  // Indicates whether to use TCP_NODELAY for new connections.
-  private boolean useTCPNoDelay;
-
-  // The connection security provider that will be used by default for new
-  // client connections.
-  private ConnectionSecurityProvider securityProvider;
-
-  // The DN of the configuration entry for this connection handler.
-  private DN configEntryDN;
-
-  // The DN of the key manager provider for this connection handler.
-  private DN keyManagerProviderDN;
-
-  // The DN of the trust manager provider for this connection handler.
-  private DN trustManagerProviderDN;
+  /* Properties that cannot be modified dynamically */
 
   // The set of addresses on which to listen for new connections.
-  private HashSet<InetAddress> listenAddresses;
+  private Set<InetAddress> listenAddresses;
 
-  // The backlog that will be used for the accept queue.
-  private int backlog;
-
-  // The port on which this connection handler should listen for requests.
+  // The port on which this connection handler should listen for
+  // requests.
   private int listenPort;
 
-  // The maximum ASN.1 element value length that will be allowed when processing
-  // requests for this connection handler.
-  private int maxRequestSize;
-
-  // The number of request handlers that should be used for this connection
-  // handler.
-  private int numRequestHandlers;
-
-  // The index to the request handler that will be used for the next connection
-  // accepted by the server.
-  private int requestHandlerIndex;
-
-  // The set of listeners for this connection handler.
-  private LinkedList<HostPort> listeners;
-
-  // The set of request handlers that are associated with this connection
-  // handler.
-  private LDAPRequestHandler[] requestHandlers;
-
-  // The set of statistics collected for this connection handler.
-  private LDAPStatistics statTracker;
-
-  // The selector that will be used to multiplex connection acceptance across
-  // multiple sockets by a single thread.
-  private Selector selector;
-
   // The SSL client auth policy used by this connection handler.
   private SSLClientAuthPolicy sslClientAuthPolicy;
 
-  // The unique name assigned to this connection handler.
-  private String handlerName;
+  // The backlog that will be used for the accept queue.
+  private int backlog;
 
-  // The protocol used by this connection handler.
-  private String protocol;
+  // Indicates whether to allow the reuse address socket option.
+  private boolean allowReuseAddress;
 
-  // The security mechanism used for connections accepted by this connection
-  // handler.
-  private String securityMechanism;
+  // The number of request handlers that should be used for this
+  // connection handler.
+  private int numRequestHandlers;
 
-  // The nickname of the SSL certificate that should be used if SSL is enabled.
-  private String sslServerCertNickname;
+  // Indicates whether the Directory Server is in the process of
+  // shutting down.
+  private boolean shutdownRequested;
+
+  /* Internal LDAP connection handler state */
+
+  // Indicates whether this connection handler is enabled.
+  private boolean enabled;
+
+  // The set of clients that are explicitly allowed access to the
+  // server.
+  private AddressMask[] allowedClients;
+
+  // The set of clients that have been explicitly denied access to the
+  // server.
+  private AddressMask[] deniedClients;
 
   // The set of SSL cipher suites that should be allowed.
   private String[] enabledSSLCipherSuites;
@@ -254,1013 +150,181 @@
   // The set of SSL protocols that should be allowed.
   private String[] enabledSSLProtocols;
 
-  // The thread being used to run this connection handler.
-  private Thread connHandlerThread;
+  // The index to the request handler that will be used for the next
+  // connection accepted by the server.
+  private int requestHandlerIndex;
+
+  // The set of listeners for this connection handler.
+  private LinkedList<HostPort> listeners;
+
+  // The set of request handlers that are associated with this
+  // connection handler.
+  private LDAPRequestHandler[] requestHandlers;
+
+  // The set of statistics collected for this connection handler.
+  private LDAPStatistics statTracker;
+
+  // The selector that will be used to multiplex connection acceptance
+  // across multiple sockets by a single thread.
+  private Selector selector;
+
+  // The unique name assigned to this connection handler.
+  private String handlerName;
+
+  // The protocol used by this connection handler.
+  private String protocol;
+
+  // The connection security provider that will be used by default for
+  // new client connections.
+  private ConnectionSecurityProvider securityProvider;
 
 
 
   /**
-   * Creates a new instance of this LDAP connection handler.  It must be
-   * initialized before it may be used.
+   * Creates a new instance of this LDAP connection handler. It must
+   * be initialized before it may be used.
    */
-  public LDAPConnectionHandler()
-  {
+  public LDAPConnectionHandler() {
     super("LDAP Connection Handler Thread");
 
-
-    // No real implementation is required.  Do all the work in the
+    // No real implementation is required. Do all the work in the
     // initializeConnectionHandler method.
   }
 
 
 
   /**
-   * Initializes this connection handler based on the information in the
-   * provided configuration entry.
+   * Indicates whether this connection handler should allow
+   * interaction with LDAPv2 clients.
    *
-   * @param  configEntry  The configuration entry that contains the information
-   *                      to use to initialize this connection handler.
-   *
-   * @throws  ConfigException  If there is a problem with the configuration for
-   *                           this connection handler.
-   *
-   * @throws  InitializationException  If a problem occurs while attempting to
-   *                                   initialize this connection handler.
+   * @return <CODE>true</CODE> if LDAPv2 is allowed, or <CODE>false</CODE>
+   *         if not.
    */
-  public void initializeConnectionHandler(ConfigEntry configEntry)
-         throws ConfigException, InitializationException
-  {
-    enabled = true;
+  public boolean allowLDAPv2() {
+    return currentConfig.isAllowLDAPV2();
+  }
 
-    configEntryDN = configEntry.getDN();
 
-    // Determine the set of addresses on which to listen.  There can be
-    // multiple addresses specified.
-    int msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_ADDRESS;
-    listenAddresses = new HashSet<InetAddress>();
-    StringConfigAttribute addrStub =
-         new StringConfigAttribute(ATTR_LISTEN_ADDRESS, getMessage(msgID),
-                                   true, true, true);
-    try
-    {
-      StringConfigAttribute addrAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(addrStub);
-      if ((addrAttr == null) || addrAttr.activeValues().isEmpty())
-      {
-        // This is fine -- we'll just listen on all IPv4 addresses.
-        listenAddresses.add(InetAddress.getByName("0.0.0.0"));
+
+  /**
+   * Indicates whether this connection handler should allow the use of
+   * the StartTLS extended operation.
+   *
+   * @return <CODE>true</CODE> if StartTLS is allowed, or <CODE>false</CODE>
+   *         if not.
+   */
+  public boolean allowStartTLS() {
+    if (currentConfig.isAllowStartTLS()) {
+      if (currentConfig.isUseSSL()) {
+        return false;
+      } else {
+        return true;
       }
-      else
-      {
-        for (String s : addrAttr.activeValues())
-        {
-          try
-          {
-            listenAddresses.add(InetAddress.getByName(s));
-          }
-          catch (UnknownHostException uhe)
-          {
-            if (debugEnabled())
-            {
-              debugCaught(DebugLogLevel.ERROR, uhe);
-            }
-
-            msgID = MSGID_LDAP_CONNHANDLER_UNKNOWN_LISTEN_ADDRESS;
-            String message = getMessage(msgID, s,
-                                        stackTraceToSingleLineString(uhe));
-            throw new ConfigException(msgID, message, uhe);
-          }
-        }
-      }
-    }
-    catch (ConfigException ce)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, ce);
-      }
-
-      throw ce;
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_LISTEN_ADDRESS;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine the port on which to listen.  There may only be a single port
-    // specified.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_PORT;
-    IntegerConfigAttribute portStub =
-         new IntegerConfigAttribute(ATTR_LISTEN_PORT, getMessage(msgID), true,
-                                    false, true, true, 1, true, 65535);
-    try
-    {
-      IntegerConfigAttribute portAttr =
-           (IntegerConfigAttribute) configEntry.getConfigAttribute(portStub);
-      if (portAttr == null)
-      {
-        msgID = MSGID_LDAP_CONNHANDLER_NO_LISTEN_PORT;
-        String message = getMessage(msgID, String.valueOf(configEntryDN));
-        throw new ConfigException(msgID, message);
-      }
-
-      listenPort = portAttr.activeIntValue();
-    }
-    catch (ConfigException ce)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, ce);
-      }
-
-      throw ce;
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_LISTEN_PORT;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine the accept backlog.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_BACKLOG;
-    IntegerConfigAttribute backlogStub =
-         new IntegerConfigAttribute(ATTR_ACCEPT_BACKLOG, getMessage(msgID),
-                                 true, false, true, true, 1, true,
-                                 Integer.MAX_VALUE);
-    try
-    {
-      IntegerConfigAttribute backlogAttr =
-           (IntegerConfigAttribute) configEntry.getConfigAttribute(backlogStub);
-      if (backlogAttr == null)
-      {
-        // This is fine -- just use the default value.
-        backlog = DEFAULT_ACCEPT_BACKLOG;
-      }
-      else
-      {
-        backlog = backlogAttr.activeIntValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_BACKLOG;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine the set of allowed clients.
-    allowedClients = null;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_ALLOWED_CLIENTS;
-    StringConfigAttribute allowedStub =
-         new StringConfigAttribute(ATTR_ALLOWED_CLIENT, getMessage(msgID),
-                                   false, true, false);
-    try
-    {
-      StringConfigAttribute allowedAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(allowedStub);
-      if (allowedAttr != null)
-      {
-        List<String> maskStrings = allowedAttr.activeValues();
-        allowedClients = new AddressMask[maskStrings.size()];
-        for (int i=0; i < allowedClients.length; i++)
-        {
-          try
-          {
-            allowedClients[i] = AddressMask.decode(maskStrings.get(i));
-          }
-          catch (ConfigException ce)
-          {
-            if (debugEnabled())
-            {
-              debugCaught(DebugLogLevel.ERROR, ce);
-            }
-
-            msgID = MSGID_LDAP_CONNHANDLER_INVALID_ADDRESS_MASK;
-            String message = getMessage(msgID, maskStrings.get(i),
-                                        ATTR_ALLOWED_CLIENT,
-                                        String.valueOf(configEntryDN),
-                                        stackTraceToSingleLineString(ce));
-            throw new ConfigException(msgID, message, ce);
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_ALLOWED_CLIENTS;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine the set of denied clients.
-    deniedClients = null;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_DENIED_CLIENTS;
-    StringConfigAttribute deniedStub =
-         new StringConfigAttribute(ATTR_DENIED_CLIENT, getMessage(msgID),
-                                   false, true, false);
-    try
-    {
-      StringConfigAttribute deniedAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(deniedStub);
-      if (deniedAttr != null)
-      {
-        List<String> maskStrings = deniedAttr.activeValues();
-        deniedClients = new AddressMask[maskStrings.size()];
-        for (int i=0; i < deniedClients.length; i++)
-        {
-          try
-          {
-            deniedClients[i] = AddressMask.decode(maskStrings.get(i));
-          }
-          catch (ConfigException ce)
-          {
-            if (debugEnabled())
-            {
-              debugCaught(DebugLogLevel.ERROR, ce);
-            }
-
-            msgID = MSGID_LDAP_CONNHANDLER_INVALID_ADDRESS_MASK;
-            String message = getMessage(msgID, maskStrings.get(i),
-                                        ATTR_ALLOWED_CLIENT,
-                                        String.valueOf(configEntryDN),
-                                        stackTraceToSingleLineString(ce));
-            throw new ConfigException(msgID, message, ce);
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_DENIED_CLIENTS;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine whether to allow LDAPv2 clients.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_ALLOW_LDAPV2;
-    BooleanConfigAttribute allowLDAPv2Stub =
-         new BooleanConfigAttribute(ATTR_ALLOW_LDAPV2, getMessage(msgID),
-                                    false);
-    try
-    {
-      BooleanConfigAttribute allowLDAPv2Attr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(allowLDAPv2Stub);
-      if (allowLDAPv2Attr == null)
-      {
-        // This is fine -- we'll just use the default behavior, which is to
-        // allow these clients.
-        allowLDAPv2 = DEFAULT_ALLOW_LDAPV2;
-      }
-      else
-      {
-        allowLDAPv2 = allowLDAPv2Attr.activeValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_ALLOW_LDAPV2;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine whether to keep LDAP statistics.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_KEEP_STATS;
-    BooleanConfigAttribute keepStatsStub =
-         new BooleanConfigAttribute(ATTR_KEEP_LDAP_STATS, getMessage(msgID),
-                                    false);
-    try
-    {
-      BooleanConfigAttribute keepStatsAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(keepStatsStub);
-      if (keepStatsAttr == null)
-      {
-        // This is fine -- we'll just use the default behavior, which is to
-        // allow these clients.
-        keepStats = DEFAULT_KEEP_LDAP_STATS;
-      }
-      else
-      {
-        keepStats = keepStatsAttr.activeValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_KEEP_STATS;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine the number of request handlers to maintain.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_NUM_REQUEST_HANDLERS;
-    IntegerConfigAttribute reqHandlerStub =
-         new IntegerConfigAttribute(ATTR_NUM_REQUEST_HANDLERS,
-                                    getMessage(msgID), true, false, true,
-                                    true, 1, false, 0);
-    try
-    {
-      IntegerConfigAttribute reqHandlerAttr =
-           (IntegerConfigAttribute)
-           configEntry.getConfigAttribute(reqHandlerStub);
-      if (reqHandlerAttr == null)
-      {
-        // This is fine -- we'll just use the default value.
-        numRequestHandlers = DEFAULT_NUM_REQUEST_HANDLERS;
-      }
-      else
-      {
-        numRequestHandlers = reqHandlerAttr.activeIntValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_NUM_REQUEST_HANDLERS;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine whether to send a notice to clients on rejection.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SEND_REJECTION_NOTICE;
-    BooleanConfigAttribute notifyRejectsStub =
-         new BooleanConfigAttribute(ATTR_SEND_REJECTION_NOTICE,
-                                    getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute notifyRejectsAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(notifyRejectsStub);
-      if (notifyRejectsAttr == null)
-      {
-        // This is fine -- we'll just use the default value.
-        sendRejectionNotice = DEFAULT_SEND_REJECTION_NOTICE;
-      }
-      else
-      {
-        sendRejectionNotice = notifyRejectsAttr.activeValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_SEND_REJECTION_NOTICE;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine whether to use TCP keepalive.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_USE_TCP_KEEPALIVE;
-    BooleanConfigAttribute keepAliveStub =
-         new BooleanConfigAttribute(ATTR_USE_TCP_KEEPALIVE, getMessage(msgID),
-                                    false);
-    try
-    {
-      BooleanConfigAttribute keepAliveAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(keepAliveStub);
-      if (keepAliveAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-        useKeepAlive = DEFAULT_USE_TCP_KEEPALIVE;
-      }
-      else
-      {
-        useKeepAlive = keepAliveAttr.activeValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_USE_TCP_KEEPALIVE;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine whether to use TCP nodelay.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_USE_TCP_NODELAY;
-    BooleanConfigAttribute noDelayStub =
-         new BooleanConfigAttribute(ATTR_USE_TCP_NODELAY, getMessage(msgID),
-                                    false);
-    try
-    {
-      BooleanConfigAttribute noDelayAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(noDelayStub);
-      if (noDelayAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-        useTCPNoDelay = DEFAULT_USE_TCP_NODELAY;
-      }
-      else
-      {
-        useTCPNoDelay = noDelayAttr.activeValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_USE_TCP_NODELAY;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine whether to allow reuse of address/port combinations.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_ALLOW_REUSE_ADDRESS;
-    BooleanConfigAttribute reuseAddrStub =
-         new BooleanConfigAttribute(ATTR_ALLOW_REUSE_ADDRESS,
-                                    getMessage(msgID), true);
-    try
-    {
-      BooleanConfigAttribute reuseAddrAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(reuseAddrStub);
-      if (reuseAddrAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-        allowReuseAddress = DEFAULT_ALLOW_REUSE_ADDRESS;
-      }
-      else
-      {
-        allowReuseAddress = reuseAddrAttr.activeValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_ALLOW_REUSE_ADDRESS;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine the maximum allowed request size.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_MAX_REQUEST_SIZE;
-    IntegerWithUnitConfigAttribute maxReqSizeStub =
-         new IntegerWithUnitConfigAttribute(ATTR_MAX_REQUEST_SIZE,
-                                            getMessage(msgID), false,
-                                            SIZE_UNITS, true, 0, true,
-                                            MAX_REQUEST_SIZE_LIMIT);
-    try
-    {
-      IntegerWithUnitConfigAttribute maxReqSizeAttr =
-           (IntegerWithUnitConfigAttribute)
-           configEntry.getConfigAttribute(maxReqSizeStub);
-      if (maxReqSizeAttr == null)
-      {
-        // This is fine -- we'll just use the default value.
-        maxRequestSize = DEFAULT_MAX_REQUEST_SIZE;
-      }
-      else
-      {
-        maxRequestSize = (int) maxReqSizeAttr.activeCalculatedValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_MAX_REQUEST_SIZE;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine whether to use SSL.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_USE_SSL;
-    BooleanConfigAttribute useSSLStub =
-         new BooleanConfigAttribute(ATTR_USE_SSL, getMessage(msgID), true);
-    try
-    {
-      BooleanConfigAttribute useSSLAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(useSSLStub);
-      if (useSSLAttr == null)
-      {
-        // This is fine -- we'll just use the default value.
-        useSSL = DEFAULT_USE_SSL;
-      }
-      else
-      {
-        useSSL = useSSLAttr.activeValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_USE_SSL;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine whether to allow the StartTLS extended operation.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_ALLOW_STARTTLS;
-    BooleanConfigAttribute startTLSStub =
-         new BooleanConfigAttribute(ATTR_ALLOW_STARTTLS, getMessage(msgID),
-                                    false);
-    try
-    {
-      BooleanConfigAttribute startTLSAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(startTLSStub);
-      if (startTLSAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-        allowStartTLS = DEFAULT_ALLOW_STARTTLS;
-      }
-      else
-      {
-        allowStartTLS = startTLSAttr.activeValue();
-      }
-
-
-      // See if both SSL and startTLS are configured.  If so, we'll have to
-      // disable startTLS because they can't both be used concurrently.
-      if (useSSL && allowStartTLS)
-      {
-        msgID = MSGID_LDAP_CONNHANDLER_CANNOT_HAVE_SSL_AND_STARTTLS;
-        String message = getMessage(msgID, String.valueOf(configEntryDN));
-        logError(ErrorLogCategory.CONFIGURATION,
-                 ErrorLogSeverity.SEVERE_WARNING, message, msgID);
-
-        allowStartTLS = false;
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_ALLOW_STARTTLS;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine how to handle SSL client authentication.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SSL_CLIENT_AUTH_POLICY;
-    HashSet<String> allowedValues = new HashSet<String>(3);
-    allowedValues.add(toLowerCase(SSLClientAuthPolicy.DISABLED.toString()));
-    allowedValues.add(toLowerCase(SSLClientAuthPolicy.OPTIONAL.toString()));
-    allowedValues.add(toLowerCase(SSLClientAuthPolicy.REQUIRED.toString()));
-    MultiChoiceConfigAttribute sslAuthPolicyStub =
-         new MultiChoiceConfigAttribute(ATTR_SSL_CLIENT_AUTH_POLICY,
-                                        getMessage(msgID), false, false, true,
-                                        allowedValues);
-    try
-    {
-      MultiChoiceConfigAttribute sslAuthPolicyAttr =
-           (MultiChoiceConfigAttribute)
-           configEntry.getConfigAttribute(sslAuthPolicyStub);
-      if (sslAuthPolicyAttr == null)
-      {
-        // This is fine -- We'll just use the default.
-        sslClientAuthPolicy = DEFAULT_SSL_CLIENT_AUTH_POLICY;
-      }
-      else
-      {
-        sslClientAuthPolicy = SSLClientAuthPolicy.policyForName(
-                                   sslAuthPolicyAttr.activeValue());
-        if (sslClientAuthPolicy == null)
-        {
-          msgID = MSGID_LDAP_CONNHANDLER_INVALID_SSL_CLIENT_AUTH_POLICY;
-          String message = getMessage(msgID, sslAuthPolicyAttr.activeValue(),
-                                      String.valueOf(configEntryDN));
-          throw new ConfigException(msgID, message);
-        }
-      }
-    }
-    catch (ConfigException ce)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, ce);
-      }
-
-      throw ce;
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_SSL_CLIENT_AUTH_POLICY;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine which SSL certificate to use.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SSL_CERT_NICKNAME;
-    StringConfigAttribute certNameStub =
-         new StringConfigAttribute(ATTR_SSL_CERT_NICKNAME, getMessage(msgID),
-                                   false, false, true);
-    try
-    {
-      StringConfigAttribute certNameAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(certNameStub);
-      if (certNameAttr == null)
-      {
-        // This is fine -- We'll just let the server pick one.
-        sslServerCertNickname = null;
-      }
-      else
-      {
-        sslServerCertNickname = certNameAttr.activeValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_SSL_CERT_NICKNAME;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine the set of SSL protocols to allow.
-    enabledSSLProtocols = null;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SSL_ENABLED_PROTOCOLS;
-    StringConfigAttribute sslProtocolsStub =
-         new StringConfigAttribute(ATTR_SSL_PROTOCOLS, getMessage(msgID), false,
-                                   true, false);
-    try
-    {
-      StringConfigAttribute sslProtocolsAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(sslProtocolsStub);
-      if (sslProtocolsAttr != null)
-      {
-        enabledSSLProtocols = listToArray(sslProtocolsAttr.activeValues());
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_SSL_PROTOCOLS;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine the set of SSL cipher suites to allow.
-    enabledSSLCipherSuites = null;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SSL_ENABLED_CIPHERS;
-    StringConfigAttribute sslCiphersStub =
-         new StringConfigAttribute(ATTR_SSL_CIPHERS, getMessage(msgID), false,
-                                   true, false);
-    try
-    {
-      StringConfigAttribute sslCiphersAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(sslCiphersStub);
-      if (sslCiphersAttr != null)
-      {
-        enabledSSLCipherSuites = listToArray(sslCiphersAttr.activeValues());
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_SSL_CIPHERS;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine the key manager provider to use.
-    keyManagerProviderDN = null;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_KEYMANAGER_DN;
-    DNConfigAttribute keyManagerStub =
-         new DNConfigAttribute(ATTR_KEYMANAGER_DN, getMessage(msgID), false,
-                               false, false);
-    try
-    {
-      DNConfigAttribute keyManagerAttr =
-           (DNConfigAttribute) configEntry.getConfigAttribute(keyManagerStub);
-      if (keyManagerAttr != null)
-      {
-        keyManagerProviderDN = keyManagerAttr.activeValue();
-        KeyManagerProvider provider =
-             DirectoryServer.getKeyManagerProvider(keyManagerProviderDN);
-        if (provider == null)
-        {
-          msgID = MSGID_LDAP_CONNHANDLER_INVALID_KEYMANAGER_DN;
-          String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                      String.valueOf(keyManagerProviderDN));
-          throw new ConfigException(msgID, message);
-        }
-      }
-    }
-    catch (ConfigException ce)
-    {
-      throw ce;
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_KEYMANAGER_DN;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Determine the trust manager provider to use.
-    trustManagerProviderDN = null;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_TRUSTMANAGER_DN;
-    DNConfigAttribute trustManagerStub =
-         new DNConfigAttribute(ATTR_TRUSTMANAGER_DN, getMessage(msgID), false,
-                               false, false);
-    try
-    {
-      DNConfigAttribute trustManagerAttr =
-           (DNConfigAttribute) configEntry.getConfigAttribute(trustManagerStub);
-      if (trustManagerAttr != null)
-      {
-        trustManagerProviderDN = trustManagerAttr.activeValue();
-        TrustManagerProvider provider =
-             DirectoryServer.getTrustManagerProvider(trustManagerProviderDN);
-        if (provider == null)
-        {
-          msgID = MSGID_LDAP_CONNHANDLER_INVALID_TRUSTMANAGER_DN;
-          String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                      String.valueOf(trustManagerProviderDN));
-          throw new ConfigException(msgID, message);
-        }
-      }
-    }
-    catch (ConfigException ce)
-    {
-      throw ce;
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_TRUSTMANAGER_DN;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    if (useSSL)
-    {
-      TLSConnectionSecurityProvider tlsProvider =
-           new TLSConnectionSecurityProvider();
-      tlsProvider.initializeConnectionSecurityProvider(null);
-      tlsProvider.setSSLClientAuthPolicy(sslClientAuthPolicy);
-      tlsProvider.setEnabledProtocols(enabledSSLProtocols);
-      tlsProvider.setEnabledCipherSuites(enabledSSLCipherSuites);
-
-      // FIXME -- Need to do something with the requested cert nickname.
-
-      securityProvider = tlsProvider;
-    }
-    else
-    {
-      securityProvider = new NullConnectionSecurityProvider();
-      securityProvider.initializeConnectionSecurityProvider(null);
-    }
-
-
-    DirectoryServer.registerConfigurableComponent(this);
-
-
-    try
-    {
-      selector = Selector.open();
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_OPEN_SELECTOR_FAILED;
-      String message = getMessage(msgID, configEntryDN,
-                                  stackTraceToSingleLineString(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Construct a unique name for this connection handler, and put together the
-    // set of listeners.
-    listeners = new LinkedList<HostPort>();
-    StringBuilder nameBuffer = new StringBuilder();
-    nameBuffer.append("LDAP Connection Handler");
-    for (InetAddress a : listenAddresses)
-    {
-      listeners.add(new HostPort(a.getHostAddress(), listenPort));
-      nameBuffer.append(" ");
-      nameBuffer.append(a.getHostAddress());
-    }
-    nameBuffer.append(" port ");
-    nameBuffer.append(listenPort);
-    handlerName = nameBuffer.toString();
-
-
-    // Set the security mechanism for this connection handler.
-    if (useSSL)
-    {
-      securityMechanism = SECURITY_MECHANISM_SSL;
-      protocol          = "LDAP+SSL";
-    }
-    else
-    {
-      securityMechanism = null;
-      protocol          = "LDAP";
-    }
-
-
-    // Perform any additional initialization that might be required.
-    connHandlerThread = null;
-    statTracker = new LDAPStatistics(handlerName + " Statistics");
-
-
-    // Create and start the request handlers.
-    requestHandlers = new LDAPRequestHandler[numRequestHandlers];
-    for (int i=0; i < numRequestHandlers; i++)
-    {
-      requestHandlers[i] = new LDAPRequestHandler(this, i);
-    }
-    for (int i=0; i < numRequestHandlers; i++)
-    {
-      requestHandlers[i].start();
+    } else {
+      return false;
     }
   }
 
 
 
   /**
-   * Closes this connection handler so that it will no longer accept new client
-   * connections.  It may or may not disconnect existing client connections
-   * based on the provided flag.  Note, however, that some connection handler
-   * implementations may not have any way to continue processing requests from
-   * existing connections, in which case they should always be closed regardless
-   * of the value of the <CODE>closeConnections</CODE> flag.
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationChange(
+      LDAPConnectionHandlerCfg config) {
+    // Create variables to include in the response.
+    ResultCode resultCode = ResultCode.SUCCESS;
+    boolean adminActionRequired = false;
+    ArrayList<String> messages = new ArrayList<String>();
+
+    // Note that the following properties cannot be modified:
+    //
+    // * listen port and addresses
+    // * use ssl
+    // * ssl policy
+    // * ssl cert nickname
+    // * accept backlog
+    // * tcp reuse address
+    // * num request handler
+
+    // Start/clear the stat tracker if LDAPv2 is being enabled.
+    if (currentConfig.isAllowLDAPV2() != config.isAllowLDAPV2()) {
+      if (config.isAllowLDAPV2()) {
+        if (statTracker == null) {
+          statTracker = new LDAPStatistics(handlerName
+              + " Statistics");
+        } else {
+          statTracker.clearStatistics();
+        }
+      }
+    }
+
+    // Apply the changes.
+    currentConfig = config;
+    enabled = config.isEnabled();
+    allowedClients = config.getAllowedClients().toArray(
+        new AddressMask[0]);
+    deniedClients = config.getDeniedClients().toArray(
+        new AddressMask[0]);
+
+    // Get the supported SSL ciphers and protocols.
+    Set<String> ciphers = config.getSSLCipherSuites();
+    if (ciphers.isEmpty()) {
+      enabledSSLCipherSuites = null;
+    } else {
+      enabledSSLCipherSuites = ciphers.toArray(new String[0]);
+    }
+
+    Set<String> protocols = config.getSSLProtocols();
+    if (protocols.isEmpty()) {
+      enabledSSLProtocols = null;
+    } else {
+      enabledSSLProtocols = protocols.toArray(new String[0]);
+    }
+
+    return new ConfigChangeResult(resultCode, adminActionRequired,
+        messages);
+  }
+
+
+
+  /**
+   * Closes this connection handler so that it will no longer accept
+   * new client connections. It may or may not disconnect existing
+   * client connections based on the provided flag. Note, however,
+   * that some connection handler implementations may not have any way
+   * to continue processing requests from existing connections, in
+   * which case they should always be closed regardless of the value
+   * of the <CODE>closeConnections</CODE> flag.
    *
-   * @param  finalizeReason    The reason that this connection handler should be
-   *                           finalized.
-   * @param  closeConnections  Indicates whether any established client
-   *                           connections associated with the connection
-   *                           handler should also be closed.
+   * @param finalizeReason
+   *          The reason that this connection handler should be
+   *          finalized.
+   * @param closeConnections
+   *          Indicates whether any established client connections
+   *          associated with the connection handler should also be
+   *          closed.
    */
   public void finalizeConnectionHandler(String finalizeReason,
-                                       boolean closeConnections)
-  {
+      boolean closeConnections) {
     shutdownRequested = true;
+    currentConfig.removeLDAPChangeListener(this);
 
-    DirectoryServer.deregisterConfigurableComponent(this);
-
-    try
-    {
+    try {
       selector.wakeup();
-    }
-    catch (Exception e)
-    {
+    } catch (Exception e) {
       if (debugEnabled())
       {
         debugCaught(DebugLogLevel.ERROR, e);
       }
     }
 
-
-    if (closeConnections)
-    {
-      for (LDAPRequestHandler requestHandler : requestHandlers)
-      {
+    if (closeConnections) {
+      for (LDAPRequestHandler requestHandler : requestHandlers) {
         requestHandler.processServerShutdown(finalizeReason);
       }
-    }
-    else
-    {
-      for (LDAPRequestHandler requestHandler : requestHandlers)
-      {
+    } else {
+      for (LDAPRequestHandler requestHandler : requestHandlers) {
         requestHandler.registerShutdownListener();
       }
     }
@@ -1269,48 +333,54 @@
 
 
   /**
-   * {@inheritDoc}
-   */
-  public String getConnectionHandlerName()
-  {
-    return handlerName;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public String getProtocol()
-  {
-    return protocol;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public Collection<HostPort> getListeners()
-  {
-    return listeners;
-  }
-
-
-
-  /**
-   * Retrieves the set of active client connections that have been established
-   * through this connection handler.
+   * Retrieves information about the set of alerts that this generator
+   * may produce. The map returned should be between the notification
+   * type for a particular notification and the human-readable
+   * description for that notification. This alert generator must not
+   * generate any alerts with types that are not contained in this
+   * list.
    *
-   * @return  The set of active client connections that have been established
-   *          through this connection handler.
+   * @return Information about the set of alerts that this generator
+   *         may produce.
    */
-  public Collection<ClientConnection> getClientConnections()
-  {
+  public LinkedHashMap<String, String> getAlerts() {
+    LinkedHashMap<String, String> alerts = new LinkedHashMap<String, String>();
+
+    alerts
+        .put(ALERT_TYPE_LDAP_CONNECTION_HANDLER_CONSECUTIVE_FAILURES,
+            ALERT_DESCRIPTION_LDAP_CONNECTION_HANDLER_CONSECUTIVE_FAILURES);
+    alerts.put(ALERT_TYPE_LDAP_CONNECTION_HANDLER_UNCAUGHT_ERROR,
+        ALERT_DESCRIPTION_LDAP_CONNECTION_HANDLER_UNCAUGHT_ERROR);
+
+    return alerts;
+  }
+
+
+
+  /**
+   * Retrieves the fully-qualified name of the Java class for this
+   * alert generator implementation.
+   *
+   * @return The fully-qualified name of the Java class for this alert
+   *         generator implementation.
+   */
+  public String getClassName() {
+    return CLASS_NAME;
+  }
+
+
+
+  /**
+   * Retrieves the set of active client connections that have been
+   * established through this connection handler.
+   *
+   * @return The set of active client connections that have been
+   *         established through this connection handler.
+   */
+  public Collection<ClientConnection> getClientConnections() {
     LinkedList<ClientConnection> connectionList =
-         new LinkedList<ClientConnection>();
-    for (LDAPRequestHandler requestHandler : requestHandlers)
-    {
+      new LinkedList<ClientConnection>();
+    for (LDAPRequestHandler requestHandler : requestHandlers) {
       connectionList.addAll(requestHandler.getClientConnections());
     }
 
@@ -1320,104 +390,492 @@
 
 
   /**
+   * Retrieves the DN of the configuration entry with which this alert
+   * generator is associated.
+   *
+   * @return The DN of the configuration entry with which this alert
+   *         generator is associated.
+   */
+  public DN getComponentEntryDN() {
+    return currentConfig.dn();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getConnectionHandlerName() {
+    return handlerName;
+  }
+
+
+
+  /**
+   * Retrieves the set of enabled SSL cipher suites configured for
+   * this connection handler.
+   *
+   * @return The set of enabled SSL cipher suites configured for this
+   *         connection handler.
+   */
+  public String[] getEnabledSSLCipherSuites() {
+    return enabledSSLCipherSuites;
+  }
+
+
+
+  /**
+   * Retrieves the set of enabled SSL protocols configured for this
+   * connection handler.
+   *
+   * @return The set of enabled SSL protocols configured for this
+   *         connection handler.
+   */
+  public String[] getEnabledSSLProtocols() {
+    return enabledSSLProtocols;
+  }
+
+
+
+  /**
+   * Retrieves the DN of the key manager provider that should be used
+   * for operations associated with this connection handler which need
+   * access to a key manager.
+   *
+   * @return The DN of the key manager provider that should be used
+   *         for operations associated with this connection handler
+   *         which need access to a key manager, or {@code null} if no
+   *         key manager provider has been configured for this
+   *         connection handler.
+   */
+  public DN getKeyManagerProviderDN() {
+    return currentConfig.getKeyManagerProviderDN();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Collection<HostPort> getListeners() {
+    return listeners;
+  }
+
+
+
+  /**
    * Retrieves the port on which this connection handler is listening
    * for client connections.
    *
-   * @return  The port on which this connection handler is listening
-   *          for client connections.
+   * @return The port on which this connection handler is listening
+   *         for client connections.
    */
-  public int getListenPort()
-  {
+  public int getListenPort() {
     return listenPort;
   }
 
 
 
   /**
-   * Operates in a loop, accepting new connections and ensuring that requests on
-   * those connections are handled properly.
+   * Retrieves the maximum ASN.1 element value length that will be
+   * allowed by this connection handler.
+   *
+   * @return The maximum ASN.1 element value length that will be
+   *         allowed by this connection handler.
    */
-  public void run()
-  {
-    connHandlerThread = Thread.currentThread();
-    setName(handlerName);
+  public int getMaxRequestSize() {
+    return (int) ((long) currentConfig.getMaxRequestSize());
+  }
 
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getProtocol() {
+    return protocol;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getShutdownListenerName() {
+    return handlerName;
+  }
+
+
+
+  /**
+   * Retrieves the nickname of the server certificate that should be
+   * used in conjunction with this LDAP connection handler.
+   *
+   * @return The nickname of the server certificate that should be
+   *         used in conjunction with this LDAP connection handler.
+   */
+  public String getSSLServerCertNickname() {
+    return currentConfig.getSSLCertNickname();
+  }
+
+
+
+  /**
+   * Retrieves the SSL client authentication policy for this
+   * connection handler.
+   *
+   * @return The SSL client authentication policy for this connection
+   *         handler.
+   */
+  public SSLClientAuthPolicy getSSLClientAuthPolicy() {
+    return sslClientAuthPolicy;
+  }
+
+
+
+  /**
+   * Retrieves the set of statistics maintained by this connection
+   * handler.
+   *
+   * @return The set of statistics maintained by this connection
+   *         handler.
+   */
+  public LDAPStatistics getStatTracker() {
+    return statTracker;
+  }
+
+
+
+  /**
+   * Retrieves the DN of the trust manager provider that should be
+   * used for operations associated with this connection handler which
+   * need access to a trust manager.
+   *
+   * @return The DN of the trust manager provider that should be used
+   *         for operations associated with this connection handler
+   *         which need access to a trust manager, or {@code null} if
+   *         no trust manager provider has been configured for this
+   *         connection handler.
+   */
+  public DN getTrustManagerProviderDN() {
+    return currentConfig.getTrustManagerProviderDN();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void initializeConnectionHandler(
+      LDAPConnectionHandlerCfg config)
+      throws ConfigException, InitializationException {
+    // SSL and StartTLS are mutually exclusive.
+    if (config.isAllowStartTLS() && config.isUseSSL()) {
+      int msgID = MSGID_LDAP_CONNHANDLER_CANNOT_HAVE_SSL_AND_STARTTLS;
+      String message = getMessage(msgID, String.valueOf(config.dn()));
+      logError(ErrorLogCategory.CONFIGURATION,
+          ErrorLogSeverity.SEVERE_WARNING, message, msgID);
+    }
+
+    // Validate the key manager provider DN.
+    DN keyManagerProviderDN = config.getKeyManagerProviderDN();
+    if (keyManagerProviderDN != null) {
+      KeyManagerProvider provider = DirectoryServer
+          .getKeyManagerProvider(keyManagerProviderDN);
+      if (provider == null) {
+        int msgID = MSGID_LDAP_CONNHANDLER_INVALID_KEYMANAGER_DN;
+        String message = getMessage(msgID, String
+            .valueOf(config.dn()), String
+            .valueOf(keyManagerProviderDN));
+        throw new ConfigException(msgID, message);
+      }
+    }
+
+    // Validate the trust manager provider DN.
+    DN trustManagerProviderDN = config.getTrustManagerProviderDN();
+    if (trustManagerProviderDN != null) {
+      TrustManagerProvider provider = DirectoryServer
+          .getTrustManagerProvider(trustManagerProviderDN);
+      if (provider == null) {
+        int msgID = MSGID_LDAP_CONNHANDLER_INVALID_TRUSTMANAGER_DN;
+        String message = getMessage(msgID, String
+            .valueOf(config.dn()), String
+            .valueOf(trustManagerProviderDN));
+        throw new ConfigException(msgID, message);
+      }
+    }
+
+    // Open the selector.
+    try {
+      selector = Selector.open();
+    } catch (Exception e) {
+      if (debugEnabled())
+      {
+        debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      int msgID = MSGID_LDAP_CONNHANDLER_OPEN_SELECTOR_FAILED;
+      String message = getMessage(msgID, config.dn(),
+          stackTraceToSingleLineString(e));
+      throw new InitializationException(msgID, message, e);
+    }
+
+    // Get the SSL auth policy.
+    switch (config.getSSLClientAuthPolicy()) {
+    case DISABLED:
+      sslClientAuthPolicy = SSLClientAuthPolicy.DISABLED;
+      break;
+    case REQUIRED:
+      sslClientAuthPolicy = SSLClientAuthPolicy.REQUIRED;
+      break;
+    default:
+      sslClientAuthPolicy = SSLClientAuthPolicy.OPTIONAL;
+      break;
+    }
+
+    // Get the supported SSL ciphers and protocols.
+    Set<String> ciphers = config.getSSLCipherSuites();
+    if (ciphers.isEmpty()) {
+      enabledSSLCipherSuites = null;
+    } else {
+      enabledSSLCipherSuites = ciphers.toArray(new String[0]);
+    }
+
+    Set<String> protocols = config.getSSLProtocols();
+    if (protocols.isEmpty()) {
+      enabledSSLProtocols = null;
+    } else {
+      enabledSSLProtocols = protocols.toArray(new String[0]);
+    }
+
+    // Initialize the security provider.
+    if (config.isUseSSL()) {
+      TLSConnectionSecurityProvider tlsProvider =
+        new TLSConnectionSecurityProvider();
+      tlsProvider.initializeConnectionSecurityProvider(null);
+      tlsProvider.setSSLClientAuthPolicy(sslClientAuthPolicy);
+      tlsProvider.setEnabledProtocols(enabledSSLProtocols);
+      tlsProvider.setEnabledCipherSuites(enabledSSLCipherSuites);
+
+      // FIXME -- Need to do something with the requested cert
+      // nickname.
+
+      securityProvider = tlsProvider;
+    } else {
+      securityProvider = new NullConnectionSecurityProvider();
+      securityProvider.initializeConnectionSecurityProvider(null);
+    }
+
+    // Save this configuration for future reference.
+    currentConfig = config;
+    enabled = config.isEnabled();
+    requestHandlerIndex = 0;
+    allowedClients = config.getAllowedClients().toArray(
+        new AddressMask[0]);
+    deniedClients = config.getDeniedClients().toArray(
+        new AddressMask[0]);
+
+    // Save properties that cannot be dynamically modified.
+    allowReuseAddress = config.isAllowTCPReuseAddress();
+    backlog = config.getAcceptBacklog();
+    listenAddresses = config.getListenAddresses();
+    listenPort = config.getListenPort();
+    numRequestHandlers = config.getNumRequestHandlers();
+
+    // Construct a unique name for this connection handler, and put
+    // together the
+    // set of listeners.
+    listeners = new LinkedList<HostPort>();
+    StringBuilder nameBuffer = new StringBuilder();
+    nameBuffer.append("LDAP Connection Handler");
+    for (InetAddress a : listenAddresses) {
+      listeners.add(new HostPort(a.getHostAddress(), listenPort));
+      nameBuffer.append(" ");
+      nameBuffer.append(a.getHostAddress());
+    }
+    nameBuffer.append(" port ");
+    nameBuffer.append(listenPort);
+    handlerName = nameBuffer.toString();
+
+    // Set the protocol for this connection handler.
+    if (config.isUseSSL()) {
+      protocol = "LDAP+SSL";
+    } else {
+      protocol = "LDAP";
+    }
+
+    // Perform any additional initialization that might be required.
+    statTracker = new LDAPStatistics(handlerName + " Statistics");
+
+    // Create and start the request handlers.
+    requestHandlers = new LDAPRequestHandler[numRequestHandlers];
+    for (int i = 0; i < numRequestHandlers; i++) {
+      requestHandlers[i] = new LDAPRequestHandler(this, i);
+    }
+
+    for (int i = 0; i < numRequestHandlers; i++) {
+      requestHandlers[i].start();
+    }
+
+    // Register this as a change listener.
+    config.addLDAPChangeListener(this);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationChangeAcceptable(
+      LDAPConnectionHandlerCfg config,
+      List<String> unacceptableReasons) {
+    boolean isAcceptable = true;
+
+    // SSL and StartTLS are mutually exclusive.
+    if (config.isAllowStartTLS() && config.isUseSSL()) {
+      int msgID = MSGID_LDAP_CONNHANDLER_CANNOT_HAVE_SSL_AND_STARTTLS;
+      unacceptableReasons.add(getMessage(msgID, String.valueOf(config
+          .dn())));
+      isAcceptable = false;
+    }
+
+    // Validate the key manager provider DN.
+    DN keyManagerProviderDN = config.getKeyManagerProviderDN();
+    if (keyManagerProviderDN != null) {
+      KeyManagerProvider provider = DirectoryServer
+          .getKeyManagerProvider(keyManagerProviderDN);
+      if (provider == null) {
+        int msgID = MSGID_LDAP_CONNHANDLER_INVALID_KEYMANAGER_DN;
+        unacceptableReasons.add(getMessage(msgID, String
+            .valueOf(config.dn()), String
+            .valueOf(keyManagerProviderDN)));
+        isAcceptable = false;
+      }
+    }
+
+    // Validate the trust manager provider DN.
+    DN trustManagerProviderDN = config.getTrustManagerProviderDN();
+    if (trustManagerProviderDN != null) {
+      TrustManagerProvider provider = DirectoryServer
+          .getTrustManagerProvider(trustManagerProviderDN);
+      if (provider == null) {
+        int msgID = MSGID_LDAP_CONNHANDLER_INVALID_TRUSTMANAGER_DN;
+        unacceptableReasons.add(getMessage(msgID, String
+            .valueOf(config.dn()), String
+            .valueOf(trustManagerProviderDN)));
+        isAcceptable = false;
+      }
+    }
+
+    return isAcceptable;
+  }
+
+
+
+  /**
+   * Indicates whether this connection handler should maintain usage
+   * statistics.
+   *
+   * @return <CODE>true</CODE> if this connection handler should
+   *         maintain usage statistics, or <CODE>false</CODE> if
+   *         not.
+   */
+  public boolean keepStats() {
+    return currentConfig.isKeepStats();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void processServerShutdown(String reason) {
+    shutdownRequested = true;
+
+    try {
+      for (LDAPRequestHandler requestHandler : requestHandlers) {
+        try {
+          requestHandler.processServerShutdown(reason);
+        } catch (Exception e) {
+        }
+      }
+    } catch (Exception e) {
+    }
+  }
+
+
+
+  /**
+   * Operates in a loop, accepting new connections and ensuring that
+   * requests on those connections are handled properly.
+   */
+  public void run() {
+    setName(handlerName);
     boolean listening = false;
 
-    while (! shutdownRequested)
-    {
-      // If this connection handler is not enabled, then just sleep for a bit
-      // and check again.
-      if (! enabled)
-      {
-        if (listening)
-        {
+    while (!shutdownRequested) {
+      // If this connection handler is not enabled, then just sleep
+      // for a bit and check again.
+      if (!enabled) {
+        if (listening) {
           cleanUpSelector();
           listening = false;
-          enabled   = false;
 
           logError(ErrorLogCategory.CONNECTION_HANDLING,
-                   ErrorLogSeverity.NOTICE,
-                   MSGID_LDAP_CONNHANDLER_STOPPED_LISTENING, handlerName);
+              ErrorLogSeverity.NOTICE,
+              MSGID_LDAP_CONNHANDLER_STOPPED_LISTENING, handlerName);
         }
 
-        try
-        {
+        try {
           Thread.sleep(1000);
-        } catch (Exception e) {}
+        } catch (Exception e) {
+        }
 
         continue;
       }
 
-
-      // If we have gotten here, then we are about to start listening for the
-      // first time since startup or since we were previously disabled.  Make
-      // sure to start with a clean selector and then create all the listeners.
-      try
-      {
+      // If we have gotten here, then we are about to start listening
+      // for the first time since startup or since we were previously
+      // disabled. Make sure to start with a clean selector and then
+      // create all the listeners.
+      try {
         cleanUpSelector();
 
         int numRegistered = 0;
-        for (InetAddress a : listenAddresses)
-        {
-          try
-          {
+        for (InetAddress a : listenAddresses) {
+          try {
             ServerSocketChannel channel = ServerSocketChannel.open();
             channel.socket().setReuseAddress(allowReuseAddress);
-            channel.socket().bind(new InetSocketAddress(a, listenPort),
-                                  backlog);
+            channel.socket().bind(
+                new InetSocketAddress(a, listenPort), backlog);
             channel.configureBlocking(false);
             channel.register(selector, SelectionKey.OP_ACCEPT);
             numRegistered++;
 
             logError(ErrorLogCategory.CONNECTION_HANDLING,
-                     ErrorLogSeverity.NOTICE,
-                     MSGID_LDAP_CONNHANDLER_STARTED_LISTENING, handlerName);
-          }
-          catch (Exception e)
-          {
+                ErrorLogSeverity.NOTICE,
+                MSGID_LDAP_CONNHANDLER_STARTED_LISTENING, handlerName);
+          } catch (Exception e) {
             if (debugEnabled())
             {
               debugCaught(DebugLogLevel.ERROR, e);
             }
 
             logError(ErrorLogCategory.CONNECTION_HANDLING,
-                     ErrorLogSeverity.SEVERE_ERROR,
-                     MSGID_LDAP_CONNHANDLER_CREATE_CHANNEL_FAILED,
-                     configEntryDN, a.getHostAddress(), listenPort,
-                     stackTraceToSingleLineString(e));
+                ErrorLogSeverity.SEVERE_ERROR,
+                MSGID_LDAP_CONNHANDLER_CREATE_CHANNEL_FAILED,
+                currentConfig.dn(), a.getHostAddress(), listenPort,
+                stackTraceToSingleLineString(e));
           }
         }
 
-
-        // If none of the listeners were created successfully, then consider the
-        // connection handler disabled and require administrative action before
-        // trying again.
-        if (numRegistered == 0)
-        {
+        // If none of the listeners were created successfully, then
+        // consider the connection handler disabled and require
+        // administrative action before trying again.
+        if (numRegistered == 0) {
           logError(ErrorLogCategory.CONNECTION_HANDLING,
-                   ErrorLogSeverity.FATAL_ERROR,
-                   MSGID_LDAP_CONNHANDLER_NO_ACCEPTORS, configEntryDN);
+              ErrorLogSeverity.FATAL_ERROR,
+              MSGID_LDAP_CONNHANDLER_NO_ACCEPTORS, currentConfig.dn());
 
           enabled = false;
           continue;
@@ -1425,66 +883,64 @@
 
         listening = true;
 
-
-        // Enter a loop, waiting for new connections to arrive and then
-        // accepting them as they come in.
+        // Enter a loop, waiting for new connections to arrive and
+        // then accepting them as they come in.
         boolean lastIterationFailed = false;
-        while (enabled && (! shutdownRequested))
-        {
-          try
-          {
-            if (selector.select() > 0)
-            {
-              Iterator<SelectionKey> iterator =
-                   selector.selectedKeys().iterator();
+        while (enabled && (!shutdownRequested)) {
+          try {
+            if (selector.select() > 0) {
+              Iterator<SelectionKey> iterator = selector
+                  .selectedKeys().iterator();
 
-              while (iterator.hasNext())
-              {
+              while (iterator.hasNext()) {
                 SelectionKey key = iterator.next();
-                if (key.isAcceptable())
-                {
+                if (key.isAcceptable()) {
                   // Accept the new client connection.
-                  ServerSocketChannel serverChannel =
-                       (ServerSocketChannel) key.channel();
-                  SocketChannel clientChannel = serverChannel.accept();
+                  ServerSocketChannel serverChannel = (ServerSocketChannel) key
+                      .channel();
+                  SocketChannel clientChannel = serverChannel
+                      .accept();
                   LDAPClientConnection clientConnection =
-                       new LDAPClientConnection(this, clientChannel);
-                  InetAddress clientAddr=clientConnection.getRemoteAddress();
-                  // Check to see if the client is on the denied list.  If so,
-                  // then reject it immediately.
-                  if((deniedClients != null) && (deniedClients.length > 0) &&
-                          AddressMask.maskListContains(clientAddr.getAddress(),
-                                  clientAddr.getHostName(), deniedClients))
-                  {
-                      clientConnection.disconnect(
-                              DisconnectReason.CONNECTION_REJECTED,
-                              sendRejectionNotice,
-                              MSGID_LDAP_CONNHANDLER_DENIED_CLIENT,
-                              clientConnection.getClientHostPort(),
-                              clientConnection.getServerHostPort());
+                    new LDAPClientConnection(this, clientChannel);
+                  InetAddress clientAddr = clientConnection
+                      .getRemoteAddress();
+                  // Check to see if the client is on the denied list.
+                  // If so, then reject it immediately.
+                  if ((deniedClients.length > 0)
+                      && AddressMask.maskListContains(clientAddr
+                          .getAddress(), clientAddr.getHostName(),
+                          deniedClients)) {
+                    clientConnection.disconnect(
+                        DisconnectReason.CONNECTION_REJECTED,
+                        currentConfig.isSendRejectionNotice(),
+                        MSGID_LDAP_CONNHANDLER_DENIED_CLIENT,
+                        clientConnection.getClientHostPort(),
+                        clientConnection.getServerHostPort());
 
-                      iterator.remove();
-                      continue;
+                    iterator.remove();
+                    continue;
                   }
-                  // Check to see if there is an allowed list and if there is
-                  // whether the client is on that list.  If not, then reject
-                  // the connection.
-                  if((allowedClients != null) && (allowedClients.length > 0) &&
-                        (!AddressMask.maskListContains(clientAddr.getAddress(),
-                                  clientAddr.getHostName(), allowedClients)))
-                  {
-                      clientConnection.disconnect(
-                              DisconnectReason.CONNECTION_REJECTED,
-                              sendRejectionNotice,
-                              MSGID_LDAP_CONNHANDLER_DISALLOWED_CLIENT,
-                              clientConnection.getClientHostPort(),
-                              clientConnection.getServerHostPort());
+                  // Check to see if there is an allowed list and if
+                  // there is whether the client is on that list. If
+                  // not, then reject the connection.
+                  if ((allowedClients.length > 0)
+                      && (!AddressMask.maskListContains(clientAddr
+                          .getAddress(), clientAddr.getHostName(),
+                          allowedClients))) {
+                    clientConnection.disconnect(
+                        DisconnectReason.CONNECTION_REJECTED,
+                        currentConfig.isSendRejectionNotice(),
+                        MSGID_LDAP_CONNHANDLER_DISALLOWED_CLIENT,
+                        clientConnection.getClientHostPort(),
+                        clientConnection.getServerHostPort());
 
-                      iterator.remove();
-                      continue;
+                    iterator.remove();
+                    continue;
                   }
-                  clientChannel.socket().setKeepAlive(useKeepAlive);
-                  clientChannel.socket().setTcpNoDelay(useTCPNoDelay);
+                  clientChannel.socket().setKeepAlive(
+                      currentConfig.isUseTCPKeepAlive());
+                  clientChannel.socket().setTcpNoDelay(
+                      currentConfig.isUseTCPNoDelay());
 
                   try
                   {
@@ -1510,69 +966,61 @@
                   }
 
 
-                  // Check to see if the core server rejected the connection
-                  // (e.g., already too many connections established).
-                  if (clientConnection.getConnectionID() < 0)
-                  {
+                  // Check to see if the core server rejected the
+                  // connection (e.g., already too many connections
+                  // established).
+                  if (clientConnection.getConnectionID() < 0) {
                     // The connection will have already been closed.
                     iterator.remove();
                     continue;
                   }
 
-                  // If we've gotten here, then we'll take the connection so
-                  // invoke the post-connect plugins and register the client
-                  // connection with a request handler.
-                  try
-                  {
-                    PluginConfigManager pluginManager =
-                         DirectoryServer.getPluginConfigManager();
-                    PostConnectPluginResult pluginResult =
-                         pluginManager.invokePostConnectPlugins(
-                              clientConnection);
-                    if (pluginResult.connectionTerminated())
-                    {
+                  // If we've gotten here, then we'll take the
+                  // connection so invoke the post-connect plugins and
+                  // register the client connection with a request
+                  // handler.
+                  try {
+                    PluginConfigManager pluginManager = DirectoryServer
+                        .getPluginConfigManager();
+                    PostConnectPluginResult pluginResult = pluginManager
+                        .invokePostConnectPlugins(clientConnection);
+                    if (pluginResult.connectionTerminated()) {
                       iterator.remove();
                       continue;
                     }
 
                     LDAPRequestHandler requestHandler =
-                         requestHandlers[requestHandlerIndex++];
-                    if (requestHandlerIndex >= numRequestHandlers)
-                    {
+                      requestHandlers[requestHandlerIndex++];
+                    if (requestHandlerIndex >= numRequestHandlers) {
                       requestHandlerIndex = 0;
                     }
 
-                    if (requestHandler.registerClient(clientConnection))
-                    {
+                    if (requestHandler
+                        .registerClient(clientConnection)) {
                       logConnect(clientConnection);
-                    }
-                    else
-                    {
+                    } else {
                       iterator.remove();
                       continue;
                     }
-                  }
-                  catch (Exception e)
-                  {
+                  } catch (Exception e) {
                     if (debugEnabled())
                     {
                       debugCaught(DebugLogLevel.ERROR, e);
                     }
 
                     int msgID =
-                             MSGID_LDAP_CONNHANDLER_UNABLE_TO_REGISTER_CLIENT;
-                    String message =
-                                getMessage(msgID,
-                                           clientConnection.getClientHostPort(),
-                                           clientConnection.getServerHostPort(),
-                                           stackTraceToSingleLineString(e));
+                      MSGID_LDAP_CONNHANDLER_UNABLE_TO_REGISTER_CLIENT;
+                    String message = getMessage(msgID,
+                        clientConnection.getClientHostPort(),
+                        clientConnection.getServerHostPort(),
+                        stackTraceToSingleLineString(e));
 
                     logError(ErrorLogCategory.CONNECTION_HANDLING,
-                             ErrorLogSeverity.SEVERE_ERROR, message, msgID);
+                        ErrorLogSeverity.SEVERE_ERROR, message, msgID);
 
-                    clientConnection.disconnect(DisconnectReason.SERVER_ERROR,
-                                                sendRejectionNotice, message,
-                                                msgID);
+                    clientConnection.disconnect(
+                        DisconnectReason.SERVER_ERROR, currentConfig
+                            .isSendRejectionNotice(), message, msgID);
 
                     iterator.remove();
                     continue;
@@ -1581,89 +1029,83 @@
 
                 iterator.remove();
               }
-            }
-            else
-            {
-              if (shutdownRequested)
-              {
+            } else {
+              if (shutdownRequested) {
                 cleanUpSelector();
                 listening = false;
-                enabled   = false;
+                enabled = false;
                 continue;
               }
             }
 
             lastIterationFailed = false;
-          }
-          catch (Exception e)
-          {
+          } catch (Exception e) {
             if (debugEnabled())
             {
               debugCaught(DebugLogLevel.ERROR, e);
             }
 
             logError(ErrorLogCategory.CONNECTION_HANDLING,
-                     ErrorLogSeverity.SEVERE_WARNING,
-                     MSGID_LDAP_CONNHANDLER_CANNOT_ACCEPT_CONNECTION,
-                     configEntryDN, stackTraceToSingleLineString(e));
+                ErrorLogSeverity.SEVERE_WARNING,
+                MSGID_LDAP_CONNHANDLER_CANNOT_ACCEPT_CONNECTION,
+                currentConfig.dn(), stackTraceToSingleLineString(e));
 
-            if (lastIterationFailed)
-            {
-              // The last time through the accept loop we also encountered a
-              // failure.  Rather than enter a potential infinite loop of
-              // failures, disable this acceptor and log an error.
+            if (lastIterationFailed) {
+              // The last time through the accept loop we also
+              // encountered a failure. Rather than enter a potential
+              // infinite loop of failures, disable this acceptor and
+              // log an error.
               int msgID = MSGID_LDAP_CONNHANDLER_CONSECUTIVE_ACCEPT_FAILURES;
-              String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                          stackTraceToSingleLineString(e));
+              String message = getMessage(msgID, String
+                  .valueOf(currentConfig.dn()),
+                  stackTraceToSingleLineString(e));
 
               logError(ErrorLogCategory.CONNECTION_HANDLING,
-                       ErrorLogSeverity.FATAL_ERROR, message, msgID);
+                  ErrorLogSeverity.FATAL_ERROR, message, msgID);
 
-              DirectoryServer.sendAlertNotification(this,
-                   ALERT_TYPE_LDAP_CONNECTION_HANDLER_CONSECUTIVE_FAILURES,
-                   msgID, message);
+              DirectoryServer
+                  .sendAlertNotification(
+                      this,
+                      ALERT_TYPE_LDAP_CONNECTION_HANDLER_CONSECUTIVE_FAILURES,
+                      msgID, message);
 
               enabled = false;
 
-              try
-              {
+              try {
                 cleanUpSelector();
+              } catch (Exception e2) {
               }
-              catch (Exception e2)
-              {
-              }
-            }
-            else
-            {
+            } else {
               lastIterationFailed = true;
             }
           }
         }
-      }
-      catch (Exception e)
-      {
+      } catch (Exception e) {
         if (debugEnabled())
         {
           debugCaught(DebugLogLevel.ERROR, e);
         }
 
-        // This is very bad because we failed outside the loop.  The only
-        // thing we can do here is log a message, send an alert, and disable the
-        // selector until an administrator can figure out what's going on.
+        // This is very bad because we failed outside the loop. The
+        // only thing we can do here is log a message, send an alert,
+        // and disable the selector until an administrator can figure
+        // out what's going on.
         int msgID = MSGID_LDAP_CONNHANDLER_UNCAUGHT_ERROR;
-        String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                    stackTraceToSingleLineString(e));
+        String message = getMessage(msgID, String
+            .valueOf(currentConfig.dn()),
+            stackTraceToSingleLineString(e));
 
         logError(ErrorLogCategory.CONNECTION_HANDLING,
-                 ErrorLogSeverity.SEVERE_ERROR, message, msgID);
+            ErrorLogSeverity.SEVERE_ERROR, message, msgID);
 
         DirectoryServer.sendAlertNotification(this,
-             ALERT_TYPE_LDAP_CONNECTION_HANDLER_UNCAUGHT_ERROR, msgID, message);
+            ALERT_TYPE_LDAP_CONNECTION_HANDLER_UNCAUGHT_ERROR, msgID,
+            message);
 
-        try
-        {
+        try {
           cleanUpSelector();
-        } catch (Exception e2) {}
+        } catch (Exception e2) {
+        }
 
         enabled = false;
       }
@@ -1673,2151 +1115,66 @@
 
 
   /**
-   * Cleans up the contents of the selector, closing any server socket channels
-   * that might be associated with it.  Any connections that might have been
-   * established through those channels should not be impacted.
+   * Appends a string representation of this connection handler to the
+   * provided buffer.
+   *
+   * @param buffer
+   *          The buffer to which the information should be appended.
    */
-  private void cleanUpSelector()
-  {
-    try
-    {
-      Iterator<SelectionKey> iterator = selector.keys().iterator();
-      while (iterator.hasNext())
-      {
-        SelectionKey key = iterator.next();
-
-        try
-        {
-          key.cancel();
-        }
-        catch (Exception e)
-        {
-          if (debugEnabled())
-          {
-            debugCaught(DebugLogLevel.ERROR, e);
-          }
-        }
-
-        try
-        {
-          key.channel().close();
-        }
-        catch (Exception e)
-        {
-          if (debugEnabled())
-          {
-            debugCaught(DebugLogLevel.ERROR, e);
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-    }
-  }
-
-
-
-  /**
-   * Indicates whether this connection handler should maintain usage statistics.
-   *
-   * @return  <CODE>true</CODE> if this connection handler should maintain usage
-   *          statistics, or <CODE>false</CODE> if not.
-   */
-  public boolean keepStats()
-  {
-    return keepStats;
-  }
-
-
-
-  /**
-   * Specifies whether this connection handler should maintain usage statistics.
-   *
-   * @param  keepStats  Specifies whether this connection handler should
-   *                    maintain usage statistics.
-   */
-  public void setKeepStats(boolean keepStats)
-  {
-    this.keepStats = keepStats;
-  }
-
-
-
-  /**
-   * Retrieves the set of statistics maintained by this connection handler.
-   *
-   * @return  The set of statistics maintained by this connection handler.
-   */
-  public LDAPStatistics getStatTracker()
-  {
-    return statTracker;
-  }
-
-
-
-  /**
-   * Indicates whether this connection handler should allow interaction with
-   * LDAPv2 clients.
-   *
-   * @return  <CODE>true</CODE> if LDAPv2 is allowed, or <CODE>false</CODE> if
-   *          not.
-   */
-  public boolean allowLDAPv2()
-  {
-    return allowLDAPv2;
-  }
-
-
-
-  /**
-   * Indicates whether this connection handler should allow the use of the
-   * StartTLS extended operation.
-   *
-   * @return  <CODE>true</CODE> if StartTLS is allowed, or <CODE>false</CODE> if
-   *          not.
-   */
-  public boolean allowStartTLS()
-  {
-    return allowStartTLS;
-  }
-
-
-
-  /**
-   * Indicates whether this connection handler should use SSL to communicate
-   * with clients.
-   *
-   * @return  {@code true} if this connection handler should use SSL to
-   *          communicate with clients, or {@code false} if not.
-   */
-  public boolean useSSL()
-  {
-    return useSSL;
-  }
-
-
-
-  /**
-   * Retrieves the SSL client authentication policy for this connection handler.
-   *
-   * @return  The SSL client authentication policy for this connection handler.
-   */
-  public SSLClientAuthPolicy getSSLClientAuthPolicy()
-  {
-    return sslClientAuthPolicy;
-  }
-
-
-
-  /**
-   * Retrieves the set of enabled SSL protocols configured for this connection
-   * handler.
-   *
-   * @return  The set of enabled SSL protocols configured for this connection
-   *          handler.
-   */
-  public String[] getEnabledSSLProtocols()
-  {
-    return enabledSSLProtocols;
-  }
-
-
-
-  /**
-   * Retrieves the set of enabled SSL cipher suites configured for this
-   * connection handler.
-   *
-   * @return  The set of enabled SSL cipher suites configured for this
-   *          connection handler.
-   */
-  public String[] getEnabledSSLCipherSuites()
-  {
-    return enabledSSLCipherSuites;
-  }
-
-
-
-  /**
-   * Retrieves the DN of the key manager provider that should be used for
-   * operations associated with this connection handler which need access to a
-   * key manager.
-   *
-   * @return  The DN of the key manager provider that should be used for
-   *          operations associated with this connection handler which need
-   *          access to a key manager, or {@code null} if no key manager
-   *          provider has been configured for this connection handler.
-   */
-  public DN getKeyManagerProviderDN()
-  {
-    return keyManagerProviderDN;
-  }
-
-
-
-  /**
-   * Retrieves the DN of the trust manager provider that should be used for
-   * operations associated with this connection handler which need access to a
-   * trust manager.
-   *
-   * @return  The DN of the trust manager provider that should be used for
-   *          operations associated with this connection handler which need
-   *          access to a trust manager, or {@code null} if no trust manager
-   *          provider has been configured for this connection handler.
-   */
-  public DN getTrustManagerProviderDN()
-  {
-    return trustManagerProviderDN;
-  }
-
-
-
-  /**
-   * Retrieves the nickname of the server certificate that should be used in
-   * conjunction with this LDAP connection handler.
-   *
-   * @return  The nickname of the server certificate that should be used in
-   *          conjunction with this LDAP connection handler.
-   */
-  public String getSSLServerCertNickname()
-  {
-    return sslServerCertNickname;
-  }
-
-
-
-  /**
-   * Retrieves the maximum ASN.1 element value length that will be allowed by
-   * this connection handler.
-   *
-   * @return  The maximum ASN.1 element value length that will be allowed by
-   *          this connection handler.
-   */
-  public int getMaxRequestSize()
-  {
-    return maxRequestSize;
-  }
-
-
-
-  /**
-   * Retrieves the human-readable name for this shutdown listener.
-   *
-   * @return  The human-readable name for this shutdown listener.
-   */
-  public String getShutdownListenerName()
-  {
-    return handlerName;
-  }
-
-
-
-  /**
-   * Indicates that the Directory Server has received a request to stop running
-   * and that this shutdown listener should take any action necessary to prepare
-   * for it.
-   *
-   * @param  reason  The human-readable reason for the shutdown.
-   */
-  public void processServerShutdown(String reason)
-  {
-    shutdownRequested = true;
-
-    try
-    {
-      for (LDAPRequestHandler requestHandler : requestHandlers)
-      {
-        try
-        {
-          requestHandler.processServerShutdown(reason);
-        } catch (Exception e) {}
-      }
-    } catch (Exception e) {}
-  }
-
-
-
-  /**
-   * Retrieves the DN of the configuration entry with which this component is
-   * associated.
-   *
-   * @return  The DN of the configuration entry with which this component is
-   *          associated.
-   */
-  public DN getConfigurableComponentEntryDN()
-  {
-    return configEntryDN;
-  }
-
-
-
-  /**
-   * Retrieves the set of configuration attributes that are associated with this
-   * configurable component.
-   *
-   * @return  The set of configuration attributes that are associated with this
-   *          configurable component.
-   */
-  public List<ConfigAttribute> getConfigurationAttributes()
-  {
-    LinkedList<ConfigAttribute> configAttrs = new LinkedList<ConfigAttribute>();
-
-    int msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_ADDRESS;
-    ArrayList<String> listenAddressStrings =
-         new ArrayList<String>(listenAddresses.size());
-    for (InetAddress a : listenAddresses)
-    {
-      listenAddressStrings.add(a.getHostAddress());
-    }
-    configAttrs.add(new StringConfigAttribute(ATTR_LISTEN_ADDRESS,
-                                              getMessage(msgID), true, true,
-                                              true, listenAddressStrings));
-
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_PORT;
-    configAttrs.add(new IntegerConfigAttribute(ATTR_LISTEN_PORT,
-                                               getMessage(msgID), true, false,
-                                               true, true, 1, true, 65535,
-                                               listenPort));
-
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_BACKLOG;
-    configAttrs.add(new IntegerConfigAttribute(ATTR_ACCEPT_BACKLOG,
-                                               getMessage(msgID), true, false,
-                                               true, true, 1, true,
-                                               Integer.MAX_VALUE, backlog));
-
-
-    if (allowedClients == null)
-    {
-      msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_ALLOWED_CLIENTS;
-      ArrayList<String> allowedMasks = new ArrayList<String>(0);
-      configAttrs.add(new StringConfigAttribute(ATTR_ALLOWED_CLIENT,
-                                                getMessage(msgID), false, true,
-                                                false, allowedMasks));
-    }
-    else
-    {
-      msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_ALLOWED_CLIENTS;
-      ArrayList<String> allowedMasks =
-           new ArrayList<String>(allowedClients.length);
-      for (AddressMask m : allowedClients)
-      {
-        allowedMasks.add(m.toString());
-      }
-      configAttrs.add(new StringConfigAttribute(ATTR_ALLOWED_CLIENT,
-                                                getMessage(msgID), false, true,
-                                                false, allowedMasks));
-    }
-
-
-    if (deniedClients == null)
-    {
-      msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_DENIED_CLIENTS;
-      ArrayList<String> deniedMasks = new ArrayList<String>(0);
-      configAttrs.add(new StringConfigAttribute(ATTR_DENIED_CLIENT,
-                                                getMessage(msgID), false, true,
-                                                false, deniedMasks));
-    }
-    else
-    {
-      msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_DENIED_CLIENTS;
-      ArrayList<String> deniedMasks =
-           new ArrayList<String>(deniedClients.length);
-      for (AddressMask m : deniedClients)
-      {
-        deniedMasks.add(m.toString());
-      }
-      configAttrs.add(new StringConfigAttribute(ATTR_DENIED_CLIENT,
-                                                getMessage(msgID), false, true,
-                                                false, deniedMasks));
-    }
-
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_ALLOW_LDAPV2;
-    configAttrs.add(new BooleanConfigAttribute(ATTR_ALLOW_LDAPV2,
-                                               getMessage(msgID), false,
-                                               allowLDAPv2));
-
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_KEEP_STATS;
-    configAttrs.add(new BooleanConfigAttribute(ATTR_KEEP_LDAP_STATS,
-                                               getMessage(msgID), false,
-                                               keepStats));
-
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_NUM_REQUEST_HANDLERS;
-    configAttrs.add(new IntegerConfigAttribute(ATTR_NUM_REQUEST_HANDLERS,
-                                               getMessage(msgID), true, false,
-                                               true, true, 1, false, 0,
-                                               numRequestHandlers));
-
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SEND_REJECTION_NOTICE;
-    configAttrs.add(new BooleanConfigAttribute(ATTR_SEND_REJECTION_NOTICE,
-                                               getMessage(msgID), false,
-                                               sendRejectionNotice));
-
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_USE_TCP_KEEPALIVE;
-    configAttrs.add(new BooleanConfigAttribute(ATTR_USE_TCP_KEEPALIVE,
-                                               getMessage(msgID), false,
-                                               useKeepAlive));
-
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_USE_TCP_NODELAY;
-    configAttrs.add(new BooleanConfigAttribute(ATTR_USE_TCP_NODELAY,
-                                               getMessage(msgID), false,
-                                               useTCPNoDelay));
-
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_ALLOW_REUSE_ADDRESS;
-    configAttrs.add(new BooleanConfigAttribute(ATTR_ALLOW_REUSE_ADDRESS,
-                                               getMessage(msgID), true,
-                                               allowReuseAddress));
-
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_MAX_REQUEST_SIZE;
-    configAttrs.add(new IntegerWithUnitConfigAttribute(ATTR_MAX_REQUEST_SIZE,
-                                                       getMessage(msgID), false,
-                                                       SIZE_UNITS, true, 0,
-                                                       true,
-                                                       MAX_REQUEST_SIZE_LIMIT,
-                                                       maxRequestSize,
-                                                       SIZE_UNIT_BYTES_FULL));
-
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_USE_SSL;
-    configAttrs.add(new BooleanConfigAttribute(ATTR_USE_SSL, getMessage(msgID),
-                                               true, useSSL));
-
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_ALLOW_STARTTLS;
-    configAttrs.add(new BooleanConfigAttribute(ATTR_ALLOW_STARTTLS,
-                                               getMessage(msgID), false,
-                                               allowStartTLS));
-
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SSL_CLIENT_AUTH_POLICY;
-    HashSet<String> allowedValues = new HashSet<String>(3);
-    allowedValues.add(toLowerCase(SSLClientAuthPolicy.DISABLED.toString()));
-    allowedValues.add(toLowerCase(SSLClientAuthPolicy.OPTIONAL.toString()));
-    allowedValues.add(toLowerCase(SSLClientAuthPolicy.REQUIRED.toString()));
-    configAttrs.add(new MultiChoiceConfigAttribute(ATTR_SSL_CLIENT_AUTH_POLICY,
-                             getMessage(msgID), false, false, true,
-                             allowedValues, sslClientAuthPolicy.toString()));
-
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SSL_CERT_NICKNAME;
-    configAttrs.add(new StringConfigAttribute(ATTR_SSL_CERT_NICKNAME,
-                                              getMessage(msgID), false, false,
-                                              true, sslServerCertNickname));
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SSL_ENABLED_PROTOCOLS;
-    configAttrs.add(new StringConfigAttribute(ATTR_SSL_PROTOCOLS,
-                             getMessage(msgID), false, true, false,
-                             arrayToList(enabledSSLProtocols)));
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SSL_ENABLED_CIPHERS;
-    configAttrs.add(new StringConfigAttribute(ATTR_SSL_CIPHERS,
-                             getMessage(msgID), false, true, false,
-                             arrayToList(enabledSSLCipherSuites)));
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_KEYMANAGER_DN;
-    configAttrs.add(new DNConfigAttribute(ATTR_KEYMANAGER_DN, getMessage(msgID),
-                                          false, false, false,
-                                          keyManagerProviderDN));
-
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_TRUSTMANAGER_DN;
-    configAttrs.add(new DNConfigAttribute(ATTR_TRUSTMANAGER_DN,
-                                          getMessage(msgID), false, false,
-                                          false, trustManagerProviderDN));
-
-
-    return configAttrs;
-  }
-
-
-
-  /**
-   * Indicates whether the provided configuration entry has an acceptable
-   * configuration for this component.  If it does not, then detailed
-   * information about the problem(s) should be added to the provided list.
-   *
-   * @param  configEntry          The configuration entry for which to make the
-   *                              determination.
-   * @param  unacceptableReasons  A list that can be used to hold messages about
-   *                              why the provided entry does not have an
-   *                              acceptable configuration.
-   *
-   * @return  <CODE>true</CODE> if the provided entry has an acceptable
-   *          configuration for this component, or <CODE>false</CODE> if not.
-   */
-  public boolean hasAcceptableConfiguration(ConfigEntry configEntry,
-                                            List<String> unacceptableReasons)
-  {
-    boolean configValid = true;
-
-
-    // Determine the set of addresses on which to listen.  There can be
-    // multiple addresses specified.
-    int msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_ADDRESS;
-    StringConfigAttribute addrStub =
-         new StringConfigAttribute(ATTR_LISTEN_ADDRESS, getMessage(msgID),
-                                   true, true, false);
-    try
-    {
-      StringConfigAttribute addrAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(addrStub);
-      if ((addrAttr == null) || addrAttr.activeValues().isEmpty())
-      {
-        // This is fine -- we'll just listen on all IPv4 addresses.
-      }
-      else
-      {
-        for (String s : addrAttr.activeValues())
-        {
-          try
-          {
-            InetAddress.getByName(s);
-          }
-          catch (UnknownHostException uhe)
-          {
-            if (debugEnabled())
-            {
-              debugCaught(DebugLogLevel.ERROR, uhe);
-            }
-
-            msgID = MSGID_LDAP_CONNHANDLER_UNKNOWN_LISTEN_ADDRESS;
-            unacceptableReasons.add(getMessage(msgID, s,
-                                         stackTraceToSingleLineString(uhe)));
-            configValid = false;
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_LISTEN_ADDRESS;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine the port on which to listen.  There may only be a single port
-    // specified.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_PORT;
-    IntegerConfigAttribute portStub =
-         new IntegerConfigAttribute(ATTR_LISTEN_PORT, getMessage(msgID), true,
-                                    false, false, true, 1, true, 65535);
-    try
-    {
-      IntegerConfigAttribute portAttr =
-           (IntegerConfigAttribute) configEntry.getConfigAttribute(portStub);
-      if (portAttr == null)
-      {
-        msgID = MSGID_LDAP_CONNHANDLER_NO_LISTEN_PORT;
-        unacceptableReasons.add(getMessage(msgID,
-                                           String.valueOf(configEntryDN)));
-        configValid = false;
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_LISTEN_PORT;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine the accept backlog to use.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_BACKLOG;
-    IntegerConfigAttribute backlogStub =
-         new IntegerConfigAttribute(ATTR_ACCEPT_BACKLOG, getMessage(msgID),
-                                    true, false, true, true, 1, true,
-                                    Integer.MAX_VALUE);
-    try
-    {
-      IntegerConfigAttribute backlogAttr =
-           (IntegerConfigAttribute) configEntry.getConfigAttribute(backlogStub);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_BACKLOG;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine the set of allowed clients.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_ALLOWED_CLIENTS;
-    StringConfigAttribute allowedStub =
-         new StringConfigAttribute(ATTR_ALLOWED_CLIENT, getMessage(msgID),
-                                   false, true, false);
-    try
-    {
-      StringConfigAttribute allowedAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(allowedStub);
-      if (allowedAttr != null)
-      {
-        for (String s : allowedAttr.activeValues())
-        {
-          try
-          {
-            AddressMask.decode(s);
-          }
-          catch (ConfigException ce)
-          {
-            if (debugEnabled())
-            {
-              debugCaught(DebugLogLevel.ERROR, ce);
-            }
-
-            msgID = MSGID_LDAP_CONNHANDLER_INVALID_ADDRESS_MASK;
-            unacceptableReasons.add(getMessage(msgID, s, ATTR_ALLOWED_CLIENT,
-                                         String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(ce)));
-            configValid = false;
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_ALLOWED_CLIENTS;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine the set of denied clients.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_DENIED_CLIENTS;
-    StringConfigAttribute deniedStub =
-         new StringConfigAttribute(ATTR_DENIED_CLIENT, getMessage(msgID),
-                                   false, true, false);
-    try
-    {
-      StringConfigAttribute deniedAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(deniedStub);
-      if (deniedAttr != null)
-      {
-        for (String s : deniedAttr.activeValues())
-        {
-          try
-          {
-            AddressMask.decode(s);
-          }
-          catch (ConfigException ce)
-          {
-            if (debugEnabled())
-            {
-              debugCaught(DebugLogLevel.ERROR, ce);
-            }
-
-            msgID = MSGID_LDAP_CONNHANDLER_INVALID_ADDRESS_MASK;
-            unacceptableReasons.add(getMessage(msgID, s, ATTR_DENIED_CLIENT,
-                                         String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(ce)));
-            configValid = false;
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_DENIED_CLIENTS;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine whether to allow LDAPv2 clients.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_ALLOW_LDAPV2;
-    BooleanConfigAttribute allowLDAPv2Stub =
-         new BooleanConfigAttribute(ATTR_ALLOW_LDAPV2, getMessage(msgID),
-                                    false);
-    try
-    {
-      BooleanConfigAttribute allowLDAPv2Attr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(allowLDAPv2Stub);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_ALLOW_LDAPV2;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine whether to keep LDAP statistics.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_KEEP_STATS;
-    BooleanConfigAttribute keepStatsStub =
-         new BooleanConfigAttribute(ATTR_KEEP_LDAP_STATS, getMessage(msgID),
-                                    false);
-    try
-    {
-      BooleanConfigAttribute keepStatsAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(keepStatsStub);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_KEEP_STATS;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine the number of request handlers to maintain.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_NUM_REQUEST_HANDLERS;
-    IntegerConfigAttribute reqHandlerStub =
-         new IntegerConfigAttribute(ATTR_NUM_REQUEST_HANDLERS,
-                                    getMessage(msgID), true, false, true,
-                                    true, 1, false, 0);
-    try
-    {
-      IntegerConfigAttribute reqHandlerAttr =
-           (IntegerConfigAttribute)
-           configEntry.getConfigAttribute(reqHandlerStub);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_NUM_REQUEST_HANDLERS;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine whether to send a notice to clients on rejection.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SEND_REJECTION_NOTICE;
-    BooleanConfigAttribute notifyRejectsStub =
-         new BooleanConfigAttribute(ATTR_SEND_REJECTION_NOTICE,
-                                    getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute notifyRejectsAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(notifyRejectsStub);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_SEND_REJECTION_NOTICE;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine whether to use TCP keepalive.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_USE_TCP_KEEPALIVE;
-    BooleanConfigAttribute keepAliveStub =
-         new BooleanConfigAttribute(ATTR_USE_TCP_KEEPALIVE, getMessage(msgID),
-                                    false);
-    try
-    {
-      BooleanConfigAttribute keepAliveAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(keepAliveStub);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_USE_TCP_KEEPALIVE;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine whether to use TCP nodelay.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_USE_TCP_NODELAY;
-    BooleanConfigAttribute noDelayStub =
-         new BooleanConfigAttribute(ATTR_USE_TCP_NODELAY, getMessage(msgID),
-                                    false);
-    try
-    {
-      BooleanConfigAttribute noDelayAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(noDelayStub);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_USE_TCP_NODELAY;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine whether to allow reuse of address/port combinations.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_ALLOW_REUSE_ADDRESS;
-    BooleanConfigAttribute reuseAddrStub =
-         new BooleanConfigAttribute(ATTR_ALLOW_REUSE_ADDRESS,
-                                    getMessage(msgID), true);
-    try
-    {
-      BooleanConfigAttribute reuseAddrAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(reuseAddrStub);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_ALLOW_REUSE_ADDRESS;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine the maximum allowed request size.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_MAX_REQUEST_SIZE;
-    IntegerWithUnitConfigAttribute maxReqSizeStub =
-         new IntegerWithUnitConfigAttribute(ATTR_MAX_REQUEST_SIZE,
-                                            getMessage(msgID), false,
-                                            SIZE_UNITS, true, 0, true,
-                                            MAX_REQUEST_SIZE_LIMIT);
-    try
-    {
-      IntegerWithUnitConfigAttribute maxReqSizeAttr =
-           (IntegerWithUnitConfigAttribute)
-           configEntry.getConfigAttribute(maxReqSizeStub);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_MAX_REQUEST_SIZE;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine whether to use SSL.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_USE_SSL;
-    boolean tmpUseSSL;
-    BooleanConfigAttribute useSSLStub =
-         new BooleanConfigAttribute(ATTR_USE_SSL, getMessage(msgID), true);
-    try
-    {
-      BooleanConfigAttribute useSSLAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(useSSLStub);
-      if (useSSLAttr == null)
-      {
-        tmpUseSSL = DEFAULT_USE_SSL;
-      }
-      else
-      {
-        tmpUseSSL = useSSLAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_USE_SSL;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-      tmpUseSSL   = DEFAULT_USE_SSL;
-    }
-
-
-    // Determine whether to allow the StartTLS extended operation.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_ALLOW_STARTTLS;
-    BooleanConfigAttribute startTLSStub =
-         new BooleanConfigAttribute(ATTR_ALLOW_STARTTLS, getMessage(msgID),
-                                    false);
-    try
-    {
-      BooleanConfigAttribute startTLSAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(startTLSStub);
-      boolean tmpAllowStartTLS;
-      if (startTLSAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-        tmpAllowStartTLS = DEFAULT_ALLOW_STARTTLS;
-      }
-      else
-      {
-        tmpAllowStartTLS = startTLSAttr.activeValue();
-      }
-
-
-      // See if both SSL and startTLS are configured.  If so, we'll have to
-      // disable startTLS because they can't both be used concurrently.
-      if (tmpUseSSL && tmpAllowStartTLS)
-      {
-        msgID = MSGID_LDAP_CONNHANDLER_CANNOT_HAVE_SSL_AND_STARTTLS;
-        unacceptableReasons.add(getMessage(msgID,
-                                           String.valueOf(configEntryDN)));
-        configValid = false;
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_ALLOW_STARTTLS;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine how to handle SSL client authentication.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SSL_CLIENT_AUTH_POLICY;
-    HashSet<String> allowedValues = new HashSet<String>(3);
-    allowedValues.add(toLowerCase(SSLClientAuthPolicy.DISABLED.toString()));
-    allowedValues.add(toLowerCase(SSLClientAuthPolicy.OPTIONAL.toString()));
-    allowedValues.add(toLowerCase(SSLClientAuthPolicy.REQUIRED.toString()));
-    MultiChoiceConfigAttribute sslAuthPolicyStub =
-         new MultiChoiceConfigAttribute(ATTR_SSL_CLIENT_AUTH_POLICY,
-                                        getMessage(msgID), false, false, true,
-                                        allowedValues);
-    try
-    {
-      MultiChoiceConfigAttribute sslAuthPolicyAttr =
-           (MultiChoiceConfigAttribute)
-           configEntry.getConfigAttribute(sslAuthPolicyStub);
-      if (sslAuthPolicyAttr == null)
-      {
-        // This is fine -- We'll just use the default.
-      }
-      else
-      {
-        SSLClientAuthPolicy tmpPolicy = SSLClientAuthPolicy.policyForName(
-                                             sslAuthPolicyAttr.activeValue());
-        if (tmpPolicy == null)
-        {
-          msgID = MSGID_LDAP_CONNHANDLER_INVALID_SSL_CLIENT_AUTH_POLICY;
-          unacceptableReasons.add(getMessage(msgID,
-                                             sslAuthPolicyAttr.activeValue(),
-                                             String.valueOf(configEntryDN)));
-          configValid = false;
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_SSL_CLIENT_AUTH_POLICY;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine which SSL certificate to use.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SSL_CERT_NICKNAME;
-    StringConfigAttribute certNameStub =
-         new StringConfigAttribute(ATTR_SSL_CERT_NICKNAME, getMessage(msgID),
-                                   false, false, true);
-    try
-    {
-      StringConfigAttribute certNameAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(certNameStub);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_SSL_CERT_NICKNAME;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine the set of SSL protocols to allow.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SSL_ENABLED_PROTOCOLS;
-    StringConfigAttribute sslProtocolsStub =
-         new StringConfigAttribute(ATTR_SSL_PROTOCOLS, getMessage(msgID),
-                                   false, true, false);
-    try
-    {
-      StringConfigAttribute sslProtocolsAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(sslProtocolsStub);
-      // FIXME -- Is there a good way to determine the set of supported
-      //          protocols to validate what the user has provided?
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_SSL_PROTOCOLS;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine the set of SSL cipher suites to allow.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SSL_ENABLED_CIPHERS;
-    StringConfigAttribute sslCiphersStub =
-         new StringConfigAttribute(ATTR_SSL_CIPHERS, getMessage(msgID),
-                                   false, true, false);
-    try
-    {
-      StringConfigAttribute sslCiphersAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(sslCiphersStub);
-      // FIXME -- Is there a good way to determine the set of supported cipher
-      //          suites to validate what the user has provided?
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_SSL_CIPHERS;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         stackTraceToSingleLineString(e)));
-      configValid = false;
-    }
-
-
-    // Determine the key manager provider to use.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_KEYMANAGER_DN;
-    DNConfigAttribute keyManagerStub =
-         new DNConfigAttribute(ATTR_KEYMANAGER_DN, getMessage(msgID), false,
-                               false, false);
-    try
-    {
-      DNConfigAttribute keyManagerAttr =
-           (DNConfigAttribute) configEntry.getConfigAttribute(keyManagerStub);
-      if (keyManagerAttr != null)
-      {
-        DN keyManagerProviderDN = keyManagerAttr.activeValue();
-        KeyManagerProvider provider =
-             DirectoryServer.getKeyManagerProvider(keyManagerProviderDN);
-        if (provider == null)
-        {
-          msgID = MSGID_LDAP_CONNHANDLER_INVALID_KEYMANAGER_DN;
-          String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                      String.valueOf(keyManagerProviderDN));
-          unacceptableReasons.add(message);
-          configValid = false;
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_KEYMANAGER_DN;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      unacceptableReasons.add(message);
-      configValid = false;
-    }
-
-
-    // Determine the trust manager provider to use.
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_TRUSTMANAGER_DN;
-    DNConfigAttribute trustManagerStub =
-         new DNConfigAttribute(ATTR_TRUSTMANAGER_DN, getMessage(msgID), false,
-                               false, false);
-    try
-    {
-      DNConfigAttribute trustManagerAttr =
-           (DNConfigAttribute) configEntry.getConfigAttribute(trustManagerStub);
-      if (trustManagerAttr != null)
-      {
-        DN trustManagerProviderDN = trustManagerAttr.activeValue();
-        TrustManagerProvider provider =
-             DirectoryServer.getTrustManagerProvider(trustManagerProviderDN);
-        if (provider == null)
-        {
-          msgID = MSGID_LDAP_CONNHANDLER_INVALID_TRUSTMANAGER_DN;
-          String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                      String.valueOf(trustManagerProviderDN));
-          unacceptableReasons.add(message);
-          configValid = false;
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_TRUSTMANAGER_DN;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  stackTraceToSingleLineString(e));
-      unacceptableReasons.add(message);
-      configValid = false;
-    }
-
-
-    return configValid;
-  }
-
-
-
-  /**
-   * Makes a best-effort attempt to apply the configuration contained in the
-   * provided entry.  Information about the result of this processing should be
-   * added to the provided message list.  Information should always be added to
-   * this list if a configuration change could not be applied.  If detailed
-   * results are requested, then information about the changes applied
-   * successfully (and optionally about parameters that were not changed) should
-   * also be included.
-   *
-   * @param  configEntry      The entry containing the new configuration to
-   *                          apply for this component.
-   * @param  detailedResults  Indicates whether detailed information about the
-   *                          processing should be added to the list.
-   *
-   * @return  Information about the result of the configuration update.
-   */
-  public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry,
-                                                  boolean detailedResults)
-  {
-    // Create variables to include in the response.
-    ResultCode        resultCode          = ResultCode.SUCCESS;
-    boolean           adminActionRequired = false;
-    ArrayList<String> messages            = new ArrayList<String>();
-
-
-    // The set of addresses and the port on which to listen are not dynamically
-    // reconfigurable, so we can skip them.
-
-
-    // The backlog is not dynamically reconfigurable, so we can skip it.
-
-
-    // Determine the set of allowed clients.
-    HashSet<AddressMask> newAllowedClients = null;
-    int msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_ALLOWED_CLIENTS;
-    StringConfigAttribute allowedStub =
-         new StringConfigAttribute(ATTR_ALLOWED_CLIENT, getMessage(msgID),
-                                   false, true, false);
-    try
-    {
-      StringConfigAttribute allowedAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(allowedStub);
-      if (allowedAttr != null)
-      {
-        newAllowedClients = new HashSet<AddressMask>();
-
-        for (String s : allowedAttr.pendingValues())
-        {
-          try
-          {
-            newAllowedClients.add(AddressMask.decode(s));
-          }
-          catch (ConfigException ce)
-          {
-            if (debugEnabled())
-            {
-              debugCaught(DebugLogLevel.ERROR, ce);
-            }
-
-            msgID = MSGID_LDAP_CONNHANDLER_INVALID_ADDRESS_MASK;
-            messages.add(getMessage(msgID, s, ATTR_ALLOWED_CLIENT,
-                                    String.valueOf(configEntryDN),
-                                    stackTraceToSingleLineString(ce)));
-            if (resultCode == ResultCode.SUCCESS)
-            {
-              resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
-            }
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_ALLOWED_CLIENTS;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-    }
-
-    boolean allowedClientsChanged = false;
-    if (resultCode == ResultCode.SUCCESS)
-    {
-      if ((allowedClients == null) || (allowedClients.length == 0))
-      {
-        allowedClientsChanged = (! ((newAllowedClients == null) ||
-                                    newAllowedClients.isEmpty()));
-      }
-      else if ((newAllowedClients == null) || newAllowedClients.isEmpty())
-      {
-        allowedClientsChanged = true;
-      }
-      else if (allowedClients.length != newAllowedClients.size())
-      {
-        allowedClientsChanged = true;
-      }
-      else
-      {
-        for (AddressMask m : allowedClients)
-        {
-          if (! newAllowedClients.contains(m))
-          {
-            allowedClientsChanged = true;
-            break;
-          }
-        }
-      }
-    }
-
-
-    // Determine the set of denied clients.
-    HashSet<AddressMask> newDeniedClients = null;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_DENIED_CLIENTS;
-    StringConfigAttribute deniedStub =
-         new StringConfigAttribute(ATTR_DENIED_CLIENT, getMessage(msgID),
-                                   false, true, false);
-    try
-    {
-      StringConfigAttribute deniedAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(deniedStub);
-      if (deniedAttr != null)
-      {
-        newDeniedClients = new HashSet<AddressMask>();
-
-        for (String s : deniedAttr.pendingValues())
-        {
-          try
-          {
-            newDeniedClients.add(AddressMask.decode(s));
-          }
-          catch (ConfigException ce)
-          {
-            if (debugEnabled())
-            {
-              debugCaught(DebugLogLevel.ERROR, ce);
-            }
-
-            msgID = MSGID_LDAP_CONNHANDLER_INVALID_ADDRESS_MASK;
-            messages.add(getMessage(msgID, s, ATTR_DENIED_CLIENT,
-                                    String.valueOf(configEntryDN),
-                                    stackTraceToSingleLineString(ce)));
-            if (resultCode == ResultCode.SUCCESS)
-            {
-              resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
-            }
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_DENIED_CLIENTS;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-    }
-
-    boolean deniedClientsChanged = false;
-    if (resultCode == ResultCode.SUCCESS)
-    {
-      if ((deniedClients == null) || (deniedClients.length == 0))
-      {
-        deniedClientsChanged = (! ((newDeniedClients == null) ||
-                                    newDeniedClients.isEmpty()));
-      }
-      else if ((newDeniedClients == null) || newDeniedClients.isEmpty())
-      {
-        deniedClientsChanged = true;
-      }
-      else if (deniedClients.length != newDeniedClients.size())
-      {
-        deniedClientsChanged = true;
-      }
-      else
-      {
-        for (AddressMask m : deniedClients)
-        {
-          if (! newDeniedClients.contains(m))
-          {
-            deniedClientsChanged = true;
-            break;
-          }
-        }
-      }
-    }
-
-
-    // Determine whether to allow LDAPv2 clients.
-    boolean newAllowLDAPv2;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_ALLOW_LDAPV2;
-    BooleanConfigAttribute allowLDAPv2Stub =
-         new BooleanConfigAttribute(ATTR_ALLOW_LDAPV2, getMessage(msgID),
-                                    false);
-    try
-    {
-      BooleanConfigAttribute allowLDAPv2Attr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(allowLDAPv2Stub);
-      if (allowLDAPv2Attr == null)
-      {
-        newAllowLDAPv2 = DEFAULT_ALLOW_LDAPV2;
-      }
-      else
-      {
-        newAllowLDAPv2 = allowLDAPv2Attr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_ALLOW_LDAPV2;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-
-      newAllowLDAPv2 = DEFAULT_ALLOW_LDAPV2;
-    }
-
-
-    // Determine whether to keep LDAP statistics.
-    boolean newKeepStats;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_KEEP_STATS;
-    BooleanConfigAttribute keepStatsStub =
-         new BooleanConfigAttribute(ATTR_KEEP_LDAP_STATS, getMessage(msgID),
-                                    false);
-    try
-    {
-      BooleanConfigAttribute keepStatsAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(keepStatsStub);
-      if (keepStatsAttr == null)
-      {
-        newKeepStats = DEFAULT_KEEP_LDAP_STATS;
-      }
-      else
-      {
-        newKeepStats = keepStatsAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_KEEP_STATS;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-
-      newKeepStats = DEFAULT_KEEP_LDAP_STATS;
-    }
-
-
-    // The number of request handlers to maintain is not dynamically
-    // reconfigurable, so we can skip it.
-
-
-    // Determine whether to send a notice to clients on rejection.
-    boolean newSendRejectionNotice;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SEND_REJECTION_NOTICE;
-    BooleanConfigAttribute notifyRejectsStub =
-         new BooleanConfigAttribute(ATTR_SEND_REJECTION_NOTICE,
-                                    getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute notifyRejectsAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(notifyRejectsStub);
-      if (notifyRejectsAttr == null)
-      {
-        newSendRejectionNotice = DEFAULT_SEND_REJECTION_NOTICE;
-      }
-      else
-      {
-        newSendRejectionNotice = notifyRejectsAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_SEND_REJECTION_NOTICE;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-
-      newSendRejectionNotice = DEFAULT_SEND_REJECTION_NOTICE;
-    }
-
-
-    // Determine whether to use TCP keepalive.
-    boolean newUseKeepAlive;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_USE_TCP_KEEPALIVE;
-    BooleanConfigAttribute keepAliveStub =
-         new BooleanConfigAttribute(ATTR_USE_TCP_KEEPALIVE, getMessage(msgID),
-                                    false);
-    try
-    {
-      BooleanConfigAttribute keepAliveAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(keepAliveStub);
-      if (keepAliveAttr == null)
-      {
-        newUseKeepAlive = DEFAULT_USE_TCP_KEEPALIVE;
-      }
-      else
-      {
-        newUseKeepAlive = keepAliveAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_USE_TCP_KEEPALIVE;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-
-      newUseKeepAlive = DEFAULT_USE_TCP_KEEPALIVE;
-    }
-
-
-    // Determine whether to use TCP nodelay.
-    boolean newUseTCPNoDelay;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_USE_TCP_NODELAY;
-    BooleanConfigAttribute noDelayStub =
-         new BooleanConfigAttribute(ATTR_USE_TCP_NODELAY, getMessage(msgID),
-                                    false);
-    try
-    {
-      BooleanConfigAttribute noDelayAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(noDelayStub);
-      if (noDelayAttr == null)
-      {
-        newUseTCPNoDelay = DEFAULT_USE_TCP_NODELAY;
-      }
-      else
-      {
-        newUseTCPNoDelay = noDelayAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_USE_TCP_NODELAY;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-
-      newUseTCPNoDelay = DEFAULT_USE_TCP_NODELAY;
-    }
-
-
-    // The reuse address option isn't dynamically reconfigurable, so we can skip
-    // it.
-
-
-    // Determine the maximum allowed request size.
-    int newMaxRequestSize;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_MAX_REQUEST_SIZE;
-    IntegerWithUnitConfigAttribute maxReqSizeStub =
-         new IntegerWithUnitConfigAttribute(ATTR_MAX_REQUEST_SIZE,
-                                            getMessage(msgID), false,
-                                            SIZE_UNITS, true, 0, true,
-                                            MAX_REQUEST_SIZE_LIMIT);
-    try
-    {
-      IntegerWithUnitConfigAttribute maxReqSizeAttr =
-           (IntegerWithUnitConfigAttribute)
-           configEntry.getConfigAttribute(maxReqSizeStub);
-      if (maxReqSizeAttr == null)
-      {
-        newMaxRequestSize = DEFAULT_MAX_REQUEST_SIZE;
-      }
-      else
-      {
-        newMaxRequestSize = (int) maxReqSizeAttr.pendingCalculatedValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_MAX_REQUEST_SIZE;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-
-      newMaxRequestSize = DEFAULT_MAX_REQUEST_SIZE;
-    }
-
-
-    // The flag specifying whether to use SSL is not dynamically reconfigurable,
-    // so we can skip it.
-
-
-    // Determine whether to allow the StartTLS extended operation.
-    boolean newAllowStartTLS;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_ALLOW_STARTTLS;
-    BooleanConfigAttribute startTLSStub =
-         new BooleanConfigAttribute(ATTR_ALLOW_STARTTLS, getMessage(msgID),
-                                    false);
-    try
-    {
-      BooleanConfigAttribute startTLSAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(startTLSStub);
-      if (startTLSAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-        newAllowStartTLS = DEFAULT_ALLOW_STARTTLS;
-      }
-      else
-      {
-        newAllowStartTLS = startTLSAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_ALLOW_STARTTLS;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-
-      newAllowStartTLS = DEFAULT_ALLOW_STARTTLS;
-    }
-
-
-    // The SSL client authentication policy and SSL certificate nickname are not
-    // dynamically reconfigurable, so we can skip them.
-
-
-    // Determine the set of SSL protocols to allow.
-    String[] newSSLProtocols;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SSL_ENABLED_PROTOCOLS;
-    StringConfigAttribute sslProtocolsStub =
-         new StringConfigAttribute(ATTR_SSL_PROTOCOLS, getMessage(msgID), false,
-                                   true, false);
-    try
-    {
-      StringConfigAttribute sslProtocolsAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(sslProtocolsStub);
-      if (sslProtocolsAttr == null)
-      {
-        newSSLProtocols = null;
-      }
-      else
-      {
-        // FIXME -- Is there a good way to validate the provided set of values?
-        newSSLProtocols = listToArray(sslProtocolsAttr.pendingValues());
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_SSL_PROTOCOLS;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-
-      newSSLProtocols = null;
-    }
-
-
-
-    // Determine the set of SSL cipher suites to allow.
-    String[] newSSLCiphers;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_SSL_ENABLED_CIPHERS;
-    StringConfigAttribute sslCiphersStub =
-         new StringConfigAttribute(ATTR_SSL_CIPHERS, getMessage(msgID), false,
-                                   true, false);
-    try
-    {
-      StringConfigAttribute sslCiphersAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(sslCiphersStub);
-      if (sslCiphersAttr == null)
-      {
-        newSSLCiphers = null;
-      }
-      else
-      {
-        // FIXME -- Is there a good way to validate the provided set of values?
-        newSSLCiphers = listToArray(sslCiphersAttr.pendingValues());
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_SSL_CIPHERS;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-
-      newSSLCiphers = null;
-    }
-
-
-    // Determine the key manager provider to use.
-    DN newKeyManagerDN = null;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_KEYMANAGER_DN;
-    DNConfigAttribute keyManagerStub =
-         new DNConfigAttribute(ATTR_KEYMANAGER_DN, getMessage(msgID), false,
-                               false, false);
-    try
-    {
-      DNConfigAttribute keyManagerAttr =
-           (DNConfigAttribute) configEntry.getConfigAttribute(keyManagerStub);
-      if (keyManagerAttr != null)
-      {
-        newKeyManagerDN = keyManagerAttr.activeValue();
-        KeyManagerProvider provider =
-             DirectoryServer.getKeyManagerProvider(newKeyManagerDN);
-        if (provider == null)
-        {
-          if (resultCode == ResultCode.SUCCESS)
-          {
-            resultCode = ResultCode.CONSTRAINT_VIOLATION;
-          }
-
-          msgID = MSGID_LDAP_CONNHANDLER_INVALID_KEYMANAGER_DN;
-          messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                  String.valueOf(newKeyManagerDN)));
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = ResultCode.CONSTRAINT_VIOLATION;
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_KEYMANAGER_DN;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-    }
-
-
-    // Determine the trust manager provider to use.
-    DN newTrustManagerDN = null;
-    msgID = MSGID_LDAP_CONNHANDLER_DESCRIPTION_TRUSTMANAGER_DN;
-    DNConfigAttribute trustManagerStub =
-         new DNConfigAttribute(ATTR_TRUSTMANAGER_DN, getMessage(msgID), false,
-                               false, false);
-    try
-    {
-      DNConfigAttribute trustManagerAttr =
-           (DNConfigAttribute) configEntry.getConfigAttribute(trustManagerStub);
-      if (trustManagerAttr != null)
-      {
-        newTrustManagerDN = trustManagerAttr.activeValue();
-        TrustManagerProvider provider =
-             DirectoryServer.getTrustManagerProvider(newTrustManagerDN);
-        if (provider == null)
-        {
-          if (resultCode == ResultCode.SUCCESS)
-          {
-            resultCode = ResultCode.CONSTRAINT_VIOLATION;
-          }
-
-          msgID = MSGID_LDAP_CONNHANDLER_INVALID_TRUSTMANAGER_DN;
-          messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                  String.valueOf(newTrustManagerDN)));
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = ResultCode.CONSTRAINT_VIOLATION;
-      }
-
-      msgID = MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_TRUSTMANAGER_DN;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              stackTraceToSingleLineString(e)));
-    }
-
-
-    // If the provided configuration is acceptable, then apply it.
-    if (resultCode == ResultCode.SUCCESS)
-    {
-      if (allowedClientsChanged)
-      {
-        AddressMask[] newAllowedArray;
-        if ((newAllowedClients == null) || newAllowedClients.isEmpty())
-        {
-          newAllowedArray = null;
-        }
-        else
-        {
-          newAllowedArray = new AddressMask[newAllowedClients.size()];
-          newAllowedClients.toArray(newAllowedArray);
-        }
-
-        allowedClients = newAllowedArray;
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_LDAP_CONNHANDLER_NEW_ALLOWED_CLIENTS,
-                                  String.valueOf(configEntryDN)));
-        }
-      }
-
-
-      if (deniedClientsChanged)
-      {
-        AddressMask[] newDeniedArray;
-        if ((newDeniedClients == null) || newDeniedClients.isEmpty())
-        {
-          newDeniedArray = null;
-        }
-        else
-        {
-          newDeniedArray = new AddressMask[newDeniedClients.size()];
-          newDeniedClients.toArray(newDeniedArray);
-        }
-
-        deniedClients = newDeniedArray;
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_LDAP_CONNHANDLER_NEW_DENIED_CLIENTS,
-                                  String.valueOf(configEntryDN)));
-        }
-      }
-
-
-      if (allowLDAPv2 != newAllowLDAPv2)
-      {
-        allowLDAPv2 = newAllowLDAPv2;
-        if (allowLDAPv2)
-        {
-          if (statTracker == null)
-          {
-            statTracker = new LDAPStatistics(handlerName + " Statistics");
-          }
-          else
-          {
-            statTracker.clearStatistics();
-          }
-        }
-
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_LDAP_CONNHANDLER_NEW_ALLOW_LDAPV2,
-                                  String.valueOf(newAllowLDAPv2),
-                                  String.valueOf(configEntryDN)));
-        }
-      }
-
-
-      if (keepStats != newKeepStats)
-      {
-        keepStats = newKeepStats;
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_LDAP_CONNHANDLER_NEW_KEEP_STATS,
-                                  String.valueOf(newKeepStats),
-                                  String.valueOf(configEntryDN)));
-        }
-      }
-
-
-      if (sendRejectionNotice != newSendRejectionNotice)
-      {
-        sendRejectionNotice = newSendRejectionNotice;
-        if (detailedResults)
-        {
-          messages.add(getMessage(
-                            MSGID_LDAP_CONNHANDLER_NEW_SEND_REJECTION_NOTICE,
-                            String.valueOf(newSendRejectionNotice),
-                            String.valueOf(configEntryDN)));
-        }
-      }
-
-
-      if (useKeepAlive != newUseKeepAlive)
-      {
-        useKeepAlive = newUseKeepAlive;
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_LDAP_CONNHANDLER_NEW_USE_KEEPALIVE,
-                                  String.valueOf(newUseKeepAlive),
-                                  String.valueOf(configEntryDN)));
-        }
-      }
-
-
-      if (useTCPNoDelay != newUseTCPNoDelay)
-      {
-        useTCPNoDelay = newUseTCPNoDelay;
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_LDAP_CONNHANDLER_NEW_USE_TCP_NODELAY,
-                                  String.valueOf(newUseTCPNoDelay),
-                                  String.valueOf(configEntryDN)));
-        }
-      }
-
-
-      if (maxRequestSize != newMaxRequestSize)
-      {
-        maxRequestSize = newMaxRequestSize;
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_LDAP_CONNHANDLER_NEW_MAX_REQUEST_SIZE,
-                                  String.valueOf(newMaxRequestSize),
-                                  String.valueOf(configEntryDN)));
-        }
-      }
-
-
-      if (allowStartTLS != newAllowStartTLS)
-      {
-        allowStartTLS = newAllowStartTLS;
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_LDAP_CONNHANDLER_NEW_ALLOW_STARTTLS,
-                                  String.valueOf(newAllowStartTLS),
-                                  String.valueOf(configEntryDN)));
-        }
-      }
-
-
-      // Update enabled SSL protocols.
-      if (! Arrays.equals(enabledSSLProtocols, newSSLProtocols))
-      {
-        enabledSSLProtocols = newSSLProtocols;
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_LDAP_CONNHANDLER_NEW_SSL_PROTOCOLS,
-                                  Arrays.toString(newSSLProtocols),
-                                  String.valueOf(configEntryDN)));
-        }
-      }
-
-
-      // Update enabled SSL cipher suites.
-      if (! Arrays.equals(enabledSSLCipherSuites, newSSLCiphers))
-      {
-        enabledSSLCipherSuites = newSSLCiphers;
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_LDAP_CONNHANDLER_NEW_SSL_CIPHERS,
-                                  Arrays.toString(newSSLCiphers),
-                                  String.valueOf(configEntryDN)));
-        }
-      }
-
-
-      // Update the key manager provider DN.
-      if (keyManagerProviderDN == null)
-      {
-        if (newKeyManagerDN != null)
-        {
-          keyManagerProviderDN = newKeyManagerDN;
-          if (detailedResults)
-          {
-            messages.add(getMessage(MSGID_LDAP_CONNHANDLER_NEW_KEYMANAGER_DN,
-                                    String.valueOf(newKeyManagerDN),
-                                    String.valueOf(configEntryDN)));
-          }
-        }
-      }
-      else if ((newKeyManagerDN == null) ||
-               (! keyManagerProviderDN.equals(newKeyManagerDN)))
-      {
-        keyManagerProviderDN = newKeyManagerDN;
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_LDAP_CONNHANDLER_NEW_KEYMANAGER_DN,
-                                  String.valueOf(newKeyManagerDN),
-                                  String.valueOf(configEntryDN)));
-        }
-      }
-
-
-      // Update the trust manager provider DN.
-      if (trustManagerProviderDN == null)
-      {
-        if (newTrustManagerDN != null)
-        {
-          trustManagerProviderDN = newTrustManagerDN;
-          if (detailedResults)
-          {
-            messages.add(getMessage(MSGID_LDAP_CONNHANDLER_NEW_TRUSTMANAGER_DN,
-                                    String.valueOf(newTrustManagerDN),
-                                    String.valueOf(configEntryDN)));
-          }
-        }
-      }
-      else if ((newTrustManagerDN == null) ||
-               (! trustManagerProviderDN.equals(newTrustManagerDN)))
-      {
-        trustManagerProviderDN = newTrustManagerDN;
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_LDAP_CONNHANDLER_NEW_TRUSTMANAGER_DN,
-                                  String.valueOf(newTrustManagerDN),
-                                  String.valueOf(configEntryDN)));
-        }
-      }
-    }
-
-
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-  }
-
-
-  /**
-   * Appends a string representation of this connection handler to the provided
-   * buffer.
-   *
-   * @param  buffer  The buffer to which the information should be appended.
-   */
-  public void toString(StringBuilder buffer)
-  {
+  public void toString(StringBuilder buffer) {
     buffer.append(handlerName);
   }
 
 
 
   /**
-   * Retrieves the DN of the configuration entry with which this alert generator
-   * is associated.
+   * Indicates whether this connection handler should use SSL to
+   * communicate with clients.
    *
-   * @return  The DN of the configuration entry with which this alert generator
-   *          is associated.
+   * @return {@code true} if this connection handler should use SSL to
+   *         communicate with clients, or {@code false} if not.
    */
-  public DN getComponentEntryDN()
-  {
-    return configEntryDN;
+  public boolean useSSL() {
+    return currentConfig.isUseSSL();
   }
 
 
 
   /**
-   * Retrieves the fully-qualified name of the Java class for this alert
-   * generator implementation.
-   *
-   * @return  The fully-qualified name of the Java class for this alert
-   *          generator implementation.
+   * Cleans up the contents of the selector, closing any server socket
+   * channels that might be associated with it. Any connections that
+   * might have been established through those channels should not be
+   * impacted.
    */
-  public String getClassName()
-  {
-    return CLASS_NAME;
-  }
+  private void cleanUpSelector() {
+    try {
+      Iterator<SelectionKey> iterator = selector.keys().iterator();
+      while (iterator.hasNext()) {
+        SelectionKey key = iterator.next();
 
+        try {
+          key.cancel();
+        } catch (Exception e) {
+          if (debugEnabled())
+          {
+            debugCaught(DebugLogLevel.ERROR, e);
+          }
+        }
 
-
-  /**
-   * Retrieves information about the set of alerts that this generator may
-   * produce.  The map returned should be between the notification type for a
-   * particular notification and the human-readable description for that
-   * notification.  This alert generator must not generate any alerts with types
-   * that are not contained in this list.
-   *
-   * @return  Information about the set of alerts that this generator may
-   *          produce.
-   */
-  public LinkedHashMap<String,String> getAlerts()
-  {
-    LinkedHashMap<String,String> alerts = new LinkedHashMap<String,String>();
-
-    alerts.put(ALERT_TYPE_LDAP_CONNECTION_HANDLER_CONSECUTIVE_FAILURES,
-               ALERT_DESCRIPTION_LDAP_CONNECTION_HANDLER_CONSECUTIVE_FAILURES);
-    alerts.put(ALERT_TYPE_LDAP_CONNECTION_HANDLER_UNCAUGHT_ERROR,
-               ALERT_DESCRIPTION_LDAP_CONNECTION_HANDLER_UNCAUGHT_ERROR);
-
-    return alerts;
+        try {
+          key.channel().close();
+        } catch (Exception e) {
+          if (debugEnabled())
+          {
+            debugCaught(DebugLogLevel.ERROR, e);
+          }
+        }
+      }
+    } catch (Exception e) {
+      if (debugEnabled())
+      {
+        debugCaught(DebugLogLevel.ERROR, e);
+      }
+    }
   }
 }
-

--
Gitblit v1.10.0