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

neil_a_wilson
24.23.2007 a9708916f4d9379375064ac29c0cde7118b8e04b
Migrate the core configuration to the admin framework.
2 files modified
3207 ■■■■ changed files
opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml 410 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/CoreConfigManager.java 2797 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml
@@ -37,6 +37,7 @@
    .
  </adm:synopsis>
  <adm:tag name="core"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.13</ldap:oid>
@@ -44,6 +45,7 @@
      <ldap:superior>top</ldap:superior>
    </ldap:object-class>
  </adm:profile>
  <adm:property name="check-schema" mandatory="true">
    <adm:synopsis>
      Indicates whether schema enforcement is active.
@@ -66,4 +68,412 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="default-password-policy" mandatory="true">
    <adm:synopsis>
      Specifies the DN of the configuration entry for the password policy that
      will be in effect for users whose entries do not specify an alternate
      password policy (either via a real or virtual attribute).
    </adm:synopsis>
    <adm:syntax>
      <adm:dn>
        <adm:base>cn=Password Policies,cn=config</adm:base>
      </adm:dn>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.202</ldap:oid>
        <ldap:name>ds-cfg-default-password-policy</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="add-missing-rdn-attributes" mandatory="false">
    <adm:synopsis>
      Indicates whether the Directory Server should automatically add any
      attribute values contained in the entry's RDN into that entry when
      processing an add request.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          true
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:boolean />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.142</ldap:oid>
        <ldap:name>ds-cfg-add-missing-rdn-attributes</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="allow-attribute-name-exceptions" mandatory="false">
    <adm:synopsis>
      Indicates whether the Directory Server should allow the use of underscores
      in attribute names, and should allow attribute names to begin with
      numeric digits (both of which are violations of the LDAP standards).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          false
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:boolean />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.5</ldap:oid>
        <ldap:name>ds-cfg-allow-attribute-name-exceptions</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="invalid-attribute-syntax-behavior" mandatory="false">
    <adm:synopsis>
      Specifies how the Directory Server should handle operations which would
      result in an attribute value that violates the associated attribute
      syntax.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          reject
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:enumeration>
        <adm:value name="accept">
          <adm:synopsis>
            The Directory Server will silently accept attribute values that are
            invalid according to their associated syntax.  Matching operations
            targeting those values may not behave as expected.
          </adm:synopsis>
        </adm:value>
        <adm:value name="reject">
          <adm:synopsis>
            The Directory Server will reject attribute values that are invalid
            according to their associated syntax.
          </adm:synopsis>
        </adm:value>
        <adm:value name="warn">
          <adm:synopsis>
            The Directory Server will accept attribute values that are invalid
            according to their associated syntax, but will also log a warning
            message to the error log.  Matching operations targeting those
            values may not behave as expected.
          </adm:synopsis>
        </adm:value>
      </adm:enumeration>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.44</ldap:oid>
        <ldap:name>ds-cfg-invalid-attribute-syntax-behavior</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="server-error-result-code" mandatory="false">
    <adm:synopsis>
      Specifies the numeric value of the result code that should be used for
      cases in which request processing fails due to an internal server error.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          80
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:integer lower-limit="0" />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.143</ldap:oid>
        <ldap:name>ds-cfg-server-error-result-code</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="single-structural-objectclass-behavior" mandatory="false">
    <adm:synopsis>
      Specifies how the Directory Server should handle operations which would
      result in an entry without any structural object class, or that would
      result in an entry containing multiple structural classes.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          reject
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:enumeration>
        <adm:value name="accept">
          <adm:synopsis>
            The Directory Server will silently accept entries that do not
            contain exactly one structural object class.  Certain schema
            features that depend on the entry's structural class may not behave
            as expected.
          </adm:synopsis>
        </adm:value>
        <adm:value name="reject">
          <adm:synopsis>
            The Directory Server will reject entries that do not contain exactly
            one structural object class.
          </adm:synopsis>
        </adm:value>
        <adm:value name="warn">
          <adm:synopsis>
            The Directory Server will accept entries that do not contain exactly
            one structural object class, but will also log a warning message to
            the error log.  Certain schema features that depend on the entry's
            structural class may not behave
            as expected.
          </adm:synopsis>
        </adm:value>
      </adm:enumeration>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.117</ldap:oid>
        <ldap:name>ds-cfg-single-structural-objectclass-behavior</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="notify-abandoned-operations" mandatory="false">
    <adm:synopsis>
      Indicates whether the Directory Server should send a response to any
      operation that is interrupted via an abandon request.  The LDAP
      specification states that abandoned operations should not receive any
      response, but this may cause problems with client applications that
      always expect to receive a response to each request.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          false
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:boolean />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.71</ldap:oid>
        <ldap:name>ds-cfg-notify-abandoned-operations</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="size-limit" mandatory="false">
    <adm:synopsis>
      Specifies the maximum number of entries that the Directory Server should
      return to the client in the course of processing a search operation.  A
      value of 0 indicates that no size limit will be enforced.  Note that this
      is the default server-wide limit, but it may be overridden on a per-user
      basis using the ds-rlim-size-limit operational attribute.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          1000
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:integer lower-limit="0" />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.118</ldap:oid>
        <ldap:name>ds-cfg-size-limit</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="time-limit" mandatory="false">
    <adm:synopsis>
      Specifies the maximum length of time that the Directory Server should
      spend procesing a search operation.  A value of 0 seconds indicates that
      no time limit will be enforced.  Note that this is the default server-wide
      time limit, but it may be overridden on a per-user basis using the
      ds-rlim-time-limit operational attribute.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          60 seconds
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:duration base-unit="s" lower-limit="0" />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.150</ldap:oid>
        <ldap:name>ds-cfg-time-limit</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="proxied-authorization-identity-mapper-dn"
    mandatory="true">
    <adm:synopsis>
      Specifies the DN of the configuration entry for the identity mapper that
      will be used to map authorization ID values (using the "u:" form) provided
      in the proxied authorization control to the corresponding user entry.
    </adm:synopsis>
    <adm:syntax>
      <adm:dn>
        <adm:base>cn=Identity Mappers,cn=config</adm:base>
      </adm:dn>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.149</ldap:oid>
        <ldap:name>ds-cfg-proxied-authorization-identity-mapper-dn</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="writability-mode" mandatory="false">
    <adm:synopsis>
      Specifies which kinds of write operations the Directory Server should
      attempt to process.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          enabled
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:enumeration>
        <adm:value name="enabled">
          <adm:synopsis>
            The Directory Server will attempt to process all write operations
            that are requested of it, regardless of their origin.
          </adm:synopsis>
        </adm:value>
        <adm:value name="disabled">
          <adm:synopsis>
            The Directory Server will reject all write operations that are
            requested of it, regardless of their origin.
          </adm:synopsis>
        </adm:value>
        <adm:value name="internal-only">
          <adm:synopsis>
            The Directory Server will attempt to process write operations
            requested as internal operations or through synchronization, but
            will reject any such operations requested from external clients.
          </adm:synopsis>
        </adm:value>
      </adm:enumeration>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.161</ldap:oid>
        <ldap:name>ds-cfg-writability-mode</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="reject-unauthenticated-requests" mandatory="false">
    <adm:synopsis>
      Indicates whether the Directory Server should reject any request (other
      than bind or StartTLS requests) received from a client that has not yet
      authenticated, whose last authentication attempt was unsuccessful, or
      whose last authentication attempt used anonymous authentication.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          false
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:boolean />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.301</ldap:oid>
        <ldap:name>ds-cfg-reject-unauthenticated-requests</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="bind-with-dn-requires-password" mandatory="false">
    <adm:synopsis>
      Indicates whether the Directory Server should reject any simple bind
      request that contains a DN but no password.  Although such bind requests
      are technically allowed by the LDAPv3 specification (and should be treated
      as anonymous simple authentication), they may introduce security problems
      in applications that do not verify that the client actually provided a
      password.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          true
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:boolean />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.163</ldap:oid>
        <ldap:name>ds-cfg-bind-with-dn-requires-password</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="lookthrough-limit" mandatory="false">
    <adm:synopsis>
      Specifies the maximum number of entries that the Directory Server should
      "look through" in the course of processing a search request.  This
      includes any entry that the server must examine in the course of
      processing the request, regardless of whether it actually matches the
      search criteria.  A value of 0 indicates that no lookthrough limit will
      be enforced.  Note that this is the default server-wide limit, but it may
      be overridden on a per-user basis using the ds-rlim-lookthrough-limit
      operational attribute.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          5000
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:integer lower-limit="0" />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.285</ldap:oid>
        <ldap:name>ds-cfg-lookthrough-limit</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opends/src/server/org/opends/server/core/CoreConfigManager.java
@@ -29,88 +29,35 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import org.opends.server.api.ConfigurableComponent;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.std.server.GlobalCfg;
import org.opends.server.admin.std.server.RootCfg;
import org.opends.server.admin.server.ServerManagementContext;
import org.opends.server.api.IdentityMapper;
import org.opends.server.config.BooleanConfigAttribute;
import org.opends.server.config.ConfigAttribute;
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.config.DNConfigAttribute;
import org.opends.server.config.IntegerConfigAttribute;
import org.opends.server.config.IntegerWithUnitConfigAttribute;
import org.opends.server.config.MultiChoiceConfigAttribute;
import org.opends.server.types.AcceptRejectWarn;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DN;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
import org.opends.server.types.InitializationException;
import org.opends.server.types.ResultCode;
import org.opends.server.types.WritabilityMode;
import static org.opends.server.config.ConfigConstants.*;
import org.opends.server.types.DebugLogLevel;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import org.opends.server.loggers.debug.DebugTracer;
import static org.opends.server.messages.ConfigMessages.*;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.util.ServerConstants.*;
/**
 * This class defines a utility that will be used to manage the configuration
 * for the core Directory Server.  It will perform the necessary initialization
 * of these settings when the server is first started, and then will manage any
 * changes to them while the server is running.
 * This class defines a utility that will be used to manage the set of core
 * configuration attributes defined in the Directory Server.  These
 * configuration attributes appear in the "cn=config" configuration entry.
 */
public class CoreConfigManager
       implements ConfigurableComponent
       implements ConfigurationChangeListener<GlobalCfg>
{
  /**
   * The tracer object for the debug logger.
   */
  private static final DebugTracer TRACER = getTracer();
  /**
   * The set of time units that will be used for the appropriate attributes.
   */
  private static final LinkedHashMap<String,Double> timeUnits =
       new LinkedHashMap<String,Double>();
  // The DN of the associated configuration entry.
  private DN configEntryDN;
  static
  {
    timeUnits.put(TIME_UNIT_SECONDS_ABBR, 1D);
    timeUnits.put(TIME_UNIT_SECONDS_FULL, 1D);
    timeUnits.put(TIME_UNIT_MINUTES_ABBR, 60D);
    timeUnits.put(TIME_UNIT_MINUTES_FULL, 60D);
    timeUnits.put(TIME_UNIT_HOURS_ABBR, (double) (60 * 60));
    timeUnits.put(TIME_UNIT_HOURS_FULL, (double) (60 * 60));
    timeUnits.put(TIME_UNIT_DAYS_ABBR, (double) (60 * 60 * 24));
    timeUnits.put(TIME_UNIT_DAYS_FULL, (double) (60 * 60 * 24));
    timeUnits.put(TIME_UNIT_WEEKS_ABBR, (double) (60 * 60 * 24 * 7));
    timeUnits.put(TIME_UNIT_WEEKS_FULL, (double) (60 * 60 * 24 * 7));
  }
  /**
   * Creates a new instance of this core config manager.
   */
  public CoreConfigManager()
@@ -121,2648 +68,172 @@
  /**
   * Initializes the configuration attributes associated with the Directory
   * Server core.  This should only be called at Directory Server startup.
   * Initializes the Directory Server's core configuration.  This should only be
   * called at server startup.
   *
   * @throws  ConfigException  If a critical configuration problem prevents the
   *                           coreinitialization from succeeding.
   * @throws  ConfigException  If a configuration problem causes the identity
   *                           mapper initialization process to fail.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   the core server that is not related to
   *                                   the configuration.
   *                                   the identity mappers that is not related
   *                                   to the server configuration.
   */
  public void initializeCoreConfig()
         throws ConfigException, InitializationException
  {
    // Get the configuration root entry, since all the attributes we care about
    // should be contained in it.
    ConfigEntry configRoot =
         DirectoryServer.getConfigHandler().getConfigRootEntry();
    configEntryDN = configRoot.getDN();
    // Get the root configuration object.
    ServerManagementContext managementContext =
         ServerManagementContext.getInstance();
    RootCfg rootConfiguration =
         managementContext.getRootConfiguration();
    // Determine whether to perform schema checking.  By default, it will be
    // enabled.
    boolean checkSchema = true;
    // Get the global configuration, register with it as a change listener, and
    // apply the configuration to the server.
    GlobalCfg globalConfig = rootConfiguration.getGlobalConfiguration();
    globalConfig.addChangeListener(this);
    applyGlobalConfiguration(globalConfig);
  }
    int msgID = MSGID_CONFIG_CORE_DESCRIPTION_CHECK_SCHEMA;
    BooleanConfigAttribute checkSchemaStub =
         new BooleanConfigAttribute(ATTR_CHECK_SCHEMA, getMessage(msgID),
                                    false);
    try
  /**
   * Applies the settings in the provided configuration to the Directory Server.
   *
   * @param  globalConfig  The configuration settings to be applied.
   */
  private static void applyGlobalConfiguration(GlobalCfg globalConfig)
  {
    DirectoryServer.setCheckSchema(globalConfig.isCheckSchema());
    DirectoryServer.setDefaultPasswordPolicyDN(
         globalConfig.getDefaultPasswordPolicy());
    DirectoryServer.setAddMissingRDNAttributes(
         globalConfig.isAddMissingRDNAttributes());
    DirectoryServer.setAllowAttributeNameExceptions(
         globalConfig.isAllowAttributeNameExceptions());
    switch (globalConfig.getInvalidAttributeSyntaxBehavior())
    {
      BooleanConfigAttribute checkSchemaAttr =
           (BooleanConfigAttribute)
           configRoot.getConfigAttribute(checkSchemaStub);
      if (checkSchemaAttr == null)
      {
        // This is fine -- just use the default value.
        DirectoryServer.setCheckSchema(checkSchema);
      }
      else
      {
        // Use the value from the attribute that we read.
        DirectoryServer.setCheckSchema(checkSchemaAttr.pendingValue());
      }
    }
    catch (Exception e)
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CORE_INVALID_CHECK_SCHEMA,
               String.valueOf(configRoot.getDN()), String.valueOf(e));
      DirectoryServer.setCheckSchema(checkSchema);
      case ACCEPT:
        DirectoryServer.setSyntaxEnforcementPolicy(AcceptRejectWarn.ACCEPT);
        break;
      case WARN:
        DirectoryServer.setSyntaxEnforcementPolicy(AcceptRejectWarn.WARN);
        break;
      case REJECT:
      default:
        DirectoryServer.setSyntaxEnforcementPolicy(AcceptRejectWarn.REJECT);
        break;
    }
    DirectoryServer.setServerErrorResultCode(
         ResultCode.valueOf(globalConfig.getServerErrorResultCode()));
    // Determine whether to allow attribute name exceptions.  By default, we
    // will not.
    boolean allowAttributeNameExceptions = false;
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_ALLOW_ATTR_EXCEPTIONS;
    BooleanConfigAttribute allowExceptionsStub =
         new BooleanConfigAttribute(ATTR_ALLOW_ATTRIBUTE_NAME_EXCEPTIONS,
                                    getMessage(msgID), false);
    try
    switch (globalConfig.getSingleStructuralObjectclassBehavior())
    {
      BooleanConfigAttribute allowExceptionsAttr =
           (BooleanConfigAttribute)
           configRoot.getConfigAttribute(allowExceptionsStub);
      if (allowExceptionsAttr == null)
      {
        // This is fine -- just use the default value.
        DirectoryServer.setAllowAttributeNameExceptions(
                             allowAttributeNameExceptions);
      }
      else
      {
        // Use the value from the attribute that we read.
        DirectoryServer.setAllowAttributeNameExceptions(
             allowExceptionsAttr.pendingValue());
      }
    }
    catch (Exception e)
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CORE_INVALID_ALLOW_EXCEPTIONS,
               String.valueOf(configRoot.getDN()), String.valueOf(e));
      DirectoryServer.setAllowAttributeNameExceptions(
                           allowAttributeNameExceptions);
    }
    // Determine whether to automatically add missing RDN attributes for add
    // operations.
    boolean addMissingRDNAttributes = false;
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_ADD_MISSING_RDN_ATTRS;
    BooleanConfigAttribute addRDNStub =
         new BooleanConfigAttribute(ATTR_ADD_MISSING_RDN_ATTRS,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute addRDNAttr =
           (BooleanConfigAttribute) configRoot.getConfigAttribute(addRDNStub);
      if (addRDNAttr == null)
      {
        // This is fine -- just use the default value.
        DirectoryServer.setAddMissingRDNAttributes(addMissingRDNAttributes);
      }
      else
      {
        // Use the value from the attribute we read.
        DirectoryServer.setAddMissingRDNAttributes(addRDNAttr.pendingValue());
      }
    }
    catch (Exception e)
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CORE_INVALID_ADD_MISSING_RDN_ATTRS,
               String.valueOf(configRoot.getDN()), String.valueOf(e));
      DirectoryServer.setAddMissingRDNAttributes(addMissingRDNAttributes);
    }
    // Determine the result code to use for internal server errors.
    ResultCode serverErrorResultCode = ResultCode.OTHER;
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_SERVER_ERROR_RESULT_CODE;
    IntegerConfigAttribute serverErrorStub =
         new IntegerConfigAttribute(ATTR_SERVER_ERROR_RESULT_CODE,
                                    getMessage(msgID), false, false, false,
                                    true, 1, false, 0);
    try
    {
      IntegerConfigAttribute serverErrorAttr =
           (IntegerConfigAttribute)
           configRoot.getConfigAttribute(serverErrorStub);
      if (serverErrorAttr == null)
      {
        // This is fine -- just use the default value.
        DirectoryServer.setServerErrorResultCode(serverErrorResultCode);
      }
      else
      {
        // Get the integer value from the provided attribute and then convert
        // that to a result code.
        int resultCodeValue = serverErrorAttr.pendingIntValue();
        serverErrorResultCode = ResultCode.valueOf(resultCodeValue);
        DirectoryServer.setServerErrorResultCode(serverErrorResultCode);
      }
    }
    catch (Exception e)
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CORE_INVALID_SERVER_ERROR_RESULT_CODE,
               String.valueOf(configRoot.getDN()), String.valueOf(e));
      DirectoryServer.setServerErrorResultCode(serverErrorResultCode);
    }
    // Determine how to handle attributes that do not conform to the associated
    // syntax.  By default, we will log a warning but the value will be
    // accepted.
    AcceptRejectWarn syntaxEnforcementPolicy = AcceptRejectWarn.WARN;
    HashSet<String> syntaxBehaviorValues = new HashSet<String>(3);
    syntaxBehaviorValues.add(AcceptRejectWarn.ACCEPT.toString());
    syntaxBehaviorValues.add(AcceptRejectWarn.REJECT.toString());
    syntaxBehaviorValues.add(AcceptRejectWarn.WARN.toString());
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_INVALID_SYNTAX_BEHAVIOR;
    MultiChoiceConfigAttribute syntaxPolicyStub =
         new MultiChoiceConfigAttribute(ATTR_INVALID_SYNTAX_BEHAVIOR,
                                        getMessage(msgID), true, false, false,
                                        syntaxBehaviorValues);
    try
    {
      MultiChoiceConfigAttribute syntaxPolicyAttr =
           (MultiChoiceConfigAttribute)
           configRoot.getConfigAttribute(syntaxPolicyStub);
      if (syntaxPolicyAttr == null)
      {
        // This is fine -- just use the default value.
        DirectoryServer.setSyntaxEnforcementPolicy(syntaxEnforcementPolicy);
      }
      else
      {
        // Use the value from the attribute that we read.
        syntaxEnforcementPolicy =
             AcceptRejectWarn.policyForName(syntaxPolicyAttr.pendingValue());
        if (syntaxEnforcementPolicy == null)
        {
          logError(ErrorLogCategory.CONFIGURATION,
                   ErrorLogSeverity.SEVERE_ERROR,
                   MSGID_CONFIG_CORE_INVALID_ENFORCE_STRICT_SYNTAX,
                   String.valueOf(configRoot.getDN()),
                   String.valueOf(syntaxPolicyAttr.pendingValue()));
          syntaxEnforcementPolicy = AcceptRejectWarn.WARN;
        }
        DirectoryServer.setSyntaxEnforcementPolicy(syntaxEnforcementPolicy);
      }
    }
    catch (Exception e)
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CORE_INVALID_ENFORCE_STRICT_SYNTAX,
               String.valueOf(configRoot.getDN()), String.valueOf(e));
      DirectoryServer.setSyntaxEnforcementPolicy(syntaxEnforcementPolicy);
    }
    // Determine how to handle entries that do not have exactly one structural
    // objectclass.  By default, we will log a warning but the entry will be
    // accepted.
    AcceptRejectWarn structuralClassPolicy = AcceptRejectWarn.WARN;
    HashSet<String> structuralClassValues = new HashSet<String>(3);
    structuralClassValues.add(AcceptRejectWarn.ACCEPT.toString());
    structuralClassValues.add(AcceptRejectWarn.REJECT.toString());
    structuralClassValues.add(AcceptRejectWarn.WARN.toString());
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_STRUCTURAL_CLASS_BEHAVIOR;
    MultiChoiceConfigAttribute structuralClassStub =
         new MultiChoiceConfigAttribute(ATTR_SINGLE_STRUCTURAL_CLASS_BEHAVIOR,
                                        getMessage(msgID), true, false, false,
                                        structuralClassValues);
    try
    {
      MultiChoiceConfigAttribute structuralClassAttr =
           (MultiChoiceConfigAttribute)
           configRoot.getConfigAttribute(structuralClassStub);
      if (structuralClassAttr == null)
      {
        // This is fine -- just use the default value.
      case ACCEPT:
        DirectoryServer.setSingleStructuralObjectClassPolicy(
                             structuralClassPolicy);
      }
      else
      {
        // Use the value from the attribute that we read.
        structuralClassPolicy =
             AcceptRejectWarn.policyForName(structuralClassAttr.pendingValue());
        if (structuralClassPolicy == null)
        {
          logError(ErrorLogCategory.CONFIGURATION,
                   ErrorLogSeverity.SEVERE_ERROR,
                   MSGID_CONFIG_CORE_INVALID_STRUCTURAL_CLASS_BEHAVIOR,
                   String.valueOf(configRoot.getDN()),
                   String.valueOf(structuralClassAttr.pendingValue()));
          structuralClassPolicy = AcceptRejectWarn.WARN;
        }
             AcceptRejectWarn.ACCEPT);
        break;
      case WARN:
        DirectoryServer.setSingleStructuralObjectClassPolicy(
                             structuralClassPolicy);
      }
             AcceptRejectWarn.WARN);
        break;
      case REJECT:
      default:
        DirectoryServer.setSingleStructuralObjectClassPolicy(
             AcceptRejectWarn.REJECT);
        break;
    }
    catch (Exception e)
    DirectoryServer.setNotifyAbandonedOperations(
         globalConfig.isNotifyAbandonedOperations());
    DirectoryServer.setSizeLimit(globalConfig.getSizeLimit());
    DirectoryServer.setTimeLimit((int) globalConfig.getTimeLimit());
    DirectoryServer.setProxiedAuthorizationIdentityMapperDN(
         globalConfig.getProxiedAuthorizationIdentityMapperDN());
    switch (globalConfig.getWritabilityMode())
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CORE_INVALID_STRUCTURAL_CLASS_BEHAVIOR,
               String.valueOf(configRoot.getDN()), String.valueOf(e));
      DirectoryServer.setSingleStructuralObjectClassPolicy(
                           structuralClassPolicy);
      case ENABLED:
        DirectoryServer.setWritabilityMode(WritabilityMode.ENABLED);
        break;
      case INTERNAL_ONLY:
        DirectoryServer.setWritabilityMode(WritabilityMode.INTERNAL_ONLY);
        break;
      case DISABLED:
      default:
        DirectoryServer.setWritabilityMode(WritabilityMode.DISABLED);
        break;
    }
    DirectoryServer.setRejectUnauthenticatedRequests(
         globalConfig.isRejectUnauthenticatedRequests());
    // Determine the maximum number of client connections that should be allowed
    // at any time.
    long maxAllowedConnections = -1;
    DirectoryServer.setBindWithDNRequiresPassword(
         globalConfig.isBindWithDNRequiresPassword());
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_MAX_ALLOWED_CONNECTIONS;
    IntegerConfigAttribute maxConnsStub =
         new IntegerConfigAttribute(ATTR_MAX_ALLOWED_CONNS, getMessage(msgID),
                                    true, false, false, true, -1, false, 0);
    try
    {
      IntegerConfigAttribute maxConnsAttr =
           (IntegerConfigAttribute) configRoot.getConfigAttribute(maxConnsStub);
      if (maxConnsAttr == null)
      {
        // This is fine -- just use the default value.
        DirectoryServer.setMaxAllowedConnections(maxAllowedConnections);
      }
      else
      {
        // Use the value from the attribute that we read.
        DirectoryServer.setMaxAllowedConnections(maxConnsAttr.activeValue());
      }
    }
    catch (Exception e)
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CORE_INVALID_MAX_ALLOWED_CONNECTIONS,
               configRoot.getDN(), String.valueOf(e));
      DirectoryServer.setMaxAllowedConnections(maxAllowedConnections);
    }
    // Determine whether to send a response to operations that have been
    // abandoned.
    boolean notifyAbandonedOperations = false;
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_NOTIFY_ABANDONED_OPERATIONS;
    BooleanConfigAttribute notifyAbandonedStub =
         new BooleanConfigAttribute(ATTR_NOTIFY_ABANDONED_OPS,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute notifyAbandonedAttr =
           (BooleanConfigAttribute)
           configRoot.getConfigAttribute(notifyAbandonedStub);
      if (notifyAbandonedAttr == null)
      {
        // This is fine -- just use the default value.
        DirectoryServer.setNotifyAbandonedOperations(notifyAbandonedOperations);
      }
      else
      {
        // Use the value from the attribute that we read.
        DirectoryServer.setNotifyAbandonedOperations(
                             notifyAbandonedAttr.activeValue());
      }
    }
    catch (Exception e)
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CORE_INVALID_NOTIFY_ABANDONED_OPERATIONS,
               configRoot.getDN(), String.valueOf(e));
      DirectoryServer.setNotifyAbandonedOperations(notifyAbandonedOperations);
    }
    // Determine the DN of the proxied authorization identity mapper.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_PROXY_MAPPER_DN;
    DNConfigAttribute proxyMapperStub =
         new DNConfigAttribute(ATTR_PROXY_MAPPER_DN, getMessage(msgID), false,
                               false, false);
    try
    {
      DNConfigAttribute proxyMapperAttr =
           (DNConfigAttribute) configRoot.getConfigAttribute(proxyMapperStub);
      if (proxyMapperAttr == null)
      {
        // This is fine -- we just won't use a mapper.
        DirectoryServer.setProxiedAuthorizationIdentityMapperDN(null);
      }
      else
      {
        // Set the identity mapper DN without any verification.  We can't check
        // whether it's valid at this point because the identity mappers haven't
        // been initialized yet.
        DirectoryServer.setProxiedAuthorizationIdentityMapperDN(
             proxyMapperAttr.activeValue());
      }
    }
    catch (Exception e)
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CORE_INVALID_PROXY_MAPPER_DN, configRoot.getDN(),
               String.valueOf(e));
      DirectoryServer.setProxiedAuthorizationIdentityMapperDN(null);
    }
    // Determine the default server size limit.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_SIZE_LIMIT;
    IntegerConfigAttribute sizeLimitStub =
         new IntegerConfigAttribute(ATTR_SIZE_LIMIT, getMessage(msgID), false,
                                    false, false, true, -1, true,
                                    Integer.MAX_VALUE);
    try
    {
      IntegerConfigAttribute sizeLimitAttr =
           (IntegerConfigAttribute)
           configRoot.getConfigAttribute(sizeLimitStub);
      if (sizeLimitAttr == null)
      {
        DirectoryServer.setSizeLimit(DEFAULT_SIZE_LIMIT);
      }
      else
      {
        DirectoryServer.setSizeLimit(sizeLimitAttr.activeIntValue());
      }
    }
    catch (Exception e)
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CORE_INVALID_SIZE_LIMIT, configRoot.getDN(),
               String.valueOf(e));
      DirectoryServer.setSizeLimit(DEFAULT_SIZE_LIMIT);
    }
    // Determine the default server time limit.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_TIME_LIMIT;
    IntegerWithUnitConfigAttribute timeLimitStub =
         new IntegerWithUnitConfigAttribute(ATTR_TIME_LIMIT, getMessage(msgID),
                                            false, timeUnits, true, -1, true,
                                            Integer.MAX_VALUE);
    try
    {
      IntegerWithUnitConfigAttribute timeLimitAttr =
           (IntegerWithUnitConfigAttribute)
           configRoot.getConfigAttribute(timeLimitStub);
      if (timeLimitAttr == null)
      {
        DirectoryServer.setTimeLimit(DEFAULT_TIME_LIMIT);
      }
      else
      {
        DirectoryServer.setTimeLimit(
             (int) timeLimitAttr.activeCalculatedValue());
      }
    }
    catch (Exception e)
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CORE_INVALID_TIME_LIMIT, configRoot.getDN(),
               String.valueOf(e));
      DirectoryServer.setTimeLimit(DEFAULT_TIME_LIMIT);
    }
    // Determine the default server lookthrough limit.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_LOOKTHROUGH_LIMIT;
    IntegerConfigAttribute lookthroughLimitStub =
         new IntegerConfigAttribute(ATTR_LOOKTHROUGH_LIMIT, getMessage(msgID),
                                    false, false, false, true, -1, true,
                                    Integer.MAX_VALUE);
    try
    {
      IntegerConfigAttribute lookthroughLimitAttr =
           (IntegerConfigAttribute)
           configRoot.getConfigAttribute(lookthroughLimitStub);
      if (lookthroughLimitAttr == null)
      {
        DirectoryServer.setLookthroughLimit(DEFAULT_LOOKTHROUGH_LIMIT);
      }
      else
      {
        DirectoryServer.setLookthroughLimit(
            lookthroughLimitAttr.activeIntValue());
      }
    }
    catch (Exception e)
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CORE_INVALID_LOOKTHROUGH_LIMIT, configRoot.getDN(),
               String.valueOf(e));
      DirectoryServer.setLookthroughLimit(DEFAULT_LOOKTHROUGH_LIMIT);
    }
    // Determine the writability mode for the Directory Server.  By default, it
    // will be writable.
    WritabilityMode writabilityMode = WritabilityMode.ENABLED;
    HashSet<String> writabilityModes = new HashSet<String>(3);
    writabilityModes.add(WritabilityMode.ENABLED.toString());
    writabilityModes.add(WritabilityMode.DISABLED.toString());
    writabilityModes.add(WritabilityMode.INTERNAL_ONLY.toString());
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_WRITABILITY_MODE;
    MultiChoiceConfigAttribute writabilityStub =
         new MultiChoiceConfigAttribute(ATTR_WRITABILITY_MODE,
                                        getMessage(msgID), true, false, false,
                                        writabilityModes);
    try
    {
      MultiChoiceConfigAttribute writabilityAttr =
           (MultiChoiceConfigAttribute)
           configRoot.getConfigAttribute(writabilityStub);
      if (writabilityAttr == null)
      {
        // This is fine -- just use the default value.
        DirectoryServer.setWritabilityMode(writabilityMode);
      }
      else
      {
        // Use the value from the attribute that we read.
        writabilityMode =
             WritabilityMode.modeForName(writabilityAttr.pendingValue());
        if (writabilityMode == null)
        {
          logError(ErrorLogCategory.CONFIGURATION,
                   ErrorLogSeverity.SEVERE_ERROR,
                   MSGID_CONFIG_CORE_INVALID_WRITABILITY_MODE,
                   String.valueOf(configRoot.getDN()),
                   String.valueOf(writabilityAttr.pendingValue()));
          writabilityMode = WritabilityMode.DISABLED;
        }
        DirectoryServer.setWritabilityMode(writabilityMode);
      }
    }
    catch (Exception e)
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CORE_INVALID_WRITABILITY_MODE,
               String.valueOf(configRoot.getDN()), String.valueOf(e));
      DirectoryServer.setWritabilityMode(writabilityMode);
    }
    // Determine whether simple binds with a DN will also be required to have a
    // password.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_BIND_WITH_DN_REQUIRES_PW;
    BooleanConfigAttribute requirePWStub =
         new BooleanConfigAttribute(ATTR_BIND_WITH_DN_REQUIRES_PW,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute requirePWAttr =
           (BooleanConfigAttribute)
           configRoot.getConfigAttribute(requirePWStub);
      if (requirePWAttr == null)
      {
        DirectoryServer.setBindWithDNRequiresPassword(
                             DEFAULT_BIND_WITH_DN_REQUIRES_PW);
      }
      else
      {
        DirectoryServer.setBindWithDNRequiresPassword(
                             requirePWAttr.activeValue());
      }
    }
    catch (Exception e)
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CORE_INVALID_BIND_WITH_DN_REQUIRES_PW,
               String.valueOf(configRoot.getDN()), String.valueOf(e));
      DirectoryServer.setBindWithDNRequiresPassword(
                           DEFAULT_BIND_WITH_DN_REQUIRES_PW);
    }
    // Get the DN of the default password policy configuration entry.  We can't
    // check its validity yet because the password policies will not have been
    // loaded from the configuration.  Instead, the validity check will occur
    // when the password policies are loaded.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_DEFAULT_PWPOLICY_DN;
    DNConfigAttribute defaultPWPolicyStub =
         new DNConfigAttribute(ATTR_DEFAULT_PWPOLICY_DN, getMessage(msgID),
                               true, false, false);
    try
    {
      DNConfigAttribute defaultPWPolicyAttr =
           (DNConfigAttribute)
           configRoot.getConfigAttribute(defaultPWPolicyStub);
      if (defaultPWPolicyAttr == null)
      {
        msgID = MSGID_CONFIG_CORE_NO_DEFAULT_PWPOLICY;
        String message = getMessage(msgID, configRoot.getDN());
        throw new ConfigException(msgID, message);
      }
      else
      {
        DirectoryServer.setDefaultPasswordPolicyDN(
                             defaultPWPolicyAttr.activeValue());
      }
    }
    catch (ConfigException ce)
    {
      throw ce;
    }
    catch (Exception e)
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
               MSGID_CONFIG_CORE_INVALID_DEFAULT_PWPOLICY_DN,
               String.valueOf(configRoot.getDN()), String.valueOf(e));
      DirectoryServer.setBindWithDNRequiresPassword(
                           DEFAULT_BIND_WITH_DN_REQUIRES_PW);
    }
   // Determine whether an uauthenticated request should be rejected.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_REJECT_UNAUTHENTICATED_REQUESTS;
    BooleanConfigAttribute rejectRequestStub =
    new BooleanConfigAttribute(ATTR_REJECT_UNAUTHENTICATED_REQ,
                              getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute rejectRequestAttr=
      (BooleanConfigAttribute)
      configRoot.getConfigAttribute(rejectRequestStub);
      if(rejectRequestAttr== null)
      {
        DirectoryServer.setRejectUnauthenticatedRequests(
                       DEFAULT_REJECT_UNAUTHENTICATED_REQ);
      }
      else
      {
        DirectoryServer.setRejectUnauthenticatedRequests(
                       rejectRequestAttr.activeValue());
      }
    }
    catch (Exception e)
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
         MSGID_CONFIG_CORE_REJECT_UNAUTHENTICATED_REQUESTS_INVALID,
         String.valueOf(configEntryDN.toString()), String.valueOf(e));
      DirectoryServer.setRejectUnauthenticatedRequests(
                       DEFAULT_REJECT_UNAUTHENTICATED_REQ);
    }
    DirectoryServer.registerConfigurableComponent(this);
    DirectoryServer.setLookthroughLimit(globalConfig.getLookthroughLimit());
  }
  /**
   * Retrieves the DN of the configuration entry with which this component is
   * associated.
   *
   * @return  The DN of the configuration entry with which this component is
   *          associated.
   * {@inheritDoc}
   */
  public DN getConfigurableComponentEntryDN()
  public boolean isConfigurationChangeAcceptable(GlobalCfg configuration,
                      List<String> unacceptableReasons)
  {
    return configEntryDN;
    boolean configAcceptable = true;
    // Make sure that the default password policy DN is valid.
    DN policyDN = configuration.getDefaultPasswordPolicy();
    PasswordPolicy policy = DirectoryServer.getPasswordPolicy(policyDN);
    if (policy == null)
    {
      int    msgID   = MSGID_CONFIG_CORE_NO_SUCH_PWPOLICY;
      String message = getMessage(msgID, String.valueOf(policyDN));
      unacceptableReasons.add(message);
      configAcceptable = false;
    }
    // Make sure that the proxied auth identity mapper is valid.
    DN mapperDN = configuration.getProxiedAuthorizationIdentityMapperDN();
    IdentityMapper mapper = DirectoryServer.getIdentityMapper(mapperDN);
    if (mapper == null)
    {
      int    msgID   = MSGID_CONFIG_CORE_NO_PROXY_MAPPER_FOR_DN;
      String message = getMessage(msgID, String.valueOf(mapperDN),
                                  String.valueOf(configuration.dn()));
      unacceptableReasons.add(message);
      configAcceptable = false;
    }
    return configAcceptable;
  }
  /**
   * Retrieves the set of configuration attributes that are associated with this
   * configurable component.
   *
   * @return  The set of configuration attributes that are associated with this
   *          configurable component.
   * {@inheritDoc}
   */
  public List<ConfigAttribute> getConfigurationAttributes()
  public ConfigChangeResult applyConfigurationChange(GlobalCfg configuration)
  {
    LinkedList<ConfigAttribute> attrs = new LinkedList<ConfigAttribute>();
    ConfigEntry configEntry;
    try
    {
      configEntry =
           DirectoryServer.getConfigHandler().getConfigEntry(configEntryDN);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR,
               MSGID_CONFIG_CANNOT_GET_CONFIG_ENTRY, configEntryDN.toString(),
               String.valueOf(e));
      return attrs;
    }
    // See if the entry indicates whether to perform schema checking.
    int msgID = MSGID_CONFIG_CORE_DESCRIPTION_CHECK_SCHEMA;
    BooleanConfigAttribute checkSchemaStub =
         new BooleanConfigAttribute(ATTR_CHECK_SCHEMA, getMessage(msgID),
                                    false);
    try
    {
      BooleanConfigAttribute checkSchemaAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(checkSchemaStub);
      if (checkSchemaAttr == null)
      {
        checkSchemaStub.setValue(DirectoryServer.checkSchema());
        checkSchemaAttr = checkSchemaStub;
      }
      attrs.add(checkSchemaAttr);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred.  Log a message and continue.
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR,
               MSGID_CONFIG_CORE_INVALID_CHECK_SCHEMA,
               configEntryDN.toString(), String.valueOf(e));
    }
    // See if the entry indicates whether to allow attribute name exceptions.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_ALLOW_ATTR_EXCEPTIONS;
    BooleanConfigAttribute allowExceptionsStub =
         new BooleanConfigAttribute(ATTR_ALLOW_ATTRIBUTE_NAME_EXCEPTIONS,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute allowExceptionsAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(allowExceptionsStub);
      if (allowExceptionsAttr == null)
      {
        allowExceptionsStub.setValue(
             DirectoryServer.allowAttributeNameExceptions());
        allowExceptionsAttr = allowExceptionsStub;
      }
      attrs.add(allowExceptionsAttr);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred.  Log a message and continue.
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR,
               MSGID_CONFIG_CORE_INVALID_ALLOW_EXCEPTIONS,
               configEntryDN.toString(), String.valueOf(e));
    }
    // See if the entry indicates whether to add missing RDN attributes.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_ADD_MISSING_RDN_ATTRS;
    BooleanConfigAttribute addRDNStub =
         new BooleanConfigAttribute(ATTR_ADD_MISSING_RDN_ATTRS,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute addRDNAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(addRDNStub);
      if (addRDNAttr == null)
      {
        addRDNStub.setValue(DirectoryServer.addMissingRDNAttributes());
        addRDNAttr = allowExceptionsStub;
      }
      attrs.add(addRDNAttr);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred.  Log a message and continue.
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR,
               MSGID_CONFIG_CORE_INVALID_ADD_MISSING_RDN_ATTRS,
               configEntryDN.toString(), String.valueOf(e));
    }
    // See if the entry specifies the result code to use for internal server
    // errors.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_SERVER_ERROR_RESULT_CODE;
    IntegerConfigAttribute serverErrorStub =
         new IntegerConfigAttribute(ATTR_SERVER_ERROR_RESULT_CODE,
                                    getMessage(msgID), false, false, false,
                                    true, 1, false, 0);
    try
    {
      IntegerConfigAttribute serverErrorAttr =
           (IntegerConfigAttribute)
           configEntry.getConfigAttribute(serverErrorStub);
      if (serverErrorAttr == null)
      {
        int value = DirectoryServer.getServerErrorResultCode().getIntValue();
        serverErrorStub.setValue(value);
        serverErrorAttr = serverErrorStub;
      }
      attrs.add(serverErrorAttr);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred.  Log a message and continue.
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR,
               MSGID_CONFIG_CORE_INVALID_SERVER_ERROR_RESULT_CODE,
               configEntryDN.toString(), String.valueOf(e));
    }
    // See if the entry indicates how to handle syntax enforcement.
    HashSet<String> syntaxBehaviorValues = new HashSet<String>(3);
    syntaxBehaviorValues.add(AcceptRejectWarn.ACCEPT.toString());
    syntaxBehaviorValues.add(AcceptRejectWarn.REJECT.toString());
    syntaxBehaviorValues.add(AcceptRejectWarn.WARN.toString());
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_INVALID_SYNTAX_BEHAVIOR;
    MultiChoiceConfigAttribute syntaxPolicyStub =
         new MultiChoiceConfigAttribute(ATTR_INVALID_SYNTAX_BEHAVIOR,
                                        getMessage(msgID), true, false, false,
                                        syntaxBehaviorValues);
    try
    {
      MultiChoiceConfigAttribute syntaxPolicyAttr =
           (MultiChoiceConfigAttribute)
           configEntry.getConfigAttribute(syntaxPolicyStub);
      if (syntaxPolicyAttr == null)
      {
        syntaxPolicyStub.setValue(
             String.valueOf(DirectoryServer.getSyntaxEnforcementPolicy()));
        syntaxPolicyAttr = syntaxPolicyStub;
      }
      attrs.add(syntaxPolicyAttr);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred.  Log a message and continue.
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR,
               MSGID_CONFIG_CORE_INVALID_ENFORCE_STRICT_SYNTAX,
               configEntryDN.toString(), String.valueOf(e));
    }
    // See if the entry indicates how to handle entries with an invalid number
    // of structural objectclasses.
    HashSet<String> structuralClassValues = new HashSet<String>(3);
    structuralClassValues.add(AcceptRejectWarn.ACCEPT.toString());
    structuralClassValues.add(AcceptRejectWarn.REJECT.toString());
    structuralClassValues.add(AcceptRejectWarn.WARN.toString());
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_STRUCTURAL_CLASS_BEHAVIOR;
    MultiChoiceConfigAttribute structuralClassStub =
         new MultiChoiceConfigAttribute(ATTR_SINGLE_STRUCTURAL_CLASS_BEHAVIOR,
                                        getMessage(msgID), true, false, false,
                                        structuralClassValues);
    try
    {
      MultiChoiceConfigAttribute structuralClassAttr =
           (MultiChoiceConfigAttribute)
           configEntry.getConfigAttribute(structuralClassStub);
      if (structuralClassAttr == null)
      {
        structuralClassStub.setValue(String.valueOf(
             DirectoryServer.getSingleStructuralObjectClassPolicy()));
        structuralClassAttr = structuralClassStub;
      }
      attrs.add(structuralClassAttr);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred.  Log a message and continue.
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR,
               MSGID_CONFIG_CORE_INVALID_STRUCTURAL_CLASS_BEHAVIOR,
               configEntryDN.toString(), String.valueOf(e));
    }
    // Determine the maximum number of client connections to allow at any given
    // time.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_MAX_ALLOWED_CONNECTIONS;
    IntegerConfigAttribute maxConnsStub =
         new IntegerConfigAttribute(ATTR_MAX_ALLOWED_CONNS, getMessage(msgID),
                                    true, false, false, true, -1, false, 0);
    try
    {
      IntegerConfigAttribute maxConnsAttr =
           (IntegerConfigAttribute)
           configEntry.getConfigAttribute(maxConnsStub);
      if (maxConnsAttr == null)
      {
        maxConnsStub.setValue(DirectoryServer.getMaxAllowedConnections());
        maxConnsAttr = maxConnsStub;
      }
      attrs.add(maxConnsAttr);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred.  Log a message and continue.
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR,
               MSGID_CONFIG_CORE_INVALID_MAX_ALLOWED_CONNECTIONS,
               configEntryDN.toString(), String.valueOf(e));
    }
    // Determine whether to send a response to abandoned operations.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_NOTIFY_ABANDONED_OPERATIONS;
    BooleanConfigAttribute notifyAbandonedStub =
         new BooleanConfigAttribute(ATTR_NOTIFY_ABANDONED_OPS,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute notifyAbandonedAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(notifyAbandonedStub);
      if (notifyAbandonedAttr == null)
      {
        notifyAbandonedStub.setValue(
             DirectoryServer.notifyAbandonedOperations());
        notifyAbandonedAttr = notifyAbandonedStub;
      }
      attrs.add(notifyAbandonedAttr);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred.  Log a message and continue.
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR,
               MSGID_CONFIG_CORE_INVALID_NOTIFY_ABANDONED_OPERATIONS,
               configEntryDN.toString(), String.valueOf(e));
    }
    // Add the DN of the proxied auth identity mapper config entry.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_PROXY_MAPPER_DN;
    DNConfigAttribute proxyMapperStub =
         new DNConfigAttribute(ATTR_PROXY_MAPPER_DN, getMessage(msgID), false,
                               false, false);
    try
    {
      DNConfigAttribute proxyMapperAttr =
           (DNConfigAttribute) configEntry.getConfigAttribute(proxyMapperStub);
      if (proxyMapperAttr == null)
      {
        proxyMapperStub.setValue(
             DirectoryServer.getProxiedAuthorizationIdentityMapperDN());
        proxyMapperAttr = proxyMapperStub;
      }
      attrs.add(proxyMapperAttr);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred.  Log a message and continue.
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR,
               MSGID_CONFIG_CORE_INVALID_PROXY_MAPPER_DN,
               configEntryDN.toString(), String.valueOf(e));
    }
    // Add the server size limit.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_SIZE_LIMIT;
    IntegerConfigAttribute sizeLimitStub =
         new IntegerConfigAttribute(ATTR_SIZE_LIMIT, getMessage(msgID), false,
                                    false, false, true, 0, true,
                                    Integer.MAX_VALUE);
    try
    {
      IntegerConfigAttribute sizeLimitAttr =
           (IntegerConfigAttribute)
           configEntry.getConfigAttribute(sizeLimitStub);
      if (sizeLimitAttr == null)
      {
        sizeLimitStub.setValue(DirectoryServer.getSizeLimit());
        sizeLimitAttr = sizeLimitStub;
      }
      attrs.add(sizeLimitAttr);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred.  Log a message and continue.
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR,
               MSGID_CONFIG_CORE_INVALID_SIZE_LIMIT,
               configEntryDN.toString(), String.valueOf(e));
    }
    // Add the server time limit.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_TIME_LIMIT;
    IntegerWithUnitConfigAttribute timeLimitStub =
         new IntegerWithUnitConfigAttribute(ATTR_TIME_LIMIT, getMessage(msgID),
                                            false, timeUnits, true, 0, true,
                                            Integer.MAX_VALUE);
    try
    {
      IntegerWithUnitConfigAttribute timeLimitAttr =
           (IntegerWithUnitConfigAttribute)
           configEntry.getConfigAttribute(timeLimitStub);
      if (timeLimitAttr == null)
      {
        timeLimitStub.setValue(DirectoryServer.getTimeLimit(),
                               TIME_UNIT_SECONDS_FULL);
        timeLimitAttr = timeLimitStub;
      }
      attrs.add(timeLimitAttr);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred.  Log a message and continue.
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR,
               MSGID_CONFIG_CORE_INVALID_TIME_LIMIT,
               configEntryDN.toString(), String.valueOf(e));
    }
    // Add the server writability mode.
    HashSet<String> writabilityModes = new HashSet<String>(3);
    writabilityModes.add(WritabilityMode.ENABLED.toString());
    writabilityModes.add(WritabilityMode.DISABLED.toString());
    writabilityModes.add(WritabilityMode.INTERNAL_ONLY.toString());
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_WRITABILITY_MODE;
    MultiChoiceConfigAttribute writabilityStub =
         new MultiChoiceConfigAttribute(ATTR_WRITABILITY_MODE,
                                        getMessage(msgID), true, false, false,
                                        writabilityModes);
    try
    {
      MultiChoiceConfigAttribute writabilityAttr =
           (MultiChoiceConfigAttribute)
           configEntry.getConfigAttribute(writabilityStub);
      if (writabilityAttr == null)
      {
        writabilityStub.setValue(String.valueOf(
             DirectoryServer.getWritabilityMode()));
        writabilityAttr = writabilityStub;
      }
      attrs.add(writabilityAttr);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred.  Log a message and continue.
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR,
               MSGID_CONFIG_CORE_INVALID_WRITABILITY_MODE,
               configEntryDN.toString(), String.valueOf(e));
    }
    // Add the bind with DN requires password attribute.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_BIND_WITH_DN_REQUIRES_PW;
    BooleanConfigAttribute requirePWStub =
         new BooleanConfigAttribute(ATTR_BIND_WITH_DN_REQUIRES_PW,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute requirePWAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(requirePWStub);
      if (requirePWAttr == null)
      {
        requirePWStub.setValue(DirectoryServer.bindWithDNRequiresPassword());
        requirePWAttr = requirePWStub;
      }
      attrs.add(requirePWAttr);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred.  Log a message and continue.
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR,
               MSGID_CONFIG_CORE_INVALID_BIND_WITH_DN_REQUIRES_PW,
               configEntryDN.toString(), String.valueOf(e));
    }
    // Add the default password policy configuration entry DN.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_DEFAULT_PWPOLICY_DN;
    DNConfigAttribute defaultPWPolicyStub =
         new DNConfigAttribute(ATTR_DEFAULT_PWPOLICY_DN, getMessage(msgID),
                               true, false, false);
    try
    {
      DNConfigAttribute defaultPWPolicyAttr =
           (DNConfigAttribute)
           configEntry.getConfigAttribute(defaultPWPolicyStub);
      if (defaultPWPolicyAttr == null)
      {
        defaultPWPolicyStub.setValue(
             DirectoryServer.getDefaultPasswordPolicyDN());
        defaultPWPolicyAttr = defaultPWPolicyStub;
      }
      attrs.add(defaultPWPolicyAttr);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred.  Log a message and continue.
      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_ERROR,
               MSGID_CONFIG_CORE_INVALID_DEFAULT_PWPOLICY_DN,
               configEntryDN.toString(), String.valueOf(e));
    }
    return attrs;
  }
  /**
   * Indicates whether the provided configuration entry has an acceptable
   * configuration for this component.  If it does not, then detailed
   * information about the problem(s) should be added to the provided list.
   *
   * @param  configEntry          The configuration entry for which to make the
   *                              determination.
   * @param  unacceptableReasons  A list that can be used to hold messages about
   *                              why the provided entry does not have an
   *                              acceptable configuration.
   *
   * @return  <CODE>true</CODE> if the provided entry has an acceptable
   *          configuration for this component, or <CODE>false</CODE> if not.
   */
  public boolean hasAcceptableConfiguration(ConfigEntry configEntry,
                                            List<String> unacceptableReasons)
  {
    // Start out assuming that the configuration is valid.
    boolean configIsAcceptable = true;
    // See if the entry indicates whether to allow perform schema checking.  If
    // so, then make sure that its value is acceptable.
    int msgID = MSGID_CONFIG_CORE_DESCRIPTION_CHECK_SCHEMA;
    BooleanConfigAttribute checkSchemaStub =
         new BooleanConfigAttribute(ATTR_CHECK_SCHEMA, getMessage(msgID),
                                    false);
    try
    {
      BooleanConfigAttribute checkSchemaAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(checkSchemaStub);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so the provided value must not be valid.
      msgID = MSGID_CONFIG_CORE_INVALID_CHECK_SCHEMA;
      unacceptableReasons.add(getMessage(msgID, configEntry.getDN().toString(),
                                         String.valueOf(e)));
      configIsAcceptable = false;
    }
    // See if the entry indicates whether to allow attribute name exceptions.
    // If so, then make sure that its value is acceptable.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_ALLOW_ATTR_EXCEPTIONS;
    BooleanConfigAttribute allowExceptionsStub =
         new BooleanConfigAttribute(ATTR_ALLOW_ATTRIBUTE_NAME_EXCEPTIONS,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute allowExceptionsAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(allowExceptionsStub);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so the provided value must not be valid.
      msgID = MSGID_CONFIG_CORE_INVALID_ALLOW_EXCEPTIONS;
      unacceptableReasons.add(getMessage(msgID, configEntry.getDN().toString(),
                                         String.valueOf(e)));
      configIsAcceptable = false;
    }
    // See if the entry indicates whether to add missing RDN attributes.  If so,
    // then make sure that its value is acceptable.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_ADD_MISSING_RDN_ATTRS;
    BooleanConfigAttribute addRDNStub =
         new BooleanConfigAttribute(ATTR_ADD_MISSING_RDN_ATTRS,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute addRDNAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(addRDNStub);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so the provided value must not be valid.
      msgID = MSGID_CONFIG_CORE_INVALID_ADD_MISSING_RDN_ATTRS;
      unacceptableReasons.add(getMessage(msgID, configEntry.getDN().toString(),
                                         String.valueOf(e)));
      configIsAcceptable = false;
    }
    // See if the entry specifies the result code for internal server errors.
    // If so, then make sure that its value is acceptable.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_SERVER_ERROR_RESULT_CODE;
    IntegerConfigAttribute serverErrorStub =
         new IntegerConfigAttribute(ATTR_SERVER_ERROR_RESULT_CODE,
                                    getMessage(msgID), false, false, false,
                                    true, 1, false, 0);
    try
    {
      IntegerConfigAttribute serverErrorAttr =
           (IntegerConfigAttribute)
           configEntry.getConfigAttribute(serverErrorStub);
      if (serverErrorAttr != null)
      {
        serverErrorAttr.pendingIntValue();
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so the provided value must not be valid.
      msgID = MSGID_CONFIG_CORE_INVALID_SERVER_ERROR_RESULT_CODE;
      unacceptableReasons.add(getMessage(msgID, configEntry.getDN().toString(),
                                         String.valueOf(e)));
      configIsAcceptable = false;
    }
    // See if the entry contains a policy to indicate how to handle syntax
    // enforcement.  If so, then make sure that its value is acceptable.
    HashSet<String> syntaxBehaviorValues = new HashSet<String>(3);
    syntaxBehaviorValues.add(AcceptRejectWarn.ACCEPT.toString());
    syntaxBehaviorValues.add(AcceptRejectWarn.REJECT.toString());
    syntaxBehaviorValues.add(AcceptRejectWarn.WARN.toString());
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_INVALID_SYNTAX_BEHAVIOR;
    MultiChoiceConfigAttribute syntaxPolicyStub =
         new MultiChoiceConfigAttribute(ATTR_INVALID_SYNTAX_BEHAVIOR,
                                        getMessage(msgID), true, false, false,
                                        syntaxBehaviorValues);
    try
    {
      MultiChoiceConfigAttribute syntaxPolicyAttr =
           (MultiChoiceConfigAttribute)
           configEntry.getConfigAttribute(syntaxPolicyStub);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so the provided value must not be valid.
      msgID = MSGID_CONFIG_CORE_INVALID_ENFORCE_STRICT_SYNTAX;
      unacceptableReasons.add(getMessage(msgID, configEntry.getDN().toString(),
                                         String.valueOf(e)));
      configIsAcceptable = false;
    }
    // See if the entry contains a policy to indicate how to handle single
    // structural class enforcement.  If so, then make sure that its value is
    // acceptable.
    HashSet<String> structuralClassValues = new HashSet<String>(3);
    structuralClassValues.add(AcceptRejectWarn.ACCEPT.toString());
    structuralClassValues.add(AcceptRejectWarn.REJECT.toString());
    structuralClassValues.add(AcceptRejectWarn.WARN.toString());
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_STRUCTURAL_CLASS_BEHAVIOR;
    MultiChoiceConfigAttribute structuralClassStub =
         new MultiChoiceConfigAttribute(ATTR_SINGLE_STRUCTURAL_CLASS_BEHAVIOR,
                                        getMessage(msgID), true, false, false,
                                        structuralClassValues);
    try
    {
      MultiChoiceConfigAttribute structuralClassAttr =
           (MultiChoiceConfigAttribute)
           configEntry.getConfigAttribute(structuralClassStub);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so the provided value must not be valid.
      msgID = MSGID_CONFIG_CORE_INVALID_STRUCTURAL_CLASS_BEHAVIOR;
      unacceptableReasons.add(getMessage(msgID, configEntry.getDN().toString(),
                                         String.valueOf(e)));
      configIsAcceptable = false;
    }
    // See if the entry contains a value for the maximum number of allowed
    // client connections.  If so, then make sure that its value is acceptable.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_MAX_ALLOWED_CONNECTIONS;
    IntegerConfigAttribute maxConnsStub =
         new IntegerConfigAttribute(ATTR_MAX_ALLOWED_CONNS, getMessage(msgID),
                                    true, false, false, true, -1, false, 0);
    try
    {
      IntegerConfigAttribute maxConnsAttr =
           (IntegerConfigAttribute)
           configEntry.getConfigAttribute(maxConnsStub);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so the provided value must not be valid.
      msgID = MSGID_CONFIG_CORE_INVALID_MAX_ALLOWED_CONNECTIONS;
      unacceptableReasons.add(getMessage(msgID, configEntry.getDN().toString(),
                                         String.valueOf(e)));
      configIsAcceptable = false;
    }
    // See if the entry indicates whether to send a response to abandoned
    // operations.  If so, then make sure that its value is acceptable.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_NOTIFY_ABANDONED_OPERATIONS;
    BooleanConfigAttribute notifyAbandonedStub =
         new BooleanConfigAttribute(ATTR_NOTIFY_ABANDONED_OPS,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute notifyAbandonedAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(notifyAbandonedStub);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so the provided value must not be valid.
      msgID = MSGID_CONFIG_CORE_INVALID_NOTIFY_ABANDONED_OPERATIONS;
      unacceptableReasons.add(getMessage(msgID, configEntry.getDN().toString(),
                                         String.valueOf(e)));
      configIsAcceptable = false;
    }
    // See if the entry specifies the DN of the proxied auth identity mapper.
    // If so, then make sure it's valid.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_PROXY_MAPPER_DN;
    DNConfigAttribute proxyMapperStub =
         new DNConfigAttribute(ATTR_PROXY_MAPPER_DN, getMessage(msgID), false,
                               false, false);
    try
    {
      DNConfigAttribute proxyMapperAttr =
           (DNConfigAttribute) configEntry.getConfigAttribute(proxyMapperStub);
      if (proxyMapperAttr != null)
      {
        DN mapperDN = proxyMapperAttr.pendingValue();
        IdentityMapper mapper = DirectoryServer.getIdentityMapper(mapperDN);
        if (mapper == null)
        {
          msgID = MSGID_CONFIG_CORE_NO_PROXY_MAPPER_FOR_DN;
          unacceptableReasons.add(getMessage(msgID,
                                             String.valueOf(mapperDN),
                                             String.valueOf(configEntryDN)));
          configIsAcceptable = false;
        }
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so the provided value must not be valid.
      msgID = MSGID_CONFIG_CORE_INVALID_PROXY_MAPPER_DN;
      unacceptableReasons.add(getMessage(msgID, configEntry.getDN().toString(),
                                         String.valueOf(e)));
      configIsAcceptable = false;
    }
    // See if the entry specifies the server size limit.  If so, them make sure
    // it's valid.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_SIZE_LIMIT;
    IntegerConfigAttribute sizeLimitStub =
         new IntegerConfigAttribute(ATTR_SIZE_LIMIT, getMessage(msgID), false,
                                    false, false, true, 0, true,
                                    Integer.MAX_VALUE);
    try
    {
      IntegerConfigAttribute sizeLimitAttr =
           (IntegerConfigAttribute)
           configEntry.getConfigAttribute(sizeLimitStub);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so the provided value must not be valid.
      msgID = MSGID_CONFIG_CORE_INVALID_SIZE_LIMIT;
      unacceptableReasons.add(getMessage(msgID, configEntry.getDN().toString(),
                                         String.valueOf(e)));
      configIsAcceptable = false;
    }
    // See if the entry specifies the server time limit.  If so, them make sure
    // it's valid.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_TIME_LIMIT;
    IntegerWithUnitConfigAttribute timeLimitStub =
         new IntegerWithUnitConfigAttribute(ATTR_TIME_LIMIT, getMessage(msgID),
                                            false,timeUnits, true, 0, true,
                                            Integer.MAX_VALUE);
    try
    {
      IntegerWithUnitConfigAttribute timeLimitAttr =
           (IntegerWithUnitConfigAttribute)
           configEntry.getConfigAttribute(timeLimitStub);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so the provided value must not be valid.
      msgID = MSGID_CONFIG_CORE_INVALID_TIME_LIMIT;
      unacceptableReasons.add(getMessage(msgID, configEntry.getDN().toString(),
                                         String.valueOf(e)));
      configIsAcceptable = false;
    }
    // See if the entry specifies the writability mode.  If so, then make sure
    // it's valid.
    HashSet<String> writabilityModes = new HashSet<String>(3);
    writabilityModes.add(WritabilityMode.ENABLED.toString());
    writabilityModes.add(WritabilityMode.DISABLED.toString());
    writabilityModes.add(WritabilityMode.INTERNAL_ONLY.toString());
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_WRITABILITY_MODE;
    MultiChoiceConfigAttribute writabilityStub =
         new MultiChoiceConfigAttribute(ATTR_WRITABILITY_MODE,
                                        getMessage(msgID), true, false, false,
                                        writabilityModes);
    try
    {
      MultiChoiceConfigAttribute writabilityAttr =
           (MultiChoiceConfigAttribute)
           configEntry.getConfigAttribute(writabilityStub);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so the provided value must not be valid.
      msgID = MSGID_CONFIG_CORE_INVALID_WRITABILITY_MODE;
      unacceptableReasons.add(getMessage(msgID, configEntry.getDN().toString(),
                                         String.valueOf(e)));
      configIsAcceptable = false;
    }
    // See if the entry specifies how to handle binds with a DN but no password.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_BIND_WITH_DN_REQUIRES_PW;
    BooleanConfigAttribute requirePWStub =
         new BooleanConfigAttribute(ATTR_BIND_WITH_DN_REQUIRES_PW,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute requirePWAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(requirePWStub);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so the provided value must not be valid.
      msgID = MSGID_CONFIG_CORE_INVALID_BIND_WITH_DN_REQUIRES_PW;
      unacceptableReasons.add(getMessage(msgID, configEntry.getDN().toString(),
                                         String.valueOf(e)));
      configIsAcceptable = false;
    }
    // See if the entry specifies whether unauthenticated requests should be
    // rejected.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_REJECT_UNAUTHENTICATED_REQUESTS;
    BooleanConfigAttribute rejectRequestStub =
    new BooleanConfigAttribute(ATTR_REJECT_UNAUTHENTICATED_REQ,
                              getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute rejectRequestAttr=
          (BooleanConfigAttribute)
              configEntry.getConfigAttribute(rejectRequestStub);
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so the provided value must not be valid.
      msgID = MSGID_CONFIG_CORE_REJECT_UNAUTHENTICATED_REQUESTS_INVALID;
      unacceptableReasons.add(getMessage(msgID, configEntry.getDN().toString(),
                                         String.valueOf(e)));
      configIsAcceptable = false;
    }
    // Get the DN of the default password policy configuration entry.  It must
    // be provided, and the DN must be associated with a valid password policy.
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_DEFAULT_PWPOLICY_DN;
    DNConfigAttribute defaultPWPolicyStub =
         new DNConfigAttribute(ATTR_DEFAULT_PWPOLICY_DN, getMessage(msgID),
                               true, false, false);
    try
    {
      DNConfigAttribute defaultPWPolicyAttr =
           (DNConfigAttribute)
           configEntry.getConfigAttribute(defaultPWPolicyStub);
      if (defaultPWPolicyAttr == null)
      {
        msgID = MSGID_CONFIG_CORE_NO_DEFAULT_PWPOLICY;
        unacceptableReasons.add(getMessage(msgID, configEntry.getDN()));
        configIsAcceptable = false;
      }
      else
      {
        PasswordPolicy p =
             DirectoryServer.getPasswordPolicy(
                  defaultPWPolicyAttr.pendingValue());
        if (p == null)
        {
          msgID = MSGID_CONFIG_CORE_NO_SUCH_PWPOLICY;
          unacceptableReasons.add(getMessage(msgID,
               String.valueOf(defaultPWPolicyAttr.pendingValue())));
          configIsAcceptable = false;
        }
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so the provided value must not be valid.
      msgID = MSGID_CONFIG_CORE_INVALID_DEFAULT_PWPOLICY_DN;
      unacceptableReasons.add(getMessage(msgID, configEntry.getDN().toString(),
                                         String.valueOf(e)));
      configIsAcceptable = false;
    }
    return configIsAcceptable;
  }
  /**
   * Makes a best-effort attempt to apply the configuration contained in the
   * provided entry.  Information about the result of this processing should be
   * added to the provided message list.  Information should always be added to
   * this list if a configuration change could not be applied.  If detailed
   * results are requested, then information about the changes applied
   * successfully (and optionally about parameters that were not changed) should
   * also be included.
   *
   * @param  configEntry      The entry containing the new configuration to
   *                          apply for this component.
   * @param  detailedResults  Indicates whether detailed information about the
   *                          processing should be added to the list.
   *
   * @return  Information about the result of the configuration update.
   */
  public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry,
                                                  boolean detailedResults)
  {
    ArrayList<String> resultMessages      = new ArrayList<String>();
    boolean           adminActionRequired = false;
    ResultCode        resultCode          = ResultCode.SUCCESS;
    boolean           adminActionRequired = false;
    ArrayList<String> messages            = new ArrayList<String>();
    applyGlobalConfiguration(configuration);
    // Determine whether to perform schema checking.  By default, we will.
    boolean checkSchema = true;
    int msgID = MSGID_CONFIG_CORE_DESCRIPTION_CHECK_SCHEMA;
    BooleanConfigAttribute checkSchemaStub =
         new BooleanConfigAttribute(ATTR_CHECK_SCHEMA, getMessage(msgID),
                                    false);
    try
    {
      BooleanConfigAttribute checkSchemaAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(checkSchemaStub);
      if (checkSchemaAttr == null)
      {
        // This is fine -- just use the default value.
      }
      else
      {
        // Use the value from the attribute that we read.
        checkSchema = checkSchemaAttr.pendingValue();
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so we will not allow this configuration change to
      // take place.
      resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      resultMessages.add(getMessage(MSGID_CONFIG_CORE_INVALID_CHECK_SCHEMA,
                                    configEntry.getDN().toString(),
                                    String.valueOf(e)));
    }
    // Determine whether to allow attribute name exceptions.  By default, we
    // will not.
    boolean allowAttributeNameExceptions = false;
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_ALLOW_ATTR_EXCEPTIONS;
    BooleanConfigAttribute allowExceptionsStub =
         new BooleanConfigAttribute(ATTR_ALLOW_ATTRIBUTE_NAME_EXCEPTIONS,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute allowExceptionsAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(allowExceptionsStub);
      if (allowExceptionsAttr == null)
      {
        // This is fine -- just use the default value.
      }
      else
      {
        // Use the value from the attribute that we read.
        allowAttributeNameExceptions = allowExceptionsAttr.pendingValue();
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so we will not allow this configuration change to
      // take place.
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      }
      resultMessages.add(getMessage(MSGID_CONFIG_CORE_INVALID_ALLOW_EXCEPTIONS,
                                    configEntry.getDN().toString(),
                                    String.valueOf(e)));
    }
    // Determine whether to add missing RDN attributes.  By default we will not.
    boolean addMissingRDNAttributes = false;
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_ADD_MISSING_RDN_ATTRS;
    BooleanConfigAttribute addRDNStub =
         new BooleanConfigAttribute(ATTR_ADD_MISSING_RDN_ATTRS,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute addRDNAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(addRDNStub);
      if (addRDNAttr == null)
      {
        // This is fine -- just use the default value.
      }
      else
      {
        // Use the value from the attribute that we read.
        addMissingRDNAttributes = addRDNAttr.pendingValue();
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so we will not allow this configuration change to
      // take place.
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      }
      resultMessages.add(getMessage(
                              MSGID_CONFIG_CORE_INVALID_ADD_MISSING_RDN_ATTRS,
                              configEntry.getDN().toString(),
                              String.valueOf(e)));
    }
    // Determine the result code to use for internal server errors.
    ResultCode serverErrorResultCode = ResultCode.OTHER;
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_SERVER_ERROR_RESULT_CODE;
    IntegerConfigAttribute serverErrorStub =
         new IntegerConfigAttribute(ATTR_SERVER_ERROR_RESULT_CODE,
                                    getMessage(msgID), false, false, false,
                                    true, 1, false, 0);
    try
    {
      IntegerConfigAttribute serverErrorAttr =
           (IntegerConfigAttribute)
           configEntry.getConfigAttribute(serverErrorStub);
      if (serverErrorAttr == null)
      {
        // This is fine -- just use the default value.
        DirectoryServer.setServerErrorResultCode(serverErrorResultCode);
      }
      else
      {
        // Get the integer value from the provided attribute and then convert
        // that to a result code.
        int resultCodeValue = serverErrorAttr.pendingIntValue();
        serverErrorResultCode = ResultCode.valueOf(resultCodeValue);
        DirectoryServer.setServerErrorResultCode(serverErrorResultCode);
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so we will not allow this configuration change to
      // take place.
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      }
      resultMessages.add(getMessage(
           MSGID_CONFIG_CORE_INVALID_SERVER_ERROR_RESULT_CODE,
           configEntry.getDN().toString(), String.valueOf(e)));
    }
    // Determine how to handle attributes that do not conform to the associated
    // syntax.  By default, we will log a warning but the value will be
    // accepted.
    AcceptRejectWarn syntaxEnforcementPolicy = AcceptRejectWarn.WARN;
    HashSet<String> syntaxBehaviorValues = new HashSet<String>(3);
    syntaxBehaviorValues.add(AcceptRejectWarn.ACCEPT.toString());
    syntaxBehaviorValues.add(AcceptRejectWarn.REJECT.toString());
    syntaxBehaviorValues.add(AcceptRejectWarn.WARN.toString());
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_INVALID_SYNTAX_BEHAVIOR;
    MultiChoiceConfigAttribute syntaxPolicyStub =
         new MultiChoiceConfigAttribute(ATTR_INVALID_SYNTAX_BEHAVIOR,
                                        getMessage(msgID), true, false, false,
                                        syntaxBehaviorValues);
    try
    {
      MultiChoiceConfigAttribute syntaxPolicyAttr =
           (MultiChoiceConfigAttribute)
           configEntry.getConfigAttribute(syntaxPolicyStub);
      if (syntaxPolicyAttr == null)
      {
        // This is fine -- just use the default value.
      }
      else
      {
        // Use the value from the attribute that we read.
        syntaxEnforcementPolicy =
             AcceptRejectWarn.policyForName(syntaxPolicyAttr.pendingValue());
        if (syntaxEnforcementPolicy == null)
        {
          resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
          resultMessages.add(getMessage(
               MSGID_CONFIG_CORE_INVALID_ENFORCE_STRICT_SYNTAX,
               String.valueOf(configEntry.getDN()),
               String.valueOf(syntaxPolicyAttr.pendingValue())));
        }
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so we will not allow this configuration change to
      // take place.
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      }
      resultMessages.add(getMessage(
           MSGID_CONFIG_CORE_INVALID_ENFORCE_STRICT_SYNTAX,
           String.valueOf(configEntry.getDN()), String.valueOf(e)));
    }
    // Determine how to handle entries that do not have exactly one structural
    // objectclass.  By default, we will log a warning but the entry will be
    // accepted.
    AcceptRejectWarn structuralClassPolicy = AcceptRejectWarn.WARN;
    HashSet<String> structuralClassValues = new HashSet<String>(3);
    structuralClassValues.add(AcceptRejectWarn.ACCEPT.toString());
    structuralClassValues.add(AcceptRejectWarn.REJECT.toString());
    structuralClassValues.add(AcceptRejectWarn.WARN.toString());
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_STRUCTURAL_CLASS_BEHAVIOR;
    MultiChoiceConfigAttribute structuralClassStub =
         new MultiChoiceConfigAttribute(ATTR_SINGLE_STRUCTURAL_CLASS_BEHAVIOR,
                                        getMessage(msgID), true, false, false,
                                        structuralClassValues);
    try
    {
      MultiChoiceConfigAttribute structuralClassAttr =
           (MultiChoiceConfigAttribute)
           configEntry.getConfigAttribute(structuralClassStub);
      if (structuralClassAttr == null)
      {
        // This is fine -- just use the default value.
      }
      else
      {
        // Use the value from the attribute that we read.
        structuralClassPolicy =
             AcceptRejectWarn.policyForName(structuralClassAttr.pendingValue());
        if (structuralClassPolicy == null)
        {
          resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
          resultMessages.add(getMessage(
               MSGID_CONFIG_CORE_INVALID_STRUCTURAL_CLASS_BEHAVIOR,
               String.valueOf(configEntry.getDN()),
               String.valueOf(structuralClassAttr.pendingValue())));
        }
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so we will not allow this configuration change to
      // take place.
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      }
      resultMessages.add(getMessage(
           MSGID_CONFIG_CORE_INVALID_STRUCTURAL_CLASS_BEHAVIOR,
           String.valueOf(configEntry.getDN()), String.valueOf(e)));
    }
    // Determine the maximum number of client connections that should be allowed
    // at any time.
    long maxAllowedConnections = -1;
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_MAX_ALLOWED_CONNECTIONS;
    IntegerConfigAttribute maxConnsStub =
         new IntegerConfigAttribute(ATTR_MAX_ALLOWED_CONNS, getMessage(msgID),
                                    true, false, false, true, -1, false, 0);
    try
    {
      IntegerConfigAttribute maxConnsAttr =
           (IntegerConfigAttribute)
           configEntry.getConfigAttribute(maxConnsStub);
      if (maxConnsAttr == null)
      {
        // This is fine -- just use the default value.
      }
      else
      {
        // Use the value from the attribute that we read.
        maxAllowedConnections = maxConnsAttr.activeValue();
      }
    }
    catch (Exception e)
    {
      // An error occurred, but this should not be considered fatal.  Log an
      // error message and use the default.
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      }
      resultMessages.add(getMessage(
                              MSGID_CONFIG_CORE_INVALID_MAX_ALLOWED_CONNECTIONS,
                              configEntry.getDN(), String.valueOf(e)));
    }
    // Determine whether to send a response to abandoned operations.  By
    // default, we will not.
    boolean notifyAbandonedOperations = false;
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_NOTIFY_ABANDONED_OPERATIONS;
    BooleanConfigAttribute notifyAbandonedStub =
         new BooleanConfigAttribute(ATTR_NOTIFY_ABANDONED_OPS,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute notifyAbandonedAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(notifyAbandonedStub);
      if (notifyAbandonedAttr == null)
      {
        // This is fine -- just use the default value.
      }
      else
      {
        // Use the value from the attribute that we read.
        notifyAbandonedOperations = notifyAbandonedAttr.pendingValue();
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so we will not allow this configuration change to
      // take place.
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      }
      resultMessages.add(getMessage(
           MSGID_CONFIG_CORE_INVALID_NOTIFY_ABANDONED_OPERATIONS,
           configEntry.getDN().toString(), String.valueOf(e)));
    }
    // Get the DN of the proxied authorization identity mapper.
    DN proxyMapperDN =
            DirectoryServer.getProxiedAuthorizationIdentityMapperDN();
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_PROXY_MAPPER_DN;
    DNConfigAttribute proxyMapperStub =
         new DNConfigAttribute(ATTR_PROXY_MAPPER_DN, getMessage(msgID), false,
                               false, false);
    try
    {
      DNConfigAttribute proxyMapperAttr =
           (DNConfigAttribute) configEntry.getConfigAttribute(proxyMapperStub);
      if (proxyMapperAttr == null)
      {
        proxyMapperDN = null;
      }
      else
      {
        proxyMapperDN = proxyMapperAttr.pendingValue();
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so we will not allow this configuration change to
      // take place.
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      }
      msgID = MSGID_CONFIG_CORE_INVALID_PROXY_MAPPER_DN;
      resultMessages.add(getMessage(msgID, configEntry.getDN().toString(),
                                    String.valueOf(e)));
    }
    // Get the server size limit.
    int sizeLimit = DEFAULT_SIZE_LIMIT;
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_SIZE_LIMIT;
    IntegerConfigAttribute sizeLimitStub =
         new IntegerConfigAttribute(ATTR_SIZE_LIMIT, getMessage(msgID), false,
                                    false, false, true, 0, true,
                                    Integer.MAX_VALUE);
    try
    {
      IntegerConfigAttribute sizeLimitAttr =
           (IntegerConfigAttribute)
           configEntry.getConfigAttribute(sizeLimitStub);
      if (sizeLimitAttr != null)
      {
        sizeLimit = sizeLimitAttr.pendingIntValue();
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so we will not allow this configuration change to
      // take place.
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      }
      msgID = MSGID_CONFIG_CORE_INVALID_SIZE_LIMIT;
      resultMessages.add(getMessage(msgID, configEntry.getDN().toString(),
                                    String.valueOf(e)));
    }
    // Get the server time limit.
    int timeLimit = DEFAULT_TIME_LIMIT;
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_TIME_LIMIT;
    IntegerWithUnitConfigAttribute timeLimitStub =
         new IntegerWithUnitConfigAttribute(ATTR_TIME_LIMIT, getMessage(msgID),
                                            false, timeUnits, true, 0, true,
                                            Integer.MAX_VALUE);
    try
    {
      IntegerWithUnitConfigAttribute timeLimitAttr =
           (IntegerWithUnitConfigAttribute)
           configEntry.getConfigAttribute(timeLimitStub);
      if (timeLimitAttr != null)
      {
        timeLimit = (int) timeLimitAttr.pendingCalculatedValue();
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so we will not allow this configuration change to
      // take place.
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      }
      msgID = MSGID_CONFIG_CORE_INVALID_TIME_LIMIT;
      resultMessages.add(getMessage(msgID, configEntry.getDN().toString(),
                                    String.valueOf(e)));
    }
    // Get the server lookthrough limit.
    int lookthroughLimit = DEFAULT_LOOKTHROUGH_LIMIT;
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_LOOKTHROUGH_LIMIT;
    IntegerConfigAttribute lookthroughLimitStub =
         new IntegerConfigAttribute(ATTR_LOOKTHROUGH_LIMIT,
             getMessage(msgID), false, false, false, true, -1, true,
             Integer.MAX_VALUE);
    try
    {
      IntegerConfigAttribute lookthroughLimitAttr =
           (IntegerConfigAttribute)
           configEntry.getConfigAttribute(lookthroughLimitStub);
      if (lookthroughLimitAttr != null)
      {
        lookthroughLimit = lookthroughLimitAttr.pendingIntValue();
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so we will not allow this configuration change to
      // take place.
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      }
      msgID = MSGID_CONFIG_CORE_INVALID_LOOKTHROUGH_LIMIT;
      resultMessages.add(getMessage(msgID, configEntry.getDN().toString(),
                                    String.valueOf(e)));
    }
    // Get the server writability mode.
    HashSet<String> writabilityModes = new HashSet<String>(3);
    writabilityModes.add(WritabilityMode.ENABLED.toString());
    writabilityModes.add(WritabilityMode.DISABLED.toString());
    writabilityModes.add(WritabilityMode.INTERNAL_ONLY.toString());
    WritabilityMode writabilityMode = WritabilityMode.ENABLED;
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_WRITABILITY_MODE;
    MultiChoiceConfigAttribute writabilityStub =
         new MultiChoiceConfigAttribute(ATTR_WRITABILITY_MODE,
                                        getMessage(msgID), true, false, false,
                                        writabilityModes);
    try
    {
      MultiChoiceConfigAttribute writabilityAttr =
           (MultiChoiceConfigAttribute)
           configEntry.getConfigAttribute(writabilityStub);
      if (writabilityAttr != null)
      {
        writabilityMode =
             WritabilityMode.modeForName(writabilityAttr.pendingValue());
        if (writabilityMode == null)
        {
          msgID = MSGID_CONFIG_CORE_INVALID_WRITABILITY_MODE;
          resultMessages.add(getMessage(msgID, String.valueOf(configEntryDN),
                                        writabilityAttr.pendingValue()));
          if (resultCode == ResultCode.SUCCESS)
          {
            resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
          }
        }
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so we will not allow this configuration change to
      // take place.
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      }
      msgID = MSGID_CONFIG_CORE_INVALID_WRITABILITY_MODE;
      resultMessages.add(getMessage(msgID, configEntry.getDN().toString(),
                                    String.valueOf(e)));
    }
    // Get the configuration for handling binds with a DN but no password.
    boolean bindWithDNRequiresPW = DEFAULT_BIND_WITH_DN_REQUIRES_PW;
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_BIND_WITH_DN_REQUIRES_PW;
    BooleanConfigAttribute requirePWStub =
         new BooleanConfigAttribute(ATTR_BIND_WITH_DN_REQUIRES_PW,
                                    getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute requirePWAttr =
           (BooleanConfigAttribute)
           configEntry.getConfigAttribute(requirePWStub);
      if (requirePWAttr != null)
      {
        bindWithDNRequiresPW = requirePWAttr.pendingValue();
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so we will not allow this configuration change to
      // take place.
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      }
      msgID = MSGID_CONFIG_CORE_INVALID_BIND_WITH_DN_REQUIRES_PW;
      resultMessages.add(getMessage(msgID, configEntry.getDN().toString(),
                                    String.valueOf(e)));
    }
    // Determine whether an uauthenticated request should be rejected.
    boolean rejectUnauthenticatedReq = DEFAULT_REJECT_UNAUTHENTICATED_REQ;
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_REJECT_UNAUTHENTICATED_REQUESTS;
    BooleanConfigAttribute rejectRequestStub =
    new BooleanConfigAttribute(ATTR_REJECT_UNAUTHENTICATED_REQ,
                              getMessage(msgID), false);
    try
    {
      BooleanConfigAttribute rejectRequestAttr=
      (BooleanConfigAttribute)
      configEntry.getConfigAttribute(rejectRequestStub);
      if(rejectRequestAttr!= null)
      {
        rejectUnauthenticatedReq = rejectRequestAttr.pendingValue();
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so we will not allow this configuration change to
      // take place.
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      }
      msgID = MSGID_CONFIG_CORE_REJECT_UNAUTHENTICATED_REQUESTS_INVALID;
      resultMessages.add(getMessage(msgID, configEntry.getDN().toString(),
                                    String.valueOf(e)));
    }
    // Ge the DN of the default password policy configuration entry.
    DN defaultPWPolicyDN = null;
    msgID = MSGID_CONFIG_CORE_DESCRIPTION_DEFAULT_PWPOLICY_DN;
    DNConfigAttribute defaultPWPolicyStub =
         new DNConfigAttribute(ATTR_DEFAULT_PWPOLICY_DN, getMessage(msgID),
                               true, false, false);
    try
    {
      DNConfigAttribute defaultPWPolicyAttr =
           (DNConfigAttribute)
           configEntry.getConfigAttribute(defaultPWPolicyStub);
      if (defaultPWPolicyAttr == null)
      {
        msgID = MSGID_CONFIG_CORE_NO_DEFAULT_PWPOLICY;
        resultMessages.add(getMessage(msgID, String.valueOf(configEntryDN)));
        if (resultCode == ResultCode.SUCCESS)
        {
          resultCode = ResultCode.OBJECTCLASS_VIOLATION;
        }
      }
      else
      {
        defaultPWPolicyDN = defaultPWPolicyAttr.pendingValue();
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      // An error occurred, so we will not allow this configuration change to
      // take place.
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      }
      msgID = MSGID_CONFIG_CORE_INVALID_DEFAULT_PWPOLICY_DN;
      resultMessages.add(getMessage(msgID, configEntry.getDN().toString(),
                                    String.valueOf(e)));
    }
    // If the result is successful, then apply the changes.
    if (resultCode == ResultCode.SUCCESS)
    {
      DirectoryServer.setCheckSchema(checkSchema);
      if (detailedResults)
      {
        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
                                      ATTR_CHECK_SCHEMA,
                                      String.valueOf(checkSchema),
                                      configEntryDN.toString()));
      }
      DirectoryServer.setAllowAttributeNameExceptions(
                           allowAttributeNameExceptions);
      if (detailedResults)
      {
        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
                                ATTR_ALLOW_ATTRIBUTE_NAME_EXCEPTIONS,
                                String.valueOf(allowAttributeNameExceptions),
                                configEntryDN.toString()));
      }
      DirectoryServer.setAddMissingRDNAttributes(addMissingRDNAttributes);
      if (detailedResults)
      {
        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
                                ATTR_ADD_MISSING_RDN_ATTRS,
                                String.valueOf(addMissingRDNAttributes),
                                configEntryDN.toString()));
      }
      DirectoryServer.setServerErrorResultCode(serverErrorResultCode);
      if (detailedResults)
      {
        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
                                ATTR_SERVER_ERROR_RESULT_CODE,
                                String.valueOf(serverErrorResultCode),
                                configEntryDN.toString()));
      }
      DirectoryServer.setSyntaxEnforcementPolicy(syntaxEnforcementPolicy);
      if (detailedResults)
      {
        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
                                ATTR_INVALID_SYNTAX_BEHAVIOR,
                                String.valueOf(syntaxEnforcementPolicy),
                                configEntryDN.toString()));
      }
      DirectoryServer.setSingleStructuralObjectClassPolicy(
                           structuralClassPolicy);
      if (detailedResults)
      {
        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
                                ATTR_SINGLE_STRUCTURAL_CLASS_BEHAVIOR,
                                String.valueOf(structuralClassPolicy),
                                configEntryDN.toString()));
      }
      DirectoryServer.setMaxAllowedConnections(maxAllowedConnections);
      if (detailedResults)
      {
        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
                                ATTR_MAX_ALLOWED_CONNS,
                                String.valueOf(maxAllowedConnections),
                                configEntryDN.toString()));
      }
      DirectoryServer.setNotifyAbandonedOperations(notifyAbandonedOperations);
      if (detailedResults)
      {
        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
                                ATTR_NOTIFY_ABANDONED_OPS,
                                String.valueOf(notifyAbandonedOperations),
                                configEntryDN.toString()));
      }
      DirectoryServer.setProxiedAuthorizationIdentityMapperDN(proxyMapperDN);
      if (detailedResults)
      {
        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
                                ATTR_PROXY_MAPPER_DN,
                                String.valueOf(proxyMapperDN),
                                configEntryDN.toString()));
      }
      DirectoryServer.setSizeLimit(sizeLimit);
      if (detailedResults)
      {
        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
                                      ATTR_SIZE_LIMIT,
                                      String.valueOf(sizeLimit),
                                      configEntryDN.toString()));
      }
      DirectoryServer.setTimeLimit(timeLimit);
      if (detailedResults)
      {
        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
                                      ATTR_TIME_LIMIT,
                                      String.valueOf(timeLimit),
                                      configEntryDN.toString()));
      }
      DirectoryServer.setLookthroughLimit(lookthroughLimit);
      if (detailedResults)
      {
        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
                                      ATTR_LOOKTHROUGH_LIMIT,
                                      String.valueOf(lookthroughLimit),
                                      configEntryDN.toString()));
      }
      DirectoryServer.setWritabilityMode(writabilityMode);
      if (detailedResults)
      {
        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
                                      ATTR_WRITABILITY_MODE,
                                      String.valueOf(writabilityMode),
                                      configEntryDN.toString()));
      }
      DirectoryServer.setBindWithDNRequiresPassword(bindWithDNRequiresPW);
      if (detailedResults)
      {
        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
                                      ATTR_BIND_WITH_DN_REQUIRES_PW,
                                      String.valueOf(bindWithDNRequiresPW),
                                      configEntryDN.toString()));
      }
      DirectoryServer.setDefaultPasswordPolicyDN(defaultPWPolicyDN);
      if (detailedResults)
      {
        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
                                      ATTR_DEFAULT_PWPOLICY_DN,
                                      String.valueOf(defaultPWPolicyDN),
                                      configEntryDN.toString()));
      }
      DirectoryServer.setRejectUnauthenticatedRequests(
                        rejectUnauthenticatedReq);
      if (detailedResults)
      {
        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
                                      ATTR_REJECT_UNAUTHENTICATED_REQ,
                                      String.valueOf(rejectUnauthenticatedReq),
                                      configEntryDN.toString()));
      }
    }
    return new ConfigChangeResult(resultCode, adminActionRequired,
                                  resultMessages);
    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
  }
}