mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

neil_a_wilson
21.44.2007 bffaa20d2efe129c2ea4ebdfef7df547978f02a9
opendj-sdk/opends/resource/config/config.ldif
@@ -265,6 +265,18 @@
ds-cfg-task-backing-file: config/tasks.ldif
ds-cfg-task-retention-time: 24 hours
dn: cn=Certificate Mappers,cn=config
objectClass: top
objectClass: ds-cfg-branch
cn: Certificate Mappers
dn: cn=Subject Equals DN,cn=Certificate Mappers,cn=config
objectClass: top
objectClass: ds-cfg-certificate-mapper
cn: Certificate Mapper
ds-cfg-certificate-mapper-class: org.opends.server.extensions.SubjectEqualsDNCertificateMapper
ds-cfg-certificate-mapper-enabled: true
dn: cn=Connection Handlers,cn=config
objectClass: top
objectClass: ds-cfg-branch
@@ -293,6 +305,31 @@
ds-cfg-ssl-client-auth-policy: optional
ds-cfg-ssl-cert-nickname: server-cert
dn: cn=LDAPS Connection Handler,cn=Connection Handlers,cn=config
objectClass: top
objectClass: ds-cfg-connection-handler
objectClass: ds-cfg-ldap-connection-handler
cn: LDAPS Connection Handler
ds-cfg-connection-handler-class: org.opends.server.protocols.ldap.LDAPConnectionHandler
ds-cfg-connection-handler-enabled: false
ds-cfg-listen-address: 0.0.0.0
ds-cfg-listen-port: 636
ds-cfg-accept-backlog: 128
ds-cfg-allow-ldapv2: true
ds-cfg-keep-stats: true
ds-cfg-use-tcp-keepalive: true
ds-cfg-use-tcp-nodelay: true
ds-cfg-allow-tcp-reuse-address: true
ds-cfg-send-rejection-notice: true
ds-cfg-max-request-size: 5 megabytes
ds-cfg-num-request-handlers: 2
ds-cfg-allow-start-tls: false
ds-cfg-use-ssl: true
ds-cfg-ssl-client-auth-policy: optional
ds-cfg-ssl-cert-nickname: server-cert
ds-cfg-key-manager-provider-dn: cn=JKS,cn=Key Manager Providers,cn=config
ds-cfg-trust-manager-provider-dn: cn=JKS,cn=Trust Manager Providers,cn=config
dn: cn=JMX Connection Handler,cn=Connection Handlers,cn=config
objectClass: top
objectClass: ds-cfg-connection-handler
@@ -373,6 +410,42 @@
ds-cfg-identity-mapper-enabled: true
ds-cfg-match-attribute: uid
dn: cn=Key Manager Providers,cn=config
objectClass: top
objectClass: ds-cfg-branch
cn: Key Manager Providers
dn: cn=JKS,cn=Key Manager Providers,cn=config
objectClass: top
objectClass: ds-cfg-key-manager-provider
objectClass: ds-cfg-file-based-key-manager-provider
cn: JKS
ds-cfg-key-manager-provider-class: org.opends.server.extensions.FileBasedKeyManagerProvider
ds-cfg-key-manager-provider-enabled: false
ds-cfg-key-store-type: JKS
ds-cfg-key-store-file: config/keystore
ds-cfg-key-store-pin-file: config/keystore.pin
dn: cn=PKCS12,cn=Key Manager Providers,cn=config
objectClass: top
objectClass: ds-cfg-key-manager-provider
objectClass: ds-cfg-file-based-key-manager-provider
cn: PKCS12
ds-cfg-key-manager-provider-class: org.opends.server.extensions.FileBasedKeyManagerProvider
ds-cfg-key-manager-provider-enabled: false
ds-cfg-key-store-type: PKCS12
ds-cfg-key-store-file: config/keystore.p12
ds-cfg-key-store-pin-file: config/keystore.pin
dn: cn=PKCS11,cn=Key Manager Providers,cn=config
objectClass: top
objectClass: ds-cfg-key-manager-provider
objectClass: ds-cfg-pkcs11-key-manager-provider
cn: PKCS11
ds-cfg-key-manager-provider-class: org.opends.server.extensions.PKCS11KeyManagerProvider
ds-cfg-key-manager-provider-enabled: false
ds-cfg-key-store-pin-file: config/keystore.pin
dn: cn=Loggers,cn=config
objectClass: top
objectClass: ds-cfg-branch
@@ -1114,6 +1187,7 @@
ds-cfg-sasl-mechanism-handler-enabled: true
ds-cfg-client-certificate-validation-policy: ifpresent
ds-cfg-certificate-attribute: userCertificate
ds-cfg-certificate-mapper-dn: cn=Subject Equals DN,cn=Certificate Mappers,cn=config
dn: cn=GSSAPI,cn=SASL Mechanisms,cn=config
objectClass: top
@@ -1134,36 +1208,6 @@
ds-cfg-sasl-mechanism-handler-enabled: true
ds-cfg-identity-mapper-dn: cn=Exact Match,cn=Identity Mappers,cn=config
dn: cn=SSL,cn=config
objectClass: top
objectClass: ds-cfg-branch
cn: SSL
dn: cn=Certificate Mapper,cn=SSL,cn=config
objectClass: top
objectClass: ds-cfg-certificate-mapper
cn: Certificate Mapper
ds-cfg-certificate-mapper-class: org.opends.server.extensions.SubjectEqualsDNCertificateMapper
ds-cfg-certificate-mapper-enabled: true
dn: cn=Key Manager Provider,cn=SSL,cn=config
objectClass: top
objectClass: ds-cfg-key-manager-provider
objectClass: ds-cfg-file-based-key-manager-provider
cn: Key Manager Provider
ds-cfg-key-manager-provider-class: org.opends.server.extensions.FileBasedKeyManagerProvider
ds-cfg-key-manager-provider-enabled: false
ds-cfg-key-store-file: config/keystore
dn: cn=Trust Manager Provider,cn=SSL,cn=config
objectClass: top
objectClass: ds-cfg-trust-manager-provider
objectClass: ds-cfg-file-based-trust-manager-provider
cn: Trust Manager Provider
ds-cfg-trust-manager-provider-class: org.opends.server.extensions.FileBasedTrustManagerProvider
ds-cfg-trust-manager-provider-enabled: false
ds-cfg-trust-store-file: config/truststore
dn: cn=Synchronization Providers,cn=config
objectClass: top
objectClass: ds-cfg-branch
@@ -1507,6 +1551,38 @@
ds-cfg-syntax-class: org.opends.server.schema.UUIDSyntax
ds-cfg-syntax-enabled: true
dn: cn=Trust Manager Providers,cn=config
objectClass: top
objectClass: ds-cfg-branch
cn: Trust Manager Providers
dn: cn=Blind Trust,cn=Trust Manager Providers,cn=config
objectClass: top
objectClass: ds-cfg-trust-manager-provider
cn: Blind Trust
ds-cfg-trust-manager-provider-class: org.opends.server.extensions.BlindTrustManagerProvider
ds-cfg-trust-manager-provider-enabled: false
dn: cn=JKS,cn=Trust Manager Providers,cn=config
objectClass: top
objectClass: ds-cfg-trust-manager-provider
objectClass: ds-cfg-file-based-trust-manager-provider
cn: JKS
ds-cfg-trust-manager-provider-class: org.opends.server.extensions.FileBasedTrustManagerProvider
ds-cfg-trust-manager-provider-enabled: false
ds-cfg-trust-store-type: JKS
ds-cfg-trust-store-file: config/truststore
dn: cn=PKCS12,cn=Trust Manager Providers,cn=config
objectClass: top
objectClass: ds-cfg-trust-manager-provider
objectClass: ds-cfg-file-based-trust-manager-provider
cn: PKCS12
ds-cfg-trust-manager-provider-class: org.opends.server.extensions.FileBasedTrustManagerProvider
ds-cfg-trust-manager-provider-enabled: false
ds-cfg-trust-store-type: PKCS12
ds-cfg-trust-store-file: config/truststore
dn: cn=Virtual Attributes,cn=config
objectClass: top
objectClass: ds-cfg-branch
opendj-sdk/opends/resource/schema/02-config.ldif
@@ -1048,6 +1048,15 @@
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.308
  NAME 'ds-cfg-default-root-privilege-name'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.309 NAME 'ds-cfg-certificate-mapper-dn'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.310
  NAME 'ds-cfg-key-manager-provider-dn' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
  SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.311
  NAME 'ds-cfg-trust-manager-provider-dn' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
  SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
  NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL
  MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled )
@@ -1116,7 +1125,8 @@
  ds-cfg-send-rejection-notice $ ds-cfg-max-request-size $
  ds-cfg-num-request-handlers $ ds-cfg-allow-start-tls $ ds-cfg-use-ssl $
  ds-cfg-ssl-client-auth-policy $ ds-cfg-ssl-cert-nickname $
  ds-cfg-accept-backlog ) X-ORIGIN 'OpenDS Directory Server' )
  ds-cfg-accept-backlog $ ds-cfg-key-manager-provider-dn $
  ds-cfg-trust-manager-provider-dn ) X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.15 NAME 'ds-cfg-entry-cache'
  SUP top STRUCTURAL MUST ( cn $ ds-cfg-entry-cache-class $
  ds-cfg-entry-cache-enabled ) X-ORIGIN 'OpenDS Directory Server' )
@@ -1242,7 +1252,8 @@
  ds-cfg-sasl-mechanism-handler-enabled ) X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.44
  NAME 'ds-cfg-external-sasl-mechanism-handler'
  SUP ds-cfg-sasl-mechanism-handler MAY ( ds-cfg-certificate-attribute $
  SUP ds-cfg-sasl-mechanism-handler MUST ds-cfg-certificate-mapper-dn
  MAY ( ds-cfg-certificate-attribute $
  ds-cfg-client-certificate-validation-policy )
  X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.45
opendj-sdk/opends/src/server/org/opends/server/api/ClientConnection.java
@@ -1442,6 +1442,52 @@
  /**
   * Retrieves the DN of the key manager provider that should be used
   * for operations requiring access to a key manager.  The default
   * implementation returns {@code null} to indicate that no key
   * manager provider is avaialble, but subclasses should override
   * this method to return a valid DN if they perform operations which
   * may need access to a key manager.
   *
   * @return  The DN of the key manager provider that should be used
   *          for operations requiring access to a key manager, or
   *          {@code null} if there is no key manager provider
   *          configured for this client connection.
   */
  public DN getKeyManagerProviderDN()
  {
    assert debugEnter(CLASS_NAME, "getKeyManagerProviderDN");
    // In the default implementation, we'll return null.
    return null;
  }
  /**
   * Retrieves the DN of the trust manager provider that should be
   * used for operations requiring access to a trust manager.  The
   * default implementation returns {@code null} to indicate that no
   * trust manager provider is avaialble, but subclasses should
   * override this method to return a valid DN if they perform
   * operations which may need access to a trust manager.
   *
   * @return  The DN of the trust manager provider that should be used
   *          for operations requiring access to a trust manager, or
   *          {@code null} if there is no trust manager provider
   *          configured for this client connection.
   */
  public DN getTrustManagerProviderDN()
  {
    assert debugEnter(CLASS_NAME, "getTrustManagerProviderDN");
    // In the default implementation, we'll return null.
    return null;
  }
  /**
   * Retrieves a string representation of this client connection.
   *
   * @return  A string representation of this client connection.
opendj-sdk/opends/src/server/org/opends/server/config/ConfigConstants.java
@@ -489,6 +489,15 @@
  /**
   * The name of the configuration attribute that holds the DN of a certificate
   * mapper configuration entry.
   */
  public static final String ATTR_CERTMAPPER_DN =
       NAME_PREFIX_CFG + "certificate-mapper-dn";
  /**
   * The name of the configuration attribute that indicates whether the
   * certificate mapper is enabled.
   */
@@ -842,6 +851,15 @@
  /**
   * The name of the configuration attribute that specifies the DN of the
   * configuration entry for the key manager provider.
   */
  public static final String ATTR_KEYMANAGER_DN =
       NAME_PREFIX_CFG + "key-manager-provider-dn";
  /**
   * The name of the configuration attribute that indicates whether the key
   * manager provider should be enabled.
   */
@@ -914,6 +932,15 @@
  /**
   * The name of the configuration attribute that specifies the DN of the
   * configuration entry for the trust manager provider.
   */
  public static final String ATTR_TRUSTMANAGER_DN =
       NAME_PREFIX_CFG + "trust-manager-provider-dn";
  /**
   * The name of the configuration attribute that indicates whether the trust
   * manager provider should be enabled.
   */
@@ -2582,36 +2609,28 @@
  /**
   * The DN of the entry that will be the base of the configuration information
   * for the Directory Server SSL provider.
   * for the Directory Server certificate mappers.
   */
  public static final String DN_SSL_CONFIG_ROOT = "cn=SSL," + DN_CONFIG_ROOT;
  public static final String DN_CERTMAPPER_CONFIG_BASE =
       "cn=Certificate Mappers," + DN_CONFIG_ROOT;
  /**
   * The DN of the entry that will hold the configuration for the Directory
   * Server certificate mapper used for SASL EXTERNAL authentication.
   * The DN of the entry that be the base of the configuration information for
   * the Directory Server key manager providers.
   */
  public static final String DN_CERTMAPPER_CONFIG =
       "cn=Certificate Mapper," + DN_SSL_CONFIG_ROOT;
  public static final String DN_KEYMANAGER_PROVIDER_CONFIG_BASE =
       "cn=Key Manager Providers," + DN_CONFIG_ROOT;
  /**
   * The DN of the entry that will hold the configuration for the Directory
   * Server key manager provider used for SSL communication.
   * The DN of the entry that be the base of the configuration information for
   * the Directory Server trust manager providers.
   */
  public static final String DN_KEYMANAGER_PROVIDER_CONFIG =
       "cn=Key Manager Provider," + DN_SSL_CONFIG_ROOT;
  /**
   * The DN of the entry that will hold the configuration for the Directory
   * Server trust manager provider used for SSL communication.
   */
  public static final String DN_TRUSTMANAGER_PROVIDER_CONFIG =
       "cn=Trust Manager Provider," + DN_SSL_CONFIG_ROOT;
  public static final String DN_TRUSTMANAGER_PROVIDER_CONFIG_BASE =
       "cn=Trust Manager Providers," + DN_CONFIG_ROOT;
@@ -2906,6 +2925,15 @@
  /**
   * The name of the objectclass that will be used for a Directory Server
   * certificate mapper.
   */
  public static final String OC_CERTIFICATE_MAPPER =
       NAME_PREFIX_CFG + "certificate-mapper";
  /**
   * The name of the objectclass that will be used for a Directory Server
   * connection handler.
   */
  public static final String OC_CONNECTION_HANDLER =
@@ -2957,6 +2985,15 @@
  /**
   * The name of the objectclass that will be used for a Directory Server key
   * manager provider.
   */
  public static final String OC_KEY_MANAGER_PROVIDER =
       NAME_PREFIX_CFG + "key-manager-provider";
  /**
   * The name of the objectclass that will be used for a Directory Server
   * matching rules.
   */
@@ -3070,6 +3107,15 @@
  /**
   * The name of the objectclass that will be used for a Directory Server trust
   * manager provider.
   */
  public static final String OC_TRUST_MANAGER_PROVIDER =
       NAME_PREFIX_CFG + "trust-manager-provider";
  /**
   * The name of the operational attribute that will appear in a user's entry to
   * indicate whether the account has been disabled.
   */
opendj-sdk/opends/src/server/org/opends/server/config/JMXMBean.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.config;
@@ -625,7 +625,7 @@
   *                                      associated with this MBean.
   */
  public Attribute getAttribute(String attributeName)
  throws AttributeNotFoundException
         throws AttributeNotFoundException
  {
    assert debugEnter(CLASS_NAME, "getAttribute");
@@ -647,7 +647,13 @@
    }
    catch (LDAPException e)
    {
      throw new AttributeNotFoundException();
      assert debugException(CLASS_NAME, "getAttribute", e);
      int    msgID   = MSGID_CONFIG_JMX_CANNOT_GET_ATTRIBUTE;
      String message = getMessage(msgID, String.valueOf(attributeName),
                                  String.valueOf(configEntryDN),
                                  stackTraceToSingleLineString(e));
      throw new AttributeNotFoundException(message);
    }
    //
@@ -662,7 +668,12 @@
    if (rc != ResultCode.SUCCESS)
    {
      jmxClientConnection = null ;
      throw new AttributeNotFoundException();
      int    msgID   = MSGID_CONFIG_JMX_CANNOT_GET_ATTRIBUTE;
      String message = getMessage(msgID, String.valueOf(attributeName),
                                  String.valueOf(configEntryDN),
                                  String.valueOf(op.getErrorMessage()));
      throw new AttributeNotFoundException(message);
    }
    try
@@ -673,11 +684,14 @@
    {
      assert debugException(CLASS_NAME, "setAttribute", e);
      int    msgID   = MSGID_CONFIG_JMX_ATTR_NO_ATTR;
      String message = getMessage(msgID, String.valueOf(configEntryDN),
                                  attributeName);
      logError(
          ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR,
          MSGID_CONFIG_JMX_ATTR_NO_ATTR, configEntryDN.toString(),
          attributeName);
      throw new AttributeNotFoundException();
          message, msgID);
      throw new AttributeNotFoundException(message);
    }
  }
@@ -712,13 +726,15 @@
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "setAttribute", e);
      int    msgID   = MSGID_CONFIG_JMX_ATTR_NO_ATTR;
      String message = getMessage(msgID, String.valueOf(configEntryDN),
                                  String.valueOf(name));
      logError(
          ErrorLogCategory.CONFIGURATION,
          ErrorLogSeverity.MILD_ERROR,
          MSGID_CONFIG_JMX_ATTR_NO_ATTR,
          configEntryDN.toString(),
          name);
      throw new AttributeNotFoundException();
          ErrorLogSeverity.MILD_ERROR, message, msgID);
      throw new AttributeNotFoundException(message);
    }
    //
@@ -788,13 +804,14 @@
    {
      assert debugException(CLASS_NAME, "setAttribute", e);
      int    msgID   = MSGID_CONFIG_JMX_CANNOT_GET_CONFIG_ENTRY;
      String message = getMessage(msgID, String.valueOf(configEntryDN),
                                  String.valueOf(e));
      logError(
          ErrorLogCategory.CONFIGURATION,
          ErrorLogSeverity.MILD_ERROR,
          MSGID_CONFIG_JMX_CANNOT_GET_CONFIG_ENTRY,
          configEntryDN.toString(),
          String.valueOf(e));
      throw new AttributeNotFoundException();
          ErrorLogSeverity.MILD_ERROR, message, msgID);
      throw new AttributeNotFoundException(message);
    }
    //
@@ -802,7 +819,10 @@
    JmxClientConnection jmxClientConnection = getClientConnection();
    if (jmxClientConnection == null)
    {
      throw new AttributeNotFoundException();
      int    msgID   = MSGID_CONFIG_JMX_SET_ATTR_NO_CONNECTION;
      String message = getMessage(msgID, attribute.getName(),
                                  String.valueOf(configEntry.getDN()));
      throw new AttributeNotFoundException(message);
    }
    //
opendj-sdk/opends/src/server/org/opends/server/core/CertificateMapperConfigManager.java
@@ -22,24 +22,29 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.core;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import org.opends.server.api.CertificateMapper;
import org.opends.server.api.ConfigAddListener;
import org.opends.server.api.ConfigChangeListener;
import org.opends.server.api.ConfigDeleteListener;
import org.opends.server.api.ConfigHandler;
import org.opends.server.api.ConfigurableComponent;
import org.opends.server.config.BooleanConfigAttribute;
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.config.StringConfigAttribute;
import org.opends.server.extensions.SubjectEqualsDNCertificateMapper;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.DN;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
@@ -51,16 +56,17 @@
import static org.opends.server.loggers.Error.*;
import static org.opends.server.messages.ConfigMessages.*;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines a utility that will be used to manage the configuration
 * for the Directory Server certificate mapper.  Only a single certificate
 * mapper may be defined, but if it is absent or disabled, then a default
 * provider will be used that will assume that the certificate subject is equal
 * to the user entry's DN.
 * This class defines a utility that will be used to manage the set of
 * certificate mappers defined in the Directory Server.  It will initialize the
 * certificate mappers when the server starts, and then will manage any
 * additions, removals, or modifications of any certificate mappers while the
 * server is running.
 */
public class CertificateMapperConfigManager
       implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener
@@ -73,251 +79,139 @@
  // A mapping between the DNs of the config entries and the associated
  // certificate mappers.
  private ConcurrentHashMap<DN,CertificateMapper> mappers;
  // The configuration handler for the Directory Server.
  private ConfigHandler configHandler;
  /**
   * Creates a new instance of this certificate mapper provider config manager.
   * Creates a new instance of this certificate mapper config manager.
   */
  public CertificateMapperConfigManager()
  {
    assert debugConstructor(CLASS_NAME);
    // No implementation is required.
    configHandler = DirectoryServer.getConfigHandler();
    mappers       = new ConcurrentHashMap<DN,CertificateMapper>();
  }
  /**
   * Initializes the configuration associated with the Directory Server
   * certificate mapper.  This should only be called at Directory Server
   * startup.  If an error occurs, then a message will be logged and the default
   * certificate mapper will be installed.
   * Initializes all certificate mappers currently defined in the Directory
   * Server configuration.  This should only be called at Directory Server
   * startup.
   *
   * @throws  InitializationException  If a problem occurs while trying to
   *                                   install the default certificate mapper.
   * @throws  ConfigException  If a configuration problem causes the certificate
   *                           mapper initialization process to fail.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   the certificate mappers that is not
   *                                   related to the server configuration.
   */
  public void initializeCertificateMapper()
         throws InitializationException
  public void initializeCertificateMappers()
         throws ConfigException, InitializationException
  {
    assert debugEnter(CLASS_NAME, "initializeCertificateMapper");
    assert debugEnter(CLASS_NAME, "initializeCertificateMappers");
    // First, install the default certificate mapper so that there will be one
    // even if we encounter a problem later.
    // First, get the configuration base entry.
    ConfigEntry baseEntry;
    try
    {
      SubjectEqualsDNCertificateMapper defaultMapper =
           new SubjectEqualsDNCertificateMapper();
      defaultMapper.initializeCertificateMapper(null);
      DirectoryServer.setCertificateMapper(defaultMapper);
      DN certMapperBase = DN.decode(DN_CERTMAPPER_CONFIG_BASE);
      baseEntry = configHandler.getConfigEntry(certMapperBase);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeCertificateMapper", e);
      assert debugException(CLASS_NAME, "initializeCertificateMappers",
                            e);
      int msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_INSTALL_DEFAULT_MAPPER;
      String message = getMessage(msgID, stackTraceToSingleLineString(e));
      throw new InitializationException(msgID, message, e);
      int    msgID   = MSGID_CONFIG_CERTMAPPER_CANNOT_GET_BASE;
      String message = getMessage(msgID, String.valueOf(e));
      throw new ConfigException(msgID, message, e);
    }
    if (baseEntry == null)
    {
      // The certificate mapper base entry does not exist.  This is not
      // acceptable, so throw an exception.
      int    msgID   = MSGID_CONFIG_CERTMAPPER_BASE_DOES_NOT_EXIST;
      String message = getMessage(msgID);
      throw new ConfigException(msgID, message);
    }
    // Get the certificate mapper configuration entry.  If it is not present,
    // then register an add listener and just go with the default mapper.
    DN configEntryDN;
    ConfigEntry configEntry;
    try
    {
      configEntryDN = DN.decode(DN_CERTMAPPER_CONFIG);
      configEntry   = DirectoryServer.getConfigEntry(configEntryDN);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeCertificateMapper", e);
    // Register add and delete listeners with the certificate mapper base entry.
    // We don't care about modifications to it.
    baseEntry.registerAddListener(this);
    baseEntry.registerDeleteListener(this);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CERTMAPPER_CANNOT_GET_CONFIG_ENTRY,
               stackTraceToSingleLineString(e));
    // See if the base entry has any children.  If not, then we don't need to do
    // anything else.
    if (! baseEntry.hasChildren())
    {
      return;
    }
    if (configEntry == null)
    // Iterate through the child entries and process them as certificate mapper
    // configuration entries.
    for (ConfigEntry childEntry : baseEntry.getChildren().values())
    {
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING,
               MSGID_CONFIG_CERTMAPPER_NO_CONFIG_ENTRY);
      childEntry.registerChangeListener(this);
      StringBuilder unacceptableReason = new StringBuilder();
      if (! configAddIsAcceptable(childEntry, unacceptableReason))
      {
        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
                 MSGID_CONFIG_CERTMAPPER_ENTRY_UNACCEPTABLE,
                 childEntry.getDN().toString(), unacceptableReason.toString());
        continue;
      }
      try
      {
        ConfigEntry parentEntry =
             DirectoryServer
            .getConfigEntry(configEntryDN.getParentDNInSuffix());
        if (parentEntry != null)
        ConfigChangeResult result = applyConfigurationAdd(childEntry);
        if (result.getResultCode() != ResultCode.SUCCESS)
        {
          parentEntry.registerAddListener(this);
          StringBuilder buffer = new StringBuilder();
          List<String> resultMessages = result.getMessages();
          if ((resultMessages == null) || (resultMessages.isEmpty()))
          {
            buffer.append(getMessage(MSGID_CONFIG_UNKNOWN_UNACCEPTABLE_REASON));
          }
          else
          {
            Iterator<String> iterator = resultMessages.iterator();
            buffer.append(iterator.next());
            while (iterator.hasNext())
            {
              buffer.append(EOL);
              buffer.append(iterator.next());
            }
          }
          logError(ErrorLogCategory.CONFIGURATION,
                   ErrorLogSeverity.SEVERE_ERROR,
                   MSGID_CONFIG_CERTMAPPER_CANNOT_CREATE_MAPPER,
                   childEntry.getDN().toString(), buffer.toString());
        }
      }
      catch (Exception e)
      {
        assert debugException(CLASS_NAME, "initializeCertificateMapper", e);
        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
                 MSGID_CONFIG_CERTMAPPER_CANNOT_REGISTER_ADD_LISTENER,
                 stackTraceToSingleLineString(e));
      }
      return;
    }
    // At this point, we have a configuration entry.  Register a change listener
    // with it so we can be notified of changes to it over time.  We will also
    // want to register a delete listener with its parent to allow us to
    // determine if the entry is deleted.
    configEntry.registerChangeListener(this);
    try
    {
      DN parentDN = configEntryDN.getParentDNInSuffix();
      ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN);
      if (parentEntry != null)
      {
        parentEntry.registerDeleteListener(this);
                 MSGID_CONFIG_CERTMAPPER_CANNOT_CREATE_MAPPER,
                 childEntry.getDN().toString(), String.valueOf(e));
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeCertificateMapper", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING,
               MSGID_CONFIG_CERTMAPPER_CANNOT_REGISTER_DELETE_LISTENER,
               stackTraceToSingleLineString(e));
    }
    // See if the entry indicates whether the certificate mapper should be
    // enabled.
    int msgID = MSGID_CONFIG_CERTMAPPER_DESCRIPTION_ENABLED;
    BooleanConfigAttribute enabledStub =
         new BooleanConfigAttribute(ATTR_CERTMAPPER_ENABLED, getMessage(msgID),
                                    false);
    try
    {
      BooleanConfigAttribute enabledAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(enabledStub);
      if (enabledAttr == null)
      {
        // The attribute is not present, so the certificate mapper will be
        // disabled.  Log a warning message and return.
        logError(ErrorLogCategory.CONFIGURATION,
                 ErrorLogSeverity.SEVERE_WARNING,
                 MSGID_CONFIG_CERTMAPPER_NO_ENABLED_ATTR);
        return;
      }
      else if (! enabledAttr.activeValue())
      {
        // The certificate mapper is explicitly disabled.  Log a mild warning
        // and return.
        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_WARNING,
                 MSGID_CONFIG_CERTMAPPER_DISABLED);
        return;
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeCertificateMapper", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CERTMAPPER_UNABLE_TO_DETERMINE_ENABLED_STATE,
               stackTraceToSingleLineString(e));
      return;
    }
    // See if it specifies the class name for the certificate mapper
    // implementation.
    String className;
    msgID = MSGID_CONFIG_CERTMAPPER_DESCRIPTION_CLASS;
    StringConfigAttribute classStub =
         new StringConfigAttribute(ATTR_CERTMAPPER_CLASS, getMessage(msgID),
                                   true, false, false);
    try
    {
      StringConfigAttribute classAttr =
           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
      if (classAttr == null)
      {
        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
                 MSGID_CONFIG_CERTMAPPER_NO_CLASS_ATTR);
        return;
      }
      else
      {
        className = classAttr.activeValue();
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeCertificateMapper", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CERTMAPPER_CANNOT_DETERMINE_CLASS,
               stackTraceToSingleLineString(e));
      return;
    }
    // Try to load the class and instantiate it as a certificate mapper.
    Class certificateMapperClass;
    try
    {
      // FIXME -- Should we use a custom class loader for this?
      certificateMapperClass = Class.forName(className);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeCertificateMapper", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CERTMAPPER_CANNOT_LOAD_CLASS,
               String.valueOf(className), stackTraceToSingleLineString(e));
      return;
    }
    CertificateMapper certificateMapper;
    try
    {
      certificateMapper =
           (CertificateMapper) certificateMapperClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeCertificateMapper", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CERTMAPPER_CANNOT_INSTANTIATE_CLASS,
               String.valueOf(className), stackTraceToSingleLineString(e));
      return;
    }
    // Try to initialize the certificate mapper with the contents of the
    // configuration entry.
    try
    {
      certificateMapper.initializeCertificateMapper(configEntry);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeCertificateMapper", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CERTMAPPER_CANNOT_INITIALIZE,
               String.valueOf(className), stackTraceToSingleLineString(e));
      return;
    }
    // Install the new certificate mapper in the server.  We don't need to do
    // anything to get rid of the previous null provider since it doesn't
    // consume any resources.
    DirectoryServer.setCertificateMapper(certificateMapper);
  }
@@ -342,21 +236,97 @@
                      String.valueOf(configEntry), "java.lang.StringBuilder");
    // See if the entry indicates whether the certificate mapper should be
    // enabled.
    int msgID = MSGID_CONFIG_CERTMAPPER_DESCRIPTION_ENABLED;
    BooleanConfigAttribute enabledStub =
         new BooleanConfigAttribute(ATTR_CERTMAPPER_ENABLED, getMessage(msgID),
                                    false);
    // Make sure that the entry has an appropriate objectclass for a certificate
    // mapper.
    if (! configEntry.hasObjectClass(OC_CERTIFICATE_MAPPER))
    {
      int    msgID   = MSGID_CONFIG_CERTMAPPER_INVALID_OBJECTCLASS;
      String message = getMessage(msgID, configEntry.getDN().toString());
      unacceptableReason.append(message);
      return false;
    }
    // Make sure that the entry specifies the mapper class name.
    StringConfigAttribute classNameAttr;
    try
    {
      BooleanConfigAttribute enabledAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(enabledStub);
      StringConfigAttribute classStub =
           new StringConfigAttribute(ATTR_CERTMAPPER_CLASS,
                    getMessage(MSGID_CONFIG_CERTMAPPER_DESCRIPTION_CLASS),
                    true, false, true);
      classNameAttr = (StringConfigAttribute)
                      configEntry.getConfigAttribute(classStub);
      if (classNameAttr == null)
      {
        int    msgID   = MSGID_CONFIG_CERTMAPPER_NO_CLASS_NAME;
        String message = getMessage(msgID, configEntry.getDN().toString());
        unacceptableReason.append(message);
        return false;
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      int    msgID   = MSGID_CONFIG_CERTMAPPER_INVALID_CLASS_NAME;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    Class mapperClass;
    try
    {
      // FIXME -- Should this be done with a custom class loader?
      mapperClass = Class.forName(classNameAttr.pendingValue());
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      int    msgID   = MSGID_CONFIG_CERTMAPPER_INVALID_CLASS_NAME;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    try
    {
      CertificateMapper mapper = (CertificateMapper) mapperClass.newInstance();
    }
    catch(Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      int    msgID   = MSGID_CONFIG_CERTMAPPER_INVALID_CLASS;
      String message = getMessage(msgID, mapperClass.getName(),
                                  String.valueOf(configEntry.getDN()),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    // See if this certificate mapper should be enabled.
    BooleanConfigAttribute enabledAttr;
    try
    {
      BooleanConfigAttribute enabledStub =
           new BooleanConfigAttribute(ATTR_CERTMAPPER_ENABLED,
                    getMessage(MSGID_CONFIG_CERTMAPPER_DESCRIPTION_ENABLED),
                               false);
      enabledAttr = (BooleanConfigAttribute)
                    configEntry.getConfigAttribute(enabledStub);
      if (enabledAttr == null)
      {
        msgID = MSGID_CONFIG_CERTMAPPER_NO_ENABLED_ATTR;
        unacceptableReason.append(getMessage(msgID));
        int    msgID   = MSGID_CONFIG_CERTMAPPER_NO_ENABLED_ATTR;
        String message = getMessage(msgID, configEntry.getDN().toString());
        unacceptableReason.append(message);
        return false;
      }
    }
@@ -364,82 +334,16 @@
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      msgID = MSGID_CONFIG_CERTMAPPER_UNABLE_TO_DETERMINE_ENABLED_STATE;
      unacceptableReason.append(getMessage(msgID,
                                           stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_CERTMAPPER_INVALID_ENABLED_VALUE;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    // See if it specifies the class name for the certificate mapper
    // implementation.
    String className;
    msgID = MSGID_CONFIG_CERTMAPPER_DESCRIPTION_CLASS;
    StringConfigAttribute classStub =
         new StringConfigAttribute(ATTR_CERTMAPPER_CLASS, getMessage(msgID),
                                   true, false, false);
    try
    {
      StringConfigAttribute classAttr =
           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
      if (classAttr == null)
      {
        msgID = MSGID_CONFIG_CERTMAPPER_NO_CLASS_ATTR;
        unacceptableReason.append(getMessage(msgID));
        return false;
      }
      else
      {
        className = classAttr.activeValue();
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_DETERMINE_CLASS;
      unacceptableReason.append(getMessage(msgID,
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    // Try to load the class and instantiate it as a certificate mapper.
    Class certificateMapperClass;
    try
    {
      // FIXME -- Should we use a custom class loader for this?
      certificateMapperClass = Class.forName(className);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_LOAD_CLASS;
      unacceptableReason.append(getMessage(msgID, String.valueOf(className),
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    try
    {
      CertificateMapper certificateMapper =
           (CertificateMapper) certificateMapperClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_INSTANTIATE_CLASS;
      unacceptableReason.append(getMessage(msgID, String.valueOf(className),
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    // If we've gotten to this point, then it is acceptable as far as we are
    // concerned.  If it is unacceptable according to the configuration, then
    // the certificate mapper itself will make that determination.
    // If we've gotten here then the certificate mapper entry appears to be
    // acceptable.
    return true;
  }
@@ -460,72 +364,78 @@
    assert debugEnter(CLASS_NAME, "applyConfigurationChange",
                      String.valueOf(configEntry));
    DN                configEntryDN       = configEntry.getDN();
    ResultCode        resultCode          = ResultCode.SUCCESS;
    boolean           adminActionRequired = false;
    ArrayList<String> messages            = new ArrayList<String>();
    // See if the entry indicates whether the certificate mapper should be
    // enabled.  If not, then make sure that the certificate mapper is disabled
    // and return since we don't need to do anything else.
    boolean needsEnabled          = false;
    String  existingProviderClass = null;
    int msgID = MSGID_CONFIG_CERTMAPPER_DESCRIPTION_ENABLED;
    BooleanConfigAttribute enabledStub =
         new BooleanConfigAttribute(ATTR_CERTMAPPER_ENABLED, getMessage(msgID),
                                    false);
    // Make sure that the entry has an appropriate objectclass for a certificate
    // mapper.
    if (! configEntry.hasObjectClass(OC_CERTIFICATE_MAPPER))
    {
      int msgID = MSGID_CONFIG_CERTMAPPER_INVALID_CLASS;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
      resultCode = ResultCode.UNWILLING_TO_PERFORM;
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Get the corresponding certificate mapper if it is active.
    CertificateMapper mapper = mappers.get(configEntryDN);
    // See if this mapper should be enabled or disabled.
    boolean needsEnabled = false;
    BooleanConfigAttribute enabledAttr;
    try
    {
      BooleanConfigAttribute enabledAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(enabledStub);
      BooleanConfigAttribute enabledStub =
           new BooleanConfigAttribute(ATTR_CERTMAPPER_ENABLED,
                    getMessage(MSGID_CONFIG_CERTMAPPER_DESCRIPTION_ENABLED),
                    false);
      enabledAttr = (BooleanConfigAttribute)
                    configEntry.getConfigAttribute(enabledStub);
      if (enabledAttr == null)
      {
        msgID = MSGID_CONFIG_CERTMAPPER_NO_ENABLED_ATTR;
        messages.add(getMessage(msgID));
        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
        int msgID = MSGID_CONFIG_CERTMAPPER_NO_ENABLED_ATTR;
        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
        resultCode = ResultCode.UNWILLING_TO_PERFORM;
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
      else if (! enabledAttr.pendingValue())
      {
        DirectoryServer.getCertificateMapper().finalizeCertificateMapper();
        // The provider should be disabled, so install the default certificate
        // mapper and return.
        try
        {
          SubjectEqualsDNCertificateMapper defaultMapper =
               new SubjectEqualsDNCertificateMapper();
          defaultMapper.initializeCertificateMapper(null);
          DirectoryServer.setCertificateMapper(defaultMapper);
          return new ConfigChangeResult(resultCode, adminActionRequired,
                                        messages);
        }
        catch (Exception e)
        {
          assert debugException(CLASS_NAME, "applyConfigurationChange", e);
          msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_INSTALL_DEFAULT_MAPPER;
          messages.add(getMessage(msgID, stackTraceToSingleLineString(e)));
          resultCode = DirectoryServer.getServerErrorResultCode();
          return new ConfigChangeResult(resultCode, adminActionRequired,
                                        messages);
        }
      }
      else
      if (enabledAttr.activeValue())
      {
        // The provider should be enabled.  If it isn't, then set a flag to
        // indicate that we need to create it when we have more information.
        if (DirectoryServer.getCertificateMapper() instanceof
            SubjectEqualsDNCertificateMapper)
        if (mapper == null)
        {
          needsEnabled = true;
        }
        else
        {
          existingProviderClass =
               DirectoryServer.getCertificateMapper().getClass().getName();
          // The mapper is already active, so no action is required.
        }
      }
      else
      {
        if (mapper == null)
        {
          // The mapper is already disabled, so no action is required and we
          // can short-circuit out of this processing.
          return new ConfigChangeResult(resultCode, adminActionRequired,
                                        messages);
        }
        else
        {
          // The mapper is active, so it needs to be disabled.  Do this and
          // return that we were successful.
          mappers.remove(configEntryDN);
          DirectoryServer.deregisterCertificateMapper(configEntryDN);
          mapper.finalizeCertificateMapper();
          return new ConfigChangeResult(resultCode, adminActionRequired,
                                        messages);
        }
      }
    }
@@ -533,133 +443,118 @@
    {
      assert debugException(CLASS_NAME, "applyConfigurationChange", e);
      msgID = MSGID_CONFIG_CERTMAPPER_UNABLE_TO_DETERMINE_ENABLED_STATE;
      messages.add(getMessage(msgID, stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_CERTMAPPER_INVALID_ENABLED_VALUE;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Get the class name from the configuration entry.
    // Make sure that the entry specifies the mapper class name.  If it has
    // changed, then we will not try to dynamically apply it.
    String className;
    msgID = MSGID_CONFIG_CERTMAPPER_DESCRIPTION_CLASS;
    StringConfigAttribute classStub =
         new StringConfigAttribute(ATTR_CERTMAPPER_CLASS, getMessage(msgID),
                                   true, false, false);
    try
    {
      StringConfigAttribute classAttr =
      StringConfigAttribute classStub =
           new StringConfigAttribute(ATTR_CERTMAPPER_CLASS,
                    getMessage(MSGID_CONFIG_CERTMAPPER_DESCRIPTION_CLASS),
                    true, false, true);
      StringConfigAttribute classNameAttr =
           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
      if (classAttr == null)
      if (classNameAttr == null)
      {
        msgID = MSGID_CONFIG_CERTMAPPER_NO_CLASS_ATTR;
        messages.add(getMessage(msgID));
        int msgID = MSGID_CONFIG_CERTMAPPER_NO_CLASS_NAME;
        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
      else
      {
        className = classAttr.activeValue();
      }
      className = classNameAttr.pendingValue();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationChange", e);
      msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_DETERMINE_CLASS;
      messages.add(getMessage(msgID, stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_CERTMAPPER_INVALID_CLASS_NAME;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // If the certificate mapper is already enabled and the specified class is
    // different from the class that is currently in use, then we won't try to
    // do anything.  The certificate mapper must be disabled and re-enabled
    // before the configuration change will be accepted.
    if (! needsEnabled)
    boolean classChanged = false;
    String  oldClassName = null;
    if (mapper != null)
    {
      if (! className.equals(existingProviderClass))
      oldClassName = mapper.getClass().getName();
      classChanged = (! className.equals(oldClassName));
    }
    if (classChanged)
    {
      // This will not be applied dynamically.  Add a message to the response
      // and indicate that admin action is required.
      adminActionRequired = true;
      messages.add(getMessage(MSGID_CONFIG_CERTMAPPER_CLASS_ACTION_REQUIRED,
                              String.valueOf(oldClassName),
                              String.valueOf(className),
                              String.valueOf(configEntryDN)));
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    if (needsEnabled)
    {
      try
      {
        msgID = MSGID_CONFIG_CERTMAPPER_NOT_SWITCHING_CLASSES;
        messages.add(getMessage(msgID, String.valueOf(existingProviderClass),
                                String.valueOf(className)));
        resultCode = ResultCode.UNWILLING_TO_PERFORM;
        adminActionRequired = true;
        // FIXME -- Should this be done with a dynamic class loader?
        Class mapperClass = Class.forName(className);
        mapper = (CertificateMapper) mapperClass.newInstance();
      }
      catch (Exception e)
      {
        assert debugException(CLASS_NAME, "applyConfigurationChange", e);
        int msgID = MSGID_CONFIG_CERTMAPPER_INVALID_CLASS;
        messages.add(getMessage(msgID, className,
                                String.valueOf(configEntryDN),
                                String.valueOf(e)));
        resultCode = DirectoryServer.getServerErrorResultCode();
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
      else
      try
      {
        // We don't need to do anything because it's already enabled and has the
        // right class.
        mapper.initializeCertificateMapper(configEntry);
      }
      catch (Exception e)
      {
        assert debugException(CLASS_NAME, "applyConfigurationChange", e);
        int msgID = MSGID_CONFIG_CERTMAPPER_INITIALIZATION_FAILED;
        messages.add(getMessage(msgID, className,
                                String.valueOf(configEntryDN),
                                String.valueOf(e)));
        resultCode = DirectoryServer.getServerErrorResultCode();
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
    }
    // Try to load the class and instantiate it as a certificate mapper.
    Class certificateMapperClass;
    try
    {
      // FIXME -- Should we use a custom class loader for this?
      certificateMapperClass = Class.forName(className);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationChange", e);
      msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_LOAD_CLASS;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    CertificateMapper certificateMapper;
    try
    {
      certificateMapper =
           (CertificateMapper) certificateMapperClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationChange", e);
      msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_INSTANTIATE_CLASS;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      mappers.put(configEntryDN, mapper);
      DirectoryServer.registerCertificateMapper(configEntryDN, mapper);
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Try to initialize the certificate mapper with the contents of the
    // configuration entry.
    try
    {
      certificateMapper.initializeCertificateMapper(configEntry);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationChange", e);
      msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_INITIALIZE;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Install the new certificate mapper in the server.  We don't need to do
    // anything to get rid of the previous default mapper since it doesn't
    // consume any resources.
    DirectoryServer.setCertificateMapper(certificateMapper);
    // If we've gotten here, then there haven't been any changes to anything
    // that we care about.
    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
  }
@@ -685,127 +580,161 @@
                      String.valueOf(configEntry), "java.lang.StringBuilder");
    // Get the DN of the provided entry and see if it is the DN that we expect
    // for the certificate mapper configuration.  If it is not, then it's not an
    // entry that we care about so return true.
    DN providedEntryDN = configEntry.getDN();
    DN expectedEntryDN;
    try
    // Make sure that no entry already exists with the specified DN.
    DN configEntryDN = configEntry.getDN();
    if (mappers.containsKey(configEntryDN))
    {
      expectedEntryDN = DN.decode(DN_CERTMAPPER_CONFIG);
    }
    catch (DirectoryException de)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", de);
      unacceptableReason.append(de.getErrorMessage());
      int    msgID   = MSGID_CONFIG_CERTMAPPER_EXISTS;
      String message = getMessage(msgID, String.valueOf(configEntryDN));
      unacceptableReason.append(message);
      return false;
    }
    if (! providedEntryDN.equals(expectedEntryDN))
    // Make sure that the entry has an appropriate objectclass for a certificate
    // mapper.
    if (! configEntry.hasObjectClass(OC_CERTIFICATE_MAPPER))
    {
      return true;
      int    msgID   = MSGID_CONFIG_CERTMAPPER_INVALID_OBJECTCLASS;
      String message = getMessage(msgID, configEntry.getDN().toString());
      unacceptableReason.append(message);
      return false;
    }
    // See if the entry indicates whether the certificate mapper should be
    // enabled.
    int msgID = MSGID_CONFIG_CERTMAPPER_DESCRIPTION_ENABLED;
    BooleanConfigAttribute enabledStub =
         new BooleanConfigAttribute(ATTR_CERTMAPPER_ENABLED, getMessage(msgID),
                                    false);
    // Make sure that the entry specifies the certificate mapper class.
    StringConfigAttribute classNameAttr;
    try
    {
      BooleanConfigAttribute enabledAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(enabledStub);
      StringConfigAttribute classStub =
           new StringConfigAttribute(ATTR_CERTMAPPER_CLASS,
                    getMessage(MSGID_CONFIG_CERTMAPPER_DESCRIPTION_CLASS),
                    true, false, true);
      classNameAttr = (StringConfigAttribute)
                      configEntry.getConfigAttribute(classStub);
      if (classNameAttr == null)
      {
        int msgID = MSGID_CONFIG_CERTMAPPER_NO_CLASS_NAME;
        String message = getMessage(msgID, configEntry.getDN().toString());
        unacceptableReason.append(message);
        return false;
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      int msgID = MSGID_CONFIG_CERTMAPPER_INVALID_CLASS_NAME;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    Class mapperClass;
    try
    {
      // FIXME -- Should this be done with a custom class loader?
      mapperClass = Class.forName(classNameAttr.pendingValue());
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      int msgID = MSGID_CONFIG_CERTMAPPER_INVALID_CLASS_NAME;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    CertificateMapper mapper;
    try
    {
      mapper = (CertificateMapper) mapperClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      int msgID = MSGID_CONFIG_CERTMAPPER_INVALID_CLASS;
      String message = getMessage(msgID, mapperClass.getName(),
                                  String.valueOf(configEntryDN),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    // See if this mapper should be enabled.
    BooleanConfigAttribute enabledAttr;
    try
    {
      BooleanConfigAttribute enabledStub =
           new BooleanConfigAttribute(ATTR_CERTMAPPER_ENABLED,
                    getMessage(MSGID_CONFIG_CERTMAPPER_DESCRIPTION_ENABLED),
                               false);
      enabledAttr = (BooleanConfigAttribute)
                    configEntry.getConfigAttribute(enabledStub);
      if (enabledAttr == null)
      {
        msgID = MSGID_CONFIG_CERTMAPPER_NO_ENABLED_ATTR;
        unacceptableReason.append(getMessage(msgID));
        int msgID = MSGID_CONFIG_CERTMAPPER_NO_ENABLED_ATTR;
        String message = getMessage(msgID, configEntry.getDN().toString());
        unacceptableReason.append(message);
        return false;
      }
      else if (! enabledAttr.pendingValue())
      {
        // The certificate mapper is not enabled so we don't need to do any
        // further validation.
        return true;
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      int msgID = MSGID_CONFIG_CERTMAPPER_INVALID_ENABLED_VALUE;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    // If the mapper is a configurable component, then make sure that its
    // configuration is valid.
    if (mapper instanceof ConfigurableComponent)
    {
      ConfigurableComponent cc = (ConfigurableComponent) mapper;
      LinkedList<String> errorMessages = new LinkedList<String>();
      if (! cc.hasAcceptableConfiguration(configEntry, errorMessages))
      {
        if (errorMessages.isEmpty())
        {
          int msgID = MSGID_CONFIG_CERTMAPPER_UNACCEPTABLE_CONFIG;
          unacceptableReason.append(getMessage(msgID,
                                               String.valueOf(configEntryDN)));
        }
        else
        {
          Iterator<String> iterator = errorMessages.iterator();
          unacceptableReason.append(iterator.next());
          while (iterator.hasNext())
          {
            unacceptableReason.append("  ");
            unacceptableReason.append(iterator.next());
          }
        }
        return false;
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      msgID = MSGID_CONFIG_CERTMAPPER_UNABLE_TO_DETERMINE_ENABLED_STATE;
      unacceptableReason.append(getMessage(msgID,
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    // See if it specifies the class name for the certificate mapper
    // implementation.
    String className;
    msgID = MSGID_CONFIG_CERTMAPPER_DESCRIPTION_CLASS;
    StringConfigAttribute classStub =
         new StringConfigAttribute(ATTR_CERTMAPPER_CLASS, getMessage(msgID),
                                   true, false, false);
    try
    {
      StringConfigAttribute classAttr =
           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
      if (classAttr == null)
      {
        msgID = MSGID_CONFIG_CERTMAPPER_NO_CLASS_ATTR;
        unacceptableReason.append(getMessage(msgID));
        return false;
      }
      else
      {
        className = classAttr.activeValue();
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_DETERMINE_CLASS;
      unacceptableReason.append(getMessage(msgID,
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    // Try to load the class and instantiate it as a certificate mapper.
    Class certificateMapperClass;
    try
    {
      // FIXME -- Should we use a custom class loader for this?
      certificateMapperClass = Class.forName(className);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_LOAD_CLASS;
      unacceptableReason.append(getMessage(msgID, String.valueOf(className),
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    try
    {
      CertificateMapper certificateMapper =
           (CertificateMapper) certificateMapperClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_INSTANTIATE_CLASS;
      unacceptableReason.append(getMessage(msgID, String.valueOf(className),
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    // If we've gotten to this point, then it is acceptable as far as we are
    // concerned.  If it is unacceptable according to the configuration, then
    // the certificate mapper itself will make that determination.
    // If we've gotten here then the mapper entry appears to be acceptable.
    return true;
  }
@@ -825,84 +754,48 @@
    assert debugEnter(CLASS_NAME, "applyConfigurationAdd",
                      String.valueOf(configEntry));
    DN                configEntryDN       = configEntry.getDN();
    ResultCode        resultCode          = ResultCode.SUCCESS;
    boolean           adminActionRequired = false;
    ArrayList<String> messages            = new ArrayList<String>();
    // Get the DN of the provided entry and see if it is the DN that we expect
    // for the certificate mapper configuration.  If it is not, then it's not an
    // entry that we care about so return without doing anything.
    DN providedEntryDN = configEntry.getDN();
    DN expectedEntryDN;
    try
    // Make sure that the entry has an appropriate objectclass for a certificate
    // mapper.
    if (! configEntry.hasObjectClass(OC_CERTIFICATE_MAPPER))
    {
      expectedEntryDN = DN.decode(DN_CERTMAPPER_CONFIG);
    }
    catch (DirectoryException de)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", de);
      messages.add(de.getErrorMessage());
      resultCode = de.getResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    if (! providedEntryDN.equals(expectedEntryDN))
    {
      int    msgID   = MSGID_CONFIG_CERTMAPPER_INVALID_OBJECTCLASS;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
      resultCode = ResultCode.UNWILLING_TO_PERFORM;
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Register as a change listener of the provided entry so that we will be
    // notified of changes to it.  We will also want to register a delete
    // listener with its parent to allow us to determine if the entry is
    // deleted.
    configEntry.registerChangeListener(this);
    // See if this mapper should be enabled or disabled.
    BooleanConfigAttribute enabledAttr;
    try
    {
      DN parentDN = configEntry.getDN().getParentDNInSuffix();
      ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN);
      if (parentEntry != null)
      {
        parentEntry.registerDeleteListener(this);
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      BooleanConfigAttribute enabledStub =
           new BooleanConfigAttribute(ATTR_CERTMAPPER_ENABLED,
                    getMessage(MSGID_CONFIG_CERTMAPPER_DESCRIPTION_ENABLED),
                               false);
      enabledAttr = (BooleanConfigAttribute)
                    configEntry.getConfigAttribute(enabledStub);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING,
               MSGID_CONFIG_CERTMAPPER_CANNOT_REGISTER_DELETE_LISTENER,
               stackTraceToSingleLineString(e));
    }
    // See if the entry indicates whether the certificate mapper should be
    // enabled.
    int msgID = MSGID_CONFIG_CERTMAPPER_DESCRIPTION_ENABLED;
    BooleanConfigAttribute enabledStub =
         new BooleanConfigAttribute(ATTR_CERTMAPPER_ENABLED, getMessage(msgID),
                                    false);
    try
    {
      BooleanConfigAttribute enabledAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(enabledStub);
      if (enabledAttr == null)
      {
        // The attribute is not present, so the certificate mapper will be
        // disabled.  Log a warning message and return.
        messages.add(getMessage(MSGID_CONFIG_CERTMAPPER_NO_ENABLED_ATTR));
        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
        // The attribute doesn't exist, so it will be disabled by default.
        int msgID = MSGID_CONFIG_CERTMAPPER_NO_ENABLED_ATTR;
        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
        resultCode = ResultCode.SUCCESS;
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
      else if (! enabledAttr.activeValue())
      {
        // The certificate mapper is explicitly disabled.  Log a mild warning
        // and return.
        messages.add(getMessage(MSGID_CONFIG_CERTMAPPER_DISABLED));
        // It is explicitly configured as disabled, so we don't need to do
        // anything.
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
@@ -911,107 +804,86 @@
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      msgID = MSGID_CONFIG_CERTMAPPER_UNABLE_TO_DETERMINE_ENABLED_STATE;
      messages.add(getMessage(msgID, stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_CERTMAPPER_INVALID_ENABLED_VALUE;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // See if it specifies the class name for the certificate mapper
    // implementation.
    // Make sure that the entry specifies the mapper class name.
    String className;
    msgID = MSGID_CONFIG_CERTMAPPER_DESCRIPTION_CLASS;
    StringConfigAttribute classStub =
         new StringConfigAttribute(ATTR_CERTMAPPER_CLASS, getMessage(msgID),
                                   true, false, false);
    try
    {
      StringConfigAttribute classAttr =
      StringConfigAttribute classStub =
           new StringConfigAttribute(ATTR_CERTMAPPER_CLASS,
                    getMessage(MSGID_CONFIG_CERTMAPPER_DESCRIPTION_CLASS),
                    true, false, true);
      StringConfigAttribute classNameAttr =
           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
      if (classAttr == null)
      if (classNameAttr == null)
      {
        messages.add(getMessage(MSGID_CONFIG_CERTMAPPER_NO_CLASS_ATTR));
        int msgID = MSGID_CONFIG_CERTMAPPER_NO_CLASS_NAME;
        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
      else
      {
        className = classAttr.activeValue();
      }
      className = classNameAttr.pendingValue();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_DETERMINE_CLASS;
      messages.add(getMessage(msgID, stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_CERTMAPPER_INVALID_CLASS_NAME;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Try to load the class and instantiate it as a certificate mapper.
    Class certificateMapperClass;
    // Load and initialize the mapper class, and register it with the Directory
    // Server.
    CertificateMapper mapper;
    try
    {
      // FIXME -- Should we use a custom class loader for this?
      certificateMapperClass = Class.forName(className);
      // FIXME -- Should this be done with a dynamic class loader?
      Class mapperClass = Class.forName(className);
      mapper = (CertificateMapper) mapperClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_LOAD_CLASS;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_CERTMAPPER_INVALID_CLASS;
      messages.add(getMessage(msgID, className, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    CertificateMapper certificateMapper;
    try
    {
      certificateMapper =
           (CertificateMapper) certificateMapperClass.newInstance();
      mapper.initializeCertificateMapper(configEntry);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_INSTANTIATE_CLASS;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_CERTMAPPER_INITIALIZATION_FAILED;
      messages.add(getMessage(msgID, className, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Try to initialize the certificate mapper with the contents of the
    // configuration entry.
    try
    {
      certificateMapper.initializeCertificateMapper(configEntry);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_INITIALIZE;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Install the new certificate mapper in the server.  We don't need to do
    // anything to get rid of the previous default mapper since it doesn't
    // consume any resources.
    DirectoryServer.setCertificateMapper(certificateMapper);
    mappers.put(configEntryDN, mapper);
    DirectoryServer.registerCertificateMapper(configEntryDN, mapper);
    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
  }
@@ -1037,46 +909,7 @@
                      String.valueOf(configEntry), "java.lang.StringBuilder");
    // Get the DN of the provided entry and see if it is the DN that we expect
    // for the certificate mapper configuration.  If it is not, then it's not an
    // entry that we care about so return true.
    DN providedEntryDN = configEntry.getDN();
    DN expectedEntryDN;
    try
    {
      expectedEntryDN = DN.decode(DN_CERTMAPPER_CONFIG);
    }
    catch (DirectoryException de)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", de);
      unacceptableReason.append(de.getErrorMessage());
      return false;
    }
    if (! providedEntryDN.equals(expectedEntryDN))
    {
      return true;
    }
    // Determine whether there is a valid certificate mapper installed (i.e.,
    // not the default mapper).  If a valid mapper is installed, then we will
    // not allow the entry to be removed.
    CertificateMapper installedMapper =
         DirectoryServer.getCertificateMapper();
    if (! (installedMapper instanceof SubjectEqualsDNCertificateMapper))
    {
      int msgID = MSGID_CONFIG_CERTMAPPER_CANNOT_REMOVE_ACTIVE_PROVIDER;
      unacceptableReason.append(getMessage(msgID,
                                     installedMapper.getClass().getName()));
      return false;
    }
    // If we've gotten to this point, then it is acceptable as far as we are
    // concerned.  If it is unacceptable according to the configuration, then
    // the certificate mapper itself will make that determination.
    // A delete should always be acceptable, so just return true.
    return true;
  }
@@ -1095,14 +928,23 @@
    assert debugEnter(CLASS_NAME, "applyConfigurationDelete",
                      String.valueOf(configEntry));
    ResultCode        resultCode          = ResultCode.SUCCESS;
    boolean           adminActionRequired = false;
    ArrayList<String> messages            = new ArrayList<String>();
    DN         configEntryDN       = configEntry.getDN();
    ResultCode resultCode          = ResultCode.SUCCESS;
    boolean    adminActionRequired = false;
    // Since we can never delete an active configuration, there is nothing that
    // we need to do if a delete does go through.
    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    // See if the entry is registered as a certificate mapper.  If so,
    // deregister it and stop the mapper.
    CertificateMapper mapper = mappers.remove(configEntryDN);
    if (mapper != null)
    {
      DirectoryServer.deregisterCertificateMapper(configEntryDN);
      mapper.finalizeCertificateMapper();
    }
    return new ConfigChangeResult(resultCode, adminActionRequired);
  }
}
opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -264,10 +264,6 @@
  // Indicates whether the server should reject unauthenticated requests.
  private boolean rejectUnauthenticatedRequests;
  // The certificate mapper used to establish a mapping between client
  // certificates and user entries.
  private CertificateMapper certificateMapper;
  // The configuration manager that will handle the certificate mapper.
  private CertificateMapperConfigManager certificateMapperConfigManager;
@@ -278,6 +274,9 @@
  private ConcurrentHashMap<DN,AccountStatusNotificationHandler>
               accountStatusNotificationHandlers;
  // The set of certificate mappers registered with the server.
  private ConcurrentHashMap<DN,CertificateMapper> certificateMappers;
  // The set of alternate bind DNs for the root users.
  private ConcurrentHashMap<DN,DN> alternateRootBindDNs;
@@ -289,6 +288,9 @@
  // between the associated configuration entry DN and the MBean).
  private ConcurrentHashMap<DN,JMXMBean> mBeans;
  // The set of key manager providers registered with the server.
  private ConcurrentHashMap<DN,KeyManagerProvider> keyManagerProviders;
  // The set of password generators registered with the Directory Server, as a
  // mapping between the DN of the associated configuration entry and the
  // generator implementation.
@@ -304,6 +306,9 @@
  // validator implementation.
  private ConcurrentHashMap<DN,PasswordValidator> passwordValidators;
  // The set of trust manager providers registered with the server.
  private ConcurrentHashMap<DN,TrustManagerProvider> trustManagerProviders;
  // The set of extended operation handlers registered with the server (mapped
  // between the OID of the extended operation and the handler).
  private ConcurrentHashMap<String,ExtendedOperationHandler>
@@ -415,9 +420,6 @@
  // a search.
  private int lookthroughLimit;
  // The key manager provider for the Directory Server.
  private KeyManagerProvider keyManagerProvider;
  // The key manager provider configuration manager for the Directory Server.
  private KeyManagerProviderConfigManager keyManagerProviderConfigManager;
@@ -529,9 +531,6 @@
  // The set of supported feature OIDs registered with the Directory Server.
  private TreeSet<String> supportedFeatures;
  // The trust manager provider for the Directory Server.
  private TrustManagerProvider trustManagerProvider;
  // The trust manager provider configuration manager for the Directory Server.
  private TrustManagerProviderConfigManager trustManagerProviderConfigManager;
@@ -625,6 +624,12 @@
         new ConcurrentHashMap<DN,AccountStatusNotificationHandler>();
    directoryServer.rootDNs = new CopyOnWriteArraySet<DN>();
    directoryServer.alternateRootBindDNs = new ConcurrentHashMap<DN,DN>();
    directoryServer.keyManagerProviders =
         new ConcurrentHashMap<DN,KeyManagerProvider>();
    directoryServer.trustManagerProviders =
         new ConcurrentHashMap<DN,TrustManagerProvider>();
    directoryServer.certificateMappers =
         new ConcurrentHashMap<DN,CertificateMapper>();
    directoryServer.passwordPolicies =
         new ConcurrentHashMap<DN,PasswordPolicyConfig>();
    directoryServer.defaultPasswordPolicyDN = null;
@@ -984,18 +989,18 @@
      // Initialize the key manager provider.
      keyManagerProviderConfigManager = new KeyManagerProviderConfigManager();
      keyManagerProviderConfigManager.initializeKeyManagerProvider();
      keyManagerProviderConfigManager.initializeKeyManagerProviders();
      // Initialize the trust manager provider.
      trustManagerProviderConfigManager =
           new TrustManagerProviderConfigManager();
      trustManagerProviderConfigManager.initializeTrustManagerProvider();
      trustManagerProviderConfigManager.initializeTrustManagerProviders();
      // Initialize the certificate mapper.
      certificateMapperConfigManager = new CertificateMapperConfigManager();
      certificateMapperConfigManager.initializeCertificateMapper();
      certificateMapperConfigManager.initializeCertificateMappers();
      // Initialize the identity mappers.
@@ -4954,97 +4959,213 @@
  /**
   * Retrieves the key manager provider for the Directory Server.
   * Retrieves the set of key manager providers registered with the Directory
   * Server.
   *
   * @return  The key manager provider for the Directory Server.
   * @return  The set of key manager providers registered with the Directory
   *          Server.
   */
  public static KeyManagerProvider getKeyManagerProvider()
  public static Map<DN,KeyManagerProvider> getKeyManagerProviders()
  {
    assert debugEnter(CLASS_NAME, "getKeyManagerProvider");
    assert debugEnter(CLASS_NAME, "getKeyManagerProviders");
    return directoryServer.keyManagerProvider;
    return directoryServer.keyManagerProviders;
  }
  /**
   * Specifies the key manager provider for the Directory Server.
   * Retrieves the key manager provider registered with the provided entry DN.
   *
   * @param  keyManagerProvider  The key manager provider for the Directory
   *                             Server.
   * @param  providerDN  The DN with which the key manager provider is
   *                     registered.
   *
   * @return  The key manager provider registered with the provided entry DN, or
   *          {@code null} if there is no such key manager provider registered
   *          with the server.
   */
  public static void setKeyManagerProvider(KeyManagerProvider
                                                keyManagerProvider)
  public static KeyManagerProvider getKeyManagerProvider(DN providerDN)
  {
    assert debugEnter(CLASS_NAME, "setKeyManagerProvider",
                      String.valueOf(keyManagerProvider));
    assert debugEnter(CLASS_NAME, "getKeyManagerProvider",
                      String.valueOf(providerDN));
    directoryServer.keyManagerProvider = keyManagerProvider;
    return directoryServer.keyManagerProviders.get(providerDN);
  }
  /**
   * Retrieves the trust manager provider for the Directory Server.
   * Registers the provided key manager provider with the Directory Server.
   *
   * @return  The trust manager provider for the Directory Server.
   * @param  providerDN  The DN with which to register the key manager provider.
   * @param  provider    The key manager provider to register with the server.
   */
  public static TrustManagerProvider getTrustManagerProvider()
  public static void registerKeyManagerProvider(DN providerDN,
                                                KeyManagerProvider provider)
  {
    assert debugEnter(CLASS_NAME, "getTrustManagerProvider");
    assert debugEnter(CLASS_NAME, "registerKeyManagerProvider",
                      String.valueOf(providerDN), String.valueOf(provider));
    return directoryServer.trustManagerProvider;
    directoryServer.keyManagerProviders.put(providerDN, provider);
  }
  /**
   * Specifies the trust manager provider for the Directory Server.
   * Deregisters the specified key manager provider with the Directory Server.
   *
   * @param  trustManagerProvider  The trust manager provider for the Directory
   *                               Server.
   * @param  providerDN  The DN with which the key manager provider is
   *                     registered.
   */
  public static void setTrustManagerProvider(TrustManagerProvider
                                                  trustManagerProvider)
  public static void deregisterKeyManagerProvider(DN providerDN)
  {
    assert debugEnter(CLASS_NAME, "setTrustManagerProvider",
                      String.valueOf(trustManagerProvider));
    assert debugEnter(CLASS_NAME, "deregisterKeyManagerProvider",
                      String.valueOf(providerDN));
    directoryServer.trustManagerProvider = trustManagerProvider;
    directoryServer.keyManagerProviders.remove(providerDN);
  }
  /**
   * Retrieves the certificate mapper for the Directory Server.
   * Retrieves the set of trust manager providers registered with the Directory
   * Server.
   *
   * @return  The certificate mapper for the Directory Server.
   * @return  The set of trust manager providers registered with the Directory
   *          Server.
   */
  public static CertificateMapper getCertificateMapper()
  public static Map<DN,TrustManagerProvider> getTrustManagerProviders()
  {
    assert debugEnter(CLASS_NAME, "getCertificateMapper");
    assert debugEnter(CLASS_NAME, "getTrustManagerProviders");
    return directoryServer.certificateMapper;
    return directoryServer.trustManagerProviders;
  }
  /**
   * Specifies the certificate mapper for the Directory Server.
   * Retrieves the trust manager provider registered with the provided entry DN.
   *
   * @param  certificateMapper  The certificate mapper for the Directory Server.
   * @param  providerDN  The DN with which the trust manager provider is
   *                     registered.
   *
   * @return  The trust manager provider registered with the provided entry DN,
   *          or {@code null} if there is no such trust manager provider
   *          registered with the server.
   */
  public static void setCertificateMapper(CertificateMapper certificateMapper)
  public static TrustManagerProvider getTrustManagerProvider(DN providerDN)
  {
    assert debugEnter(CLASS_NAME, "setCertificateMapper",
                      String.valueOf(certificateMapper));
    assert debugEnter(CLASS_NAME, "getTrustManagerProvider",
                      String.valueOf(providerDN));
    directoryServer.certificateMapper = certificateMapper;
    return directoryServer.trustManagerProviders.get(providerDN);
  }
  /**
   * Registers the provided trust manager provider with the Directory Server.
   *
   * @param  providerDN  The DN with which to register the trust manager
   *                     provider.
   * @param  provider    The trust manager provider to register with the server.
   */
  public static void registerTrustManagerProvider(DN providerDN,
                                                  TrustManagerProvider provider)
  {
    assert debugEnter(CLASS_NAME, "registerTrustManagerProvider",
                      String.valueOf(providerDN), String.valueOf(provider));
    directoryServer.trustManagerProviders.put(providerDN, provider);
  }
  /**
   * Deregisters the specified trust manager provider with the Directory Server.
   *
   * @param  providerDN  The DN with which the trust manager provider is
   *                     registered.
   */
  public static void deregisterTrustManagerProvider(DN providerDN)
  {
    assert debugEnter(CLASS_NAME, "deregisterTrustManagerProvider",
                      String.valueOf(providerDN));
    directoryServer.trustManagerProviders.remove(providerDN);
  }
  /**
   * Retrieves the set of certificate mappers registered with the Directory
   * Server.
   *
   * @return  The set of certificate mappers registered with the Directory
   *          Server.
   */
  public static Map<DN,CertificateMapper> getCertificateMappers()
  {
    assert debugEnter(CLASS_NAME, "getCertificateMappers");
    return directoryServer.certificateMappers;
  }
  /**
   * Retrieves the certificate mapper registered with the provided entry DN.
   *
   * @param  mapperDN  The DN with which the certificate mapper is registered.
   *
   * @return  The certificate mapper registered with the provided entry DN, or
   *          {@code null} if there is no such certificate mapper registered
   *          with the server.
   */
  public static CertificateMapper getCertificateMapper(DN mapperDN)
  {
    assert debugEnter(CLASS_NAME, "getCertificateMapper",
                      String.valueOf(mapperDN));
    return directoryServer.certificateMappers.get(mapperDN);
  }
  /**
   * Registers the provided certificate mapper with the Directory Server.
   *
   * @param  mapperDN  The DN with which to register the certificate mapper.
   * @param  mapper    The certificate mapper to register with the server.
   */
  public static void registerCertificateMapper(DN mapperDN,
                                               CertificateMapper mapper)
  {
    assert debugEnter(CLASS_NAME, "registerCertificateMapper",
                      String.valueOf(mapperDN), String.valueOf(mapper));
    directoryServer.certificateMappers.put(mapperDN, mapper);
  }
  /**
   * Deregisters the specified certificate mapper with the Directory Server.
   *
   * @param  mapperDN  The DN with which the certificate mapper is registered.
   */
  public static void deregisterCertificateMapper(DN mapperDN)
  {
    assert debugEnter(CLASS_NAME, "deregisterCertificateMapper",
                      String.valueOf(mapperDN));
    directoryServer.certificateMappers.remove(mapperDN);
  }
  /**
   * Retrieves the set of privileges that should automatically be granted to
   * root users when they authenticate.
   *
opendj-sdk/opends/src/server/org/opends/server/core/KeyManagerProviderConfigManager.java
@@ -22,24 +22,29 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.core;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import org.opends.server.api.ConfigAddListener;
import org.opends.server.api.ConfigChangeListener;
import org.opends.server.api.ConfigDeleteListener;
import org.opends.server.api.ConfigHandler;
import org.opends.server.api.ConfigurableComponent;
import org.opends.server.api.KeyManagerProvider;
import org.opends.server.config.BooleanConfigAttribute;
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.config.StringConfigAttribute;
import org.opends.server.extensions.NullKeyManagerProvider;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.DN;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
@@ -51,15 +56,17 @@
import static org.opends.server.loggers.Error.*;
import static org.opends.server.messages.ConfigMessages.*;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines a utility that will be used to manage the configuration
 * for the Directory Server key manager provider.  Only a single key manager
 * provider may be defined, but if it is absent or disabled, then a null
 * provider will be used which will not allow any key manager interaction.
 * This class defines a utility that will be used to manage the set of
 * key manager providers defined in the Directory Server.  It will initialize
 * the providers when the server starts, and then will manage any additions,
 * removals, or modifications of any key manager providers while the server is
 * running.
 */
public class KeyManagerProviderConfigManager
       implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener
@@ -72,6 +79,15 @@
  // A mapping between the DNs of the config entries and the associated
  // key manager providers.
  private ConcurrentHashMap<DN,KeyManagerProvider> providers;
  // The configuration handler for the Directory Server.
  private ConfigHandler configHandler;
  /**
   * Creates a new instance of this key manager provider config manager.
   */
@@ -79,242 +95,123 @@
  {
    assert debugConstructor(CLASS_NAME);
    // No implementation is required.
    configHandler = DirectoryServer.getConfigHandler();
    providers     = new ConcurrentHashMap<DN,KeyManagerProvider>();
  }
  /**
   * Initializes the configuration associated with the Directory Server key
   * manager provider.  This should only be called at Directory Server startup.
   * If an error occurs, then a message will be logged and the null key manager
   * provider will be installed.
   * Initializes all key manager providers currently defined in the Directory
   * Server configuration.  This should only be called at Directory Server
   * startup.
   *
   * @throws  InitializationException  If a problem occurs while trying to
   *                                   install the null key manager provider.
   * @throws  ConfigException  If a configuration problem causes the key manager
   *                           provider initialization process to fail.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   the key manager providers that is not
   *                                   related to the server configuration.
   */
  public void initializeKeyManagerProvider()
         throws InitializationException
  public void initializeKeyManagerProviders()
         throws ConfigException, InitializationException
  {
    assert debugEnter(CLASS_NAME, "initializeKeyManagerProvider");
    assert debugEnter(CLASS_NAME, "initializeKeyManagerProviders");
    // First, install a null key manager provider so that there will be one even
    // if we encounter a problem later.
    // First, get the configuration base entry.
    ConfigEntry baseEntry;
    try
    {
      NullKeyManagerProvider nullProvider = new NullKeyManagerProvider();
      nullProvider.initializeKeyManagerProvider(null);
      DirectoryServer.setKeyManagerProvider(nullProvider);
      DN providerBase = DN.decode(DN_KEYMANAGER_PROVIDER_CONFIG_BASE);
      baseEntry = configHandler.getConfigEntry(providerBase);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeKeyManagerProvider", e);
      assert debugException(CLASS_NAME, "initializeKeyManagerProviders",
                            e);
      int msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_INSTALL_NULL_PROVIDER;
      String message = getMessage(msgID, stackTraceToSingleLineString(e));
      throw new InitializationException(msgID, message, e);
      int    msgID   = MSGID_CONFIG_KEYMANAGER_CANNOT_GET_BASE;
      String message = getMessage(msgID, String.valueOf(e));
      throw new ConfigException(msgID, message, e);
    }
    if (baseEntry == null)
    {
      // The key manager provider base entry does not exist.  This is not
      // acceptable, so throw an exception.
      int    msgID   = MSGID_CONFIG_KEYMANAGER_BASE_DOES_NOT_EXIST;
      String message = getMessage(msgID);
      throw new ConfigException(msgID, message);
    }
    // Get the key manager provider configuration entry.  If it is not present,
    // then register an add listener and just go with the null provider.
    DN configEntryDN;
    ConfigEntry configEntry;
    try
    {
      configEntryDN = DN.decode(DN_KEYMANAGER_PROVIDER_CONFIG);
      configEntry   = DirectoryServer.getConfigEntry(configEntryDN);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeKeyManagerProvider", e);
    // Register add and delete listeners with the key manager provider base
    // entry.  We don't care about modifications to it.
    baseEntry.registerAddListener(this);
    baseEntry.registerDeleteListener(this);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_KEYMANAGER_CANNOT_GET_CONFIG_ENTRY,
               stackTraceToSingleLineString(e));
    // See if the base entry has any children.  If not, then we don't need to do
    // anything else.
    if (! baseEntry.hasChildren())
    {
      return;
    }
    if (configEntry == null)
    // Iterate through the child entries and process them as key manager
    // provider configuration entries.
    for (ConfigEntry childEntry : baseEntry.getChildren().values())
    {
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING,
               MSGID_CONFIG_KEYMANAGER_NO_CONFIG_ENTRY);
      childEntry.registerChangeListener(this);
      StringBuilder unacceptableReason = new StringBuilder();
      if (! configAddIsAcceptable(childEntry, unacceptableReason))
      {
        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
                 MSGID_CONFIG_KEYMANAGER_ENTRY_UNACCEPTABLE,
                 childEntry.getDN().toString(), unacceptableReason.toString());
        continue;
      }
      try
      {
        ConfigEntry parentEntry = DirectoryServer
            .getConfigEntry(configEntryDN.getParentDNInSuffix());
        if (parentEntry != null)
        ConfigChangeResult result = applyConfigurationAdd(childEntry);
        if (result.getResultCode() != ResultCode.SUCCESS)
        {
          parentEntry.registerAddListener(this);
          StringBuilder buffer = new StringBuilder();
          List<String> resultMessages = result.getMessages();
          if ((resultMessages == null) || (resultMessages.isEmpty()))
          {
            buffer.append(getMessage(MSGID_CONFIG_UNKNOWN_UNACCEPTABLE_REASON));
          }
          else
          {
            Iterator<String> iterator = resultMessages.iterator();
            buffer.append(iterator.next());
            while (iterator.hasNext())
            {
              buffer.append(EOL);
              buffer.append(iterator.next());
            }
          }
          logError(ErrorLogCategory.CONFIGURATION,
                   ErrorLogSeverity.SEVERE_ERROR,
                   MSGID_CONFIG_KEYMANAGER_CANNOT_CREATE_PROVIDER,
                   childEntry.getDN().toString(), buffer.toString());
        }
      }
      catch (Exception e)
      {
        assert debugException(CLASS_NAME, "initializeKeyManagerProvider", e);
        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
                 MSGID_CONFIG_KEYMANAGER_CANNOT_REGISTER_ADD_LISTENER,
                 stackTraceToSingleLineString(e));
      }
      return;
    }
    // At this point, we have a configuration entry.  Register a change listener
    // with it so we can be notified of changes to it over time.  We will also
    // want to register a delete listener with its parent to allow us to
    // determine if the entry is deleted.
    configEntry.registerChangeListener(this);
    try
    {
      DN parentDN = configEntryDN.getParentDNInSuffix();
      ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN);
      if (parentEntry != null)
      {
        parentEntry.registerDeleteListener(this);
                 MSGID_CONFIG_KEYMANAGER_CANNOT_CREATE_PROVIDER,
                 childEntry.getDN().toString(), String.valueOf(e));
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeKeyManagerProvider", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING,
               MSGID_CONFIG_KEYMANAGER_CANNOT_REGISTER_DELETE_LISTENER,
               stackTraceToSingleLineString(e));
    }
    // See if the entry indicates whether the key manager provider should be
    // enabled.
    int msgID = MSGID_CONFIG_KEYMANAGER_DESCRIPTION_ENABLED;
    BooleanConfigAttribute enabledStub =
         new BooleanConfigAttribute(ATTR_KEYMANAGER_ENABLED, getMessage(msgID),
                                    false);
    try
    {
      BooleanConfigAttribute enabledAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(enabledStub);
      if (enabledAttr == null)
      {
        // The attribute is not present, so the key manager provider will be
        // disabled.  Log a warning message and return.
        logError(ErrorLogCategory.CONFIGURATION,
                 ErrorLogSeverity.SEVERE_WARNING,
                 MSGID_CONFIG_KEYMANAGER_NO_ENABLED_ATTR);
        return;
      }
      else if (! enabledAttr.activeValue())
      {
        // The key manager provider is explicitly disabled.  Log a mild warning
        // and return.
        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_WARNING,
                 MSGID_CONFIG_KEYMANAGER_DISABLED);
        return;
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeKeyManagerProvider", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_KEYMANAGER_UNABLE_TO_DETERMINE_ENABLED_STATE,
               stackTraceToSingleLineString(e));
      return;
    }
    // See if it specifies the class name for the key manager provider
    // implementation.
    String className;
    msgID = MSGID_CONFIG_KEYMANAGER_DESCRIPTION_CLASS;
    StringConfigAttribute classStub =
         new StringConfigAttribute(ATTR_KEYMANAGER_CLASS, getMessage(msgID),
                                   true, false, false);
    try
    {
      StringConfigAttribute classAttr =
           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
      if (classAttr == null)
      {
        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
                 MSGID_CONFIG_KEYMANAGER_NO_CLASS_ATTR);
        return;
      }
      else
      {
        className = classAttr.activeValue();
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeKeyManagerProvider", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_KEYMANAGER_CANNOT_DETERMINE_CLASS,
               stackTraceToSingleLineString(e));
      return;
    }
    // Try to load the class and instantiate it as a key manager provider.
    Class keyManagerProviderClass;
    try
    {
      // FIXME -- Should we use a custom class loader for this?
      keyManagerProviderClass = Class.forName(className);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeKeyManagerProvider", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_KEYMANAGER_CANNOT_LOAD_CLASS,
               String.valueOf(className), stackTraceToSingleLineString(e));
      return;
    }
    KeyManagerProvider keyManagerProvider;
    try
    {
      keyManagerProvider =
           (KeyManagerProvider) keyManagerProviderClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeKeyManagerProvider", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_KEYMANAGER_CANNOT_INSTANTIATE_CLASS,
               String.valueOf(className), stackTraceToSingleLineString(e));
      return;
    }
    // Try to initialize the key manager provider with the contents of the
    // configuration entry.
    try
    {
      keyManagerProvider.initializeKeyManagerProvider(configEntry);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeKeyManagerProvider", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_KEYMANAGER_CANNOT_INITIALIZE,
               String.valueOf(className), stackTraceToSingleLineString(e));
      return;
    }
    // Install the new key manager provider in the server.  We don't need to do
    // anything to get rid of the previous null provider since it doesn't
    // consume any resources.
    DirectoryServer.setKeyManagerProvider(keyManagerProvider);
  }
@@ -339,21 +236,98 @@
                      String.valueOf(configEntry), "java.lang.StringBuilder");
    // See if the entry indicates whether the key manager provider should be
    // enabled.
    int msgID = MSGID_CONFIG_KEYMANAGER_DESCRIPTION_ENABLED;
    BooleanConfigAttribute enabledStub =
         new BooleanConfigAttribute(ATTR_KEYMANAGER_ENABLED, getMessage(msgID),
                                    false);
    // Make sure that the entry has an appropriate objectclass for a key manager
    // provider.
    if (! configEntry.hasObjectClass(OC_KEY_MANAGER_PROVIDER))
    {
      int    msgID   = MSGID_CONFIG_KEYMANAGER_INVALID_OBJECTCLASS;
      String message = getMessage(msgID, configEntry.getDN().toString());
      unacceptableReason.append(message);
      return false;
    }
    // Make sure that the entry specifies the provider class name.
    StringConfigAttribute classNameAttr;
    try
    {
      BooleanConfigAttribute enabledAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(enabledStub);
      StringConfigAttribute classStub =
           new StringConfigAttribute(ATTR_KEYMANAGER_CLASS,
                    getMessage(MSGID_CONFIG_KEYMANAGER_DESCRIPTION_CLASS),
                    true, false, true);
      classNameAttr = (StringConfigAttribute)
                      configEntry.getConfigAttribute(classStub);
      if (classNameAttr == null)
      {
        int    msgID   = MSGID_CONFIG_KEYMANAGER_NO_CLASS_NAME;
        String message = getMessage(msgID, configEntry.getDN().toString());
        unacceptableReason.append(message);
        return false;
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      int    msgID   = MSGID_CONFIG_KEYMANAGER_INVALID_CLASS_NAME;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    Class providerClass;
    try
    {
      // FIXME -- Should this be done with a custom class loader?
      providerClass = Class.forName(classNameAttr.pendingValue());
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      int    msgID   = MSGID_CONFIG_KEYMANAGER_INVALID_CLASS_NAME;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    try
    {
      KeyManagerProvider provider =
           (KeyManagerProvider) providerClass.newInstance();
    }
    catch(Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      int    msgID   = MSGID_CONFIG_KEYMANAGER_INVALID_CLASS;
      String message = getMessage(msgID, providerClass.getName(),
                                  String.valueOf(configEntry.getDN()),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    // See if this key manager provider should be enabled.
    BooleanConfigAttribute enabledAttr;
    try
    {
      BooleanConfigAttribute enabledStub =
           new BooleanConfigAttribute(ATTR_KEYMANAGER_ENABLED,
                    getMessage(MSGID_CONFIG_KEYMANAGER_DESCRIPTION_ENABLED),
                               false);
      enabledAttr = (BooleanConfigAttribute)
                    configEntry.getConfigAttribute(enabledStub);
      if (enabledAttr == null)
      {
        msgID = MSGID_CONFIG_KEYMANAGER_NO_ENABLED_ATTR;
        unacceptableReason.append(getMessage(msgID));
        int    msgID   = MSGID_CONFIG_KEYMANAGER_NO_ENABLED_ATTR;
        String message = getMessage(msgID, configEntry.getDN().toString());
        unacceptableReason.append(message);
        return false;
      }
    }
@@ -361,82 +335,16 @@
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      msgID = MSGID_CONFIG_KEYMANAGER_UNABLE_TO_DETERMINE_ENABLED_STATE;
      unacceptableReason.append(getMessage(msgID,
                                           stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_KEYMANAGER_INVALID_ENABLED_VALUE;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    // See if it specifies the class name for the key manager provider
    // implementation.
    String className;
    msgID = MSGID_CONFIG_KEYMANAGER_DESCRIPTION_CLASS;
    StringConfigAttribute classStub =
         new StringConfigAttribute(ATTR_KEYMANAGER_CLASS, getMessage(msgID),
                                   true, false, false);
    try
    {
      StringConfigAttribute classAttr =
           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
      if (classAttr == null)
      {
        msgID = MSGID_CONFIG_KEYMANAGER_NO_CLASS_ATTR;
        unacceptableReason.append(getMessage(msgID));
        return false;
      }
      else
      {
        className = classAttr.activeValue();
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_DETERMINE_CLASS;
      unacceptableReason.append(getMessage(msgID,
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    // Try to load the class and instantiate it as a key manager provider.
    Class keyManagerProviderClass;
    try
    {
      // FIXME -- Should we use a custom class loader for this?
      keyManagerProviderClass = Class.forName(className);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_LOAD_CLASS;
      unacceptableReason.append(getMessage(msgID, String.valueOf(className),
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    try
    {
      KeyManagerProvider keyManagerProvider =
           (KeyManagerProvider) keyManagerProviderClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_INSTANTIATE_CLASS;
      unacceptableReason.append(getMessage(msgID, String.valueOf(className),
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    // If we've gotten to this point, then it is acceptable as far as we are
    // concerned.  If it is unacceptable according to the configuration, then
    // the key manager provider itself will make that determination.
    // If we've gotten here then the key manager provider entry appears to be
    // acceptable.
    return true;
  }
@@ -457,71 +365,78 @@
    assert debugEnter(CLASS_NAME, "applyConfigurationChange",
                      String.valueOf(configEntry));
    DN                configEntryDN       = configEntry.getDN();
    ResultCode        resultCode          = ResultCode.SUCCESS;
    boolean           adminActionRequired = false;
    ArrayList<String> messages            = new ArrayList<String>();
    // See if the entry indicates whether the key manager provider should be
    // enabled.  If not, then make sure that the key manager is disabled and
    // return since we don't need to do anything else.
    boolean needsEnabled          = false;
    String  existingProviderClass = null;
    int msgID = MSGID_CONFIG_KEYMANAGER_DESCRIPTION_ENABLED;
    BooleanConfigAttribute enabledStub =
         new BooleanConfigAttribute(ATTR_KEYMANAGER_ENABLED, getMessage(msgID),
                                    false);
    // Make sure that the entry has an appropriate objectclass for a key manager
    // provider.
    if (! configEntry.hasObjectClass(OC_KEY_MANAGER_PROVIDER))
    {
      int msgID = MSGID_CONFIG_KEYMANAGER_INVALID_CLASS;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
      resultCode = ResultCode.UNWILLING_TO_PERFORM;
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Get the corresponding key manager provider if it is active.
    KeyManagerProvider provider = providers.get(configEntryDN);
    // See if this provider should be enabled or disabled.
    boolean needsEnabled = false;
    BooleanConfigAttribute enabledAttr;
    try
    {
      BooleanConfigAttribute enabledAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(enabledStub);
      BooleanConfigAttribute enabledStub =
           new BooleanConfigAttribute(ATTR_KEYMANAGER_ENABLED,
                    getMessage(MSGID_CONFIG_KEYMANAGER_DESCRIPTION_ENABLED),
                    false);
      enabledAttr = (BooleanConfigAttribute)
                    configEntry.getConfigAttribute(enabledStub);
      if (enabledAttr == null)
      {
        msgID = MSGID_CONFIG_KEYMANAGER_NO_ENABLED_ATTR;
        messages.add(getMessage(msgID));
        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
        int msgID = MSGID_CONFIG_KEYMANAGER_NO_ENABLED_ATTR;
        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
        resultCode = ResultCode.UNWILLING_TO_PERFORM;
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
      else if (! enabledAttr.pendingValue())
      {
        DirectoryServer.getKeyManagerProvider().finalizeKeyManagerProvider();
        // The provider should be disabled, so install the null key manager and
        // return.
        try
        {
          NullKeyManagerProvider nullProvider = new NullKeyManagerProvider();
          nullProvider.initializeKeyManagerProvider(null);
          DirectoryServer.setKeyManagerProvider(nullProvider);
          return new ConfigChangeResult(resultCode, adminActionRequired,
                                        messages);
        }
        catch (Exception e)
        {
          assert debugException(CLASS_NAME, "applyConfigurationChange", e);
          msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_INSTALL_NULL_PROVIDER;
          messages.add(getMessage(msgID, stackTraceToSingleLineString(e)));
          resultCode = DirectoryServer.getServerErrorResultCode();
          return new ConfigChangeResult(resultCode, adminActionRequired,
                                        messages);
        }
      }
      else
      if (enabledAttr.activeValue())
      {
        // The provider should be enabled.  If it isn't, then set a flag to
        // indicate that we need to create it when we have more information.
        if (DirectoryServer.getKeyManagerProvider() instanceof
            NullKeyManagerProvider)
        if (provider == null)
        {
          needsEnabled = true;
        }
        else
        {
          existingProviderClass =
               DirectoryServer.getKeyManagerProvider().getClass().getName();
          // The provider is already active, so no action is required.
        }
      }
      else
      {
        if (provider == null)
        {
          // The provider is already disabled, so no action is required and we
          // can short-circuit out of this processing.
          return new ConfigChangeResult(resultCode, adminActionRequired,
                                        messages);
        }
        else
        {
          // The provider is active, so it needs to be disabled.  Do this and
          // return that we were successful.
          providers.remove(configEntryDN);
          DirectoryServer.deregisterKeyManagerProvider(configEntryDN);
          provider.finalizeKeyManagerProvider();
          return new ConfigChangeResult(resultCode, adminActionRequired,
                                        messages);
        }
      }
    }
@@ -529,133 +444,118 @@
    {
      assert debugException(CLASS_NAME, "applyConfigurationChange", e);
      msgID = MSGID_CONFIG_KEYMANAGER_UNABLE_TO_DETERMINE_ENABLED_STATE;
      messages.add(getMessage(msgID, stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_KEYMANAGER_INVALID_ENABLED_VALUE;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Get the class name from the configuration entry.
    // Make sure that the entry specifies the provider class name.  If it has
    // changed, then we will not try to dynamically apply it.
    String className;
    msgID = MSGID_CONFIG_KEYMANAGER_DESCRIPTION_CLASS;
    StringConfigAttribute classStub =
         new StringConfigAttribute(ATTR_KEYMANAGER_CLASS, getMessage(msgID),
                                   true, false, false);
    try
    {
      StringConfigAttribute classAttr =
      StringConfigAttribute classStub =
           new StringConfigAttribute(ATTR_KEYMANAGER_CLASS,
                    getMessage(MSGID_CONFIG_KEYMANAGER_DESCRIPTION_CLASS),
                    true, false, true);
      StringConfigAttribute classNameAttr =
           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
      if (classAttr == null)
      if (classNameAttr == null)
      {
        msgID = MSGID_CONFIG_KEYMANAGER_NO_CLASS_ATTR;
        messages.add(getMessage(msgID));
        int msgID = MSGID_CONFIG_KEYMANAGER_NO_CLASS_NAME;
        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
      else
      {
        className = classAttr.activeValue();
      }
      className = classNameAttr.pendingValue();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationChange", e);
      msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_DETERMINE_CLASS;
      messages.add(getMessage(msgID, stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_KEYMANAGER_INVALID_CLASS_NAME;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // If the key manager provider is already enabled and the specified class is
    // different from the class that is currently in use, then we won't try to
    // do anything.  The key manager provider must be disabled and re-enabled
    // before the configuration change will be accepted.
    if (! needsEnabled)
    boolean classChanged = false;
    String  oldClassName = null;
    if (provider != null)
    {
      if (! className.equals(existingProviderClass))
      oldClassName = provider.getClass().getName();
      classChanged = (! className.equals(oldClassName));
    }
    if (classChanged)
    {
      // This will not be applied dynamically.  Add a message to the response
      // and indicate that admin action is required.
      adminActionRequired = true;
      messages.add(getMessage(MSGID_CONFIG_KEYMANAGER_CLASS_ACTION_REQUIRED,
                              String.valueOf(oldClassName),
                              String.valueOf(className),
                              String.valueOf(configEntryDN)));
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    if (needsEnabled)
    {
      try
      {
        msgID = MSGID_CONFIG_KEYMANAGER_NOT_SWITCHING_CLASSES;
        messages.add(getMessage(msgID, String.valueOf(existingProviderClass),
                                String.valueOf(className)));
        resultCode = ResultCode.UNWILLING_TO_PERFORM;
        adminActionRequired = true;
        // FIXME -- Should this be done with a dynamic class loader?
        Class providerClass = Class.forName(className);
        provider = (KeyManagerProvider) providerClass.newInstance();
      }
      catch (Exception e)
      {
        assert debugException(CLASS_NAME, "applyConfigurationChange", e);
        int msgID = MSGID_CONFIG_KEYMANAGER_INVALID_CLASS;
        messages.add(getMessage(msgID, className,
                                String.valueOf(configEntryDN),
                                String.valueOf(e)));
        resultCode = DirectoryServer.getServerErrorResultCode();
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
      else
      try
      {
        // We don't need to do anything because it's already enabled and has the
        // right class.
        provider.initializeKeyManagerProvider(configEntry);
      }
      catch (Exception e)
      {
        assert debugException(CLASS_NAME, "applyConfigurationChange", e);
        int msgID = MSGID_CONFIG_KEYMANAGER_INITIALIZATION_FAILED;
        messages.add(getMessage(msgID, className,
                                String.valueOf(configEntryDN),
                                String.valueOf(e)));
        resultCode = DirectoryServer.getServerErrorResultCode();
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
    }
    // Try to load the class and instantiate it as a key manager provider.
    Class keyManagerProviderClass;
    try
    {
      // FIXME -- Should we use a custom class loader for this?
      keyManagerProviderClass = Class.forName(className);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationChange", e);
      msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_LOAD_CLASS;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    KeyManagerProvider keyManagerProvider;
    try
    {
      keyManagerProvider =
           (KeyManagerProvider) keyManagerProviderClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationChange", e);
      msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_INSTANTIATE_CLASS;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      providers.put(configEntryDN, provider);
      DirectoryServer.registerKeyManagerProvider(configEntryDN, provider);
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Try to initialize the key manager provider with the contents of the
    // configuration entry.
    try
    {
      keyManagerProvider.initializeKeyManagerProvider(configEntry);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationChange", e);
      msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_INITIALIZE;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Install the new key manager provider in the server.  We don't need to do
    // anything to get rid of the previous null provider since it doesn't
    // consume any resources.
    DirectoryServer.setKeyManagerProvider(keyManagerProvider);
    // If we've gotten here, then there haven't been any changes to anything
    // that we care about.
    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
  }
@@ -681,127 +581,161 @@
                      String.valueOf(configEntry), "java.lang.StringBuilder");
    // Get the DN of the provided entry and see if it is the DN that we expect
    // for the key manager configuration.  If it is not, then it's not an entry
    // that we care about so return true.
    DN providedEntryDN = configEntry.getDN();
    DN expectedEntryDN;
    try
    // Make sure that no entry already exists with the specified DN.
    DN configEntryDN = configEntry.getDN();
    if (providers.containsKey(configEntryDN))
    {
      expectedEntryDN = DN.decode(DN_KEYMANAGER_PROVIDER_CONFIG);
    }
    catch (DirectoryException de)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", de);
      unacceptableReason.append(de.getErrorMessage());
      int    msgID   = MSGID_CONFIG_KEYMANAGER_EXISTS;
      String message = getMessage(msgID, String.valueOf(configEntryDN));
      unacceptableReason.append(message);
      return false;
    }
    if (! providedEntryDN.equals(expectedEntryDN))
    // Make sure that the entry has an appropriate objectclass for a key manager
    // provider.
    if (! configEntry.hasObjectClass(OC_KEY_MANAGER_PROVIDER))
    {
      return true;
      int    msgID   = MSGID_CONFIG_KEYMANAGER_INVALID_OBJECTCLASS;
      String message = getMessage(msgID, configEntry.getDN().toString());
      unacceptableReason.append(message);
      return false;
    }
    // See if the entry indicates whether the key manager provider should be
    // enabled.
    int msgID = MSGID_CONFIG_KEYMANAGER_DESCRIPTION_ENABLED;
    BooleanConfigAttribute enabledStub =
         new BooleanConfigAttribute(ATTR_KEYMANAGER_ENABLED, getMessage(msgID),
                                    false);
    // Make sure that the entry specifies the key manager provider class.
    StringConfigAttribute classNameAttr;
    try
    {
      BooleanConfigAttribute enabledAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(enabledStub);
      StringConfigAttribute classStub =
           new StringConfigAttribute(ATTR_KEYMANAGER_CLASS,
                    getMessage(MSGID_CONFIG_KEYMANAGER_DESCRIPTION_CLASS),
                    true, false, true);
      classNameAttr = (StringConfigAttribute)
                      configEntry.getConfigAttribute(classStub);
      if (classNameAttr == null)
      {
        int msgID = MSGID_CONFIG_KEYMANAGER_NO_CLASS_NAME;
        String message = getMessage(msgID, configEntry.getDN().toString());
        unacceptableReason.append(message);
        return false;
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      int msgID = MSGID_CONFIG_KEYMANAGER_INVALID_CLASS_NAME;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    Class providerClass;
    try
    {
      // FIXME -- Should this be done with a custom class loader?
      providerClass = Class.forName(classNameAttr.pendingValue());
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      int msgID = MSGID_CONFIG_KEYMANAGER_INVALID_CLASS_NAME;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    KeyManagerProvider provider;
    try
    {
      provider = (KeyManagerProvider) providerClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      int msgID = MSGID_CONFIG_KEYMANAGER_INVALID_CLASS;
      String message = getMessage(msgID, providerClass.getName(),
                                  String.valueOf(configEntryDN),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    // See if this provider should be enabled.
    BooleanConfigAttribute enabledAttr;
    try
    {
      BooleanConfigAttribute enabledStub =
           new BooleanConfigAttribute(ATTR_KEYMANAGER_ENABLED,
                    getMessage(MSGID_CONFIG_KEYMANAGER_DESCRIPTION_ENABLED),
                               false);
      enabledAttr = (BooleanConfigAttribute)
                    configEntry.getConfigAttribute(enabledStub);
      if (enabledAttr == null)
      {
        msgID = MSGID_CONFIG_KEYMANAGER_NO_ENABLED_ATTR;
        unacceptableReason.append(getMessage(msgID));
        int msgID = MSGID_CONFIG_KEYMANAGER_NO_ENABLED_ATTR;
        String message = getMessage(msgID, configEntry.getDN().toString());
        unacceptableReason.append(message);
        return false;
      }
      else if (! enabledAttr.pendingValue())
      {
        // The key manager provider is not enabled, so we don't need to do any
        // further validation.
        return true;
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      int msgID = MSGID_CONFIG_KEYMANAGER_INVALID_ENABLED_VALUE;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    // If the provider is a configurable component, then make sure that its
    // configuration is valid.
    if (provider instanceof ConfigurableComponent)
    {
      ConfigurableComponent cc = (ConfigurableComponent) provider;
      LinkedList<String> errorMessages = new LinkedList<String>();
      if (! cc.hasAcceptableConfiguration(configEntry, errorMessages))
      {
        if (errorMessages.isEmpty())
        {
          int msgID = MSGID_CONFIG_KEYMANAGER_UNACCEPTABLE_CONFIG;
          unacceptableReason.append(getMessage(msgID,
                                               String.valueOf(configEntryDN)));
        }
        else
        {
          Iterator<String> iterator = errorMessages.iterator();
          unacceptableReason.append(iterator.next());
          while (iterator.hasNext())
          {
            unacceptableReason.append("  ");
            unacceptableReason.append(iterator.next());
          }
        }
        return false;
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      msgID = MSGID_CONFIG_KEYMANAGER_UNABLE_TO_DETERMINE_ENABLED_STATE;
      unacceptableReason.append(getMessage(msgID,
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    // See if it specifies the class name for the key manager provider
    // implementation.
    String className;
    msgID = MSGID_CONFIG_KEYMANAGER_DESCRIPTION_CLASS;
    StringConfigAttribute classStub =
         new StringConfigAttribute(ATTR_KEYMANAGER_CLASS, getMessage(msgID),
                                   true, false, false);
    try
    {
      StringConfigAttribute classAttr =
           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
      if (classAttr == null)
      {
        msgID = MSGID_CONFIG_KEYMANAGER_NO_CLASS_ATTR;
        unacceptableReason.append(getMessage(msgID));
        return false;
      }
      else
      {
        className = classAttr.activeValue();
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_DETERMINE_CLASS;
      unacceptableReason.append(getMessage(msgID,
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    // Try to load the class and instantiate it as a key manager provider.
    Class keyManagerProviderClass;
    try
    {
      // FIXME -- Should we use a custom class loader for this?
      keyManagerProviderClass = Class.forName(className);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_LOAD_CLASS;
      unacceptableReason.append(getMessage(msgID, String.valueOf(className),
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    try
    {
      KeyManagerProvider keyManagerProvider =
           (KeyManagerProvider) keyManagerProviderClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_INSTANTIATE_CLASS;
      unacceptableReason.append(getMessage(msgID, String.valueOf(className),
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    // If we've gotten to this point, then it is acceptable as far as we are
    // concerned.  If it is unacceptable according to the configuration, then
    // the key manager provider itself will make that determination.
    // If we've gotten here then the provider entry appears to be acceptable.
    return true;
  }
@@ -821,84 +755,48 @@
    assert debugEnter(CLASS_NAME, "applyConfigurationAdd",
                      String.valueOf(configEntry));
    DN                configEntryDN       = configEntry.getDN();
    ResultCode        resultCode          = ResultCode.SUCCESS;
    boolean           adminActionRequired = false;
    ArrayList<String> messages            = new ArrayList<String>();
    // Get the DN of the provided entry and see if it is the DN that we expect
    // for the key manager configuration.  If it is not, then it's not an entry
    // that we care about so return without doing anything.
    DN providedEntryDN = configEntry.getDN();
    DN expectedEntryDN;
    try
    // Make sure that the entry has an appropriate objectclass for a key manager
    // provider.
    if (! configEntry.hasObjectClass(OC_KEY_MANAGER_PROVIDER))
    {
      expectedEntryDN = DN.decode(DN_KEYMANAGER_PROVIDER_CONFIG);
    }
    catch (DirectoryException de)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", de);
      messages.add(de.getErrorMessage());
      resultCode = de.getResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    if (! providedEntryDN.equals(expectedEntryDN))
    {
      int    msgID   = MSGID_CONFIG_KEYMANAGER_INVALID_OBJECTCLASS;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
      resultCode = ResultCode.UNWILLING_TO_PERFORM;
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Register as a change listener of the provided entry so that we will be
    // notified of changes to it.  We will also want to register a delete
    // listener with its parent to allow us to determine if the entry is
    // deleted.
    configEntry.registerChangeListener(this);
    // See if this provider should be enabled or disabled.
    BooleanConfigAttribute enabledAttr;
    try
    {
      DN parentDN = configEntry.getDN().getParentDNInSuffix();
      ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN);
      if (parentEntry != null)
      {
        parentEntry.registerDeleteListener(this);
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      BooleanConfigAttribute enabledStub =
           new BooleanConfigAttribute(ATTR_KEYMANAGER_ENABLED,
                    getMessage(MSGID_CONFIG_KEYMANAGER_DESCRIPTION_ENABLED),
                               false);
      enabledAttr = (BooleanConfigAttribute)
                    configEntry.getConfigAttribute(enabledStub);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING,
               MSGID_CONFIG_KEYMANAGER_CANNOT_REGISTER_DELETE_LISTENER,
               stackTraceToSingleLineString(e));
    }
    // See if the entry indicates whether the key manager provider should be
    // enabled.
    int msgID = MSGID_CONFIG_KEYMANAGER_DESCRIPTION_ENABLED;
    BooleanConfigAttribute enabledStub =
         new BooleanConfigAttribute(ATTR_KEYMANAGER_ENABLED, getMessage(msgID),
                                    false);
    try
    {
      BooleanConfigAttribute enabledAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(enabledStub);
      if (enabledAttr == null)
      {
        // The attribute is not present, so the key manager provider will be
        // disabled.  Log a warning message and return.
        messages.add(getMessage(MSGID_CONFIG_KEYMANAGER_NO_ENABLED_ATTR));
        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
        // The attribute doesn't exist, so it will be disabled by default.
        int msgID = MSGID_CONFIG_KEYMANAGER_NO_ENABLED_ATTR;
        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
        resultCode = ResultCode.SUCCESS;
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
      else if (! enabledAttr.activeValue())
      {
        // The key manager provider is explicitly disabled.  Log a mild warning
        // and return.
        messages.add(getMessage(MSGID_CONFIG_KEYMANAGER_DISABLED));
        // It is explicitly configured as disabled, so we don't need to do
        // anything.
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
@@ -907,107 +805,86 @@
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      msgID = MSGID_CONFIG_KEYMANAGER_UNABLE_TO_DETERMINE_ENABLED_STATE;
      messages.add(getMessage(msgID, stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_KEYMANAGER_INVALID_ENABLED_VALUE;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // See if it specifies the class name for the key manager provider
    // implementation.
    // Make sure that the entry specifies the provider class name.
    String className;
    msgID = MSGID_CONFIG_KEYMANAGER_DESCRIPTION_CLASS;
    StringConfigAttribute classStub =
         new StringConfigAttribute(ATTR_KEYMANAGER_CLASS, getMessage(msgID),
                                   true, false, false);
    try
    {
      StringConfigAttribute classAttr =
      StringConfigAttribute classStub =
           new StringConfigAttribute(ATTR_KEYMANAGER_CLASS,
                    getMessage(MSGID_CONFIG_KEYMANAGER_DESCRIPTION_CLASS),
                    true, false, true);
      StringConfigAttribute classNameAttr =
           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
      if (classAttr == null)
      if (classNameAttr == null)
      {
        messages.add(getMessage(MSGID_CONFIG_KEYMANAGER_NO_CLASS_ATTR));
        int msgID = MSGID_CONFIG_KEYMANAGER_NO_CLASS_NAME;
        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
      else
      {
        className = classAttr.activeValue();
      }
      className = classNameAttr.pendingValue();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_DETERMINE_CLASS;
      messages.add(getMessage(msgID, stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_KEYMANAGER_INVALID_CLASS_NAME;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Try to load the class and instantiate it as a key manager provider.
    Class keyManagerProviderClass;
    // Load and initialize the provider class, and register it with the
    // Directory Server.
    KeyManagerProvider provider;
    try
    {
      // FIXME -- Should we use a custom class loader for this?
      keyManagerProviderClass = Class.forName(className);
      // FIXME -- Should this be done with a dynamic class loader?
      Class providerClass = Class.forName(className);
      provider = (KeyManagerProvider) providerClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_LOAD_CLASS;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_KEYMANAGER_INVALID_CLASS;
      messages.add(getMessage(msgID, className, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    KeyManagerProvider keyManagerProvider;
    try
    {
      keyManagerProvider =
           (KeyManagerProvider) keyManagerProviderClass.newInstance();
      provider.initializeKeyManagerProvider(configEntry);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_INSTANTIATE_CLASS;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_KEYMANAGER_INITIALIZATION_FAILED;
      messages.add(getMessage(msgID, className, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Try to initialize the key manager provider with the contents of the
    // configuration entry.
    try
    {
      keyManagerProvider.initializeKeyManagerProvider(configEntry);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_INITIALIZE;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Install the new key manager provider in the server.  We don't need to do
    // anything to get rid of the previous null provider since it doesn't
    // consume any resources.
    DirectoryServer.setKeyManagerProvider(keyManagerProvider);
    providers.put(configEntryDN, provider);
    DirectoryServer.registerKeyManagerProvider(configEntryDN, provider);
    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
  }
@@ -1033,46 +910,7 @@
                      String.valueOf(configEntry), "java.lang.StringBuilder");
    // Get the DN of the provided entry and see if it is the DN that we expect
    // for the key manager configuration.  If it is not, then it's not an entry
    // that we care about so return true.
    DN providedEntryDN = configEntry.getDN();
    DN expectedEntryDN;
    try
    {
      expectedEntryDN = DN.decode(DN_KEYMANAGER_PROVIDER_CONFIG);
    }
    catch (DirectoryException de)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", de);
      unacceptableReason.append(de.getErrorMessage());
      return false;
    }
    if (! providedEntryDN.equals(expectedEntryDN))
    {
      return true;
    }
    // Determine whether there is a valid key manager provider installed (i.e.,
    // not the null provider).  If a valid provider is installed, then we will
    // not allow the entry to be removed.
    KeyManagerProvider installedProvider =
         DirectoryServer.getKeyManagerProvider();
    if (! (installedProvider instanceof NullKeyManagerProvider))
    {
      int msgID = MSGID_CONFIG_KEYMANAGER_CANNOT_REMOVE_ACTIVE_PROVIDER;
      unacceptableReason.append(getMessage(msgID,
                                     installedProvider.getClass().getName()));
      return false;
    }
    // If we've gotten to this point, then it is acceptable as far as we are
    // concerned.  If it is unacceptable according to the configuration, then
    // the key manager provider itself will make that determination.
    // A delete should always be acceptable, so just return true.
    return true;
  }
@@ -1091,14 +929,23 @@
    assert debugEnter(CLASS_NAME, "applyConfigurationDelete",
                      String.valueOf(configEntry));
    ResultCode        resultCode          = ResultCode.SUCCESS;
    boolean           adminActionRequired = false;
    ArrayList<String> messages            = new ArrayList<String>();
    DN         configEntryDN       = configEntry.getDN();
    ResultCode resultCode          = ResultCode.SUCCESS;
    boolean    adminActionRequired = false;
    // Since we can never delete an active configuration, there is nothing that
    // we need to do if a delete does go through.
    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    // See if the entry is registered as a key manager provider.  If so,
    // deregister it and stop the provider.
    KeyManagerProvider provider = providers.remove(configEntryDN);
    if (provider != null)
    {
      DirectoryServer.deregisterKeyManagerProvider(configEntryDN);
      provider.finalizeKeyManagerProvider();
    }
    return new ConfigChangeResult(resultCode, adminActionRequired);
  }
}
opendj-sdk/opends/src/server/org/opends/server/core/TrustManagerProviderConfigManager.java
@@ -22,24 +22,29 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.core;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import org.opends.server.api.ConfigAddListener;
import org.opends.server.api.ConfigChangeListener;
import org.opends.server.api.ConfigDeleteListener;
import org.opends.server.api.ConfigHandler;
import org.opends.server.api.ConfigurableComponent;
import org.opends.server.api.TrustManagerProvider;
import org.opends.server.config.BooleanConfigAttribute;
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.config.StringConfigAttribute;
import org.opends.server.extensions.NullTrustManagerProvider;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.DN;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
@@ -51,15 +56,17 @@
import static org.opends.server.loggers.Error.*;
import static org.opends.server.messages.ConfigMessages.*;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines a utility that will be used to manage the configuration
 * for the Directory Server trust manager provider.  Only a single trust manager
 * provider may be defined, but if it is absent or disabled, then a null
 * provider will be used which will not allow any trust manager interaction.
 * This class defines a utility that will be used to manage the set of
 * trust manager providers defined in the Directory Server.  It will initialize
 * the providers when the server starts, and then will manage any additions,
 * removals, or modifications of any trust manager providers while the server is
 * running.
 */
public class TrustManagerProviderConfigManager
       implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener
@@ -72,6 +79,15 @@
  // A mapping between the DNs of the config entries and the associated
  // trust manager providers.
  private ConcurrentHashMap<DN,TrustManagerProvider> providers;
  // The configuration handler for the Directory Server.
  private ConfigHandler configHandler;
  /**
   * Creates a new instance of this trust manager provider config manager.
   */
@@ -79,243 +95,123 @@
  {
    assert debugConstructor(CLASS_NAME);
    // No implementation is required.
    configHandler = DirectoryServer.getConfigHandler();
    providers     = new ConcurrentHashMap<DN,TrustManagerProvider>();
  }
  /**
   * Initializes the configuration associated with the Directory Server trust
   * manager provider.  This should only be called at Directory Server startup.
   * If an error occurs, then a message will be logged and the null trust
   * manager provider will be installed.
   * Initializes all trust manager providers currently defined in the Directory
   * Server configuration.  This should only be called at Directory Server
   * startup.
   *
   * @throws  InitializationException  If a problem occurs while trying to
   *                                   install the null trust manager provider.
   * @throws  ConfigException  If a configuration problem causes the trust
   *                           manager provider initialization process to fail.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   the trust manager providers that is not
   *                                   related to the server configuration.
   */
  public void initializeTrustManagerProvider()
         throws InitializationException
  public void initializeTrustManagerProviders()
         throws ConfigException, InitializationException
  {
    assert debugEnter(CLASS_NAME, "initializeTrustManagerProvider");
    assert debugEnter(CLASS_NAME, "initializeTrustManagerProviders");
    // First, install a null trust manager provider so that there will be one
    // even if we encounter a problem later.
    // First, get the configuration base entry.
    ConfigEntry baseEntry;
    try
    {
      NullTrustManagerProvider nullProvider = new NullTrustManagerProvider();
      nullProvider.initializeTrustManagerProvider(null);
      DirectoryServer.setTrustManagerProvider(nullProvider);
      DN providerBase = DN.decode(DN_TRUSTMANAGER_PROVIDER_CONFIG_BASE);
      baseEntry = configHandler.getConfigEntry(providerBase);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeTrustManagerProvider", e);
      assert debugException(CLASS_NAME, "initializeTrustManagerProviders",
                            e);
      int msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_INSTALL_NULL_PROVIDER;
      String message = getMessage(msgID, stackTraceToSingleLineString(e));
      throw new InitializationException(msgID, message, e);
      int    msgID   = MSGID_CONFIG_TRUSTMANAGER_CANNOT_GET_BASE;
      String message = getMessage(msgID, String.valueOf(e));
      throw new ConfigException(msgID, message, e);
    }
    if (baseEntry == null)
    {
      // The trust manager provider base entry does not exist.  This is not
      // acceptable, so throw an exception.
      int    msgID   = MSGID_CONFIG_TRUSTMANAGER_BASE_DOES_NOT_EXIST;
      String message = getMessage(msgID);
      throw new ConfigException(msgID, message);
    }
    // Get the trust manager provider configuration entry.  If it is not
    // present, then register an add listener and just go with the null
    // provider.
    DN configEntryDN;
    ConfigEntry configEntry;
    try
    {
      configEntryDN = DN.decode(DN_TRUSTMANAGER_PROVIDER_CONFIG);
      configEntry   = DirectoryServer.getConfigEntry(configEntryDN);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeTrustManagerProvider", e);
    // Register add and delete listeners with the trust manager provider base
    // entry.  We don't care about modifications to it.
    baseEntry.registerAddListener(this);
    baseEntry.registerDeleteListener(this);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_TRUSTMANAGER_CANNOT_GET_CONFIG_ENTRY,
               stackTraceToSingleLineString(e));
    // See if the base entry has any children.  If not, then we don't need to do
    // anything else.
    if (! baseEntry.hasChildren())
    {
      return;
    }
    if (configEntry == null)
    // Iterate through the child entries and process them as trust manager
    // provider configuration entries.
    for (ConfigEntry childEntry : baseEntry.getChildren().values())
    {
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING,
               MSGID_CONFIG_TRUSTMANAGER_NO_CONFIG_ENTRY);
      childEntry.registerChangeListener(this);
      StringBuilder unacceptableReason = new StringBuilder();
      if (! configAddIsAcceptable(childEntry, unacceptableReason))
      {
        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
                 MSGID_CONFIG_TRUSTMANAGER_ENTRY_UNACCEPTABLE,
                 childEntry.getDN().toString(), unacceptableReason.toString());
        continue;
      }
      try
      {
        ConfigEntry parentEntry = DirectoryServer
            .getConfigEntry(configEntryDN.getParentDNInSuffix());
        if (parentEntry != null)
        ConfigChangeResult result = applyConfigurationAdd(childEntry);
        if (result.getResultCode() != ResultCode.SUCCESS)
        {
          parentEntry.registerAddListener(this);
          StringBuilder buffer = new StringBuilder();
          List<String> resultMessages = result.getMessages();
          if ((resultMessages == null) || (resultMessages.isEmpty()))
          {
            buffer.append(getMessage(MSGID_CONFIG_UNKNOWN_UNACCEPTABLE_REASON));
          }
          else
          {
            Iterator<String> iterator = resultMessages.iterator();
            buffer.append(iterator.next());
            while (iterator.hasNext())
            {
              buffer.append(EOL);
              buffer.append(iterator.next());
            }
          }
          logError(ErrorLogCategory.CONFIGURATION,
                   ErrorLogSeverity.SEVERE_ERROR,
                   MSGID_CONFIG_TRUSTMANAGER_CANNOT_CREATE_PROVIDER,
                   childEntry.getDN().toString(), buffer.toString());
        }
      }
      catch (Exception e)
      {
        assert debugException(CLASS_NAME, "initializeTrustManagerProvider", e);
        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
                 MSGID_CONFIG_TRUSTMANAGER_CANNOT_REGISTER_ADD_LISTENER,
                 stackTraceToSingleLineString(e));
      }
      return;
    }
    // At this point, we have a configuration entry.  Register a change listener
    // with it so we can be notified of changes to it over time.  We will also
    // want to register a delete listener with its parent to allow us to
    // determine if the entry is deleted.
    configEntry.registerChangeListener(this);
    try
    {
      DN parentDN = configEntryDN.getParentDNInSuffix();
      ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN);
      if (parentEntry != null)
      {
        parentEntry.registerDeleteListener(this);
                 MSGID_CONFIG_TRUSTMANAGER_CANNOT_CREATE_PROVIDER,
                 childEntry.getDN().toString(), String.valueOf(e));
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeTrustManagerProvider", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING,
               MSGID_CONFIG_TRUSTMANAGER_CANNOT_REGISTER_DELETE_LISTENER,
               stackTraceToSingleLineString(e));
    }
    // See if the entry indicates whether the trust manager provider should be
    // enabled.
    int msgID = MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_ENABLED;
    BooleanConfigAttribute enabledStub =
         new BooleanConfigAttribute(ATTR_TRUSTMANAGER_ENABLED,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute enabledAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(enabledStub);
      if (enabledAttr == null)
      {
        // The attribute is not present, so the trust manager provider will be
        // disabled.  Log a warning message and return.
        logError(ErrorLogCategory.CONFIGURATION,
                 ErrorLogSeverity.SEVERE_WARNING,
                 MSGID_CONFIG_TRUSTMANAGER_NO_ENABLED_ATTR);
        return;
      }
      else if (! enabledAttr.activeValue())
      {
        // The trust manager provider is explicitly disabled.  Log a mild
        // warning and return.
        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_WARNING,
                 MSGID_CONFIG_TRUSTMANAGER_DISABLED);
        return;
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeTrustManagerProvider", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_TRUSTMANAGER_UNABLE_TO_DETERMINE_ENABLED_STATE,
               stackTraceToSingleLineString(e));
      return;
    }
    // See if it specifies the class name for the trust manager provider
    // implementation.
    String className;
    msgID = MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_CLASS;
    StringConfigAttribute classStub =
         new StringConfigAttribute(ATTR_TRUSTMANAGER_CLASS, getMessage(msgID),
                                   true, false, false);
    try
    {
      StringConfigAttribute classAttr =
           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
      if (classAttr == null)
      {
        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
                 MSGID_CONFIG_TRUSTMANAGER_NO_CLASS_ATTR);
        return;
      }
      else
      {
        className = classAttr.activeValue();
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeTrustManagerProvider", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_TRUSTMANAGER_CANNOT_DETERMINE_CLASS,
               stackTraceToSingleLineString(e));
      return;
    }
    // Try to load the class and instantiate it as a trust manager provider.
    Class trustManagerProviderClass;
    try
    {
      // FIXME -- Should we use a custom class loader for this?
      trustManagerProviderClass = Class.forName(className);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeTrustManagerProvider", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_TRUSTMANAGER_CANNOT_LOAD_CLASS,
               String.valueOf(className), stackTraceToSingleLineString(e));
      return;
    }
    TrustManagerProvider trustManagerProvider;
    try
    {
      trustManagerProvider =
           (TrustManagerProvider) trustManagerProviderClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeTrustManagerProvider", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_TRUSTMANAGER_CANNOT_INSTANTIATE_CLASS,
               String.valueOf(className), stackTraceToSingleLineString(e));
      return;
    }
    // Try to initialize the trust manager provider with the contents of the
    // configuration entry.
    try
    {
      trustManagerProvider.initializeTrustManagerProvider(configEntry);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeTrustManagerProvider", e);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_TRUSTMANAGER_CANNOT_INITIALIZE,
               String.valueOf(className), stackTraceToSingleLineString(e));
      return;
    }
    // Install the new trust manager provider in the server.  We don't need to
    // do anything to get rid of the previous null provider since it doesn't
    // consume any resources.
    DirectoryServer.setTrustManagerProvider(trustManagerProvider);
  }
@@ -340,21 +236,98 @@
                      String.valueOf(configEntry), "java.lang.StringBuilder");
    // See if the entry indicates whether the trust manager provider should be
    // enabled.
    int msgID = MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_ENABLED;
    BooleanConfigAttribute enabledStub =
         new BooleanConfigAttribute(ATTR_TRUSTMANAGER_ENABLED,
                                    getMessage(msgID), false);
    // Make sure that the entry has an appropriate objectclass for a trust
    // manager provider.
    if (! configEntry.hasObjectClass(OC_TRUST_MANAGER_PROVIDER))
    {
      int    msgID   = MSGID_CONFIG_TRUSTMANAGER_INVALID_OBJECTCLASS;
      String message = getMessage(msgID, configEntry.getDN().toString());
      unacceptableReason.append(message);
      return false;
    }
    // Make sure that the entry specifies the provider class name.
    StringConfigAttribute classNameAttr;
    try
    {
      BooleanConfigAttribute enabledAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(enabledStub);
      StringConfigAttribute classStub =
           new StringConfigAttribute(ATTR_TRUSTMANAGER_CLASS,
                    getMessage(MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_CLASS),
                    true, false, true);
      classNameAttr = (StringConfigAttribute)
                      configEntry.getConfigAttribute(classStub);
      if (classNameAttr == null)
      {
        int    msgID   = MSGID_CONFIG_TRUSTMANAGER_NO_CLASS_NAME;
        String message = getMessage(msgID, configEntry.getDN().toString());
        unacceptableReason.append(message);
        return false;
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      int    msgID   = MSGID_CONFIG_TRUSTMANAGER_INVALID_CLASS_NAME;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    Class providerClass;
    try
    {
      // FIXME -- Should this be done with a custom class loader?
      providerClass = Class.forName(classNameAttr.pendingValue());
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      int    msgID   = MSGID_CONFIG_TRUSTMANAGER_INVALID_CLASS_NAME;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    try
    {
      TrustManagerProvider provider =
           (TrustManagerProvider) providerClass.newInstance();
    }
    catch(Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      int    msgID   = MSGID_CONFIG_TRUSTMANAGER_INVALID_CLASS;
      String message = getMessage(msgID, providerClass.getName(),
                                  String.valueOf(configEntry.getDN()),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    // See if this trust manager provider should be enabled.
    BooleanConfigAttribute enabledAttr;
    try
    {
      BooleanConfigAttribute enabledStub =
           new BooleanConfigAttribute(ATTR_TRUSTMANAGER_ENABLED,
                    getMessage(MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_ENABLED),
                               false);
      enabledAttr = (BooleanConfigAttribute)
                    configEntry.getConfigAttribute(enabledStub);
      if (enabledAttr == null)
      {
        msgID = MSGID_CONFIG_TRUSTMANAGER_NO_ENABLED_ATTR;
        unacceptableReason.append(getMessage(msgID));
        int    msgID   = MSGID_CONFIG_TRUSTMANAGER_NO_ENABLED_ATTR;
        String message = getMessage(msgID, configEntry.getDN().toString());
        unacceptableReason.append(message);
        return false;
      }
    }
@@ -362,83 +335,16 @@
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_UNABLE_TO_DETERMINE_ENABLED_STATE;
      unacceptableReason.append(getMessage(msgID,
                                           stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_TRUSTMANAGER_INVALID_ENABLED_VALUE;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    // See if it specifies the class name for the trust manager provider
    // implementation.
    String className;
    msgID = MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_CLASS;
    StringConfigAttribute classStub =
         new StringConfigAttribute(ATTR_TRUSTMANAGER_CLASS, getMessage(msgID),
                                   true, false, false);
    try
    {
      StringConfigAttribute classAttr =
           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
      if (classAttr == null)
      {
        msgID = MSGID_CONFIG_TRUSTMANAGER_NO_CLASS_ATTR;
        unacceptableReason.append(getMessage(msgID));
        return false;
      }
      else
      {
        className = classAttr.activeValue();
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_DETERMINE_CLASS;
      unacceptableReason.append(getMessage(msgID,
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    // Try to load the class and instantiate it as a trust manager provider.
    Class trustManagerProviderClass;
    try
    {
      // FIXME -- Should we use a custom class loader for this?
      trustManagerProviderClass = Class.forName(className);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_LOAD_CLASS;
      unacceptableReason.append(getMessage(msgID, String.valueOf(className),
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    try
    {
      TrustManagerProvider trustManagerProvider =
           (TrustManagerProvider) trustManagerProviderClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configChangeIsAcceptable", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_INSTANTIATE_CLASS;
      unacceptableReason.append(getMessage(msgID, String.valueOf(className),
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    // If we've gotten to this point, then it is acceptable as far as we are
    // concerned.  If it is unacceptable according to the configuration, then
    // the trust manager provider itself will make that determination.
    // If we've gotten here then the trust manager provider entry appears to be
    // acceptable.
    return true;
  }
@@ -459,73 +365,78 @@
    assert debugEnter(CLASS_NAME, "applyConfigurationChange",
                      String.valueOf(configEntry));
    DN                configEntryDN       = configEntry.getDN();
    ResultCode        resultCode          = ResultCode.SUCCESS;
    boolean           adminActionRequired = false;
    ArrayList<String> messages            = new ArrayList<String>();
    // See if the entry indicates whether the trust manager provider should be
    // enabled.  If not, then make sure that the trust manager is disabled and
    // return since we don't need to do anything else.
    boolean needsEnabled          = false;
    String  existingProviderClass = null;
    int msgID = MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_ENABLED;
    BooleanConfigAttribute enabledStub =
         new BooleanConfigAttribute(ATTR_TRUSTMANAGER_ENABLED,
                                    getMessage(msgID), false);
    // Make sure that the entry has an appropriate objectclass for a trust
    // manager provider.
    if (! configEntry.hasObjectClass(OC_TRUST_MANAGER_PROVIDER))
    {
      int msgID = MSGID_CONFIG_TRUSTMANAGER_INVALID_CLASS;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
      resultCode = ResultCode.UNWILLING_TO_PERFORM;
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Get the corresponding trust manager provider if it is active.
    TrustManagerProvider provider = providers.get(configEntryDN);
    // See if this provider should be enabled or disabled.
    boolean needsEnabled = false;
    BooleanConfigAttribute enabledAttr;
    try
    {
      BooleanConfigAttribute enabledAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(enabledStub);
      BooleanConfigAttribute enabledStub =
           new BooleanConfigAttribute(ATTR_TRUSTMANAGER_ENABLED,
                    getMessage(MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_ENABLED),
                    false);
      enabledAttr = (BooleanConfigAttribute)
                    configEntry.getConfigAttribute(enabledStub);
      if (enabledAttr == null)
      {
        msgID = MSGID_CONFIG_TRUSTMANAGER_NO_ENABLED_ATTR;
        messages.add(getMessage(msgID));
        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
        int msgID = MSGID_CONFIG_TRUSTMANAGER_NO_ENABLED_ATTR;
        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
        resultCode = ResultCode.UNWILLING_TO_PERFORM;
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
      else if (! enabledAttr.pendingValue())
      {
        DirectoryServer.getTrustManagerProvider().
             finalizeTrustManagerProvider();
        // The provider should be disabled, so install the null trust manager
        // and return.
        try
        {
          NullTrustManagerProvider nullProvider =
               new NullTrustManagerProvider();
          nullProvider.initializeTrustManagerProvider(null);
          DirectoryServer.setTrustManagerProvider(nullProvider);
          return new ConfigChangeResult(resultCode, adminActionRequired,
                                        messages);
        }
        catch (Exception e)
        {
          assert debugException(CLASS_NAME, "applyConfigurationChange", e);
          msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_INSTALL_NULL_PROVIDER;
          messages.add(getMessage(msgID, stackTraceToSingleLineString(e)));
          resultCode = DirectoryServer.getServerErrorResultCode();
          return new ConfigChangeResult(resultCode, adminActionRequired,
                                        messages);
        }
      }
      else
      if (enabledAttr.activeValue())
      {
        // The provider should be enabled.  If it isn't, then set a flag to
        // indicate that we need to create it when we have more information.
        if (DirectoryServer.getTrustManagerProvider() instanceof
            NullTrustManagerProvider)
        if (provider == null)
        {
          needsEnabled = true;
        }
        else
        {
          existingProviderClass =
               DirectoryServer.getTrustManagerProvider().getClass().getName();
          // The provider is already active, so no action is required.
        }
      }
      else
      {
        if (provider == null)
        {
          // The provider is already disabled, so no action is required and we
          // can short-circuit out of this processing.
          return new ConfigChangeResult(resultCode, adminActionRequired,
                                        messages);
        }
        else
        {
          // The provider is active, so it needs to be disabled.  Do this and
          // return that we were successful.
          providers.remove(configEntryDN);
          DirectoryServer.deregisterTrustManagerProvider(configEntryDN);
          provider.finalizeTrustManagerProvider();
          return new ConfigChangeResult(resultCode, adminActionRequired,
                                        messages);
        }
      }
    }
@@ -533,133 +444,118 @@
    {
      assert debugException(CLASS_NAME, "applyConfigurationChange", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_UNABLE_TO_DETERMINE_ENABLED_STATE;
      messages.add(getMessage(msgID, stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_TRUSTMANAGER_INVALID_ENABLED_VALUE;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Get the class name from the configuration entry.
    // Make sure that the entry specifies the provider class name.  If it has
    // changed, then we will not try to dynamically apply it.
    String className;
    msgID = MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_CLASS;
    StringConfigAttribute classStub =
         new StringConfigAttribute(ATTR_TRUSTMANAGER_CLASS, getMessage(msgID),
                                   true, false, false);
    try
    {
      StringConfigAttribute classAttr =
      StringConfigAttribute classStub =
           new StringConfigAttribute(ATTR_TRUSTMANAGER_CLASS,
                    getMessage(MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_CLASS),
                    true, false, true);
      StringConfigAttribute classNameAttr =
           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
      if (classAttr == null)
      if (classNameAttr == null)
      {
        msgID = MSGID_CONFIG_TRUSTMANAGER_NO_CLASS_ATTR;
        messages.add(getMessage(msgID));
        int msgID = MSGID_CONFIG_TRUSTMANAGER_NO_CLASS_NAME;
        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
      else
      {
        className = classAttr.activeValue();
      }
      className = classNameAttr.pendingValue();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationChange", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_DETERMINE_CLASS;
      messages.add(getMessage(msgID, stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_TRUSTMANAGER_INVALID_CLASS_NAME;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // If the trust manager provider is already enabled and the specified class
    // is different from the class that is currently in use, then we won't try
    // to do anything.  The trust manager provider must be disabled and
    // re-enabled before the configuration change will be accepted.
    if (! needsEnabled)
    boolean classChanged = false;
    String  oldClassName = null;
    if (provider != null)
    {
      if (! className.equals(existingProviderClass))
      oldClassName = provider.getClass().getName();
      classChanged = (! className.equals(oldClassName));
    }
    if (classChanged)
    {
      // This will not be applied dynamically.  Add a message to the response
      // and indicate that admin action is required.
      adminActionRequired = true;
      messages.add(getMessage(MSGID_CONFIG_TRUSTMANAGER_CLASS_ACTION_REQUIRED,
                              String.valueOf(oldClassName),
                              String.valueOf(className),
                              String.valueOf(configEntryDN)));
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    if (needsEnabled)
    {
      try
      {
        msgID = MSGID_CONFIG_TRUSTMANAGER_NOT_SWITCHING_CLASSES;
        messages.add(getMessage(msgID, String.valueOf(existingProviderClass),
                                String.valueOf(className)));
        resultCode = ResultCode.UNWILLING_TO_PERFORM;
        adminActionRequired = true;
        // FIXME -- Should this be done with a dynamic class loader?
        Class providerClass = Class.forName(className);
        provider = (TrustManagerProvider) providerClass.newInstance();
      }
      catch (Exception e)
      {
        assert debugException(CLASS_NAME, "applyConfigurationChange", e);
        int msgID = MSGID_CONFIG_TRUSTMANAGER_INVALID_CLASS;
        messages.add(getMessage(msgID, className,
                                String.valueOf(configEntryDN),
                                String.valueOf(e)));
        resultCode = DirectoryServer.getServerErrorResultCode();
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
      else
      try
      {
        // We don't need to do anything because it's already enabled and has the
        // right class.
        provider.initializeTrustManagerProvider(configEntry);
      }
      catch (Exception e)
      {
        assert debugException(CLASS_NAME, "applyConfigurationChange", e);
        int msgID = MSGID_CONFIG_TRUSTMANAGER_INITIALIZATION_FAILED;
        messages.add(getMessage(msgID, className,
                                String.valueOf(configEntryDN),
                                String.valueOf(e)));
        resultCode = DirectoryServer.getServerErrorResultCode();
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
    }
    // Try to load the class and instantiate it as a trust manager provider.
    Class trustManagerProviderClass;
    try
    {
      // FIXME -- Should we use a custom class loader for this?
      trustManagerProviderClass = Class.forName(className);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationChange", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_LOAD_CLASS;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    TrustManagerProvider trustManagerProvider;
    try
    {
      trustManagerProvider =
           (TrustManagerProvider) trustManagerProviderClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationChange", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_INSTANTIATE_CLASS;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      providers.put(configEntryDN, provider);
      DirectoryServer.registerTrustManagerProvider(configEntryDN, provider);
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Try to initialize the trust manager provider with the contents of the
    // configuration entry.
    try
    {
      trustManagerProvider.initializeTrustManagerProvider(configEntry);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationChange", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_INITIALIZE;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Install the new trust manager provider in the server.  We don't need to
    // do anything to get rid of the previous null provider since it doesn't
    // consume any resources.
    DirectoryServer.setTrustManagerProvider(trustManagerProvider);
    // If we've gotten here, then there haven't been any changes to anything
    // that we care about.
    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
  }
@@ -685,127 +581,161 @@
                      String.valueOf(configEntry), "java.lang.StringBuilder");
    // Get the DN of the provided entry and see if it is the DN that we expect
    // for the trust manager configuration.  If it is not, then it's not an
    // entry that we care about so return true.
    DN providedEntryDN = configEntry.getDN();
    DN expectedEntryDN;
    try
    // Make sure that no entry already exists with the specified DN.
    DN configEntryDN = configEntry.getDN();
    if (providers.containsKey(configEntryDN))
    {
      expectedEntryDN = DN.decode(DN_TRUSTMANAGER_PROVIDER_CONFIG);
    }
    catch (DirectoryException de)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", de);
      unacceptableReason.append(de.getErrorMessage());
      int    msgID   = MSGID_CONFIG_TRUSTMANAGER_EXISTS;
      String message = getMessage(msgID, String.valueOf(configEntryDN));
      unacceptableReason.append(message);
      return false;
    }
    if (! providedEntryDN.equals(expectedEntryDN))
    // Make sure that the entry has an appropriate objectclass for a trust
    // manager provider.
    if (! configEntry.hasObjectClass(OC_TRUST_MANAGER_PROVIDER))
    {
      return true;
      int    msgID   = MSGID_CONFIG_TRUSTMANAGER_INVALID_OBJECTCLASS;
      String message = getMessage(msgID, configEntry.getDN().toString());
      unacceptableReason.append(message);
      return false;
    }
    // See if the entry indicates whether the trust manager provider should be
    // enabled.
    int msgID = MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_ENABLED;
    BooleanConfigAttribute enabledStub =
         new BooleanConfigAttribute(ATTR_TRUSTMANAGER_ENABLED,
                                    getMessage(msgID), false);
    // Make sure that the entry specifies the trust manager provider class.
    StringConfigAttribute classNameAttr;
    try
    {
      BooleanConfigAttribute enabledAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(enabledStub);
      StringConfigAttribute classStub =
           new StringConfigAttribute(ATTR_TRUSTMANAGER_CLASS,
                    getMessage(MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_CLASS),
                    true, false, true);
      classNameAttr = (StringConfigAttribute)
                      configEntry.getConfigAttribute(classStub);
      if (classNameAttr == null)
      {
        int msgID = MSGID_CONFIG_TRUSTMANAGER_NO_CLASS_NAME;
        String message = getMessage(msgID, configEntry.getDN().toString());
        unacceptableReason.append(message);
        return false;
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      int msgID = MSGID_CONFIG_TRUSTMANAGER_INVALID_CLASS_NAME;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    Class providerClass;
    try
    {
      // FIXME -- Should this be done with a custom class loader?
      providerClass = Class.forName(classNameAttr.pendingValue());
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      int msgID = MSGID_CONFIG_TRUSTMANAGER_INVALID_CLASS_NAME;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    TrustManagerProvider provider;
    try
    {
      provider = (TrustManagerProvider) providerClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      int msgID = MSGID_CONFIG_TRUSTMANAGER_INVALID_CLASS;
      String message = getMessage(msgID, providerClass.getName(),
                                  String.valueOf(configEntryDN),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    // See if this provider should be enabled.
    BooleanConfigAttribute enabledAttr;
    try
    {
      BooleanConfigAttribute enabledStub =
           new BooleanConfigAttribute(ATTR_TRUSTMANAGER_ENABLED,
                    getMessage(MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_ENABLED),
                               false);
      enabledAttr = (BooleanConfigAttribute)
                    configEntry.getConfigAttribute(enabledStub);
      if (enabledAttr == null)
      {
        msgID = MSGID_CONFIG_TRUSTMANAGER_NO_ENABLED_ATTR;
        unacceptableReason.append(getMessage(msgID));
        int msgID = MSGID_CONFIG_TRUSTMANAGER_NO_ENABLED_ATTR;
        String message = getMessage(msgID, configEntry.getDN().toString());
        unacceptableReason.append(message);
        return false;
      }
      else if (! enabledAttr.pendingValue())
      {
        // The trust manager provider is not enabled, so we don't need to do any
        // further validation.
        return true;
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      int msgID = MSGID_CONFIG_TRUSTMANAGER_INVALID_ENABLED_VALUE;
      String message = getMessage(msgID, configEntry.getDN().toString(),
                                  String.valueOf(e));
      unacceptableReason.append(message);
      return false;
    }
    // If the provider is a configurable component, then make sure that its
    // configuration is valid.
    if (provider instanceof ConfigurableComponent)
    {
      ConfigurableComponent cc = (ConfigurableComponent) provider;
      LinkedList<String> errorMessages = new LinkedList<String>();
      if (! cc.hasAcceptableConfiguration(configEntry, errorMessages))
      {
        if (errorMessages.isEmpty())
        {
          int msgID = MSGID_CONFIG_TRUSTMANAGER_UNACCEPTABLE_CONFIG;
          unacceptableReason.append(getMessage(msgID,
                                               String.valueOf(configEntryDN)));
        }
        else
        {
          Iterator<String> iterator = errorMessages.iterator();
          unacceptableReason.append(iterator.next());
          while (iterator.hasNext())
          {
            unacceptableReason.append("  ");
            unacceptableReason.append(iterator.next());
          }
        }
        return false;
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_UNABLE_TO_DETERMINE_ENABLED_STATE;
      unacceptableReason.append(getMessage(msgID,
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    // See if it specifies the class name for the trust manager provider
    // implementation.
    String className;
    msgID = MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_CLASS;
    StringConfigAttribute classStub =
         new StringConfigAttribute(ATTR_TRUSTMANAGER_CLASS, getMessage(msgID),
                                   true, false, false);
    try
    {
      StringConfigAttribute classAttr =
           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
      if (classAttr == null)
      {
        msgID = MSGID_CONFIG_TRUSTMANAGER_NO_CLASS_ATTR;
        unacceptableReason.append(getMessage(msgID));
        return false;
      }
      else
      {
        className = classAttr.activeValue();
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_DETERMINE_CLASS;
      unacceptableReason.append(getMessage(msgID,
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    // Try to load the class and instantiate it as a trust manager provider.
    Class trustManagerProviderClass;
    try
    {
      // FIXME -- Should we use a custom class loader for this?
      trustManagerProviderClass = Class.forName(className);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_LOAD_CLASS;
      unacceptableReason.append(getMessage(msgID, String.valueOf(className),
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    try
    {
      TrustManagerProvider trustManagerProvider =
           (TrustManagerProvider) trustManagerProviderClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_INSTANTIATE_CLASS;
      unacceptableReason.append(getMessage(msgID, String.valueOf(className),
                                           stackTraceToSingleLineString(e)));
      return false;
    }
    // If we've gotten to this point, then it is acceptable as far as we are
    // concerned.  If it is unacceptable according to the configuration, then
    // the trust manager provider itself will make that determination.
    // If we've gotten here then the provider entry appears to be acceptable.
    return true;
  }
@@ -825,84 +755,48 @@
    assert debugEnter(CLASS_NAME, "applyConfigurationAdd",
                      String.valueOf(configEntry));
    DN                configEntryDN       = configEntry.getDN();
    ResultCode        resultCode          = ResultCode.SUCCESS;
    boolean           adminActionRequired = false;
    ArrayList<String> messages            = new ArrayList<String>();
    // Get the DN of the provided entry and see if it is the DN that we expect
    // for the trust manager configuration.  If it is not, then it's not an
    // entry that we care about so return without doing anything.
    DN providedEntryDN = configEntry.getDN();
    DN expectedEntryDN;
    try
    // Make sure that the entry has an appropriate objectclass for a trust
    // manager provider.
    if (! configEntry.hasObjectClass(OC_TRUST_MANAGER_PROVIDER))
    {
      expectedEntryDN = DN.decode(DN_TRUSTMANAGER_PROVIDER_CONFIG);
    }
    catch (DirectoryException de)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", de);
      messages.add(de.getErrorMessage());
      resultCode = de.getResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    if (! providedEntryDN.equals(expectedEntryDN))
    {
      int    msgID   = MSGID_CONFIG_TRUSTMANAGER_INVALID_OBJECTCLASS;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
      resultCode = ResultCode.UNWILLING_TO_PERFORM;
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Register as a change listener of the provided entry so that we will be
    // notified of changes to it.  We will also want to register a delete
    // listener with its parent to allow us to determine if the entry is
    // deleted.
    configEntry.registerChangeListener(this);
    // See if this provider should be enabled or disabled.
    BooleanConfigAttribute enabledAttr;
    try
    {
      DN parentDN = configEntry.getDN().getParentDNInSuffix();
      ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN);
      if (parentEntry != null)
      {
        parentEntry.registerDeleteListener(this);
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      BooleanConfigAttribute enabledStub =
           new BooleanConfigAttribute(ATTR_TRUSTMANAGER_ENABLED,
                    getMessage(MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_ENABLED),
                               false);
      enabledAttr = (BooleanConfigAttribute)
                    configEntry.getConfigAttribute(enabledStub);
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING,
               MSGID_CONFIG_TRUSTMANAGER_CANNOT_REGISTER_DELETE_LISTENER,
               stackTraceToSingleLineString(e));
    }
    // See if the entry indicates whether the trust manager provider should be
    // enabled.
    int msgID = MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_ENABLED;
    BooleanConfigAttribute enabledStub =
         new BooleanConfigAttribute(ATTR_TRUSTMANAGER_ENABLED,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute enabledAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(enabledStub);
      if (enabledAttr == null)
      {
        // The attribute is not present, so the trust manager provider will be
        // disabled.  Log a warning message and return.
        messages.add(getMessage(MSGID_CONFIG_TRUSTMANAGER_NO_ENABLED_ATTR));
        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
        // The attribute doesn't exist, so it will be disabled by default.
        int msgID = MSGID_CONFIG_TRUSTMANAGER_NO_ENABLED_ATTR;
        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
        resultCode = ResultCode.SUCCESS;
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
      else if (! enabledAttr.activeValue())
      {
        // The trust manager provider is explicitly disabled.  Log a mild
        // warning and return.
        messages.add(getMessage(MSGID_CONFIG_TRUSTMANAGER_DISABLED));
        // It is explicitly configured as disabled, so we don't need to do
        // anything.
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
@@ -911,107 +805,86 @@
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_UNABLE_TO_DETERMINE_ENABLED_STATE;
      messages.add(getMessage(msgID, stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_TRUSTMANAGER_INVALID_ENABLED_VALUE;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // See if it specifies the class name for the trust manager provider
    // implementation.
    // Make sure that the entry specifies the provider class name.
    String className;
    msgID = MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_CLASS;
    StringConfigAttribute classStub =
         new StringConfigAttribute(ATTR_TRUSTMANAGER_CLASS, getMessage(msgID),
                                   true, false, false);
    try
    {
      StringConfigAttribute classAttr =
      StringConfigAttribute classStub =
           new StringConfigAttribute(ATTR_TRUSTMANAGER_CLASS,
                    getMessage(MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_CLASS),
                    true, false, true);
      StringConfigAttribute classNameAttr =
           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
      if (classAttr == null)
      if (classNameAttr == null)
      {
        messages.add(getMessage(MSGID_CONFIG_TRUSTMANAGER_NO_CLASS_ATTR));
        int msgID = MSGID_CONFIG_TRUSTMANAGER_NO_CLASS_NAME;
        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
        return new ConfigChangeResult(resultCode, adminActionRequired,
                                      messages);
      }
      else
      {
        className = classAttr.activeValue();
      }
      className = classNameAttr.pendingValue();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_DETERMINE_CLASS;
      messages.add(getMessage(msgID, stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_TRUSTMANAGER_INVALID_CLASS_NAME;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Try to load the class and instantiate it as a trust manager provider.
    Class trustManagerProviderClass;
    // Load and initialize the provider class, and register it with the
    // Directory Server.
    TrustManagerProvider provider;
    try
    {
      // FIXME -- Should we use a custom class loader for this?
      trustManagerProviderClass = Class.forName(className);
      // FIXME -- Should this be done with a dynamic class loader?
      Class providerClass = Class.forName(className);
      provider = (TrustManagerProvider) providerClass.newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_LOAD_CLASS;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_TRUSTMANAGER_INVALID_CLASS;
      messages.add(getMessage(msgID, className, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    TrustManagerProvider trustManagerProvider;
    try
    {
      trustManagerProvider =
           (TrustManagerProvider) trustManagerProviderClass.newInstance();
      provider.initializeTrustManagerProvider(configEntry);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_INSTANTIATE_CLASS;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      int msgID = MSGID_CONFIG_TRUSTMANAGER_INITIALIZATION_FAILED;
      messages.add(getMessage(msgID, className, String.valueOf(configEntryDN),
                              String.valueOf(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Try to initialize the trust manager provider with the contents of the
    // configuration entry.
    try
    {
      trustManagerProvider.initializeTrustManagerProvider(configEntry);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyConfigurationAdd", e);
      msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_INITIALIZE;
      messages.add(getMessage(msgID, String.valueOf(className),
                              stackTraceToSingleLineString(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Install the new trust manager provider in the server.  We don't need to
    // do anything to get rid of the previous null provider since it doesn't
    // consume any resources.
    DirectoryServer.setTrustManagerProvider(trustManagerProvider);
    providers.put(configEntryDN, provider);
    DirectoryServer.registerTrustManagerProvider(configEntryDN, provider);
    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
  }
@@ -1037,46 +910,7 @@
                      String.valueOf(configEntry), "java.lang.StringBuilder");
    // Get the DN of the provided entry and see if it is the DN that we expect
    // for the trust manager configuration.  If it is not, then it's not an
    // entry that we care about so return true.
    DN providedEntryDN = configEntry.getDN();
    DN expectedEntryDN;
    try
    {
      expectedEntryDN = DN.decode(DN_TRUSTMANAGER_PROVIDER_CONFIG);
    }
    catch (DirectoryException de)
    {
      assert debugException(CLASS_NAME, "configAddIsAcceptable", de);
      unacceptableReason.append(de.getErrorMessage());
      return false;
    }
    if (! providedEntryDN.equals(expectedEntryDN))
    {
      return true;
    }
    // Determine whether there is a valid trust manager provider installed
    // (i.e., not the null provider).  If a valid provider is installed, then we
    // will not allow the entry to be removed.
    TrustManagerProvider installedProvider =
         DirectoryServer.getTrustManagerProvider();
    if (! (installedProvider instanceof NullTrustManagerProvider))
    {
      int msgID = MSGID_CONFIG_TRUSTMANAGER_CANNOT_REMOVE_ACTIVE_PROVIDER;
      unacceptableReason.append(getMessage(msgID,
                                     installedProvider.getClass().getName()));
      return false;
    }
    // If we've gotten to this point, then it is acceptable as far as we are
    // concerned.  If it is unacceptable according to the configuration, then
    // the trust manager provider itself will make that determination.
    // A delete should always be acceptable, so just return true.
    return true;
  }
@@ -1095,14 +929,23 @@
    assert debugEnter(CLASS_NAME, "applyConfigurationDelete",
                      String.valueOf(configEntry));
    ResultCode        resultCode          = ResultCode.SUCCESS;
    boolean           adminActionRequired = false;
    ArrayList<String> messages            = new ArrayList<String>();
    DN         configEntryDN       = configEntry.getDN();
    ResultCode resultCode          = ResultCode.SUCCESS;
    boolean    adminActionRequired = false;
    // Since we can never delete an active configuration, there is nothing that
    // we need to do if a delete does go through.
    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    // See if the entry is registered as a trust manager provider.  If so,
    // deregister it and stop the provider.
    TrustManagerProvider provider = providers.remove(configEntryDN);
    if (provider != null)
    {
      DirectoryServer.deregisterTrustManagerProvider(configEntryDN);
      provider.finalizeTrustManagerProvider();
    }
    return new ConfigChangeResult(resultCode, adminActionRequired);
  }
}
opendj-sdk/opends/src/server/org/opends/server/extensions/ExternalSASLMechanismHandler.java
@@ -33,6 +33,7 @@
import java.util.LinkedList;
import java.util.List;
import org.opends.server.api.CertificateMapper;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.ConfigurableComponent;
import org.opends.server.api.ConnectionSecurityProvider;
@@ -40,6 +41,7 @@
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.MultiChoiceConfigAttribute;
import org.opends.server.config.StringConfigAttribute;
import org.opends.server.core.BindOperation;
@@ -110,6 +112,9 @@
  // client with a certificate in the user's entry.
  private CertificateValidationPolicy validationPolicy;
  // The DN of the configuration entry for the associated certificate mapper.
  private DN certificateMapperDN;
  // The DN of the configuration entry for this SASL mechanism handler.
  private DN configEntryDN;
@@ -217,6 +222,48 @@
    }
    // Get the DN of the certificate mapper to use with this handler.
    msgID = MSGID_SASLEXTERNAL_DESCRIPTION_CERT_MAPPER_DN;
    DNConfigAttribute certMapperStub =
         new DNConfigAttribute(ATTR_CERTMAPPER_DN, getMessage(msgID), true,
                               false, false);
    try
    {
      DNConfigAttribute certMapperAttr =
           (DNConfigAttribute) configEntry.getConfigAttribute(certMapperStub);
      if (certMapperAttr == null)
      {
        msgID = MSGID_SASLEXTERNAL_NO_CERTIFICATE_MAPPER_DN;
        String message = getMessage(msgID, String.valueOf(configEntryDN));
        throw new ConfigException(msgID, message);
      }
      else
      {
        certificateMapperDN = certMapperAttr.activeValue();
        CertificateMapper mapper =
             DirectoryServer.getCertificateMapper(certificateMapperDN);
        if (mapper == null)
        {
          msgID = MSGID_SASLEXTERNAL_INVALID_CERTIFICATE_MAPPER_DN;
          String message = getMessage(msgID, String.valueOf(configEntryDN),
                                      String.valueOf(certificateMapperDN));
          throw new ConfigException(msgID, message);
        }
      }
    }
    catch (ConfigException ce)
    {
      throw ce;
    }
    catch (Exception e)
    {
      msgID = MSGID_SASLEXTERNAL_CANNOT_GET_CERT_MAPPER_DN;
      String message = getMessage(msgID, String.valueOf(configEntryDN),
                                  stackTraceToSingleLineString(e));
      throw new ConfigException(msgID, message);
    }
    DirectoryServer.registerSASLMechanismHandler(SASL_MECHANISM_EXTERNAL, this);
    DirectoryServer.registerConfigurableComponent(this);
  }
@@ -306,13 +353,27 @@
    }
    // Get the certificate mapper to use to map the certificate to a user entry.
    CertificateMapper certificateMapper =
         DirectoryServer.getCertificateMapper(certificateMapperDN);
    if (certificateMapper == null)
    {
      bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
      int    msgID   = MSGID_SASLEXTERNAL_INVALID_CERTIFICATE_MAPPER_DN;
      String message = getMessage(msgID, String.valueOf(configEntryDN),
                                  String.valueOf(certificateMapperDN));
      bindOperation.setAuthFailureReason(msgID, message);
      return;
    }
    // Use the Directory Server certificate mapper to map the client certificate
    // chain to a single user DN.
    Entry userEntry;
    try
    {
      userEntry = DirectoryServer.getCertificateMapper().mapCertificateToUser(
                                                              clientCertChain);
      userEntry = certificateMapper.mapCertificateToUser(clientCertChain);
    }
    catch (DirectoryException de)
    {
@@ -506,6 +567,11 @@
                                           getMessage(msgID), false, false,
                                           false, certTypeStr));
    msgID = MSGID_SASLEXTERNAL_DESCRIPTION_CERT_MAPPER_DN;
    attrList.add(new DNConfigAttribute(ATTR_CERTMAPPER_DN, getMessage(msgID),
                                       true, false, false,
                                       certificateMapperDN));
    return attrList;
  }
@@ -602,6 +668,47 @@
    }
    // Look at the certificate mapper DN.
    msgID = MSGID_SASLEXTERNAL_DESCRIPTION_CERT_MAPPER_DN;
    DNConfigAttribute certMapperStub =
         new DNConfigAttribute(ATTR_CERTMAPPER_DN, getMessage(msgID), true,
                               false, false);
    try
    {
      DNConfigAttribute certMapperAttr =
           (DNConfigAttribute) configEntry.getConfigAttribute(certMapperStub);
      if (certMapperAttr == null)
      {
        msgID = MSGID_SASLEXTERNAL_NO_CERTIFICATE_MAPPER_DN;
        String message = getMessage(msgID, String.valueOf(configEntryDN));
        unacceptableReasons.add(message);
        return false;
      }
      else
      {
        DN certMapperDN = certMapperAttr.activeValue();
        CertificateMapper mapper =
             DirectoryServer.getCertificateMapper(certMapperDN);
        if (mapper == null)
        {
          msgID = MSGID_SASLEXTERNAL_INVALID_CERTIFICATE_MAPPER_DN;
          String message = getMessage(msgID, String.valueOf(configEntryDN),
                                      String.valueOf(certMapperDN));
          unacceptableReasons.add(message);
          return false;
        }
      }
    }
    catch (Exception e)
    {
      msgID = MSGID_SASLEXTERNAL_CANNOT_GET_CERT_MAPPER_DN;
      String message = getMessage(msgID, String.valueOf(configEntryDN),
                                  stackTraceToSingleLineString(e));
      unacceptableReasons.add(message);
      return false;
    }
    // If we've gotten to this point, then everything must be OK.
    return true;
  }
@@ -716,6 +823,57 @@
    }
    // Look at the certificate mapper DN.
    DN newCertificateMapperDN = null;
    msgID = MSGID_SASLEXTERNAL_DESCRIPTION_CERT_MAPPER_DN;
    DNConfigAttribute certMapperStub =
         new DNConfigAttribute(ATTR_CERTMAPPER_DN, getMessage(msgID), true,
                               false, false);
    try
    {
      DNConfigAttribute certMapperAttr =
           (DNConfigAttribute) configEntry.getConfigAttribute(certMapperStub);
      if (certMapperAttr == null)
      {
        if (resultCode == ResultCode.SUCCESS)
        {
          resultCode = ResultCode.OBJECTCLASS_VIOLATION;
        }
        msgID = MSGID_SASLEXTERNAL_NO_CERTIFICATE_MAPPER_DN;
        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
      }
      else
      {
        newCertificateMapperDN = certMapperAttr.activeValue();
        CertificateMapper mapper =
             DirectoryServer.getCertificateMapper(newCertificateMapperDN);
        if (mapper == null)
        {
          if (resultCode == ResultCode.SUCCESS)
          {
            resultCode = ResultCode.OBJECTCLASS_VIOLATION;
          }
          msgID = MSGID_SASLEXTERNAL_INVALID_CERTIFICATE_MAPPER_DN;
          messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                                  String.valueOf(newCertificateMapperDN)));
        }
      }
    }
    catch (Exception e)
    {
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
      }
      msgID = MSGID_SASLEXTERNAL_CANNOT_GET_CERT_MAPPER_DN;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                              stackTraceToSingleLineString(e)));
    }
    // If everything has been successful, then apply any changes that were made.
    if (resultCode == ResultCode.SUCCESS)
    {
@@ -742,6 +900,18 @@
                                  certificateAttributeType.getNameOrOID()));
        }
      }
      if (! newCertificateMapperDN.equals(certificateMapperDN))
      {
        certificateMapperDN = newCertificateMapperDN;
        if (detailedResults)
        {
          msgID = MSGID_SASLEXTERNAL_UPDATED_CERT_MAPPER_DN;
          messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                                  String.valueOf(newCertificateMapperDN)));
        }
      }
    }
opendj-sdk/opends/src/server/org/opends/server/extensions/FileBasedKeyManagerProvider.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.extensions;
@@ -639,6 +639,9 @@
                      String.valueOf(configEntry), "java.util.List<String>");
    DN configEntryDN = configEntry.getDN();
    // Make sure that a keystore file was provided.
    int msgID = MSGID_FILE_KEYMANAGER_DESCRIPTION_FILE;
    StringConfigAttribute fileStub =
@@ -734,6 +737,7 @@
    // Make sure that there is some way to determine the PIN.  Look for the PIN
    // in a property, environment variable, file, or configuration attribute, in
    // that order.
    char[] keyStorePIN = null;
pinSelection:
    {
      msgID = MSGID_FILE_KEYMANAGER_DESCRIPTION_PIN_PROPERTY;
@@ -759,6 +763,7 @@
          }
          else
          {
            keyStorePIN = pinStr.toCharArray();
            break pinSelection;
          }
        }
@@ -797,6 +802,7 @@
          }
          else
          {
            keyStorePIN = pinStr.toCharArray();
            break pinSelection;
          }
        }
@@ -864,6 +870,7 @@
            }
            else
            {
              keyStorePIN = pinStr.toCharArray();
              break pinSelection;
            }
          }
@@ -891,6 +898,7 @@
             configEntry.getConfigAttribute(pinStub);
        if (pinAttr != null)
        {
          keyStorePIN = pinAttr.pendingValue().toCharArray();
          break pinSelection;
        }
      }
opendj-sdk/opends/src/server/org/opends/server/extensions/NullKeyManagerProvider.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.extensions;
@@ -37,7 +37,6 @@
import org.opends.server.types.InitializationException;
import static org.opends.server.loggers.Debug.*;
import static org.opends.server.messages.ExtensionsMessages.*;
import static org.opends.server.messages.MessageHandler.*;
opendj-sdk/opends/src/server/org/opends/server/extensions/PKCS11KeyManagerProvider.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.extensions;
@@ -517,10 +517,13 @@
    assert debugEnter(CLASS_NAME, "hasAcceptableConfiguration",
                      String.valueOf(configEntry), "java.util.List<String>");
    DN configEntryDN = configEntry.getDN();
    // Make sure that there is some way to determine the PIN.  Look for the PIN
    // in a property, environment variable, file, or configuration attribute, in
    // that order.
    char[] keyStorePIN = null;
pinSelection:
    {
      int msgID = MSGID_PKCS11_KEYMANAGER_DESCRIPTION_PIN_PROPERTY;
@@ -546,6 +549,7 @@
          }
          else
          {
            keyStorePIN = pinStr.toCharArray();
            break pinSelection;
          }
        }
@@ -584,6 +588,7 @@
          }
          else
          {
            keyStorePIN = pinStr.toCharArray();
            break pinSelection;
          }
        }
@@ -651,6 +656,7 @@
            }
            else
            {
              keyStorePIN = pinStr.toCharArray();
              break pinSelection;
            }
          }
@@ -678,6 +684,7 @@
             configEntry.getConfigAttribute(pinStub);
        if (pinAttr != null)
        {
          keyStorePIN = pinAttr.pendingValue().toCharArray();
          break pinSelection;
        }
      }
opendj-sdk/opends/src/server/org/opends/server/extensions/TLSConnectionSecurityProvider.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.extensions;
@@ -160,6 +160,7 @@
                                        SocketChannel socketChannel,
                                        TLSConnectionSecurityProvider
                                             parentProvider)
          throws DirectoryException
  {
    super();
@@ -171,7 +172,43 @@
    Socket socket = socketChannel.socket();
    InetAddress inetAddress = socketChannel.socket().getInetAddress();
    sslContext = parentProvider.sslContext;
    // Create an SSL session based on the configured key and trust stores in the
    // Directory Server.
    KeyManagerProvider keyManagerProvider =
         DirectoryServer.getKeyManagerProvider(
              clientConnection.getKeyManagerProviderDN());
    if (keyManagerProvider == null)
    {
      keyManagerProvider = new NullKeyManagerProvider();
    }
    TrustManagerProvider trustManagerProvider =
         DirectoryServer.getTrustManagerProvider(
              clientConnection.getTrustManagerProviderDN());
    if (trustManagerProvider == null)
    {
      trustManagerProvider = new NullTrustManagerProvider();
    }
    try
    {
      // FIXME -- Is it bad to create a new SSLContext for each connection?
      sslContext = SSLContext.getInstance(SSL_CONTEXT_INSTANCE_NAME);
      sslContext.init(keyManagerProvider.getKeyManagers(),
                      trustManagerProvider.getTrustManagers(), null);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeConnectionSecurityProvider",
                            e);
      int msgID = MSGID_TLS_SECURITY_PROVIDER_CANNOT_INITIALIZE;
      String message = getMessage(msgID, stackTraceToSingleLineString(e));
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                   message, msgID, e);
    }
    sslEngine = sslContext.createSSLEngine(inetAddress.getHostName(),
                                           socket.getPort());
    sslEngine.setUseClientMode(false);
@@ -259,32 +296,7 @@
    sslEngine        = null;
    // Create an SSL session based on the configured key and trust stores in the
    // Directory Server.
    KeyManagerProvider keyManagerProvider =
         DirectoryServer.getKeyManagerProvider();
    TrustManagerProvider trustManagerProvider =
         DirectoryServer.getTrustManagerProvider();
    try
    {
      sslContext = SSLContext.getInstance(SSL_CONTEXT_INSTANCE_NAME);
      sslContext.init(keyManagerProvider.getKeyManagers(),
                      trustManagerProvider.getTrustManagers(), null);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeConnectionSecurityProvider",
                            e);
      int msgID = MSGID_TLS_SECURITY_PROVIDER_CANNOT_INITIALIZE;
      String message = getMessage(msgID, stackTraceToSingleLineString(e));
      throw new InitializationException(msgID, message, e);
    }
    enabledProtocols = null;
    enabledProtocols    = null;
    enabledCipherSuites = null;
    sslClientAuthPolicy = SSLClientAuthPolicy.OPTIONAL;
  }
opendj-sdk/opends/src/server/org/opends/server/loggers/SignatureAction.java
@@ -22,25 +22,25 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.loggers;
import java.io.BufferedInputStream;
//import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.RandomAccessFile;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.X509Certificate;
import javax.net.ssl.KeyManager;
import javax.net.ssl.X509KeyManager;
//import java.io.FileInputStream;
//import java.io.RandomAccessFile;
//import java.security.MessageDigest;
//import java.security.PrivateKey;
//import java.security.PublicKey;
//import java.security.Signature;
//import java.security.cert.X509Certificate;
//import javax.net.ssl.KeyManager;
//import javax.net.ssl.X509KeyManager;
import org.opends.server.core.DirectoryServer;
//import org.opends.server.core.DirectoryServer;
import static org.opends.server.loggers.Debug.*;
//import static org.opends.server.loggers.Debug.*;
/**
 * This class implements a post rotation action that signs
@@ -101,73 +101,80 @@
   */
  public boolean execute()
  {
    FileInputStream fis = null;
    boolean inputStreamOpen = false;
    try
    {
      KeyManager[] keyMgrs =
           DirectoryServer.getKeyManagerProvider().getKeyManagers();
      if(keyMgrs.length == 0)
      {
        // No keys available.
        // FIXME - Log in error log.
        System.err.println("No private key available to sign with.");
        return false;
      }
      X509KeyManager mgr = (X509KeyManager) keyMgrs[0];
      PrivateKey priv = mgr.getPrivateKey(alias);
      Signature sig = Signature.getInstance(signatureAlgorithm);
      sig.initSign(priv);
      MessageDigest md = MessageDigest.getInstance(digestAlgorithm);
      md.reset();
      fis = new FileInputStream(originalFile);
      inputStreamOpen = true;
      BufferedInputStream bufin = new BufferedInputStream(fis);
      byte[] buffer = new byte[1024];
      int len;
      while (bufin.available() != 0)
      {
        len = bufin.read(buffer);
        md.update(buffer, 0, len);
      }
      bufin.close();
      // Create a hash of the log file contents.
      byte[] hash = md.digest();
      // printBytes(hash);
      sig.update(hash);
      // Sign the hash.
      byte[] realSig = sig.sign();
      // printBytes(realSig);
      // Append the signature to the end of the file.
      RandomAccessFile raf = new RandomAccessFile(originalFile, "rw");
      raf.seek(raf.length());
      raf.write(delimiter.getBytes());
      raf.write("\n".getBytes());
      raf.write(realSig);
      return true;
    } catch(Exception ioe)
    {
      assert debugException(CLASS_NAME, "execute", ioe);
      if(inputStreamOpen)
      {
        try
        {
          fis.close();
        } catch(Exception fe)
        {
                assert debugException(CLASS_NAME, "execute", fe);
          // Cannot do much. Ignore.
        }
      }
      return false;
    }
    // FIXME -- It is currently not possible to sign on rotate because of the
    // way that they key manager providers are defined.  However, this function
    // wasn't implemented in an ideal fashion anyway, so the signing capability
    // should remain disabled until the rotation action mechanism is rewritten.
    // The original code has been preserved here for reference purposes.
    return false;
//
//    FileInputStream fis = null;
//    boolean inputStreamOpen = false;
//    try
//    {
//      KeyManager[] keyMgrs =
//           DirectoryServer.getKeyManagerProvider().getKeyManagers();
//      if(keyMgrs.length == 0)
//      {
//        // No keys available.
//        // FIXME - Log in error log.
//        System.err.println("No private key available to sign with.");
//        return false;
//      }
//      X509KeyManager mgr = (X509KeyManager) keyMgrs[0];
//      PrivateKey priv = mgr.getPrivateKey(alias);
//
//      Signature sig = Signature.getInstance(signatureAlgorithm);
//      sig.initSign(priv);
//
//      MessageDigest md = MessageDigest.getInstance(digestAlgorithm);
//      md.reset();
//
//      fis = new FileInputStream(originalFile);
//      inputStreamOpen = true;
//      BufferedInputStream bufin = new BufferedInputStream(fis);
//      byte[] buffer = new byte[1024];
//      int len;
//      while (bufin.available() != 0)
//      {
//        len = bufin.read(buffer);
//        md.update(buffer, 0, len);
//      }
//      bufin.close();
//
//      // Create a hash of the log file contents.
//      byte[] hash = md.digest();
//      // printBytes(hash);
//      sig.update(hash);
//
//      // Sign the hash.
//      byte[] realSig = sig.sign();
//      // printBytes(realSig);
//
//      // Append the signature to the end of the file.
//      RandomAccessFile raf = new RandomAccessFile(originalFile, "rw");
//      raf.seek(raf.length());
//      raf.write(delimiter.getBytes());
//      raf.write("\n".getBytes());
//      raf.write(realSig);
//
//      return true;
//    } catch(Exception ioe)
//    {
//      assert debugException(CLASS_NAME, "execute", ioe);
//      if(inputStreamOpen)
//      {
//        try
//        {
//          fis.close();
//        } catch(Exception fe)
//        {
//                assert debugException(CLASS_NAME, "execute", fe);
//          // Cannot do much. Ignore.
//        }
//      }
//      return false;
//    }
  }
@@ -180,84 +187,90 @@
   */
  public boolean verify()
  {
    RandomAccessFile inFile = null;
    boolean inputStreamOpen = false;
    try
    {
      KeyManager[] keyMgrs =
           DirectoryServer.getKeyManagerProvider().getKeyManagers();
      if(keyMgrs.length == 0)
      {
        // No keys available.
        // FIXME - Log in error log.
        System.err.println("No public key available to verify signature with.");
        return false;
      }
      X509KeyManager mgr = (X509KeyManager) keyMgrs[0];
      X509Certificate[] certChain = mgr.getCertificateChain(alias);
      if(certChain == null || certChain.length == 0)
      {
        System.err.println("Cannot find the public key for the signature.");
        return false;
      }
      PublicKey pubKey = certChain[0].getPublicKey();
      Signature sig = Signature.getInstance(signatureAlgorithm);
      sig.initVerify(pubKey);
      MessageDigest md = MessageDigest.getInstance(digestAlgorithm);
      md.reset();
      inFile = new RandomAccessFile(originalFile, "r");
      inputStreamOpen = true;
      String line = null;
      while ((line = inFile.readLine()) != null)
      {
        if(line.equals(delimiter))
        {
          break;
        }
        // int len = line.length();
        // md.update(line.getBytes(), 0, len);
        byte[] b = (line + "\n").getBytes();
        md.update(b);
      }
      // Read signature
      byte[] sigToVerify = new byte[128];
      int val = inFile.read(sigToVerify, 0, 128);
      // printBytes(sigToVerify);
      // Create a hash of the log file contents.
      byte[] hash = md.digest();
      // printBytes(hash);
      sig.update(hash);
      // Verify the hash.
      boolean verifies = sig.verify(sigToVerify);
      return verifies;
    } catch(Exception ioe)
    {
      assert debugException(CLASS_NAME, "execute", ioe);
      if(inputStreamOpen)
      {
        try
        {
          inFile.close();
        } catch(Exception fe)
        {
                assert debugException(CLASS_NAME, "execute", fe);
          // Cannot do much. Ignore.
        }
      }
      return false;
    }
    // FIXME -- It is currently not possible to sign on rotate because of the
    // way that they key manager providers are defined.  However, this function
    // wasn't implemented in an ideal fashion anyway, so the signing capability
    // should remain disabled until the rotation action mechanism is rewritten.
    // The original code has been preserved here for reference purposes.
    return false;
//    RandomAccessFile inFile = null;
//    boolean inputStreamOpen = false;
//    try
//    {
//      KeyManager[] keyMgrs =
//           DirectoryServer.getKeyManagerProvider().getKeyManagers();
//
//      if(keyMgrs.length == 0)
//      {
//        // No keys available.
//        // FIXME - Log in error log.
//        System.err.println("No public key available to verify signature.");
//        return false;
//      }
//
//      X509KeyManager mgr = (X509KeyManager) keyMgrs[0];
//      X509Certificate[] certChain = mgr.getCertificateChain(alias);
//
//      if(certChain == null || certChain.length == 0)
//      {
//        System.err.println("Cannot find the public key for the signature.");
//        return false;
//      }
//
//      PublicKey pubKey = certChain[0].getPublicKey();
//
//      Signature sig = Signature.getInstance(signatureAlgorithm);
//      sig.initVerify(pubKey);
//
//      MessageDigest md = MessageDigest.getInstance(digestAlgorithm);
//      md.reset();
//
//      inFile = new RandomAccessFile(originalFile, "r");
//      inputStreamOpen = true;
//      String line = null;
//      while ((line = inFile.readLine()) != null)
//      {
//        if(line.equals(delimiter))
//        {
//          break;
//        }
//        // int len = line.length();
//        // md.update(line.getBytes(), 0, len);
//        byte[] b = (line + "\n").getBytes();
//        md.update(b);
//      }
//
//      // Read signature
//      byte[] sigToVerify = new byte[128];
//      int val = inFile.read(sigToVerify, 0, 128);
//      // printBytes(sigToVerify);
//
//      // Create a hash of the log file contents.
//      byte[] hash = md.digest();
//      // printBytes(hash);
//      sig.update(hash);
//
//
//      // Verify the hash.
//      boolean verifies = sig.verify(sigToVerify);
//
//      return verifies;
//    } catch(Exception ioe)
//    {
//      assert debugException(CLASS_NAME, "execute", ioe);
//      if(inputStreamOpen)
//      {
//        try
//        {
//          inFile.close();
//        } catch(Exception fe)
//        {
//                assert debugException(CLASS_NAME, "execute", fe);
//          // Cannot do much. Ignore.
//        }
//      }
//      return false;
//    }
  }
opendj-sdk/opends/src/server/org/opends/server/messages/ConfigMessages.java
@@ -3361,61 +3361,6 @@
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to install the null key manager provider.  This takes a single
   * argument, which is a string representation of the exception that was
   * caught.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_CANNOT_INSTALL_NULL_PROVIDER =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 308;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to retrieve the key manager provider configuration entry.  This
   * takes a single argument, which is a string representation of the exception
   * that was caught.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_CANNOT_GET_CONFIG_ENTRY =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 309;
  /**
   * The message ID for the message that will be used if the key manager
   * provider configuration entry does not exist.  This does not take any
   * arguments.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_NO_CONFIG_ENTRY =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 310;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to register to watch for the key manager provider configuration
   * entry to be created.  This takes a single argument, which is a string
   * representation of the exception that was caught.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_CANNOT_REGISTER_ADD_LISTENER =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 311;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to register to watch for the key manager provider configuration
   * entry to be removed.  This takes a single argument, which is a string
   * representation of the exception that was caught.
   */
  public static final int
       MSGID_CONFIG_KEYMANAGER_CANNOT_REGISTER_DELETE_LISTENER =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 312;
  /**
   * The message ID for the message that will be used as the description for the
   * key manager provider enabled attribute.  This does not take any arguments.
   */
@@ -3435,27 +3380,6 @@
  /**
   * The message ID for the message that will be used if the key manager
   * provider has been explicitly disabled.  This does not take any arguments.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_DISABLED =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 315;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to determine whether the key manager provider should be enabled.
   * This takes a single argument, which is a string representation of the
   * exception that was caught.
   */
  public static final int
       MSGID_CONFIG_KEYMANAGER_UNABLE_TO_DETERMINE_ENABLED_STATE =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 316;
  /**
   * The message ID for the message that will be used as the description for the
   * key manager provider class attribute.  This does not take any arguments.
   */
@@ -3465,117 +3389,6 @@
  /**
   * The message ID for the message that will be used if the entry key manager
   * provider configuration entry does not contain a class name attribute.  This
   * does not take any arguments.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_NO_CLASS_ATTR =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 318;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to determine the class to use for the key manager provider.
   * This takes a single argument, which is a string representation of the
   * exception that was caught.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_CANNOT_DETERMINE_CLASS =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 319;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to load the key manager provider class.  This takes two
   * arguments, which are the class name and a string representation of the
   * exception that was caught.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_CANNOT_LOAD_CLASS =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 320;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to instantiate the key manager provider class.  This takes two
   * arguments, which are the class name and a string representation of the
   * exception that was caught.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_CANNOT_INSTANTIATE_CLASS =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 321;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to initialize the key manager provider.  This takes two
   * arguments, which are the class name and a string representation of the
   * exception that was caught.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_CANNOT_INITIALIZE =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 322;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to install the null trust manager provider.  This takes a single
   * argument, which is a string representation of the exception that was
   * caught.
   */
  public static final int
       MSGID_CONFIG_TRUSTMANAGER_CANNOT_INSTALL_NULL_PROVIDER =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 323;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to retrieve the trust manager provider configuration entry.
   * This takes a single argument, which is a string representation of the
   * exception that was caught.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_CANNOT_GET_CONFIG_ENTRY =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 324;
  /**
   * The message ID for the message that will be used if the trust manager
   * provider configuration entry does not exist.  This does not take any
   * arguments.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_NO_CONFIG_ENTRY =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 325;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to register to watch for the trust manager provider
   * configuration entry to be created.  This takes a single argument, which is
   * a string representation of the exception that was caught.
   */
  public static final int
       MSGID_CONFIG_TRUSTMANAGER_CANNOT_REGISTER_ADD_LISTENER =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 326;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to register to watch for the trust manager provider
   * configuration entry to be removed.  This takes a single argument, which is
   * a string representation of the exception that was caught.
   */
  public static final int
       MSGID_CONFIG_TRUSTMANAGER_CANNOT_REGISTER_DELETE_LISTENER =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 327;
  /**
   * The message ID for the message that will be used as the description for the
   * trust manager provider enabled attribute.  This does not take any
   * arguments.
@@ -3596,27 +3409,6 @@
  /**
   * The message ID for the message that will be used if the trust manager
   * provider has been explicitly disabled.  This does not take any arguments.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_DISABLED =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 330;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to determine whether the trust manager provider should be
   * enabled.  This takes a single argument, which is a string representation of
   * the exception that was caught.
   */
  public static final int
       MSGID_CONFIG_TRUSTMANAGER_UNABLE_TO_DETERMINE_ENABLED_STATE =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 331;
  /**
   * The message ID for the message that will be used as the description for the
   * trust manager provider class attribute.  This does not take any arguments.
   */
@@ -3626,163 +3418,6 @@
  /**
   * The message ID for the message that will be used if the entry trust manager
   * provider configuration entry does not contain a class name attribute.  This
   * does not take any arguments.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_NO_CLASS_ATTR =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 333;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to determine the class to use for the trust manager provider.
   * This takes a single argument, which is a string representation of the
   * exception that was caught.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_CANNOT_DETERMINE_CLASS =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 334;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to load the trust manager provider class.  This takes two
   * arguments, which are the class name and a string representation of the
   * exception that was caught.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_CANNOT_LOAD_CLASS =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 335;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to instantiate the trust manager provider class.  This takes two
   * arguments, which are the class name and a string representation of the
   * exception that was caught.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_CANNOT_INSTANTIATE_CLASS =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 336;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to initialize the trust manager provider.  This takes two
   * arguments, which are the class name and a string representation of the
   * exception that was caught.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_CANNOT_INITIALIZE =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 337;
  /**
   * The message ID for the message that will be used if an attempt is made to
   * change the class used to implement a key manager provider while the
   * existing key manager provider is still enabled.  This takes two arguments,
   * which are the class name of the current key manager provider and the class
   * name of the requested new key manager provider.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_NOT_SWITCHING_CLASSES =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_MILD_ERROR | 338;
  /**
   * The message ID for the message that will be used if an attempt is made to
   * remove the key manager provider configuration entry while the provider is
   * still enabled.  This takes a single argument, which is the class name of
   * the active key manager provider.
   */
  public static final int
       MSGID_CONFIG_KEYMANAGER_CANNOT_REMOVE_ACTIVE_PROVIDER =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_MILD_ERROR | 339;
  /**
   * The message ID for the message that will be used if an attempt is made to
   * change the class used to implement a trust manager provider while the
   * existing trust manager provider is still enabled.  This takes two
   * arguments, which are the class name of the current trust manager provider
   * and the class name of the requested new trust manager provider.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_NOT_SWITCHING_CLASSES =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_MILD_ERROR | 340;
  /**
   * The message ID for the message that will be used if an attempt is made to
   * remove the trust manager provider configuration entry while the provider is
   * still enabled.  This takes a single argument, which is the class name of
   * the active trust manager provider.
   */
  public static final int
       MSGID_CONFIG_TRUSTMANAGER_CANNOT_REMOVE_ACTIVE_PROVIDER =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_MILD_ERROR | 341;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to install the default certificate mapper.  This takes a single
   * argument, which is a string representation of the exception that was
   * caught.
   */
  public static final int
       MSGID_CONFIG_CERTMAPPER_CANNOT_INSTALL_DEFAULT_MAPPER =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 342;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to retrieve the certificate mapper configuration entry.  This
   * takes a single argument, which is a string representation of the exception
   * that was caught.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_CANNOT_GET_CONFIG_ENTRY =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 343;
  /**
   * The message ID for the message that will be used if the certificate mapper
   * configuration entry does not exist.  This does not take any arguments.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_NO_CONFIG_ENTRY =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 344;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to register to watch for the certificate mapper configuration
   * entry to be created.  This takes a single argument, which is a string
   * representation of the exception that was caught.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_CANNOT_REGISTER_ADD_LISTENER =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 345;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to register to watch for the certificate mapper configuration
   * entry to be removed.  This takes a single argument, which is a string
   * representation of the exception that was caught.
   */
  public static final int
       MSGID_CONFIG_CERTMAPPER_CANNOT_REGISTER_DELETE_LISTENER =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 346;
  /**
   * The message ID for the message that will be used as the description for the
   * certificate mapper enabled attribute.  This does not take any arguments.
   */
@@ -3793,8 +3428,8 @@
  /**
   * The message ID for the message that will be used if the certificate mapper
   * configuration entry does not contain an enabled attribute.  This does not
   * take any arguments.
   * configuration entry does not contain an enabled attribute.  This takes a
   * single argument, which is the DN of the configuration entry.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_NO_ENABLED_ATTR =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 348;
@@ -3802,27 +3437,6 @@
  /**
   * The message ID for the message that will be used if the certificate mapper
   * has been explicitly disabled.  This does not take any arguments.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_DISABLED =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 349;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to determine whether the certificate mapper should be enabled.
   * This takes a single argument, which is a string representation of the
   * exception that was caught.
   */
  public static final int
       MSGID_CONFIG_CERTMAPPER_UNABLE_TO_DETERMINE_ENABLED_STATE =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 350;
  /**
   * The message ID for the message that will be used as the description for the
   * certificate mapper class attribute.  This does not take any arguments.
   */
@@ -3832,60 +3446,6 @@
  /**
   * The message ID for the message that will be used if the entry certificate
   * mapper configuration entry does not contain a class name attribute.  This
   * does not take any arguments.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_NO_CLASS_ATTR =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 352;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to determine the class to use for the certificate mapper.  This
   * takes a single argument, which is a string representation of the
   * exception that was caught.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_CANNOT_DETERMINE_CLASS =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 353;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to load the certificate mapper class.  This takes two arguments,
   * which are the class name and a string representation of the exception
   * exception that was caught.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_CANNOT_LOAD_CLASS =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 354;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to instantiate the certificate mapper class.  This takes two
   * arguments, which are the class name and a string representation of the
   * exception that was caught.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_CANNOT_INSTANTIATE_CLASS =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 355;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to initialize the certificate mapper.  This takes two arguments,
   * which are the class name and a string representation of the exception that
   * was caught.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_CANNOT_INITIALIZE =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 356;
  /**
   * The message ID for the message that will be used if no log retention
   * policy is specified.
   */
@@ -3918,30 +3478,6 @@
  /**
   * The message ID for the message that will be used if an attempt is made to
   * change the class used to implement a certificate mapper while the existing
   * certificate mapper is still enabled.  This takes two arguments, which are
   * the class name of the current certificate mapper and the class name of the
   * requested new certificate mapper.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_NOT_SWITCHING_CLASSES =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_MILD_ERROR | 361;
  /**
   * The message ID for the message that will be used if an attempt is made to
   * remove the certificate mapper configuration entry while the provider is
   * still enabled.  This takes a single argument, which is the class name of
   * the active certificate mapper.
   */
  public static final int
       MSGID_CONFIG_CERTMAPPER_CANNOT_REMOVE_ACTIVE_PROVIDER =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_MILD_ERROR | 362;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to retrieve the password storage scheme base entry from the
   * configuration.  This takes a single argument, which is a string
@@ -6494,6 +6030,454 @@
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to retrieve the certificate mapper base entry from the
   * configuration.  This takes a single argument, which is a string
   * representation of the exception that was caught.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_CANNOT_GET_BASE =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_FATAL_ERROR | 604;
  /**
   * The message ID for the message that will be used if the certificate mapper
   * base entry does not exist in the Directory Server configuration.  This does
   * not take any arguments.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_BASE_DOES_NOT_EXIST =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_WARNING | 605;
  /**
   * The message ID for the message that will be used if a certificate mapper
   * configuration entry does not contain an acceptable mapper configuration.
   * This takes two arguments, which are the DN of the configuration entry and
   * the reason that it is not acceptable.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_ENTRY_UNACCEPTABLE =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 606;
  /**
   * The message ID for the message that will be used if an error occurs while
   * trying to create a certificate mapper from a configuration entry.  This
   * takes two arguments, which are the DN of the configuration entry and a
   * message that explains the problem that occurred.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_CANNOT_CREATE_MAPPER =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 607;
  /**
   * The message ID for the message that will be used if an entry below the
   * certificate mapper base does not contain a valid objectclass.  This takes a
   * single argument, which is the DN of the configuration entry.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_INVALID_OBJECTCLASS =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 608;
  /**
   * The message ID for the message that will be used if an entry below the
   * certificate mapper base does not contain a value for the class name.  This
   * takes a single argument, which is the DN of the configuration entry.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_NO_CLASS_NAME =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 609;
  /**
   * The message ID for the message that will be used if an entry below the
   * certificate mapper base contains an invalid value for the class name.  This
   * takes two arguments, which are the DN of the configuration entry and a
   * string representation of the exception that was caught.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_INVALID_CLASS_NAME =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 610;
  /**
   * The message ID for the message that will be used if a configuration entry
   * defines a Directory Server certificate mapper but the associated class
   * cannot be instantiated as a certificate mapper.  This takes three
   * arguments, which are the mapper class name, the DN of the configuration
   * entry, and a string representation of the exception that was caught.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_INVALID_CLASS =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 611;
  /**
   * The message ID for the message that will be used if an entry below the
   * certificate mapper base has an invalid value for the enabled attribute.
   * This takes two arguments, which are the DN of the configuration entry and a
   * string representation of the exception that was caught.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_INVALID_ENABLED_VALUE =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 612;
  /**
   * The message ID for the message that will be used if the certificate mapper
   * class has changed and will require administrative action to take effect.
   * This takes three arguments, which are the old class name, the new class
   * name, and the DN of the associated configuration entry.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_CLASS_ACTION_REQUIRED =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_INFORMATIONAL | 613;
  /**
   * The message ID for the message that will be used if an error occurs while
   * initializing a Directory Server certificate maper.  This takes three
   * arguments, which are the class name for the mapper class, the DN of the
   * configuration entry, and a string representation of the exception that was
   * caught.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_INITIALIZATION_FAILED =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_MILD_ERROR | 614;
  /**
   * The message ID for the message that will be used if an attempt is made to
   * add a new certificate mapper with a DN that matches the DN of a mapper that
   * already exists.  This takes a single argument, which is the DN of the
   * mapper configuration entry.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_EXISTS =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_MILD_ERROR | 615;
  /**
   * The message ID for the message that will be used if a certificate mapper
   * entry contains an unacceptable configuration but does not provide any
   * specific details about the nature of the problem.  This takes a single
   * argument, which is the DN of the configuration entry.
   */
  public static final int MSGID_CONFIG_CERTMAPPER_UNACCEPTABLE_CONFIG =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 616;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to retrieve the key manager provider base entry from the
   * configuration.  This takes a single argument, which is a string
   * representation of the exception that was caught.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_CANNOT_GET_BASE =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_FATAL_ERROR | 617;
  /**
   * The message ID for the message that will be used if the key manager
   * provider base entry does not exist in the Directory Server configuration.
   * This does not take any arguments.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_BASE_DOES_NOT_EXIST =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_WARNING | 618;
  /**
   * The message ID for the message that will be used if a key manager provider
   * configuration entry does not contain an acceptable provider configuration.
   * This takes two arguments, which are the DN of the configuration entry and
   * the reason that it is not acceptable.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_ENTRY_UNACCEPTABLE =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 619;
  /**
   * The message ID for the message that will be used if an error occurs while
   * trying to create a key manager provider from a configuration entry.  This
   * takes two arguments, which are the DN of the configuration entry and a
   * message that explains the problem that occurred.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_CANNOT_CREATE_PROVIDER =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 620;
  /**
   * The message ID for the message that will be used if an entry below the
   * key manager provider base does not contain a valid objectclass.  This takes
   * a single argument, which is the DN of the configuration entry.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_INVALID_OBJECTCLASS =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 621;
  /**
   * The message ID for the message that will be used if an entry below the
   * key manager provider base does not contain a value for the class name.
   * This takes a single argument, which is the DN of the configuration entry.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_NO_CLASS_NAME =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 622;
  /**
   * The message ID for the message that will be used if an entry below the
   * key manager provider base contains an invalid value for the class name.
   * This takes two arguments, which are the DN of the configuration entry and a
   * string representation of the exception that was caught.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_INVALID_CLASS_NAME =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 623;
  /**
   * The message ID for the message that will be used if a configuration entry
   * defines a Directory Server key manager provider but the associated class
   * cannot be instantiated as a provider.  This takes three arguments, which
   * are the provider class name, the DN of the configuration entry, and a
   * string representation of the exception that was caught.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_INVALID_CLASS =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 624;
  /**
   * The message ID for the message that will be used if an entry below the
   * key manager provider base has an invalid value for the enabled attribute.
   * This takes two arguments, which are the DN of the configuration entry and a
   * string representation of the exception that was caught.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_INVALID_ENABLED_VALUE =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 625;
  /**
   * The message ID for the message that will be used if the key manager
   * provider class has changed and will require administrative action to take
   * effect.  This takes three arguments, which are the old class name, the new
   * class name, and the DN of the associated configuration entry.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_CLASS_ACTION_REQUIRED =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_INFORMATIONAL | 626;
  /**
   * The message ID for the message that will be used if an error occurs while
   * initializing a Directory Server key manager provider.  This takes three
   * arguments, which are the class name for the provider class, the DN of the
   * configuration entry, and a string representation of the exception that was
   * caught.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_INITIALIZATION_FAILED =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_MILD_ERROR | 627;
  /**
   * The message ID for the message that will be used if an attempt is made to
   * add a new key manager provider with a DN that matches the DN of a provider
   * that already exists.  This takes a single argument, which is the DN of the
   * provider configuration entry.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_EXISTS =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_MILD_ERROR | 628;
  /**
   * The message ID for the message that will be used if a key manager provider
   * entry contains an unacceptable configuration but does not provide any
   * specific details about the nature of the problem.  This takes a single
   * argument, which is the DN of the configuration entry.
   */
  public static final int MSGID_CONFIG_KEYMANAGER_UNACCEPTABLE_CONFIG =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 629;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to retrieve the trust manager provider base entry from the
   * configuration.  This takes a single argument, which is a string
   * representation of the exception that was caught.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_CANNOT_GET_BASE =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_FATAL_ERROR | 630;
  /**
   * The message ID for the message that will be used if the trust manager
   * provider base entry does not exist in the Directory Server configuration.
   * This does not take any arguments.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_BASE_DOES_NOT_EXIST =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_WARNING | 631;
  /**
   * The message ID for the message that will be used if a trust manager
   * provider configuration entry does not contain an acceptable provider
   * configuration. This takes two arguments, which are the DN of the
   * configuration entry and the reason that it is not acceptable.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_ENTRY_UNACCEPTABLE =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 632;
  /**
   * The message ID for the message that will be used if an error occurs while
   * trying to create a trust manager provider from a configuration entry.  This
   * takes two arguments, which are the DN of the configuration entry and a
   * message that explains the problem that occurred.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_CANNOT_CREATE_PROVIDER =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 633;
  /**
   * The message ID for the message that will be used if an entry below the
   * trust manager provider base does not contain a valid objectclass.  This
   * takes a single argument, which is the DN of the configuration entry.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_INVALID_OBJECTCLASS =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 634;
  /**
   * The message ID for the message that will be used if an entry below the
   * trust manager provider base does not contain a value for the class name.
   * This takes a single argument, which is the DN of the configuration entry.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_NO_CLASS_NAME =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 635;
  /**
   * The message ID for the message that will be used if an entry below the
   * trust manager provider base contains an invalid value for the class name.
   * This takes two arguments, which are the DN of the configuration entry and a
   * string representation of the exception that was caught.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_INVALID_CLASS_NAME =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 636;
  /**
   * The message ID for the message that will be used if a configuration entry
   * defines a Directory Server trust manager provider but the associated class
   * cannot be instantiated as a provider.  This takes three arguments, which
   * are the provider class name, the DN of the configuration entry, and a
   * string representation of the exception that was caught.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_INVALID_CLASS =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 637;
  /**
   * The message ID for the message that will be used if an entry below the
   * trust manager provider base has an invalid value for the enabled attribute.
   * This takes two arguments, which are the DN of the configuration entry and a
   * string representation of the exception that was caught.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_INVALID_ENABLED_VALUE =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 638;
  /**
   * The message ID for the message that will be used if the trust manager
   * provider class has changed and will require administrative action to take
   * effect.  This takes three arguments, which are the old class name, the new
   * class name, and the DN of the associated configuration entry.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_CLASS_ACTION_REQUIRED =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_INFORMATIONAL | 639;
  /**
   * The message ID for the message that will be used if an error occurs while
   * initializing a Directory Server trust manager provider.  This takes three
   * arguments, which are the class name for the provider class, the DN of the
   * configuration entry, and a string representation of the exception that was
   * caught.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_INITIALIZATION_FAILED =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_MILD_ERROR | 640;
  /**
   * The message ID for the message that will be used if an attempt is made to
   * add a new trust manager provider with a DN that matches the DN of a
   * provider that already exists.  This takes a single argument, which is the
   * DN of the provider configuration entry.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_EXISTS =
            CATEGORY_MASK_CONFIG | SEVERITY_MASK_MILD_ERROR | 641;
  /**
   * The message ID for the message that will be used if a trust manager
   * provider entry contains an unacceptable configuration but does not provide
   * any specific details about the nature of the problem.  This takes a single
   * argument, which is the DN of the configuration entry.
   */
  public static final int MSGID_CONFIG_TRUSTMANAGER_UNACCEPTABLE_CONFIG =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 642;
  /**
   * The message ID for the message that will be used if it is not possible to
   * retrieve a JMX attribute.  This takes three arguments, which are the name
   * of the attribute to retrieve, the DN of the associated configuration entry,
   * and a message explaining the problem that occurred.
   */
  public static final int MSGID_CONFIG_JMX_CANNOT_GET_ATTRIBUTE =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 643;
  /**
   * The message ID for the message that will be used if it is not possible to
   * set a JMX attribute because there is no available JMX connection.  This
   * takes two arguments, which are the name of the attribute and the DN of the
   * associated configuration entry.
   */
  public static final int MSGID_CONFIG_JMX_SET_ATTR_NO_CONNECTION =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 644;
  /**
   * Associates a set of generic messages with the message IDs defined in this
   * class.
   */
@@ -7177,6 +7161,13 @@
                    "The Directory Server could not register a JMX MBean for " +
                    "the component associated with configuration entry %s:  " +
                    "%s ");
    registerMessage(MSGID_CONFIG_JMX_CANNOT_GET_ATTRIBUTE,
                    "Unable to retrieve JMX attribute %s associated with " +
                    "configuration entry %s:  %s.");
    registerMessage(MSGID_CONFIG_JMX_SET_ATTR_NO_CONNECTION,
                    "Unable to set the value of JMX attribute %s associated " +
                    "with configuration entry %s because no JMX connection " +
                    "is avaialble.");
    registerMessage(MSGID_CONFIG_WORK_QUEUE_DESCRIPTION_NUM_THREADS,
@@ -8190,37 +8181,40 @@
                    "should be excluded from the access log file.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_CANNOT_INSTALL_NULL_PROVIDER,
                    "An unexpected error occurred that prevented the server " +
                    "from installing a default null key manager provider for " +
                    "use until the actual provider could be created from the " +
                    "configuration:  %s.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_CANNOT_GET_CONFIG_ENTRY,
                    "An unexpected error occurred while attempting to get " +
                    "the \"" + DN_KEYMANAGER_PROVIDER_CONFIG +
                    "\" entry, which holds the key manager provider " +
                    "configuration:  %s.  No key manager provider will be " +
                    "available.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_NO_CONFIG_ENTRY,
                    "The key manager provider configuration entry \"" +
                    DN_KEYMANAGER_PROVIDER_CONFIG + "\" does not exist in " +
                    "the Directory Server configuration.  No key manager " +
                    "provider will be available until this entry is created " +
                    "with a valid key manager provider configuration.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_CANNOT_REGISTER_ADD_LISTENER,
                    "An error occurred while attempting to register an " +
                    "add listener to watch for the key manager provider " +
                    "configuration entry to be created:  %s.  If a " +
                    "key manager provider configuration is added while the " +
                    "server is online, it will not be detected until the " +
                    "server is restarted.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_CANNOT_REGISTER_DELETE_LISTENER,
                    "An error occurred while attempting to register a " +
                    "delete listener to watch for the key manager provider " +
                    "configuration entry to be deleted: %s.  If the key " +
                    "manager provider configuration entry is deleted while " +
                    "the server is online, it will not be detected until the " +
                    "server is restarted.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_CANNOT_GET_BASE,
                    "An error occurred while attempting to retrieve the key " +
                    "manager provider base entry " +
                    DN_KEYMANAGER_PROVIDER_CONFIG_BASE +
                    " from the Directory Server configuration:  %s.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_BASE_DOES_NOT_EXIST,
                    "The key manager provider configuration base " +
                    DN_KEYMANAGER_PROVIDER_CONFIG_BASE + " does not exist in " +
                    "the Directory Server configuration.  This entry must be " +
                    "present for the server to function properly.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_ENTRY_UNACCEPTABLE,
                    "Configuration entry %s does not contain a valid key " +
                    "manager provider configuration:  %s.  It will be " +
                    "ignored.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_CANNOT_CREATE_PROVIDER,
                    "An error occurred while attempting to create a " +
                    "Directory Server key manager provider from the " +
                    "information in configuration entry %s:  %s.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_INVALID_OBJECTCLASS,
                    "Configuration entry %s does not contain the " +
                    OC_KEY_MANAGER_PROVIDER + " objectclass, which is " +
                    "required for key manager provider definitions.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_NO_CLASS_NAME,
                    "Configuration entry %s does not contain a valid value " +
                    "for configuration attribute " + ATTR_KEYMANAGER_CLASS +
                    " which specifies the fully-qualified class name for " +
                    "the associated key manager provider.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_INVALID_CLASS_NAME,
                    "Configuration entry %s has an invalid value for " +
                    "attribute " + ATTR_KEYMANAGER_CLASS + ":  %s.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_INVALID_CLASS,
                    "Class %s specified in configuration entry %s does not " +
                    "contain a valid key manager provider implementation:  " +
                    "%s.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_DESCRIPTION_ENABLED,
                    "Indicates whether the Directory Server key manager " +
                    "provider should be enabled.  A key manager provider is " +
@@ -8230,101 +8224,75 @@
                    "immediately, but will only impact future attempts to " +
                    "access the key manager.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_NO_ENABLED_ATTR,
                    "Configuration entry \"" + DN_KEYMANAGER_PROVIDER_CONFIG +
                    "\" does not contain a value for attribute " +
                    ATTR_KEYMANAGER_ENABLED + ", which indicates whether " +
                    "the key manager provider is enabled for use in the " +
                    "server.  As a result, the key manager provider will be " +
                    "disabled.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_DISABLED,
                    "The Directory Server key manager provider configured in " +
                    "entry \"" + DN_KEYMANAGER_PROVIDER_CONFIG +
                    "\" has been disabled.  No key manager access will be " +
                    "available within the server.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_UNABLE_TO_DETERMINE_ENABLED_STATE,
                    "An unexpected error occurred while attempting to " +
                    "determine whether the key manager provider configured " +
                    "in entry \"" + DN_KEYMANAGER_PROVIDER_CONFIG +
                    "\" is enabled:  %s.  As a result, the key manager " +
                    "provider will be disabled.");
                    "Configuration entry \"%s\" does not contain a value for " +
                    "attribute " + ATTR_KEYMANAGER_ENABLED +
                    ", which indicates whether the key manager provider is " +
                    "enabled for use in the server.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_INVALID_ENABLED_VALUE,
                    "Configuration entry %s has an invalid value for " +
                    "attribute " + ATTR_KEYMANAGER_ENABLED + ":  %s.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_DESCRIPTION_CLASS,
                    "Specifies the fully-qualified name of the Java class " +
                    "that includes the key manager provider implementation.  " +
                    "Changes to this configuration attribute will not take " +
                    "effect until the key manager provider has been disabled " +
                    "and then re-enabled, or until the server is restarted.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_NO_CLASS_ATTR,
                    "Configuration entry \"" + DN_KEYMANAGER_PROVIDER_CONFIG +
                    "\" does not contain a value for attribute " +
                    ATTR_KEYMANAGER_CLASS + "\", which specifies the class " +
                    "name for the key manager provider implementation.  As a " +
                    "result, no key manager access will be available.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_CANNOT_DETERMINE_CLASS,
                    "An unexpected error occurred while attempting to " +
                    "determine the value of the " + ATTR_KEYMANAGER_CLASS +
                    " attribute in configuration entry \"" +
                    DN_KEYMANAGER_PROVIDER_CONFIG + "\":  %s.  No key " +
                    "manager access will be available.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_CANNOT_LOAD_CLASS,
                    "The class %s defined in attribute " +
                    ATTR_KEYMANAGER_CLASS + " of configuration entry \"" +
                    DN_KEYMANAGER_PROVIDER_CONFIG + "\" could not be " +
                    "loaded:  %s.  No key manager access will be available.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_CANNOT_INSTANTIATE_CLASS,
                    "The class %s defined in attribute " +
                    ATTR_KEYMANAGER_CLASS + " of configuration entry \"" +
                    DN_KEYMANAGER_PROVIDER_CONFIG + "\" could not be " +
                    "instantiated as a Directory Server key manager " +
                    "provider:  %s.  No key manager access will be available.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_CANNOT_INITIALIZE,
                    "An error occurred while attempting to initialize " +
                    "an instance of class %s for use as the Directory Server " +
                    "key manager provider:  %s.  No key manager access will " +
                    "be available.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_NOT_SWITCHING_CLASSES,
                    "The Directory Server key manager provider is currently " +
                    "enabled as an instance of class %s.  The requested new " +
                    "class %s will not be used until the current key " +
                    "manager provider is disabled.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_CANNOT_REMOVE_ACTIVE_PROVIDER,
                    "The Directory Server will not allow the removal of " +
                    "configuration entry " + DN_KEYMANAGER_PROVIDER_CONFIG +
                    " while it contains a configuration that is actively in " +
                    "use.  The configured provider %s is still active and " +
                    "must be disabled before this entry may be removed.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_CLASS_ACTION_REQUIRED,
                    "The requested change in the key manager provider class " +
                    "name from %s to %s in configuration entry %s cannot be " +
                    "dynamically applied.  This change will not take effect " +
                    "until the provider is disabled and re-enabled or the " +
                    "Directory Server is restarted.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_INITIALIZATION_FAILED,
                    "An error occurred while trying to initialize an " +
                    "instance of class %s as a key manager provider as " +
                    "defined in configuration entry %s:  %s.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_EXISTS,
                    "Unable to add a new key manager provider entry with DN " +
                    "%s because there is already a provider registered with " +
                    "that DN.");
    registerMessage(MSGID_CONFIG_KEYMANAGER_UNACCEPTABLE_CONFIG,
                    "The configuration for the key manager provider defined " +
                    "in configuration entry %s was not acceptable according " +
                    "to its internal validation.  However, no specific " +
                    "information is available regarding the problem(s) with " +
                    "the entry.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_CANNOT_INSTALL_NULL_PROVIDER,
                    "An unexpected error occurred that prevented the server " +
                    "from installing a default null trust manager provider " +
                    "for use until the actual provider could be created from " +
                    "the configuration:  %s.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_CANNOT_GET_CONFIG_ENTRY,
                    "An unexpected error occurred while attempting to get " +
                    "the \"" + DN_TRUSTMANAGER_PROVIDER_CONFIG +
                    "\" entry, which holds the trust manager provider " +
                    "configuration:  %s.  No trust manager provider will be " +
                    "available.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_NO_CONFIG_ENTRY,
                    "The trust manager provider configuration entry \"" +
                    DN_TRUSTMANAGER_PROVIDER_CONFIG + "\" does not exist in " +
                    "the Directory Server configuration.  No trust manager " +
                    "provider will be available until this entry is created " +
                    "with a valid trust manager provider configuration.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_CANNOT_REGISTER_ADD_LISTENER,
                    "An error occurred while attempting to register an " +
                    "add listener to watch for the trust manager provider " +
                    "configuration entry to be created:  %s.  If a " +
                    "trust manager provider configuration is added while the " +
                    "server is online, it will not be detected until the " +
                    "server is restarted.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_CANNOT_REGISTER_DELETE_LISTENER,
                    "An error occurred while attempting to register a " +
                    "delete listener to watch for the trust manager provider " +
                    "configuration entry to be deleted: %s.  If the trust " +
                    "manager provider configuration entry is deleted while " +
                    "the server is online, it will not be detected until the " +
                    "server is restarted.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_CANNOT_GET_BASE,
                    "An error occurred while attempting to retrieve the " +
                    "trust manager provider base entry " +
                    DN_TRUSTMANAGER_PROVIDER_CONFIG_BASE +
                    " from the Directory Server configuration:  %s.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_BASE_DOES_NOT_EXIST,
                    "The trust manager provider configuration base " +
                    DN_TRUSTMANAGER_PROVIDER_CONFIG_BASE + " does not exist " +
                    "in the Directory Server configuration.  This entry must " +
                    "be present for the server to function properly.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_ENTRY_UNACCEPTABLE,
                    "Configuration entry %s does not contain a valid trust " +
                    "manager provider configuration:  %s.  It will be " +
                    "ignored.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_CANNOT_CREATE_PROVIDER,
                    "An error occurred while attempting to create a " +
                    "Directory Server trust manager provider from the " +
                    "information in configuration entry %s:  %s.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_INVALID_OBJECTCLASS,
                    "Configuration entry %s does not contain the " +
                    OC_TRUST_MANAGER_PROVIDER + " objectclass, which is " +
                    "required for trust manager provider definitions.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_NO_CLASS_NAME,
                    "Configuration entry %s does not contain a valid value " +
                    "for configuration attribute " + ATTR_TRUSTMANAGER_CLASS +
                    " which specifies the fully-qualified class name for " +
                    "the associated trust manager provider.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_INVALID_CLASS_NAME,
                    "Configuration entry %s has an invalid value for " +
                    "attribute " + ATTR_TRUSTMANAGER_CLASS + ":  %s.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_INVALID_CLASS,
                    "Class %s specified in configuration entry %s does not " +
                    "contain a valid trust manager provider implementation:  " +
                    "%s.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_ENABLED,
                    "Indicates whether the Directory Server trust manager " +
                    "provider should be enabled.  A trust manager provider " +
@@ -8334,99 +8302,75 @@
                    "immediately, but will only impact future attempts to " +
                    "access the trust manager.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_NO_ENABLED_ATTR,
                    "Configuration entry \"" + DN_TRUSTMANAGER_PROVIDER_CONFIG +
                    "\" does not contain a value for attribute " +
                    ATTR_TRUSTMANAGER_ENABLED + ", which indicates whether " +
                    "the trust manager provider is enabled for use in the " +
                    "server.  As a result, the trust manager provider will " +
                    "be disabled.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_DISABLED,
                    "The Directory Server trust manager provider configured " +
                    "in entry \"" + DN_TRUSTMANAGER_PROVIDER_CONFIG +
                    "\" has been disabled.  No trust manager access will be " +
                    "available within the server.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_UNABLE_TO_DETERMINE_ENABLED_STATE,
                    "An unexpected error occurred while attempting to " +
                    "determine whether the trust manager provider configured " +
                    "in entry \"" + DN_TRUSTMANAGER_PROVIDER_CONFIG +
                    "\" is enabled:  %s.  As a result, the trust manager " +
                    "provider will be disabled.");
                    "Configuration entry \"%s\" does not contain a value for " +
                    "attribute " + ATTR_TRUSTMANAGER_ENABLED +
                    ", which indicates whether the trust manager provider is " +
                    "enabled for use in the server.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_INVALID_ENABLED_VALUE,
                    "Configuration entry %s has an invalid value for " +
                    "attribute " + ATTR_TRUSTMANAGER_ENABLED + ":  %s.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_DESCRIPTION_CLASS,
                    "Specifies the fully-qualified name of the Java class " +
                    "that includes the trust manager provider " +
                    "implementation.  Changes to this configuration " +
                    "attribute will not take effect until the key manager " +
                    "attribute will not take effect until the trust manager " +
                    "provider has been disabled and then re-enabled, or " +
                    "until the server is restarted.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_NO_CLASS_ATTR,
                    "Configuration entry \"" + DN_TRUSTMANAGER_PROVIDER_CONFIG +
                    "\" does not contain a value for attribute " +
                    ATTR_TRUSTMANAGER_CLASS + "\", which specifies the class " +
                    "name for the trust manager provider implementation.  " +
                    "As a result, no trust manager access will be available.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_CANNOT_DETERMINE_CLASS,
                    "An unexpected error occurred while attempting to " +
                    "determine the value of the " + ATTR_TRUSTMANAGER_CLASS +
                    " attribute in configuration entry \"" +
                    DN_TRUSTMANAGER_PROVIDER_CONFIG + "\":  %s.  No trust " +
                    "manager access will be available.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_CANNOT_LOAD_CLASS,
                    "The class %s defined in attribute " +
                    ATTR_TRUSTMANAGER_CLASS + " of configuration entry \"" +
                    DN_TRUSTMANAGER_PROVIDER_CONFIG + "\" could not be " +
                    "loaded:  %s.  No trust manager access will be available.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_CANNOT_INSTANTIATE_CLASS,
                    "The class %s defined in attribute " +
                    ATTR_TRUSTMANAGER_CLASS + " of configuration entry \"" +
                    DN_TRUSTMANAGER_PROVIDER_CONFIG + "\" could not be " +
                    "instantiated as a Directory Server trust manager " +
                    "provider:  %s.  No trust manager access will be " +
                    "available.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_CANNOT_INITIALIZE,
                    "An error occurred while attempting to initialize " +
                    "an instance of class %s for use as the Directory Server " +
                    "trust manager provider:  %s.  No key manager access " +
                    "will be available.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_NOT_SWITCHING_CLASSES,
                    "The Directory Server trust manager provider is " +
                    "currently enabled as an instance of class %s.  The " +
                    "requested new class %s will not be used until the " +
                    "current trust manager provider is disabled.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_CANNOT_REMOVE_ACTIVE_PROVIDER,
                    "The Directory Server will not allow the removal of " +
                    "configuration entry " + DN_TRUSTMANAGER_PROVIDER_CONFIG +
                    " while it contains a configuration that is actively in " +
                    "use.  The configured provider %s is still active and " +
                    "must be disabled before this entry may be removed.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_CLASS_ACTION_REQUIRED,
                    "The requested change in the trust manager provider " +
                    "class name from %s to %s in configuration entry %s " +
                    "cannot be dynamically applied.  This change will not " +
                    "take effect until the provider is disabled and " +
                    "re-enabled or the Directory Server is restarted.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_INITIALIZATION_FAILED,
                    "An error occurred while trying to initialize an " +
                    "instance of class %s as a trust manager provider as " +
                    "defined in configuration entry %s:  %s.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_EXISTS,
                    "Unable to add a new trust manager provider entry with " +
                    "DN %s because there is already a provider registered " +
                    "with that DN.");
    registerMessage(MSGID_CONFIG_TRUSTMANAGER_UNACCEPTABLE_CONFIG,
                    "The configuration for the trust manager provider " +
                    "defined in configuration entry %s was not acceptable " +
                    "according to its internal validation.  However, no " +
                    "specific information is available regarding the " +
                    "problem(s) with the entry.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_CANNOT_INSTALL_DEFAULT_MAPPER,
                    "An unexpected error occurred that prevented the server " +
                    "from installing the default certificate mapper:  %s.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_CANNOT_GET_CONFIG_ENTRY,
                    "An unexpected error occurred while attempting to get " +
                    "the \"" + DN_CERTMAPPER_CONFIG + "\" entry, which holds " +
                    "the certificate mapper configuration:  %s.  The default " +
                    "certificate mapper will be used.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_NO_CONFIG_ENTRY,
                    "The certificate mapper configuration entry \"" +
                    DN_CERTMAPPER_CONFIG + "\" does not exist in the " +
                    "Directory Server configuration.  The default " +
                    "certificate mapper will be used.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_CANNOT_REGISTER_ADD_LISTENER,
                    "An error occurred while attempting to register an " +
                    "add listener to watch for the certificate mapper " +
                    "configuration entry to be created:  %s.  If a " +
                    "certificate mapper configuration is added while the " +
                    "server is online, it will not be detected until the " +
                    "server is restarted.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_CANNOT_REGISTER_DELETE_LISTENER,
                    "An error occurred while attempting to register a " +
                    "delete listener to watch for the certificate mapper " +
                    "configuration entry to be deleted: %s.  If the " +
                    "certificate mapper configuration entry is deleted while " +
                    "the server is online, it will not be detected until the " +
                    "server is restarted.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_CANNOT_GET_BASE,
                    "An error occurred while attempting to retrieve the " +
                    "certificate mapper base entry " +
                    DN_CERTMAPPER_CONFIG_BASE +
                    " from the Directory Server configuration:  %s.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_BASE_DOES_NOT_EXIST,
                    "The certificate mapper configuration base " +
                    DN_CERTMAPPER_CONFIG_BASE + " does not exist in the " +
                    "Directory Server configuration.  This entry must be " +
                    "present for the server to function properly.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_ENTRY_UNACCEPTABLE,
                    "Configuration entry %s does not contain a valid " +
                    "certificate mapper configuration:  %s.  It will be " +
                    "ignored.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_CANNOT_CREATE_MAPPER,
                    "An error occurred while attempting to create a " +
                    "Directory Server certificate mapper from the " +
                    "information in configuration entry %s:  %s.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_INVALID_OBJECTCLASS,
                    "Configuration entry %s does not contain the " +
                    OC_CERTIFICATE_MAPPER + " objectclass, which is required " +
                    "for certificate mapper definitions.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_NO_CLASS_NAME,
                    "Configuration entry %s does not contain a valid value " +
                    "for configuration attribute " + ATTR_CERTMAPPER_CLASS +
                    " which specifies the fully-qualified class name for " +
                    "the associated certificate mapper.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_INVALID_CLASS_NAME,
                    "Configuration entry %s has an invalid value for " +
                    "attribute " + ATTR_CERTMAPPER_CLASS + ":  %s.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_INVALID_CLASS,
                    "Class %s specified in configuration entry %s does not " +
                    "contain a valid certificate mapper implementation:  %s.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_DESCRIPTION_ENABLED,
                    "Indicates whether the Directory Server certificate " +
                    "mapper should be enabled.  A certificate mapper is " +
@@ -8436,67 +8380,39 @@
                    "purposes.  Changes to this configuration attribute will " +
                    "take effect immediately.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_NO_ENABLED_ATTR,
                    "Configuration entry \"" + DN_CERTMAPPER_CONFIG +
                    "\" does not contain a value for attribute " +
                    ATTR_CERTMAPPER_ENABLED + ", which indicates whether " +
                    "the certificate mapper is enabled for use in the " +
                    "server.  As a result, the default certificate mapper " +
                    "will be used.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_DISABLED,
                    "The Directory Server certificate mapper configured in " +
                    "entry \"" + DN_CERTMAPPER_CONFIG + "\" has been " +
                    "disabled.  The default certificate mapper will be used.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_UNABLE_TO_DETERMINE_ENABLED_STATE,
                    "An unexpected error occurred while attempting to " +
                    "determine whether the certificate mapper configured " +
                    "in entry \"" + DN_CERTMAPPER_CONFIG + "\" is enabled:  " +
                    "%s.  As a result, the default certificate mapper will " +
                    "be used.");
                    "Configuration entry \"%s\" does not contain a value for " +
                    "attribute " + ATTR_CERTMAPPER_ENABLED +
                    ", which indicates whether the certificate mapper is " +
                    "enabled for use in the server.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_INVALID_ENABLED_VALUE,
                    "Configuration entry %s has an invalid value for " +
                    "attribute " + ATTR_CERTMAPPER_ENABLED + ":  %s.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_DESCRIPTION_CLASS,
                    "Specifies the fully-qualified name of the Java class " +
                    "that includes the certificate mapper implementation.  " +
                    "Changes to this configuration attribute will not take " +
                    "effect until the certificate mapper has been disabled " +
                    "and then re-enabled, or until the server is restarted.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_NO_CLASS_ATTR,
                    "Configuration entry \"" + DN_CERTMAPPER_CONFIG +
                    "\" does not contain a value for attribute " +
                    ATTR_CERTMAPPER_CLASS + "\", which specifies the class " +
                    "name for the certificate mapper implementation.  As a " +
                    "result, the default certificate mapper will be used.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_CANNOT_DETERMINE_CLASS,
                    "An unexpected error occurred while attempting to " +
                    "determine the value of the " + ATTR_CERTMAPPER_CLASS +
                    " attribute in configuration entry \"" +
                    DN_CERTMAPPER_CONFIG + "\":  %s.  The default " +
                    "certificate mapper will be used.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_CANNOT_LOAD_CLASS,
                    "The class %s defined in attribute " +
                    ATTR_CERTMAPPER_CLASS + " of configuration entry \"" +
                    DN_CERTMAPPER_CONFIG + "\" could not be loaded:  %s.  " +
                    "The default certificate mapper will be used.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_CANNOT_INSTANTIATE_CLASS,
                    "The class %s defined in attribute " +
                    ATTR_CERTMAPPER_CLASS + " of configuration entry \"" +
                    DN_CERTMAPPER_CONFIG + "\" could not be instantiated as " +
                    "a Directory Server certificate mapper:  %s.  The " +
                    "%default certificate mapper will be used.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_CANNOT_INITIALIZE,
                    "An error occurred while attempting to initialize " +
                    "an instance of class %s for use as the Directory Server " +
                    "certificate mapper:  %s.  The default certificate " +
                    "mapper will be used.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_NOT_SWITCHING_CLASSES,
                    "The Directory Server certificate mapper is currently " +
                    "enabled as an instance of class %s.  The requested new " +
                    "class %s will not be used until the current certificate " +
                    "mapper is disabled.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_CANNOT_REMOVE_ACTIVE_PROVIDER,
                    "The Directory Server will not allow the removal of " +
                    "configuration entry " + DN_CERTMAPPER_CONFIG +
                    " while it contains a configuration that is actively in " +
                    "use.  The configured mapper %s is still active and " +
                    "must be disabled before this entry may be removed.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_CLASS_ACTION_REQUIRED,
                    "The requested change in the certificate mapper class " +
                    "name from %s to %s in configuration entry %s cannot be " +
                    "dynamically applied.  This change will not take effect " +
                    "until the mapper is disabled and re-enabled or the " +
                    "Directory Server is restarted.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_INITIALIZATION_FAILED,
                    "An error occurred while trying to initialize an " +
                    "instance of class %s as a certificate mapper as defined " +
                    "in configuration entry %s:  %s.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_EXISTS,
                    "Unable to add a new certificate mapper entry with DN %s " +
                    "because there is already a mapper registered with that " +
                    "DN.");
    registerMessage(MSGID_CONFIG_CERTMAPPER_UNACCEPTABLE_CONFIG,
                    "The configuration for the certificate mapper defined in " +
                    "configuration entry %s was not acceptable according to " +
                    "its internal validation.  However, no specific " +
                    "information is available regarding the problem(s) with " +
                    "the entry.");
    registerMessage(MSGID_CONFIG_PWSCHEME_CANNOT_GET_BASE,
opendj-sdk/opends/src/server/org/opends/server/messages/ExtensionsMessages.java
@@ -476,15 +476,6 @@
  /**
   * The message ID for the message that will be used if an attempt is made to
   * access a key manager without having one defined in the configuration.
   */
  public static final int MSGID_NULL_KEYMANAGER_NO_MANAGER =
       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 42;
  /**
   * The message ID for the message that will be used as the description of the
   * configuration attribute specifying the location of the key manager file.
   * This does not take any arguments.
@@ -4285,6 +4276,59 @@
  /**
   * The message ID for the message that will be used as the description of the
   * certificate mapper DN configuration attribute.  It does not take any
   * arguments.
   */
  public static final int MSGID_SASLEXTERNAL_DESCRIPTION_CERT_MAPPER_DN =
       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 406;
  /**
   * The message ID for the message that will be used the SASL EXTERNAL
   * configuration entry does not specify the certificate mapper DN. This takes
   * a single argument, which is the DN of the configuration entry.
   */
  public static final int MSGID_SASLEXTERNAL_NO_CERTIFICATE_MAPPER_DN =
       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 407;
  /**
   * The message ID for the message that will be used the SASL EXTERNAL
   * configuration entry contains a certificate mapper DN that does not refer to
   * a valid certificate mapper. This takes two arguments, which are the DN of
   * the configuration entry and the certificate mapper DN.
   */
  public static final int MSGID_SASLEXTERNAL_INVALID_CERTIFICATE_MAPPER_DN =
       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 408;
  /**
   * The message ID for the message that will be used if an error occurs while
   * trying to determine the certificate mapper to use with the SASL EXTERNAL
   * handler.  This takes two arguments, which are the DN of the configuration
   * entry and a string representation of the exception that was caught.
   */
  public static final int MSGID_SASLEXTERNAL_CANNOT_GET_CERT_MAPPER_DN =
       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 409;
  /**
   * The message ID for the message that will be used to indicate that the
   * certificate mapper DN for has been updated.  This takes two arguments,
   * which are the DN of the configuration entry and the new certificate mapper
   * DN.
   */
  public static final int MSGID_SASLEXTERNAL_UPDATED_CERT_MAPPER_DN =
       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 410;
  /**
   * Associates a set of generic messages with the message IDs defined in this
   * class.
   */
@@ -4591,14 +4635,6 @@
                    "no-op control was present in the request.");
    registerMessage(MSGID_NULL_KEYMANAGER_NO_MANAGER,
                    "The Directory Server is unable to process an operation " +
                    "which requires access to an SSL key manager because no " +
                    "valid key manager has been defined in entry " +
                    DN_KEYMANAGER_PROVIDER_CONFIG +
                    " of the server configuration.");
    registerMessage(MSGID_FILE_KEYMANAGER_DESCRIPTION_FILE,
                    "Specifies the path to the file containing the Directory " +
                    "Server keystore information.  Changes to this " +
@@ -5077,6 +5113,23 @@
                    "Directory Server schema.  The attribute that is to be " +
                    "used for certificate validation during SASL EXTERNAL " +
                    "authentication must be defined in the server schema.");
    registerMessage(MSGID_SASLEXTERNAL_DESCRIPTION_CERT_MAPPER_DN,
                    "Specifies the DN of the configuration entry that " +
                    "defines the certificate mapper to use when mapping a " +
                    "certificate to a user entry.  Changes to this " +
                    "configuration attribute will take effect immediately.");
    registerMessage(MSGID_SASLEXTERNAL_NO_CERTIFICATE_MAPPER_DN,
                    "Configuration entry %s does not contain attribute " +
                    ATTR_CERTMAPPER_DN + " which is required to specify " +
                    "which certificate mapper should be used to map " +
                    "certificates to user entries.");
    registerMessage(MSGID_SASLEXTERNAL_INVALID_CERTIFICATE_MAPPER_DN,
                    "Configuration entry %s contains a certificate mapper DN " +
                    "of %s, but no such certificate mapper is enabled for " +
                    "use in the Directory Server.");
    registerMessage(MSGID_SASLEXTERNAL_CANNOT_GET_CERT_MAPPER_DN,
                    "An error occurred while attempting to retrieve the " +
                    "certificate mapper DN from configuration entry %s:  %s.");
    registerMessage(MSGID_SASLEXTERNAL_NO_CERT_IN_ENTRY,
                    "Unable to authenticate via SASL EXTERNAL because the " +
                    "mapped user entry %s does not have any certificates " +
@@ -5098,6 +5151,11 @@
                    " in configuration entry %s has been updated.  The %s " +
                    "attribute will now be used when validating peer " +
                    "certificates.");
    registerMessage(MSGID_SASLEXTERNAL_UPDATED_CERT_MAPPER_DN,
                    "Attribute " + ATTR_CERTMAPPER_DN +
                    " in configuration entry %s has been updated.  " +
                    "Certificate mapper %s will now be used to map " +
                    "certificates to user entries.");
    registerMessage(MSGID_STARTTLS_NO_CLIENT_CONNECTION,
opendj-sdk/opends/src/server/org/opends/server/messages/ProtocolMessages.java
@@ -4228,6 +4228,126 @@
  /**
   * The message ID for the message that will be used as the description of the
   * key manager provider DN configuration attribute.  This does not take any
   * arguments.
   */
  public static final int MSGID_LDAP_CONNHANDLER_DESCRIPTION_KEYMANAGER_DN =
       CATEGORY_MASK_PROTOCOL | SEVERITY_MASK_INFORMATIONAL | 390;
  /**
   * The message ID for the message that will be used if the specified key
   * manager provider does not exist or is not enabled.  This takes two
   * arguments, which are the DN of the configuration entry and the key manager
   * provider DN.
   */
  public static final int MSGID_LDAP_CONNHANDLER_INVALID_KEYMANAGER_DN =
       CATEGORY_MASK_PROTOCOL | SEVERITY_MASK_SEVERE_ERROR | 391;
  /**
   * The message ID for the message that will be used if an unexpected error
   * occurs while trying to determine the key manager provider DN to use.  This
   * takes two arguments, which are the DN of the configuration entry and a
   * string representation of the exception that was caught.
   */
  public static final int
       MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_KEYMANAGER_DN =
            CATEGORY_MASK_PROTOCOL | SEVERITY_MASK_SEVERE_ERROR | 392;
  /**
   * The message ID for the message that will be used as the description of the
   * trust manager provider DN configuration attribute.  This does not take any
   * arguments.
   */
  public static final int MSGID_LDAP_CONNHANDLER_DESCRIPTION_TRUSTMANAGER_DN =
       CATEGORY_MASK_PROTOCOL | SEVERITY_MASK_INFORMATIONAL | 393;
  /**
   * The message ID for the message that will be used if the specified trust
   * manager provider does not exist or is not enabled.  This takes two
   * arguments, which are the DN of the configuration entry and the trust
   * manager provider DN.
   */
  public static final int MSGID_LDAP_CONNHANDLER_INVALID_TRUSTMANAGER_DN =
       CATEGORY_MASK_PROTOCOL | SEVERITY_MASK_SEVERE_ERROR | 394;
  /**
   * The message ID for the message that will be used if an unexpected error
   * occurs while trying to determine the trust manager provider DN to use.
   * This takes two arguments, which are the DN of the configuration entry and a
   * string representation of the exception that was caught.
   */
  public static final int
       MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_TRUSTMANAGER_DN =
            CATEGORY_MASK_PROTOCOL | SEVERITY_MASK_SEVERE_ERROR | 395;
  /**
   * The message ID for the message that will be used to indicate that a new
   * value has been applied for the key manager provider DN configuration
   * option.  This takes two arguments, which are a string representation of the
   * new key manager provider DN and the DN of the configuration entry.
   */
  public static final int MSGID_LDAP_CONNHANDLER_NEW_KEYMANAGER_DN =
       CATEGORY_MASK_PROTOCOL | SEVERITY_MASK_INFORMATIONAL | 396;
  /**
   * The message ID for the message that will be used to indicate that a new
   * value has been applied for the trust manager provider DN configuration
   * option.  This takes two arguments, which are a string representation of the
   * new trust manager provider DN and the DN of the configuration entry.
   */
  public static final int MSGID_LDAP_CONNHANDLER_NEW_TRUSTMANAGER_DN =
       CATEGORY_MASK_PROTOCOL | SEVERITY_MASK_INFORMATIONAL | 397;
  /**
   * The message ID for the message that will be used as the description of the
   * configuration attribute specifying the DN of the key manager provider for
   * the JMX connection handler.
   */
  public static final int MSGID_JMX_CONNHANDLER_DESCRIPTION_KEYMANAGER_DN =
       CATEGORY_MASK_PROTOCOL | SEVERITY_MASK_INFORMATIONAL | 398;
  /**
   * The message ID for the message that will be used if the provided key
   * manager DN does not refer to a valid, enabled key manager.  This takes two
   * arguments, which are the DN of the configuration entry and the provided key
   * manager provider DN.
   */
  public static final int MSGID_JMX_CONNHANDLER_INVALID_KEY_MANAGER_DN =
       CATEGORY_MASK_PROTOCOL | SEVERITY_MASK_SEVERE_ERROR | 399;
  /**
   * The message ID for the message that will be used if an unexpected error
   * occurs while trying to determine the DN of the key manager provider to use.
   * This takes two arguments, which are the DN of the configuration entry and a
   * string representation of the exception that was caught.
   */
  public static final int MSGID_JMX_CONNHANDLER_CANNOT_DETERMINE_KEYMANAGER_DN =
       CATEGORY_MASK_PROTOCOL | SEVERITY_MASK_SEVERE_ERROR | 400;
  /**
   * Associates a set of generic messages with the message IDs defined in this
   * class.
   */
@@ -5420,6 +5540,40 @@
                    ATTR_SSL_PROTOCOLS + " attribute in configuration " +
                    "entry %s, which is used to specify the names of the " +
                    "SSL cipher suites to allow for SSL/TLS sessions:  %s.");
    registerMessage(MSGID_LDAP_CONNHANDLER_DESCRIPTION_KEYMANAGER_DN,
                    "Specifies the DN of the configuration entry for the key " +
                    "manager provider that should be used with this LDAP " +
                    "connection handler.  Changes to this attribute will " +
                    "take effect immediately, but only for subsequent " +
                    "attempts to access the key manager provider for " +
                    "associated client connections.");
    registerMessage(MSGID_LDAP_CONNHANDLER_INVALID_KEYMANAGER_DN,
                    "Configuration attribute " + ATTR_KEYMANAGER_DN +
                    " of configuration entry %s has an invalid value %s " +
                    "which does not reference an enabled key manager " +
                    "provider.");
    registerMessage(MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_KEYMANAGER_DN,
                    "An error occurred while processing the " +
                    ATTR_KEYMANAGER_DN + " attribute in configuration entry " +
                    "%s, which is used to specify the key manager provider " +
                    "for use with the LDAP connection handler:  %s.");
    registerMessage(MSGID_LDAP_CONNHANDLER_DESCRIPTION_TRUSTMANAGER_DN,
                    "Specifies the DN of the configuration entry for the " +
                    "trust manager provider that should be used with this " +
                    "LDAP connection handler.  Changes to this attribute " +
                    "will take effect immediately, but only for subsequent " +
                    "attempts to access the trust manager provider for " +
                    "associated client connections.");
    registerMessage(MSGID_LDAP_CONNHANDLER_INVALID_TRUSTMANAGER_DN,
                    "Configuration attribute " + ATTR_TRUSTMANAGER_DN +
                    " of configuration entry %s has an invalid value %s " +
                    "which does not reference an enabled trust manager " +
                    "provider.");
    registerMessage(MSGID_LDAP_CONNHANDLER_CANNOT_DETERMINE_TRUSTMANAGER_DN,
                    "An error occurred while processing the " +
                    ATTR_TRUSTMANAGER_DN + " attribute in configuration " +
                    "entry %s, which is used to specify the trust manager " +
                    "provider for use with the LDAP connection handler:  %s.");
    registerMessage(MSGID_LDAP_CONNHANDLER_INVALID_ADDRESS_MASK,
                    "The string %s defined in attribute %s of configuration " +
                    "entry %s could not be decoded as a valid address mask:  "+
@@ -5466,6 +5620,14 @@
                    "The value of the " + ATTR_SSL_CIPHERS +
                    " attribute has been updated to %s in configuration " +
                    "entry %s.");
    registerMessage(MSGID_LDAP_CONNHANDLER_NEW_KEYMANAGER_DN,
                    "The value of the " + ATTR_KEYMANAGER_DN +
                    " attribute has been updated to %s in configuration " +
                    "entry %s.");
    registerMessage(MSGID_LDAP_CONNHANDLER_NEW_TRUSTMANAGER_DN,
                    "The value of the " + ATTR_TRUSTMANAGER_DN +
                    " attribute has been updated to %s in configuration " +
                    "entry %s.");
    registerMessage(MSGID_LDAP_CONNHANDLER_STARTED_LISTENING,
                    "Started listening for new connections on %s.");
    registerMessage(MSGID_LDAP_CONNHANDLER_STOPPED_LISTENING,
@@ -5949,6 +6111,22 @@
            "entry %s, which is used to specify the nickname of the " +
            "certificate to use for accepting SSL/TSL connections:  " +
            "%s.");
    registerMessage(MSGID_JMX_CONNHANDLER_DESCRIPTION_KEYMANAGER_DN,
            "Specifies the DN of the key manager provider that the " +
            "connection handler should use when accepting SSL-based " +
            "connections or performing StartTLS negotiation.  " +
            "Changes to this configuration attribute will take effect " +
            "immediately.");
    registerMessage(MSGID_JMX_CONNHANDLER_INVALID_KEY_MANAGER_DN,
            "An error occurred while processing the " + ATTR_KEYMANAGER_DN +
            " attribute in configuration entry %s, because the provided " +
            "key manager DN %s does not refer to an enabled key manager " +
            "provider.");
    registerMessage(MSGID_JMX_CONNHANDLER_CANNOT_DETERMINE_KEYMANAGER_DN,
            "An unexpected error occurred while processing the " +
            ATTR_KEYMANAGER_DN + " attribute in configuration " +
            "entry %s, which is used to specify the DN of the key manager " +
            "provider to use for accepting SSL/TSL connections:  %s.");
    registerMessage(MSGID_PWPOLICYREQ_CONTROL_HAS_VALUE,
opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.protocols.jmx;
@@ -44,9 +44,6 @@
import org.opends.server.api.AlertGenerator;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.ConfigAddListener;
import org.opends.server.api.ConfigChangeListener;
import org.opends.server.api.ConfigDeleteListener;
import org.opends.server.api.ConfigurableComponent;
import org.opends.server.api.ConnectionHandler;
import org.opends.server.api.KeyManagerProvider;
@@ -54,6 +51,7 @@
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.StringConfigAttribute;
import org.opends.server.core.DirectoryServer;
@@ -73,9 +71,7 @@
 * handler should be used.
 */
public class JmxConnectionHandler
    extends ConnectionHandler implements ConfigurableComponent,
    ConfigChangeListener, ConfigDeleteListener, ConfigAddListener,
    AlertGenerator
    extends ConnectionHandler implements ConfigurableComponent, AlertGenerator
{
  /**
   * The fully-qualified name of this class for debugging purposes.
@@ -89,12 +85,6 @@
  private DN configEntryDN;
  /**
   * The RDN of the key Manager, if exists.
   * TODO Should we move this 'static' definition into another file?
   */
  private final static String KeyManagerRDN = "cn=Key Manager Provider";
  /**
   * Indicates whether this connection handler is enabled.
   */
  protected boolean enabled;
@@ -150,9 +140,20 @@
  private IntegerConfigAttribute listenPortAtt;
  /**
   * The key manager to used for encryption.
   * The DN of the key manager provider to use with this connection handler.
   */
  protected KeyManagerProvider jmxKeyManager;
  protected DN keyManagerProviderDN;
  /**
   * The key manager provider for this connection handler.
   */
  protected KeyManagerProvider keyManagerProvider;
  /**
   * The attribute which represents the DN of the key manager provider for this
   * connection handler.
   */
  private DNConfigAttribute keyManagerDNAtt;
  /**
   * Key that may be placed into a JMX connection environment map to
@@ -206,199 +207,6 @@
  }
  /**
   * Indicates whether the configuration entry that will result from a
   * proposed add is acceptable to this add listener.
   * <br>
   * Up to now, only a keyManager could be added under the JMX
   * Connector.
   *
   * @param configEntry
   *            The configuration entry that will result from the
   *            requested add.
   * @param unacceptableReason
   *            A buffer to which this method can append a human-readable
   *            message explaining why the proposed entry is not
   *            acceptable.
   * @return <CODE>true</CODE> if the proposed entry contains an
   *         acceptable configuration, or <CODE>false</CODE> if it does
   *         not.
   */
  public boolean configAddIsAcceptable(
      ConfigEntry configEntry, StringBuilder unacceptableReason)
  {
    assert debugEnter(CLASS_NAME, "configAddIsAcceptable");
    //
    // First check if we already have a key manager. If yes, this means
    // that the enter is already here and cannot be added ...
    if (jmxKeyManager != null)
    {
      return false;
    }
    // Check if it's the correct DN:
    // - Only child "key manager" is registered
    // - We should have no more than one child under the JMX connection
    // handler ...
    DN JmxKeymanagerDN = null;
    try
    {
      JmxKeymanagerDN = DN.decode(KeyManagerRDN + ", " + this.configEntryDN);
    }
    catch (Exception e)
    {
      return false;
    }
    if (!(JmxKeymanagerDN.equals(configEntry.getDN())))
    {
      return false;
    }
    //
    // return part: all other cases are valid
    return true;
  }
  /**
   * Attempts to apply a new configuration based on the provided added
   * entry.
   *
   * @param configEntry
   *            The new configuration entry that contains the
   *            configuration to apply.
   * @return Information about the result of processing the configuration
   *         change.
   */
  public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry)
  {
    assert debugEnter(CLASS_NAME, "applyConfigurationAdd");
    jmxKeyManager = getJmxKeyManager(configEntry);
    //
    // Ok, we have a key manager and if we have to use SSL, just do it.
    if (useSSL)
    {
      applyNewConfiguration(listenPort, useSSL, sslServerCertNickname);
    }
    return new ConfigChangeResult(ResultCode.SUCCESS, false);
  }
  /**
   * Indicates whether it is acceptable to remove the provided
   * configuration entry.
   *
   * @param configEntry
   *            The configuration entry that will be removed from the
   *            configuration.
   * @param unacceptableReason
   *            A buffer to which this method can append a human-readable
   *            message explaining why the proposed delete is not
   *            acceptable.
   * @return <CODE>true</CODE> if the proposed entry may be removed
   *         from the configuration, or <CODE>false</CODE> if not.
   */
  public boolean configDeleteIsAcceptable(
      ConfigEntry configEntry, StringBuilder unacceptableReason)
  {
    //
    // We can allow to remove the key manager only if we don't use it.
    if (useSSL)
    {
      return false;
    }
    else
    {
      return true;
    }
  }
  /**
   * Attempts to apply a new configuration based on the provided deleted
   * entry.
   *
   * @param configEntry
   *            The new configuration entry that has been deleted.
   * @return Information about the result of processing the configuration
   *         change.
   */
  public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry)
  {
    //
    // Just set the key manager to null
    jmxKeyManager = null;
    return new ConfigChangeResult(ResultCode.SUCCESS, false);
  }
  /**
   * Indicates whether the configuration entry that will result from a
   * proposed modification is acceptable to this change listener.
   *
   * @param configEntry
   *            The configuration entry that will result from the
   *            requested update.
   * @param unacceptableReason
   *            A buffer to which this method can append a human-readable
   *            message explaining why the proposed change is not
   *            acceptable.
   * @return <CODE>true</CODE> if the proposed entry contains an
   *         acceptable configuration, or <CODE>false</CODE> if it does
   *         not.
   */
  public boolean configChangeIsAcceptable(
      ConfigEntry configEntry, StringBuilder unacceptableReason)
  {
    //
    // We are checking first if we are dealing with a change
    // in the current entry.
    // Always return true as the check will be performed by the
    // hasAcceptableConfiguration call
    if (configEntry.getDN().equals(configEntryDN))
    {
      return true;
    }
    //
    // Then, we are checking that a change in the key manager
    // is acceptable.
    if (useSSL)
    {
      return false;
    }
    else
    {
      return true;
    }
  }
  /**
   * Attempts to apply a new configuration to this Directory Server
   * component based on the provided changed entry.
   *
   * @param configEntry
   *            The configuration entry that containing the updated
   *            configuration for this component.
   * @return Information about the result of processing the configuration
   *         change.
   */
  public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry)
  {
    //
    // We are checking first if we are dealing with a change
    // in the current entry.
    if (configEntry.getDN().equals(configEntryDN))
    {
      ArrayList<String> messages = new ArrayList<String>();
      return new ConfigChangeResult(ResultCode.SUCCESS, false, messages);
    }
    //
    // Only child "key manager" are registered
    jmxKeyManager = getJmxKeyManager(configEntry);
    return new ConfigChangeResult(ResultCode.SUCCESS, false);
  }
  /**
   * Initializes this connection handler based on the information in the
   * provided configuration entry.
   *
@@ -449,42 +257,18 @@
    sslServerCertNickname = sslServerCertNickNameAtt.activeValue();
    //
    // At this point, we have a configuration entry. Register a change
    // listener with it so we can be notified of changes to it over
    // time.
    // We will also want to register a delete and add listeners with
    // its parent.
    configEntry.registerDeleteListener(this);
    configEntry.registerChangeListener(this);
    configEntry.registerAddListener(this);
    //
    // Get the KeyManager, if specified.
    if (useSSL)
    // Determine which key manager provider to use.
    keyManagerDNAtt = getKeyManagerDN(configEntry);
    configAttrs.add(keyManagerDNAtt);
    if (keyManagerDNAtt == null)
    {
      ConfigEntry keyManagerConfigEntry;
      try
      {
        DN KeyManagerDN = DN.decode(KeyManagerRDN + ", " + configEntryDN);
        keyManagerConfigEntry = DirectoryServer.getConfigEntry(KeyManagerDN);
        jmxKeyManager = getJmxKeyManager(keyManagerConfigEntry);
      }
      catch (Exception e)
      {
        assert debugException(CLASS_NAME, "initializeKeyManagerProvider", e);
        logError(
            ErrorLogCategory.CONFIGURATION,
            ErrorLogSeverity.SEVERE_ERROR,
            MSGID_CONFIG_KEYMANAGER_CANNOT_GET_CONFIG_ENTRY,
            stackTraceToSingleLineString(e));
        configEntry.registerAddListener(this);
        jmxKeyManager = null;
      }
      keyManagerProviderDN = null;
    }
    else
    {
      jmxKeyManager = null;
      keyManagerProviderDN = keyManagerDNAtt.activeValue();
      keyManagerProvider =
           DirectoryServer.getKeyManagerProvider(keyManagerProviderDN);
    }
    // Create the associated RMI Connector
@@ -496,7 +280,7 @@
    //
    // Check if we have a correct SSL configuration
    if ((useSSL && jmxKeyManager == null))
    if ((useSSL && keyManagerProvider == null))
    {
      //
@@ -695,11 +479,39 @@
    }
    //
    // Determine the DN of the key manager provider.
    DN newKeyManagerProviderDN = null;
    KeyManagerProvider newKeyManagerProvider = null;
    try
    {
      DNConfigAttribute attr = getKeyManagerDN(configEntry);
      if (attr == null)
      {
        newKeyManagerProviderDN = null;
      }
      else
      {
        newKeyManagerProviderDN = attr.pendingValue();
        newKeyManagerProvider   =
             DirectoryServer.getKeyManagerProvider(newKeyManagerProviderDN);
      }
    }
    catch (Exception e)
    {
      int msgID = MSGID_JMX_CONNHANDLER_CANNOT_DETERMINE_KEYMANAGER_DN;
      unacceptableReasons.add(getMessage(
          msgID,
          String.valueOf(configEntryDN),
          stackTraceToSingleLineString(e)));
      configValid = false;
    }
    //
    // Determine whether to use SSL.
    try
    {
      boolean newUseSSL = getUseSSL(configEntry).activeValue();
      if (newUseSSL && (jmxKeyManager == null))
      if (newUseSSL && (newKeyManagerProvider == null))
      {
        //
        // TODO Set an appropriate message (instead of null)
@@ -834,13 +646,65 @@
    }
    //
    // Determine which key manager provider to use.
    DN newKeyManagerProviderDN = keyManagerProviderDN;
    KeyManagerProvider newKeyManagerProvider = keyManagerProvider;
    try
    {
      DNConfigAttribute attr = getKeyManagerDN(configEntry);
      if (attr == null)
      {
        newKeyManagerProviderDN = null;
        newKeyManagerProvider   = null;
        if (keyManagerProviderDN != null)
        {
          rmiConnectorRestart = true;
        }
      }
      else
      {
        newKeyManagerProviderDN = attr.pendingValue();
        newKeyManagerProvider =
             DirectoryServer.getKeyManagerProvider(newKeyManagerProviderDN);
        if (newUseSSL && (newKeyManagerProvider == null))
        {
          int msgID = MSGID_JMX_CONNHANDLER_INVALID_KEY_MANAGER_DN;
          messages.add(getMessage(
              msgID,
              String.valueOf(configEntryDN),
              String.valueOf(newKeyManagerProviderDN)));
          resultCode = DirectoryServer.getServerErrorResultCode();
        }
        else
        {
          if (! newKeyManagerProviderDN.equals(keyManagerProviderDN))
          {
            rmiConnectorRestart = true;
          }
        }
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyNewConfiguration", e);
      int msgID = MSGID_JMX_CONNHANDLER_CANNOT_DETERMINE_KEYMANAGER_DN;
      messages.add(getMessage(
          msgID,
          String.valueOf(configEntryDN),
          stackTraceToSingleLineString(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
    }
    //
    // Apply new config, best effort mode
    if (rmiConnectorRestart)
    {
      applyNewConfiguration(
          newListenPort,
          newUseSSL,
          newSslServerCertNickname);
          newSslServerCertNickname,
          newKeyManagerProviderDN,
          newKeyManagerProvider);
    }
    //
@@ -857,9 +721,14 @@
   *            Indicates if we should use ssl
   * @param newSslServerCertNickname
   *            Indicates the new server certificate nickname
   * @param newKeyManagerProviderDN
   *            The new key manager provider DN.
   * @param newKeyManagerProvider
   *            The new key manager provider instance.
   */
  private void applyNewConfiguration(
      int newListenPort, boolean newUseSSL, String newSslServerCertNickname)
      int newListenPort, boolean newUseSSL, String newSslServerCertNickname,
      DN newKeyManagerProviderDN, KeyManagerProvider newKeyManagerProvider)
  {
    //
    // Stop the current connector
@@ -901,6 +770,39 @@
      }
    }
    if (keyManagerProviderDN == null)
    {
      if (newKeyManagerProviderDN != null)
      {
        try
        {
          keyManagerProviderDN = newKeyManagerProviderDN;
          keyManagerProvider   = newKeyManagerProvider;
          keyManagerDNAtt.setValue(newKeyManagerProviderDN);
        }
        catch (Exception e)
        {
          // TODO
          // Print error message
        }
      }
    }
    else if ((newKeyManagerProviderDN == null) ||
             (! newKeyManagerProviderDN.equals(keyManagerProviderDN)))
    {
      try
      {
        keyManagerProviderDN = newKeyManagerProviderDN;
        keyManagerProvider   = newKeyManagerProvider;
        keyManagerDNAtt.setValue(newKeyManagerProviderDN);
      }
      catch (Exception e)
      {
        // TODO
        // Print error message
      }
    }
    if (useSSL)
    {
      protocol = "JMX+SSL";
@@ -1180,191 +1082,37 @@
  }
  /**
   * Retrieve the KeyManager configured for the JMX Connection handler.
   * With look for the child config entry (We should have no more than
   * one child entry)
   *
   * @param jmxConnectorDN the DN of the associated JMX connector
   * entry
   *
   * @return the configured key manager if set or the server
   * key manager
   * Determine if the specified Configuration entry defines the
   * key manager provider DN.
   * @param configEntry The entry to check.
   * @return The key manager provider DN.
   * @throws InitializationException
   *      If a problem occurs while attempting to get the key manager
   *      provider DN.
   */
  private KeyManagerProvider getJmxKeyManager(
      ConfigEntry keyManagerConfigEntry)
  private DNConfigAttribute getKeyManagerDN(ConfigEntry configEntry)
      throws InitializationException
  {
    //
    // Get the key manager provider configuration entry. If it is not
    // present, then register an add listener.
    boolean shouldReturnNull = false;
    if (keyManagerConfigEntry == null)
    {
      logError(
          ErrorLogCategory.CONFIGURATION,
          ErrorLogSeverity.SEVERE_WARNING,
          MSGID_CONFIG_KEYMANAGER_NO_CONFIG_ENTRY);
      return null;
    }
    //
    // See if the entry indicates whether the key manager provider
    // should be enabled.
    int msgID = MSGID_CONFIG_KEYMANAGER_DESCRIPTION_ENABLED;
    BooleanConfigAttribute enabledStub = new BooleanConfigAttribute(
        ATTR_KEYMANAGER_ENABLED, getMessage(msgID), false);
    int msgID = MSGID_JMX_CONNHANDLER_DESCRIPTION_KEYMANAGER_DN;
    DNConfigAttribute keyManagerStub = new DNConfigAttribute(
        ATTR_KEYMANAGER_DN, getMessage(msgID), false, false, false);
    DNConfigAttribute keyManagerAttr = null;
    try
    {
      BooleanConfigAttribute enabledAttr = (BooleanConfigAttribute)
         keyManagerConfigEntry.getConfigAttribute(enabledStub);
      if (enabledAttr == null)
      {
        //
        // The attribute is not present, so the key manager
        // provider will be disabled.
        // Log a warning message and return.
        // FIXME -- Message shouldn't be the same than the server one
        logError(
            ErrorLogCategory.CONFIGURATION,
            ErrorLogSeverity.SEVERE_WARNING,
            MSGID_CONFIG_KEYMANAGER_NO_ENABLED_ATTR);
        shouldReturnNull = true;
      }
      else if (!enabledAttr.activeValue())
      {
        //
        // The key manager provider is explicitly disabled. Log a
        // mild warning and return.
        // FIXME -- Message shouldn't be the same than the server one
        logError(
            ErrorLogCategory.CONFIGURATION,
            ErrorLogSeverity.MILD_WARNING,
            MSGID_CONFIG_KEYMANAGER_DISABLED);
        shouldReturnNull = true;
      }
      keyManagerAttr = (DNConfigAttribute) configEntry
          .getConfigAttribute(keyManagerStub);
      return keyManagerAttr;
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeKeyManagerProvider", e);
      assert debugException(CLASS_NAME, "initializeConnectionHandler", e);
      // FIXME -- Message shouldn't be the same than the server one
      logError(
          ErrorLogCategory.CONFIGURATION,
          ErrorLogSeverity.SEVERE_ERROR,
          MSGID_CONFIG_KEYMANAGER_UNABLE_TO_DETERMINE_ENABLED_STATE,
      msgID = MSGID_JMX_CONNHANDLER_CANNOT_DETERMINE_KEYMANAGER_DN;
      String message = getMessage(
          msgID,
          String.valueOf(configEntryDN),
          stackTraceToSingleLineString(e));
      return null;
    }
    //
    // See if it specifies the class name for the key manager provider
    // implementation.
    String className;
    msgID = MSGID_CONFIG_KEYMANAGER_DESCRIPTION_CLASS;
    StringConfigAttribute classStub = new StringConfigAttribute(
        ATTR_KEYMANAGER_CLASS, getMessage(msgID), true, false, false);
    try
    {
      StringConfigAttribute classAttr = (StringConfigAttribute)
            keyManagerConfigEntry.getConfigAttribute(classStub);
      if (classAttr == null)
      {
        // FIXME -- Message shouldn't be the same than the server one
        logError(
            ErrorLogCategory.CONFIGURATION,
            ErrorLogSeverity.SEVERE_ERROR,
            MSGID_CONFIG_KEYMANAGER_NO_CLASS_ATTR);
        return null;
      }
      else
      {
        className = classAttr.activeValue();
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeKeyManagerProvider", e);
      // FIXME Message shouldn't be the same than the server one
      logError(
          ErrorLogCategory.CONFIGURATION,
          ErrorLogSeverity.SEVERE_ERROR,
          MSGID_CONFIG_KEYMANAGER_CANNOT_DETERMINE_CLASS,
          stackTraceToSingleLineString(e));
      return null;
    }
    //
    // Try to load the class and instantiate it as a key manager
    // provider.
    Class keyManagerProviderClass;
    try
    {
      // FIXME -- Should we use a custom class loader for this?
      keyManagerProviderClass = Class.forName(className);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeKeyManagerProvider", e);
      // FIXME -- Message shouldn't be the same than the server one
      logError(
          ErrorLogCategory.CONFIGURATION,
          ErrorLogSeverity.SEVERE_ERROR,
          MSGID_CONFIG_KEYMANAGER_CANNOT_LOAD_CLASS,
          String.valueOf(className),
          stackTraceToSingleLineString(e));
      return null;
    }
    KeyManagerProvider keyManagerProvider;
    try
    {
      keyManagerProvider = (KeyManagerProvider) keyManagerProviderClass
          .newInstance();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeKeyManagerProvider", e);
      // FIXME -- Message shouldn't be the same than the server one
      logError(
          ErrorLogCategory.CONFIGURATION,
          ErrorLogSeverity.SEVERE_ERROR,
          MSGID_CONFIG_KEYMANAGER_CANNOT_INSTANTIATE_CLASS,
          String.valueOf(className),
          stackTraceToSingleLineString(e));
      return null;
    }
    //
    // Try to initialize the key manager provider with the contents of
    // the configuration entry.
    try
    {
      keyManagerProvider.initializeKeyManagerProvider(keyManagerConfigEntry);
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeKeyManagerProvider", e);
      // FIXME -- Message shouldn't be the same than the server one
      logError(
          ErrorLogCategory.CONFIGURATION,
          ErrorLogSeverity.SEVERE_WARNING,
          MSGID_CONFIG_KEYMANAGER_CANNOT_INITIALIZE,
          String.valueOf(className),
          e.getMessage());
      return null;
    }
    if (shouldReturnNull)
    {
      return null;
    }
    else
    {
      return keyManagerProvider;
      throw new InitializationException(msgID, message, e);
    }
  }
}
opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/RmiConnector.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.protocols.jmx;
@@ -41,7 +41,9 @@
import javax.management.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnectorServer;
import org.opends.server.api.KeyManagerProvider;
import org.opends.server.config.JMXMBean;
import org.opends.server.extensions.NullKeyManagerProvider;
import org.opends.server.types.DebugLogCategory;
import org.opends.server.types.DebugLogSeverity;
@@ -318,9 +320,15 @@
        // ---------------------
        //
        // Get a Server socket factory
        KeyManagerProvider provider = jmxConnectionHandler.keyManagerProvider;
        if (provider == null)
        {
          provider = new NullKeyManagerProvider();
        }
        SSLContext ctx = SSLContext.getInstance("TLSv1");
        ctx.init(
            jmxConnectionHandler.jmxKeyManager.getKeyManagers(),
            provider.getKeyManagers(),
            null,
            null);
        SSLSocketFactory ssf = ctx.getSocketFactory();
opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -2629,5 +2629,29 @@
    sendLDAPMessage(clearSecurityProvider,
                    operationToResponseLDAPMessage(operation));
  }
  /**
   * {@inheritDoc}
   */
  public DN getKeyManagerProviderDN()
  {
    assert debugEnter(CLASS_NAME, "getKeyManagerProviderDN");
    return connectionHandler.getKeyManagerProviderDN();
  }
  /**
   * {@inheritDoc}
   */
  public DN getTrustManagerProviderDN()
  {
    assert debugEnter(CLASS_NAME, "getTrustManagerProviderDN");
    return connectionHandler.getTrustManagerProviderDN();
  }
}
opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.protocols.ldap;
@@ -50,6 +50,8 @@
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.TrustManagerProvider;
import org.opends.server.api.plugin.PostConnectPluginResult;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.PluginConfigManager;
@@ -57,6 +59,7 @@
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;
@@ -186,6 +189,12 @@
  // 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;
  // The set of addresses on which to listen for new connections.
  private HashSet<InetAddress> listenAddresses;
@@ -965,6 +974,84 @@
    }
    // 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)
    {
      assert debugException(CLASS_NAME, "initializeConnectionHandler", 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)
    {
      assert debugException(CLASS_NAME, "initializeConnectionHandler", 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 =
@@ -1667,6 +1754,44 @@
  /**
   * 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()
  {
    assert debugEnter(CLASS_NAME, "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()
  {
    assert debugEnter(CLASS_NAME, "getTrustManagerProviderDN");
    return trustManagerProviderDN;
  }
  /**
   * Retrieves the maximum ASN.1 element value length that will be allowed by
   * this connection handler.
   *
@@ -1913,6 +2038,16 @@
                             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;
  }
@@ -2491,6 +2626,78 @@
    }
    // 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)
    {
      assert debugException(CLASS_NAME, "initializeConnectionHandler", 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)
    {
      assert debugException(CLASS_NAME, "initializeConnectionHandler", 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;
  }
@@ -3039,6 +3246,92 @@
    }
    // 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)
    {
      assert debugException(CLASS_NAME, "initializeConnectionHandler", 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)
    {
      assert debugException(CLASS_NAME, "initializeConnectionHandler", 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)
    {
@@ -3207,6 +3500,60 @@
                                  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)));
        }
      }
    }
opendj-sdk/opends/tests/unit-tests-testng/resource/config-changes.ldif
@@ -10,6 +10,26 @@
-
replace: ds-cfg-allow-start-tls
ds-cfg-allow-start-tls: true
-
replace: ds-cfg-key-manager-provider-dn
ds-cfg-key-manager-provider-dn: cn=JKS,cn=Key Manager Providers,cn=config
-
replace: ds-cfg-trust-manager-provider-dn
ds-cfg-trust-manager-provider-dn: cn=JKS,cn=Trust Manager Providers,cn=config
dn: cn=LDAPS Connection Handler,cn=Connection Handlers,cn=config
changeType: modify
replace: ds-cfg-connection-handler-enabled
ds-cfg-connection-handler-enabled: true
-
replace: ds-cfg-listen-port
ds-cfg-listen-port: #ldapsport#
-
replace: ds-cfg-key-manager-provider-dn
ds-cfg-key-manager-provider-dn: cn=JKS,cn=Key Manager Providers,cn=config
-
replace: ds-cfg-trust-manager-provider-dn
ds-cfg-trust-manager-provider-dn: cn=JKS,cn=Trust Manager Providers,cn=config
dn: cn=JMX Connection Handler,cn=Connection Handlers,cn=config
changeType: modify
@@ -273,31 +293,7 @@
ds-cfg-plugin-type: preOperationAdd
ds-cfg-plugin-type: preOperationModify
dn: cn=LDAPS Connection Handler,cn=Connection Handlers,cn=config
changetype: add
objectClass: top
objectClass: ds-cfg-connection-handler
objectClass: ds-cfg-ldap-connection-handler
cn: LDAPS Connection Handler
ds-cfg-connection-handler-class: org.opends.server.protocols.ldap.LDAPConnectionHandler
ds-cfg-connection-handler-enabled: true
ds-cfg-listen-address: 0.0.0.0
ds-cfg-listen-port: #ldapsport#
ds-cfg-accept-backlog: 128
ds-cfg-allow-ldapv2: true
ds-cfg-keep-stats: true
ds-cfg-use-tcp-keepalive: true
ds-cfg-use-tcp-nodelay: true
ds-cfg-allow-tcp-reuse-address: true
ds-cfg-send-rejection-notice: true
ds-cfg-max-request-size: 5 megabytes
ds-cfg-num-request-handlers: 2
ds-cfg-allow-start-tls: false
ds-cfg-use-ssl: true
ds-cfg-ssl-client-auth-policy: optional
ds-cfg-ssl-cert-nickname: server-cert
dn: cn=Key Manager Provider,cn=SSL,cn=config
dn: cn=JKS,cn=Key Manager Providers,cn=config
changetype: modify
replace: ds-cfg-key-manager-provider-enabled
ds-cfg-key-manager-provider-enabled: true
@@ -307,8 +303,23 @@
-
replace: ds-cfg-key-store-pin
ds-cfg-key-store-pin: password
-
replace: ds-cfg-key-store-pin-file
dn: cn=Trust Manager Provider,cn=SSL,cn=config
dn: cn=PKCS12,cn=Key Manager Providers,cn=config
changetype: modify
replace: ds-cfg-key-manager-provider-enabled
ds-cfg-key-manager-provider-enabled: true
-
replace: ds-cfg-key-store-file
ds-cfg-key-store-file: config/server-cert.p12
-
replace: ds-cfg-key-store-pin
ds-cfg-key-store-pin: password
-
replace: ds-cfg-key-store-pin-file
dn: cn=JKS,cn=Trust Manager Providers,cn=config
changetype: modify
replace: ds-cfg-trust-manager-provider-enabled
ds-cfg-trust-manager-provider-enabled: true
@@ -318,6 +329,8 @@
-
replace: ds-cfg-trust-store-pin
ds-cfg-trust-store-pin: password
-
replace: ds-cfg-key-store-pin-file
dn: cn=File-Based Debug Logger,cn=Loggers,cn=config
changetype: modify
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/RejectUnauthReqTests.java
@@ -53,9 +53,9 @@
import static org.opends.server.util.ServerConstants.*;
/**
 * A set of testcases for configuration attribute
 * A set of testcases for configuration attribute
 * "ds-cfg-reject-unauthenticated-requests".
 *
 *
 */
public class RejectUnauthReqTests extends CoreTestCase
@@ -713,8 +713,6 @@
  @AfterClass()
  public void  testResetRejUnauthReqCfgAttr()  throws Exception
  {
    //Verify the modified setting of the configuration attribute.
    assertEquals(DirectoryServer.rejectUnauthenticatedRequests(),true);
    String path = TestCaseUtils.createTempFile(
       "dn: cn=config",
       "changetype: modify",
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FileBasedKeyManagerProviderTestCase.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.extensions;
@@ -317,25 +317,5 @@
    FileBasedKeyManagerProvider provider = new FileBasedKeyManagerProvider();
    provider.initializeKeyManagerProvider(configEntry);
  }
  /**
   * Tests the <CODE>getKeyManagers</CODE> method.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testGetKeyManagers()
         throws Exception
  {
    FileBasedKeyManagerProvider provider =
         (FileBasedKeyManagerProvider) DirectoryServer.getKeyManagerProvider();
    assertNotNull(provider);
    KeyManager[] keyManagers = provider.getKeyManagers();
    assertNotNull(keyManagers);
    assertFalse(keyManagers.length == 0);
  }
}
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FileBasedTrustManagerProviderTestCase.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.extensions;
@@ -305,31 +305,10 @@
    FileBasedTrustManagerProvider provider =
         new FileBasedTrustManagerProvider();
    provider.initializeTrustManagerProvider(configEntry);
for (StringBuilder sb : e.toLDIF())
{
  System.err.println(sb.toString());
}
  }
  /**
   * Tests the <CODE>getTrustManagers</CODE> method.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testGetTrustManagers()
         throws Exception
  {
    FileBasedTrustManagerProvider provider =
         (FileBasedTrustManagerProvider)
         DirectoryServer.getTrustManagerProvider();
    assertNotNull(provider);
    TrustManager[] trustManagers = provider.getTrustManagers();
    assertNotNull(trustManagers);
    assertFalse(trustManagers.length == 0);
    for (StringBuilder sb : e.toLDIF())
    {
      System.err.println(sb.toString());
    }
  }
}
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxConnectTest.java
@@ -39,6 +39,7 @@
import java.util.Set;
import javax.management.Attribute;
import javax.management.AttributeNotFoundException;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.net.ssl.TrustManager;
@@ -356,31 +357,10 @@
  @Test(enabled=true)
  public void sslConnect() throws Exception
  {
    // configure the JMX ssl key manager
    ConfigEntry config = new ConfigEntry(TestCaseUtils.makeEntry(
        "dn: cn=Key Manager Provider,cn=JMX Connection Handler,cn=Connection Handlers,cn=config",
        "objectClass: top",
        "objectClass: ds-cfg-key-manager-provider",
        "objectClass: ds-cfg-file-based-key-manager-provider",
        "ds-cfg-key-manager-provider-class: org.opends.server.extensions.FileBasedKeyManagerProvider",
        "ds-cfg-key-manager-provider-enabled: true",
        "ds-cfg-key-store-file: " + getJmxKeystorePath(),
        "ds-cfg-key-store-type: JKS",
        "ds-cfg-key-store-pin: password"
         ), null);
    JmxConnectionHandler jmxConnectionHandler = getJmxConnectionHandler();
    assertNotNull(jmxConnectionHandler);
    StringBuilder reason = new StringBuilder();
    assertTrue(jmxConnectionHandler.configAddIsAcceptable(config, reason));
    ConfigChangeResult result =
      jmxConnectionHandler.applyConfigurationAdd(config);
    assertEquals(ResultCode.SUCCESS, result.getResultCode());
    // Enable SSL by setting ds-cfg-use-ssl boolean and the
    // certificate alias using ds-cfg-ssl-cert-nickname attribute.
    int initJmxPort = (int) TestCaseUtils.getServerJmxPort();
    config = new ConfigEntry(TestCaseUtils.makeEntry(
    ConfigEntry config = new ConfigEntry(TestCaseUtils.makeEntry(
        "dn: cn=JMX Connection Handler,cn=Connection Handlers,cn=config",
        "objectClass: top",
        "objectClass: ds-cfg-connection-handler",
@@ -390,6 +370,7 @@
        "ds-cfg-connection-handler-enabled: true",
        "ds-cfg-use-ssl: true",
        "ds-cfg-listen-port: " + initJmxPort ,
        "ds-cfg-key-manager-provider-dn: cn=JKS,cn=Key Manager Providers,cn=config",
        "cn: JMX Connection Handler"
         ), null);
@@ -610,11 +591,19 @@
  {
    String jmxName = JMXMBean.getJmxName(DN.decode(dn));
    ObjectName name = ObjectName.getInstance(jmxName);
    Attribute status = (Attribute) mbsc.getAttribute(name, attributeName);
    if (status == null)
    try
    {
      Attribute status = (Attribute) mbsc.getAttribute(name, attributeName);
      if (status == null)
        return null;
      else
        return status.getValue();
    }
    catch (AttributeNotFoundException anfe)
    {
      return null;
    else
      return status.getValue();
    }
  }
  /**