From a58e7b46dfb39b744ef3ea3970d55696ba68c646 Mon Sep 17 00:00:00 2001
From: lutoff <lutoff@localhost>
Date: Fri, 27 Apr 2007 07:10:02 +0000
Subject: [PATCH] Fix for Issue #1485 (use new admin framework for password policy configuration)

---
 opends/src/server/org/opends/server/core/DirectoryServer.java                                |   28 
 opends/src/server/org/opends/server/core/PasswordPolicyConfig.java                           |  363 ---------
 opends/src/server/org/opends/server/core/PasswordPolicyConfigManager.java                    |  185 +--
 opends/tests/unit-tests-testng/src/server/org/opends/server/core/PasswordPolicyTestCase.java |    9 
 opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyConfiguration.xml            |  919 ++++++++++++++++++++++++
 opends/src/server/org/opends/server/core/PasswordPolicy.java                                 |  737 +-----------------
 opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml                      |    8 
 7 files changed, 1,121 insertions(+), 1,128 deletions(-)

diff --git a/opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyConfiguration.xml
new file mode 100644
index 0000000..6e545b7
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyConfiguration.xml
@@ -0,0 +1,919 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<adm:managed-object name="password-policy"
+  plural-name="password-policys" package="org.opends.server.admin.std"
+  xmlns:adm="http://www.opends.org/admin"
+  xmlns:ldap="http://www.opends.org/admin-ldap">
+  <adm:synopsis>
+    Define a number of password management rules, as well as
+    requirements for authentication processing.
+  </adm:synopsis>
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:oid>1.3.6.1.4.1.26027.1.2.62</ldap:oid>
+      <ldap:name>ds-cfg-password-policy</ldap:name>
+      <ldap:superior>top</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+
+  <adm:property name="password-attribute" mandatory="true"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the attribute type used to hold user passwords.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the attribute type used to hold user passwords. This
+      attribute type must be defined in the server schema. Changes to
+      this configuration attribute will take effect immediately.
+    </adm:description>
+    <adm:syntax>
+      <adm:oid />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.192</ldap:oid>
+        <ldap:name>ds-cfg-password-attribute</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="default-password-storage-scheme" mandatory="true"
+    multi-valued="true">
+    <adm:synopsis>
+      Specifies the password storage scheme (or set of schemes) that
+      will be used to encode clear-text passwords.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the password storage scheme (or set of schemes) that
+      will be used to encode clear-text passwords. If multiple default
+      storage schemes are defined for a password policy, then the same
+      password will be encoded using all of those schemes. Changes to
+      this configuration attribute will take effect immediately.
+    </adm:description>
+    <adm:syntax>
+      <adm:string />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.178</ldap:oid>
+        <ldap:name>ds-cfg-default-password-storage-scheme</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="deprecated-password-storage-scheme"
+    mandatory="false" multi-valued="true">
+    <adm:synopsis>
+      Specifies the password storage scheme (or set of schemes) that
+      should be considered deprecated.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the password storage scheme (or set of schemes) that
+      should be considered deprecated. If an authenticating user has a
+      password encoded with one of these schemes, those passwords will
+      be removed and replaced with passwords encoded using the default
+      schemes. Changes to this configuration attribute will take effect
+      immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:undefined />
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:string />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.179</ldap:oid>
+        <ldap:name>ds-cfg-deprecated-password-storage-scheme</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="password-validator-dn" mandatory="false"
+    multi-valued="true">
+    <adm:synopsis>
+      Specifies the DN(s) of the password validator(s) that should be
+      used with the associated password storage scheme.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the DN(s) of the password validator(s) that should be
+      used with the associated password storage scheme. Changes to this
+      configuration attribute will take effect immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:undefined />
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:dn />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.195</ldap:oid>
+        <ldap:name>ds-cfg-password-validator-dn</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="account-status-notification-handler-dn"
+    mandatory="false" multi-valued="true">
+    <adm:synopsis>
+      Specifies the DN(s) of the account status notification handler(s)
+      that should be used with the associated password storage scheme.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the DN(s) of the account status notification handler(s)
+      that should be used with the associated password storage scheme.
+      Changes to this configuration attribute will take effect
+      immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:undefined />
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:dn />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.174</ldap:oid>
+        <ldap:name>
+          ds-cfg-account-status-notification-handler-dn
+        </ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="allow-user-password-changes" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Indicates whether users will be allowed to change their own
+      passwords.
+    </adm:synopsis>
+    <adm:description>
+      Indicates whether users will be allowed to change their own
+      passwords. This check is made in addition to access control
+      evaluation, and therefore both must allow the password change for
+      it to occur. Changes to this configuration attribute will take
+      effect immediately.
+    </adm:description>
+    <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.177</ldap:oid>
+        <ldap:name>ds-cfg-allow-user-password-changes</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="password-change-requires-current-password"
+    mandatory="false" multi-valued="false">
+    <adm:synopsis>
+      Indicates whether user password changes will be required to use
+      the password modify extended operation and include the user's
+      current password before the change will be allowed.
+    </adm:synopsis>
+    <adm:description>
+      Indicates whether user password changes will be required to use
+      the password modify extended operation and include the user's
+      current password before the change will be allowed. Changes to
+      this configuration attribute will take effect immediately.
+    </adm:description>
+    <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.198</ldap:oid>
+        <ldap:name>
+          ds-cfg-password-change-requires-current-password
+        </ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+
+  </adm:property>
+  <adm:property name="force-change-on-add" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Indicates whether users will be forced to change their passwords
+      upon first authenticating to the Directory Server after their
+      account has been created.
+    </adm:synopsis>
+    <adm:description>
+      Indicates whether users will be forced to change their passwords
+      upon first authenticating to the Directory Server after their
+      account has been created. Changes to this configuration attribute
+      will take effect immediately.
+    </adm:description>
+    <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.208</ldap:oid>
+        <ldap:name>ds-cfg-force-change-on-add</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+
+
+  <adm:property name="force-change-on-reset" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Indicates whether users will be forced to change their passwords
+      if they are reset by an administrator.
+    </adm:synopsis>
+    <adm:description>
+      Indicates whether users will be forced to change their passwords
+      if they are reset by an administrator. For this purpose, anyone
+      with permission to change a given user's password other than that
+      user will be considered an administrator. Changes to this
+      configuration attribute will take effect immediately.
+    </adm:description>
+    <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.181</ldap:oid>
+        <ldap:name>ds-cfg-force-change-on-reset</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+
+
+  </adm:property>
+  <adm:property name="skip-validation-for-administrators"
+    mandatory="false" multi-valued="false">
+    <adm:synopsis>
+      Indicates whether passwords set by administrators will be allowed
+      to bypass the password validation process that will be required
+      for user password changes.
+    </adm:synopsis>
+    <adm:description>
+      Indicates whether passwords set by administrators (in add, modify,
+      or password modify operations) will be allowed to bypass the
+      password validation process that will be required for user
+      password changes. Changes to this configuration attribute will
+      take effect immediately.
+    </adm:description>
+    <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.201</ldap:oid>
+        <ldap:name>ds-cfg-skip-validation-for-administrators</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+
+  <adm:property name="password-generator-dn" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the DN of the configuration entry that references the
+      password generator for use with the associated password policy.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the DN of the configuration entry that references the
+      password generator for use with the associated password policy.
+      This will be used in conjunction with the password modify extended
+      operation to generate a new password for a user when none was
+      provided in the request. Changes to this configuration attribute
+      will take effect immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:undefined />
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:dn />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.194</ldap:oid>
+        <ldap:name>ds-cfg-password-generator-dn</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+
+  <adm:property name="require-secure-authentication" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Indicates whether users with the associated password policy will
+      be required to authenticate in a secure manner.
+    </adm:synopsis>
+    <adm:description>
+      Indicates whether users with the associated password policy will
+      be required to authenticate in a secure manner. This could mean
+      either using a secure communication channel between the client and
+      the server, or using a SASL mechanism that does not expose the
+      credentials. Changes to this configuration attribute will take
+      effect immediately.
+    </adm:description>
+    <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.199</ldap:oid>
+        <ldap:name>ds-cfg-require-secure-authentication</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+
+  <adm:property name="require-secure-password-changes" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Indicates whether users with the associated password policy will
+      be required to change their password in a secure manner that does
+      not expose the credentials.
+    </adm:synopsis>
+    <adm:description>
+      Indicates whether users with the associated password policy will
+      be required to change their password in a secure manner that does
+      not expose the credentials. Changes to this configuration
+      attribute will take effect immediately.
+    </adm:description>
+    <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.200</ldap:oid>
+        <ldap:name>ds-cfg-require-secure-password-changes</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+
+  <adm:property name="allow-multiple-password-values" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Indicates whether user entries will be allowed to have multiple
+      distinct values for the password attribute.
+    </adm:synopsis>
+    <adm:description>
+      Indicates whether user entries will be allowed to have multiple
+      distinct values for the password attribute. This is potentially
+      dangerous because many mechanisms used to change the password do
+      not work well with such a configuration. If multiple password
+      values are allowed, then any of them may be used to authenticate,
+      and they will all be subject to the same policy constraints.
+      Changes to this configuration attribute will take effect
+      immediately.
+    </adm:description>
+    <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.209</ldap:oid>
+        <ldap:name>ds-cfg-allow-multiple-password-values</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="allow-pre-encoded-passwords" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      _Indicates whether users will be allowed to change their passwords
+      by providing a pre-encoded value.
+    </adm:synopsis>
+    <adm:description>
+      Indicates whether users will be allowed to change their passwords
+      by providing a pre-encoded value. This can cause a security risk
+      because the clear-text version of the password is not known and
+      therefore validation checks cannot be applied to it. Changes to
+      this configuration attribute will take effect immediately.
+    </adm:description>
+    <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.176</ldap:oid>
+        <ldap:name>ds-cfg-allow-pre-encoded-passwords</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="minimum-password-age" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the minimum length of time that must pass after a
+      password change before the user will be allowed to change the
+      password again.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the minimum length of time that must pass after a
+      password change before the user will be allowed to change the
+      password again. The value of this attribute should be an integer
+      followed by a unit of seconds, minutes, hours, days, or weeks.
+      This setting can be used to prevent users from changing their
+      passwords repeatedly over a short period of time to flush and old
+      password from the history so that it may be re-used. Changes to
+      this configuration attribute will take effect immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>0 seconds</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:duration />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.191</ldap:oid>
+        <ldap:name>ds-cfg-minimum-password-age</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="maximum-password-age" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the maximum length of time that a user may continue
+      using the same password before it must be changed.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the maximum length of time that a user may continue
+      using the same password before it must be changed (i.e., the
+      password expiration interval). The value of this attribute should
+      be an integer followed by a unit of seconds, minutes, hours, days,
+      or weeks. A value of 0 seconds will disable password expiration.
+      Changes to this configuration attribute will take effect
+      immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>0 seconds</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:duration />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.189</ldap:oid>
+        <ldap:name>ds-cfg-maximum-password-age</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+
+  <adm:property name="maximum-password-reset-age" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the maximum length of time that users have to change
+      passwords after they have been reset by an administrator before
+      they become locked.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the maximum length of time that users have to change
+      passwords after they have been reset by an administrator before
+      they become locked. The value of this attribute should be an
+      integer followed by a unit of seconds, minutes, hours, days, or
+      weeks. A value of 0 seconds will disable this feature. Changes to
+      this configuration attribute will take effect immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>0 seconds</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:duration />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.190</ldap:oid>
+        <ldap:name>ds-cfg-maximum-password-reset-age</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="password-expiration-warning-interval"
+    mandatory="false" multi-valued="false">
+    <adm:synopsis>
+      Specifies the maximum length of time before a user's password
+      actually expires that the server will begin to include warning
+      notifications in bind responses for that user.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the maximum length of time before a user's password
+      actually expires that the server will begin to include warning
+      notifications in bind responses for that user. The value of this
+      attribute should be an integer followed by a unit of seconds,
+      minutes, hours, days, or weeks. A value of 0 seconds will disable
+      the warning interval. Changes to this configuration attribute will
+      take effect immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>5 days</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:duration />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.193</ldap:oid>
+        <ldap:name>
+          ds-cfg-password-expiration-warning-interval
+        </ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="expire-passwords-without-warning"
+    mandatory="false" multi-valued="false">
+    <adm:synopsis>
+      Indicates whether the Directory Server should allow a user's
+      password to expire even if that user has never seen an expiration
+      warning notification.
+    </adm:synopsis>
+    <adm:description>
+      Indicates whether the Directory Server should allow a user's
+      password to expire even if that user has never seen an expiration
+      warning notification. If this setting is enabled, then accounts
+      will always be expired when the expiration time arrives. If it is
+      disabled, then the user will always receive at least one warning
+      notification, and the password expiration will be set to the
+      warning time plus the warning interval. Changes to this
+      configuration attribute will take effect immediately.
+    </adm:description>
+    <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.180</ldap:oid>
+        <ldap:name>ds-cfg-expire-passwords-without-warning</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="allow-expired-password-changes" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Indicates whether a user whose password is expired will still be
+      allowed to change that password using the password modify extended
+      operation.
+    </adm:synopsis>
+    <adm:description>
+      Indicates whether a user whose password is expired will still be
+      allowed to change that password using the password modify extended
+      operation. Changes to this configuration attribute will take
+      effect immediately.
+    </adm:description>
+    <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.175</ldap:oid>
+        <ldap:name>ds-cfg-allow-expired-password-changes</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="grace-login-count" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the number of grace logins that a user will be allowed
+      after the account has expired to allow that user to choose a new
+      password.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the number of grace logins that a user will be allowed
+      after the account has expired to allow that user to choose a new
+      password. A value of 0 indicates that no grace logins will be
+      allowed. Changes to this configuration attribute will take effect
+      immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>0</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:integer lower-limit="0" upper-limit="2147483647" />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.182</ldap:oid>
+        <ldap:name>ds-cfg-grace-login-count</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="lockout-failure-count" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the maximum number of authentication failures that a
+      user should be allowed before the account is locked out.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the maximum number of authentication failures that a
+      user should be allowed before the account is locked out. A value
+      of 0 indicates that accounts should never be locked out due to
+      failed attempts. changes to this configuration attribute will take
+      effect immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>0</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:integer lower-limit="0" upper-limit="2147483647" />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.187</ldap:oid>
+        <ldap:name>ds-cfg-lockout-failure-count</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="lockout-duration" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the length of time that an account should be locked
+      after too many authentication failures.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the length of time that an account should be locked
+      after too many authentication failures. The value of this
+      attribute should be an integer followed by a unit of seconds,
+      minutes, hours, days, or weeks. A value of 0 seconds indicates
+      that the account should remain locked until an administrator
+      resets the password. Changes to this configuration attribute will
+      take effect immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>0 seconds</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:duration />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.186</ldap:oid>
+        <ldap:name>ds-cfg-lockout-duration</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="lockout-failure-expiration-interval"
+    mandatory="false" multi-valued="false">
+    <adm:synopsis>
+      pecifies the length of time that should pass before an
+      authentication failure is no longer counted against a user for the
+      purposes of account lockout.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the length of time that should pass before an
+      authentication failure is no longer counted against a user for the
+      purposes of account lockout. The value of this attribute should be
+      an integer followed by a unit of seconds, minutes, hours, days, or
+      weeks. A value of 0 seconds indicates that the authentication
+      failures should never expire. The failure count will always be
+      cleared upon a successful authentication. Changes to this
+      configuration attribute will take effect immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>0 seconds</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:duration />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.188</ldap:oid>
+        <ldap:name>
+          ds-cfg-lockout-failure-expiration-interval
+        </ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="require-change-by-time" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the time by which all users with the associated password
+      policy must change their passwords.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the time by which all users with the associated password
+      policy must change their passwords. The value should be expressed
+      in a generalized time format. If this time is equal to the current
+      time or is in the past, then all users will be required to change
+      their passwords immediately. The behavior of the server in this
+      mode will be identical to the behavior observed when users are
+      forced to change their passwords after an administrative reset.
+      Changes to this configuration attribute will take effect
+      immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:undefined />
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:string />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.197</ldap:oid>
+        <ldap:name>ds-cfg-require-change-by-time</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="last-login-time-attribute" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the name or OID of the attribute type that should be
+      used to hold the last login time for users with the associated
+      password policy.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the name or OID of the attribute type that should be
+      used to hold the last login time for users with the associated
+      password policy. This attribute type must be defined in the
+      Directory Server schema and must either be defined as an
+      operational attribute or must be allowed by the set of
+      objectClasses for all users with the associated password policy.
+      Changes to this configuration attribute will take effect
+      immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:undefined />
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:oid />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.184</ldap:oid>
+        <ldap:name>ds-cfg-last-login-time-attribute</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="last-login-time-format" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the format string that should be used to generate the
+      last login time value for users with the associated password
+      policy.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the format string that should be used to generate the
+      last login time value for users with the associated password
+      policy. This format string should conform to the syntax described
+      in the API documentation for the java.text.SimpleDateFormat class.
+      Changes to this configuration attribute will take effect
+      immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:undefined />
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:string />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.185</ldap:oid>
+        <ldap:name>ds-cfg-last-login-time-format</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="previous-last-login-time-format" mandatory="false"
+    multi-valued="true">
+    <adm:synopsis>
+      Specifies the format string(s) that may have been used with the
+      last login time at any point in the past for users associated with
+      the password policy.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the format string(s) that may have been used with the
+      last login time at any point in the past for users associated with
+      the password policy. These values are used to make it possible to
+      parse previous values, but will not be used to set new values.
+      These format strings should conform to the syntax described in the
+      API documentation for the java.text.SimpleDateFormat class.
+      Changes to this configuration attribute will take effect
+      immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:undefined />
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:string />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.196</ldap:oid>
+        <ldap:name>ds-cfg-previous-last-login-time-format</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="idle-lockout-interval" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the maximum length of time that an account may remain
+      idle (i.e., the associated user does notauthenticate to the
+      server) before that user is locked out.
+    </adm:synopsis>
+    <adm:description>
+      Specifies the maximum length of time that an account may remain
+      idle (i.e., the associated user does notauthenticate to the
+      server) before that user is locked out. The value of this
+      attribute should be an integer followed by a unit of seconds,
+      minutes, hours, days, or weeks. A value of 0 seconds indicates
+      that idle accounts should not automatically be locked out. This
+      feature will only be available if the last login time is
+      maintained. Changes to this configuration attribute will take
+      effect immediately.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>0 seconds</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:duration />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.183</ldap:oid>
+        <ldap:name>ds-cfg-idle-lockout-interval</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+</adm:managed-object>
\ No newline at end of file
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
index 9f68116..61bd1bd 100644
--- a/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
+++ b/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
@@ -116,5 +116,13 @@
       </ldap:rdn-sequence>
     </adm:profile>
   </adm:relation>
+  <adm:relation name="password-policy">
+    <adm:one-to-many />
+    <adm:profile name="ldap">
+      <ldap:rdn-sequence>
+        cn=Password Policies,cn=config
+      </ldap:rdn-sequence>
+    </adm:profile>
+  </adm:relation>
   <adm:product-name>OpenDS Directory Server</adm:product-name>
 </adm:root-managed-object>
diff --git a/opends/src/server/org/opends/server/core/DirectoryServer.java b/opends/src/server/org/opends/server/core/DirectoryServer.java
index a44d5e7..2e4f507 100644
--- a/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -4932,6 +4932,24 @@
   }
 
 
+  /**
+   * Retrieves the password policy registered for the provided configuration
+   * entry.
+   *
+   * @param  configEntryDN  The DN of the configuration entry for which to
+   *                        retrieve the associated password policy.
+   *
+   * @return  The password policy config registered for the provided
+   *          configuration entry, or <CODE>null</CODE> if there is
+   *          no such policy.
+   */
+  public static PasswordPolicyConfig getPasswordPolicyConfig(DN configEntryDN)
+  {
+    Validator.ensureNotNull(configEntryDN);
+
+    return directoryServer.passwordPolicies.get(configEntryDN);
+  }
+
 
   /**
    * Registers the provided password policy with the Directory Server.  If a
@@ -4940,14 +4958,13 @@
    *
    * @param  configEntryDN  The DN of the configuration entry that defines the
    *                        password policy.
-   * @param  policy         The password policy to register with the server.
+   * @param  config         The password policy config to register with the
+   *                        server.
    */
   public static void registerPasswordPolicy(DN configEntryDN,
-                                            PasswordPolicy policy)
+                                            PasswordPolicyConfig config)
   {
-    Validator.ensureNotNull(configEntryDN, policy);
-
-    PasswordPolicyConfig config = new PasswordPolicyConfig(policy);
+    Validator.ensureNotNull(configEntryDN, config);
 
     directoryServer.passwordPolicies.put(configEntryDN, config);
   }
@@ -4972,7 +4989,6 @@
 
     PasswordPolicyConfig config
             = directoryServer.passwordPolicies.remove(configEntryDN);
-    if (null != config) config.finalizePasswordPolicyConfig();
   }
 
 
diff --git a/opends/src/server/org/opends/server/core/PasswordPolicy.java b/opends/src/server/org/opends/server/core/PasswordPolicy.java
index 54efbcb..d709d67 100644
--- a/opends/src/server/org/opends/server/core/PasswordPolicy.java
+++ b/opends/src/server/org/opends/server/core/PasswordPolicy.java
@@ -33,24 +33,19 @@
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
-import java.util.List;
+import java.util.SortedSet;
 import java.util.TimeZone;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CopyOnWriteArraySet;
 
+import org.opends.server.admin.std.server.PasswordPolicyCfg;
 import org.opends.server.admin.std.server.PasswordValidatorCfg;
 import org.opends.server.api.AccountStatusNotificationHandler;
 import org.opends.server.api.PasswordGenerator;
 import org.opends.server.api.PasswordStorageScheme;
 import org.opends.server.api.PasswordValidator;
-import org.opends.server.config.BooleanConfigAttribute;
-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.StringConfigAttribute;
 import org.opends.server.protocols.asn1.ASN1OctetString;
 import org.opends.server.schema.GeneralizedTimeSyntax;
 import org.opends.server.types.AttributeType;
@@ -222,7 +217,7 @@
    * provided configuration entry.  Any parameters not included in the provided
    * configuration entry will be assigned server-wide default values.
    *
-   * @param  configEntry  The configuration entry with the information to use to
+   * @param  configuration  The configuration with the information to use to
    *                      initialize this password policy.
    *
    * @throws  ConfigException  If the provided entry does not contain a valid
@@ -232,7 +227,7 @@
    *                                   password policy that is not related to
    *                                   the server configuration.
    */
-  public PasswordPolicy(ConfigEntry configEntry)
+  public PasswordPolicy(PasswordPolicyCfg configuration)
          throws ConfigException, InitializationException
   {
     // Create a list of units and values that we can use to represent time
@@ -250,19 +245,15 @@
     timeUnits.put(TIME_UNIT_WEEKS_FULL, (double) (60 * 60 * 24 * 7));
 
 
-    this.configEntryDN = configEntry.getDN();
+    this.configEntryDN = configuration.dn();
+    int msgID;
 
     // Get the password attribute.  If specified, it must have either the
     // user password or auth password syntax.
-    int msgID = MSGID_PWPOLICY_DESCRIPTION_PW_ATTR;
-    StringConfigAttribute pwAttrStub =
-         new StringConfigAttribute(ATTR_PWPOLICY_PASSWORD_ATTRIBUTE,
-                                   getMessage(msgID), false, false, false);
+    String passwordAttr = configuration.getPasswordAttribute();
     try
     {
-      StringConfigAttribute pwAttrAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(pwAttrStub);
-      if (pwAttrAttr == null)
+      if (passwordAttr == null)
       {
         this.passwordAttribute  = null;
         this.authPasswordSyntax = false;
@@ -273,13 +264,13 @@
       }
       else
       {
-        String lowerName = toLowerCase(pwAttrAttr.pendingValue());
+        String lowerName = toLowerCase(passwordAttr);
         AttributeType pwAttrType = DirectoryServer.getAttributeType(lowerName);
         if (pwAttrType == null)
         {
           msgID = MSGID_PWPOLICY_UNDEFINED_PASSWORD_ATTRIBUTE;
           String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                String.valueOf(pwAttrAttr.pendingValue()));
+                                String.valueOf(passwordAttr));
           throw new ConfigException(msgID, message);
         }
 
@@ -304,7 +295,7 @@
 
           msgID = MSGID_PWPOLICY_INVALID_PASSWORD_ATTRIBUTE_SYNTAX;
           String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                      String.valueOf(pwAttrAttr.pendingValue()),
+                                      String.valueOf(passwordAttr),
                                       String.valueOf(syntax));
           throw new ConfigException(msgID, message);
         }
@@ -330,16 +321,11 @@
 
     // Get the default storage schemes.  They must all reference valid storage
     // schemes that support the syntax for the specified password attribute.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_DEFAULT_STORAGE_SCHEMES;
-    StringConfigAttribute defaultSchemeStub =
-           new StringConfigAttribute(ATTR_PWPOLICY_DEFAULT_SCHEME,
-                                     getMessage(msgID), false, true, false);
+    SortedSet<String> storageSchemes =
+      configuration.getDefaultPasswordStorageScheme();
     try
     {
-      StringConfigAttribute defaultSchemeAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(defaultSchemeStub);
-      if (defaultSchemeAttr == null)
+      if (storageSchemes == null)
       {
         msgID = MSGID_PWPOLICY_NO_DEFAULT_STORAGE_SCHEMES;
         String message = getMessage(msgID, String.valueOf(configEntryDN));
@@ -349,7 +335,7 @@
       {
         LinkedList<PasswordStorageScheme> schemes =
              new LinkedList<PasswordStorageScheme>();
-        for (String schemeName : defaultSchemeAttr.pendingValues())
+        for (String schemeName : storageSchemes)
         {
           PasswordStorageScheme scheme;
           if (this.authPasswordSyntax)
@@ -398,20 +384,14 @@
 
 
     // Get the names of the deprecated storage schemes.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_DEPRECATED_STORAGE_SCHEMES;
-    StringConfigAttribute deprecatedSchemeStub =
-         new StringConfigAttribute(ATTR_PWPOLICY_DEPRECATED_SCHEME,
-                                   getMessage(msgID), false, true, false);
+    SortedSet<String> deprecatedStorageSchemes =
+      configuration.getDeprecatedPasswordStorageScheme();
     try
     {
-      StringConfigAttribute deprecatedSchemeAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(deprecatedSchemeStub);
-      if (deprecatedSchemeAttr != null)
+      if (deprecatedStorageSchemes != null)
       {
         this.deprecatedStorageSchemes =
-             new CopyOnWriteArraySet<String>(
-                      deprecatedSchemeAttr.pendingValues());
+             new CopyOnWriteArraySet<String>(deprecatedStorageSchemes);
       }
     }
     catch (Exception e)
@@ -429,15 +409,11 @@
 
 
     // Get the password validators.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_PASSWORD_VALIDATORS;
-    DNConfigAttribute validatorStub =
-         new DNConfigAttribute(ATTR_PWPOLICY_PASSWORD_VALIDATOR,
-                               getMessage(msgID), false, true, false);
+    SortedSet<DN> passwordValidators =
+      configuration.getPasswordValidatorDN();
     try
     {
-      DNConfigAttribute validatorAttr =
-           (DNConfigAttribute) configEntry.getConfigAttribute(validatorStub);
-      if (validatorAttr != null)
+      if (passwordValidators != null)
       {
         ConcurrentHashMap<DN,
              PasswordValidator<? extends PasswordValidatorCfg>>
@@ -445,7 +421,7 @@
                   new ConcurrentHashMap<DN,
                        PasswordValidator<? extends
                             PasswordValidatorCfg>>();
-        for (DN validatorDN : validatorAttr.pendingValues())
+        for (DN validatorDN : passwordValidators)
         {
           PasswordValidator<? extends PasswordValidatorCfg>
                validator = DirectoryServer.getPasswordValidator(validatorDN);
@@ -482,19 +458,15 @@
 
 
     // Get the status notification handlers.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_NOTIFICATION_HANDLERS;
-    DNConfigAttribute notificationStub =
-         new DNConfigAttribute(ATTR_PWPOLICY_NOTIFICATION_HANDLER,
-                               getMessage(msgID), false, true, false);
+    SortedSet<DN> statusNotificationHandlers =
+      configuration.getAccountStatusNotificationHandlerDN();
     try
     {
-      DNConfigAttribute notificationAttr =
-           (DNConfigAttribute) configEntry.getConfigAttribute(notificationStub);
-      if (notificationAttr != null)
+      if (statusNotificationHandlers != null)
       {
         ConcurrentHashMap<DN,AccountStatusNotificationHandler> handlers =
              new ConcurrentHashMap<DN,AccountStatusNotificationHandler>();
-        for (DN handlerDN : notificationAttr.pendingValues())
+        for (DN handlerDN : statusNotificationHandlers)
         {
           AccountStatusNotificationHandler handler =
                DirectoryServer.getAccountStatusNotificationHandler(handlerDN);
@@ -531,173 +503,39 @@
 
 
     // Determine whether to allow user password changes.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_ALLOW_USER_PW_CHANGES;
-    BooleanConfigAttribute userChangeStub =
-         new BooleanConfigAttribute(ATTR_PWPOLICY_ALLOW_USER_CHANGE,
-                                    getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute userChangeAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(userChangeStub);
-      if (userChangeAttr != null)
-      {
-        this.allowUserPasswordChanges = userChangeAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_ALLOW_USER_PW_CHANGES;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.allowUserPasswordChanges = configuration.isAllowUserPasswordChanges();
 
     // Determine whether to require the current password for user changes.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_REQUIRE_CURRENT_PW;
-    BooleanConfigAttribute requirePWStub =
-         new BooleanConfigAttribute(ATTR_PWPOLICY_REQUIRE_CURRENT_PASSWORD,
-                                    getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute requirePWAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(requirePWStub);
-      if (requirePWAttr != null)
-      {
-        this.requireCurrentPassword = requirePWAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_REQUIRE_CURRENT_PW;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.requireCurrentPassword =
+      configuration.isPasswordChangeRequiresCurrentPassword();
 
     // Determine whether to force password changes on add.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_FORCE_CHANGE_ON_ADD;
-    BooleanConfigAttribute forceChangeOnAddStub =
-         new BooleanConfigAttribute(ATTR_PWPOLICY_FORCE_CHANGE_ON_ADD,
-                                    getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute forceChangeOnAddAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(forceChangeOnAddStub);
-      if (forceChangeOnAddAttr != null)
-      {
-        this.forceChangeOnAdd = forceChangeOnAddAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_FORCE_CHANGE_ON_ADD;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.forceChangeOnAdd = configuration.isForceChangeOnAdd();
 
     // Determine whether to force password changes on reset.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_FORCE_CHANGE_ON_RESET;
-    BooleanConfigAttribute forceChangeOnResetStub =
-      new BooleanConfigAttribute(ATTR_PWPOLICY_FORCE_CHANGE_ON_RESET,
-                                 getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute forceChangeAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(forceChangeOnResetStub);
-      if (forceChangeAttr != null)
-      {
-        this.forceChangeOnReset = forceChangeAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_FORCE_CHANGE_ON_RESET;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.forceChangeOnReset = configuration.isForceChangeOnReset();
 
     // Determine whether to validate reset passwords.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_SKIP_ADMIN_VALIDATION;
-    BooleanConfigAttribute validateResetStub =
-         new BooleanConfigAttribute(ATTR_PWPOLICY_SKIP_ADMIN_VALIDATION,
-                                    getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute validateResetAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(validateResetStub);
-      if (validateResetAttr != null)
-      {
-        this.skipValidationForAdministrators =
-             validateResetAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_SKIP_ADMIN_VALIDATION;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.skipValidationForAdministrators =
+      configuration.isSkipValidationForAdministrators();
 
     // Get the password generator.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_PASSWORD_GENERATOR;
-    DNConfigAttribute generatorStub =
-         new DNConfigAttribute(ATTR_PWPOLICY_PASSWORD_GENERATOR,
-                               getMessage(msgID), false, false, false);
+    DN passGenDN = configuration.getPasswordGeneratorDN() ;
     try
     {
-      DNConfigAttribute generatorAttr =
-           (DNConfigAttribute) configEntry.getConfigAttribute(generatorStub);
-      if (generatorAttr != null)
+      if (passGenDN != null)
       {
         PasswordGenerator generator =
-             DirectoryServer.getPasswordGenerator(generatorAttr.pendingValue());
+             DirectoryServer.getPasswordGenerator(passGenDN);
         if (generator == null)
         {
           msgID = MSGID_PWPOLICY_NO_SUCH_GENERATOR;
           String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                String.valueOf(generatorAttr.pendingValue()));
+                                String.valueOf(passGenDN));
           throw new ConfigException(msgID, message);
         }
 
-        this.passwordGeneratorDN = generatorAttr.pendingValue();
+        this.passwordGeneratorDN = passGenDN;
         this.passwordGenerator   = generator;
       }
     }
@@ -720,272 +558,37 @@
 
 
     // Determine whether to require secure authentication.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_REQUIRE_SECURE_AUTH;
-    BooleanConfigAttribute secureAuthStub =
-         new BooleanConfigAttribute(ATTR_PWPOLICY_REQUIRE_SECURE_AUTHENTICATION,
-                                    getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute secureAuthAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(secureAuthStub);
-      if (secureAuthAttr != null)
-      {
-        this.requireSecureAuthentication = secureAuthAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_REQUIRE_SECURE_AUTH;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.requireSecureAuthentication =
+      configuration.isRequireSecureAuthentication();
 
     // Determine whether to require secure password changes.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_REQUIRE_SECURE_CHANGES;
-    BooleanConfigAttribute secureChangeStub =
-         new BooleanConfigAttribute(
-                  ATTR_PWPOLICY_REQUIRE_SECURE_PASSWORD_CHANGES,
-                  getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute secureChangeAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(secureChangeStub);
-      if (secureChangeAttr != null)
-      {
-        this.requireSecurePasswordChanges = secureChangeAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_REQUIRE_SECURE_CHANGES;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.requireSecurePasswordChanges =
+      configuration.isRequireSecurePasswordChanges() ;
 
     // Determine whether to allow multiple password values.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_ALLOW_MULTIPLE_PW_VALUES;
-    BooleanConfigAttribute allowMultiplePWStub =
-         new BooleanConfigAttribute(ATTR_PWPOLICY_ALLOW_MULTIPLE_PW_VALUES,
-                                    getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute allowMultiplePWAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(allowMultiplePWStub);
-      if (allowMultiplePWAttr != null)
-      {
-        this.allowMultiplePasswordValues = allowMultiplePWAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_ALLOW_MULTIPLE_PW_VALUES;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.allowMultiplePasswordValues =
+      configuration.isAllowMultiplePasswordValues();
 
     // Determine whether to allow pre-encoded passwords.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_ALLOW_PREENCODED;
-    BooleanConfigAttribute preEncodedStub =
-         new BooleanConfigAttribute(ATTR_PWPOLICY_ALLOW_PRE_ENCODED_PASSWORDS,
-                                    getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute preEncodedAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(preEncodedStub);
-      if (preEncodedAttr != null)
-      {
-        this.allowPreEncodedPasswords = preEncodedAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_ALLOW_PREENCODED;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.allowPreEncodedPasswords = configuration.isAllowPreEncodedPasswords();
 
     // Get the minimum password age.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_MIN_AGE;
-    IntegerWithUnitConfigAttribute minAgeStub =
-         new IntegerWithUnitConfigAttribute(ATTR_PWPOLICY_MINIMUM_PASSWORD_AGE,
-                                            getMessage(msgID), false, timeUnits,
-                                            true, 0, true, Integer.MAX_VALUE);
-    try
-    {
-      IntegerWithUnitConfigAttribute minAgeAttr =
-           (IntegerWithUnitConfigAttribute)
-           configEntry.getConfigAttribute(minAgeStub);
-      if (minAgeAttr != null)
-      {
-        this.minimumPasswordAge = (int) minAgeAttr.pendingCalculatedValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_MIN_AGE;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.minimumPasswordAge = (int) configuration.getMinimumPasswordAge();
 
     // Get the maximum password age.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_MAX_AGE;
-    IntegerWithUnitConfigAttribute maxAgeStub =
-         new IntegerWithUnitConfigAttribute(ATTR_PWPOLICY_MAXIMUM_PASSWORD_AGE,
-                                            getMessage(msgID), false, timeUnits,
-                                            true, 0, true, Integer.MAX_VALUE);
-    try
-    {
-      IntegerWithUnitConfigAttribute maxAgeAttr =
-           (IntegerWithUnitConfigAttribute)
-           configEntry.getConfigAttribute(maxAgeStub);
-      if (maxAgeAttr != null)
-      {
-        this.maximumPasswordAge = (int) maxAgeAttr.pendingCalculatedValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_MAX_AGE;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.maximumPasswordAge = (int) configuration.getMaximumPasswordAge();
 
     // Get the maximum password reset age.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_MAX_RESET_AGE;
-    IntegerWithUnitConfigAttribute maxResetStub =
-         new IntegerWithUnitConfigAttribute(
-                  ATTR_PWPOLICY_MAXIMUM_PASSWORD_RESET_AGE, getMessage(msgID),
-                  false, timeUnits, true, 0, true, Integer.MAX_VALUE);
-    try
-    {
-      IntegerWithUnitConfigAttribute maxResetAttr =
-           (IntegerWithUnitConfigAttribute)
-           configEntry.getConfigAttribute(maxResetStub);
-      if (maxResetAttr != null)
-      {
-        this.maximumPasswordResetAge =
-             (int) maxResetAttr.pendingCalculatedValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_MAX_RESET_AGE;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.maximumPasswordResetAge = (int) configuration
+        .getMaximumPasswordResetAge();
 
     // Get the warning interval.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_WARNING_INTERVAL;
-    IntegerWithUnitConfigAttribute warningStub =
-         new IntegerWithUnitConfigAttribute(ATTR_PWPOLICY_WARNING_INTERVAL,
-                                            getMessage(msgID), false, timeUnits,
-                                            true, 0, true, Integer.MAX_VALUE);
-    try
-    {
-      IntegerWithUnitConfigAttribute warningAttr =
-           (IntegerWithUnitConfigAttribute)
-           configEntry.getConfigAttribute(warningStub);
-      if (warningAttr != null)
-      {
-        this.warningInterval = (int) warningAttr.pendingCalculatedValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_WARNING_INTERVAL;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.warningInterval = (int) configuration
+        .getPasswordExpirationWarningInterval();
 
     // Determine whether to expire passwords without warning.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_EXPIRE_WITHOUT_WARNING;
-    BooleanConfigAttribute expireWithoutWarningStub =
-         new BooleanConfigAttribute(ATTR_PWPOLICY_EXPIRE_WITHOUT_WARNING,
-                                    getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute expireWithoutWarningAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(expireWithoutWarningStub);
-      if (expireWithoutWarningAttr != null)
-      {
-        this.expirePasswordsWithoutWarning =
-             expireWithoutWarningAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_EXPIRE_WITHOUT_WARNING;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.expirePasswordsWithoutWarning = configuration
+        .isExpirePasswordsWithoutWarning();
 
     // If the expire without warning option is disabled, then there must be a
     // warning interval.
@@ -997,173 +600,30 @@
       throw new ConfigException(msgID, message);
     }
 
-
     // Determine whether to allow user changes for expired passwords.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_ALLOW_EXPIRED_CHANGES;
-    BooleanConfigAttribute allowExpiredChangesStub =
-         new BooleanConfigAttribute(ATTR_PWPOLICY_ALLOW_EXPIRED_CHANGES,
-                                    getMessage(msgID), false);
-    try
-    {
-      BooleanConfigAttribute allowExpiredChangesAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(allowExpiredChangesStub);
-      if (allowExpiredChangesAttr != null)
-      {
-        this.allowExpiredPasswordChanges =
-             allowExpiredChangesAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_ALLOW_EXPIRED_CHANGES;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.allowExpiredPasswordChanges = configuration
+        .isAllowExpiredPasswordChanges();
 
     // Get the grace login count.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_GRACE_LOGIN_COUNT;
-    IntegerConfigAttribute graceStub =
-         new IntegerConfigAttribute(ATTR_PWPOLICY_GRACE_LOGIN_COUNT,
-                                    getMessage(msgID), false, false, false,
-                                    true, 0, true, Integer.MAX_VALUE);
-    try
-    {
-      IntegerConfigAttribute graceAttr =
-           (IntegerConfigAttribute) configEntry.getConfigAttribute(graceStub);
-      if (graceAttr != null)
-      {
-        this.graceLoginCount = graceAttr.pendingIntValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_GRACE_LOGIN_COUNT;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.graceLoginCount = configuration.getGraceLoginCount();
 
     // Get the lockout failure count.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_LOCKOUT_FAILURE_COUNT;
-    IntegerConfigAttribute failureCountStub =
-         new IntegerConfigAttribute(ATTR_PWPOLICY_LOCKOUT_FAILURE_COUNT,
-                                    getMessage(msgID), false, false, false,
-                                    true, 0, true, Integer.MAX_VALUE);
-    try
-    {
-      IntegerConfigAttribute failureCountAttr =
-           (IntegerConfigAttribute)
-           configEntry.getConfigAttribute(failureCountStub);
-      if (failureCountAttr != null)
-      {
-        this.lockoutFailureCount = failureCountAttr.pendingIntValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_LOCKOUT_FAILURE_COUNT;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.lockoutFailureCount = configuration.getLockoutFailureCount();
 
     // Get the lockout duration.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_LOCKOUT_DURATION;
-    IntegerWithUnitConfigAttribute lockoutDurationStub =
-         new IntegerWithUnitConfigAttribute(ATTR_PWPOLICY_LOCKOUT_DURATION,
-                                            getMessage(msgID), false, timeUnits,
-                                            true, 0, true, Integer.MAX_VALUE);
-    try
-    {
-      IntegerWithUnitConfigAttribute lockoutDurationAttr =
-           (IntegerWithUnitConfigAttribute)
-           configEntry.getConfigAttribute(lockoutDurationStub);
-      if (lockoutDurationAttr != null)
-      {
-        this.lockoutDuration =
-             (int) lockoutDurationAttr.pendingCalculatedValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_LOCKOUT_DURATION;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.lockoutDuration = (int) configuration.getLockoutDuration();
 
     // Get the lockout failure expiration interval.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_FAILURE_EXPIRATION;
-    IntegerWithUnitConfigAttribute failureExpirationStub =
-         new IntegerWithUnitConfigAttribute(
-                  ATTR_PWPOLICY_LOCKOUT_FAILURE_EXPIRATION_INTERVAL,
-                  getMessage(msgID), false, timeUnits, true, 0, true,
-                  Integer.MAX_VALUE);
-    try
-    {
-      IntegerWithUnitConfigAttribute failureExpirationAttr =
-           (IntegerWithUnitConfigAttribute)
-           configEntry.getConfigAttribute(failureExpirationStub);
-      if (failureExpirationAttr != null)
-      {
-        this.lockoutFailureExpirationInterval =
-             (int) failureExpirationAttr.pendingCalculatedValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_FAILURE_EXPIRATION;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.lockoutFailureExpirationInterval = (int) configuration
+        .getLockoutFailureExpirationInterval();
 
     // Get the required change time.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_REQUIRE_CHANGE_BY_TIME;
-    StringConfigAttribute requireChangeByStub =
-         new StringConfigAttribute(ATTR_PWPOLICY_REQUIRE_CHANGE_BY_TIME,
-                                   getMessage(msgID), false, false, false);
+    String requireChangeBy = configuration.getRequireChangeByTime();
     try
     {
-      StringConfigAttribute requireChangeByAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(requireChangeByStub);
-      if (requireChangeByAttr != null)
+      if (requireChangeBy != null)
       {
-        ByteString valueString = new
-             ASN1OctetString(requireChangeByAttr.pendingValue());
+        ByteString valueString = new ASN1OctetString(requireChangeBy);
 
         GeneralizedTimeSyntax syntax =
              (GeneralizedTimeSyntax)
@@ -1202,25 +662,19 @@
     // the server schema.  It does not need to have a generalized time syntax
     // because the value that it will store will not necessarily conform to this
     // format.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_LAST_LOGIN_TIME_ATTR;
-    StringConfigAttribute lastLoginAttrStub =
-         new StringConfigAttribute(ATTR_PWPOLICY_LAST_LOGIN_TIME_ATTRIBUTE,
-                                   getMessage(msgID), false, false, false);
+    String lastLoginTimeAtt = configuration.getLastLoginTimeAttribute();
     try
     {
-      StringConfigAttribute lastLoginAttrAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(lastLoginAttrStub);
-      if (lastLoginAttrAttr != null)
+      if (lastLoginTimeAtt != null)
       {
-        String lowerName = toLowerCase(lastLoginAttrAttr.pendingValue());
+        String lowerName = toLowerCase(lastLoginTimeAtt);
         AttributeType attrType = DirectoryServer.getAttributeType(lowerName);
         if (attrType == null)
         {
           msgID = MSGID_PWPOLICY_UNDEFINED_LAST_LOGIN_TIME_ATTRIBUTE;
           String message =
                getMessage(msgID, String.valueOf(configEntryDN),
-                          String.valueOf(lastLoginAttrAttr.pendingValue()));
+                          String.valueOf(lastLoginTimeAtt));
           throw new ConfigException(msgID, message);
         }
 
@@ -1246,19 +700,11 @@
 
     // Get the last login time format.  If specified, it must be a valid format
     // string.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_LAST_LOGIN_TIME_FORMAT;
-    StringConfigAttribute lastLoginFormatStub =
-         new StringConfigAttribute(ATTR_PWPOLICY_LAST_LOGIN_TIME_FORMAT,
-                                   getMessage(msgID), false, false, false);
+    String formatString = configuration.getLastLoginTimeFormat();
     try
     {
-      StringConfigAttribute lastLoginFormatAttr =
-           (StringConfigAttribute)
-           configEntry.getConfigAttribute(lastLoginFormatStub);
-      if (lastLoginFormatAttr != null)
+      if (formatString != null)
       {
-        String formatString = lastLoginFormatAttr.pendingValue();
-
         try
         {
           new SimpleDateFormat(formatString);
@@ -1299,19 +745,12 @@
 
     // Get the previous last login time formats.  If specified, they must all
     // be valid format strings.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_PREVIOUS_LAST_LOGIN_TIME_FORMAT;
-    StringConfigAttribute previousFormatStub =
-         new StringConfigAttribute(
-                  ATTR_PWPOLICY_PREVIOUS_LAST_LOGIN_TIME_FORMAT,
-                  getMessage(msgID), false, true, false);
+    SortedSet<String> formatStrings =
+      configuration.getPreviousLastLoginTimeFormat() ;
     try
     {
-      StringConfigAttribute previousFormatAttr =
-             (StringConfigAttribute)
-             configEntry.getConfigAttribute(previousFormatStub);
-      if (previousFormatAttr != null)
+      if (formatStrings != null)
       {
-        List<String> formatStrings = previousFormatAttr.pendingValues();
         for (String s : formatStrings)
         {
           try
@@ -1355,35 +794,7 @@
 
 
     // Get the idle lockout duration.
-    msgID = MSGID_PWPOLICY_DESCRIPTION_IDLE_LOCKOUT_INTERVAL;
-    IntegerWithUnitConfigAttribute idleIntervalStub =
-         new IntegerWithUnitConfigAttribute(ATTR_PWPOLICY_IDLE_LOCKOUT_INTERVAL,
-                                            getMessage(msgID), false, timeUnits,
-                                            true, 0, true, Integer.MAX_VALUE);
-    try
-    {
-      IntegerWithUnitConfigAttribute idleIntervalAttr =
-           (IntegerWithUnitConfigAttribute)
-           configEntry.getConfigAttribute(idleIntervalStub);
-      if (idleIntervalAttr != null)
-      {
-        this.idleLockoutInterval =
-             (int) idleIntervalAttr.pendingCalculatedValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_IDLE_LOCKOUT_INTERVAL;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
+    this.idleLockoutInterval = (int) configuration.getIdleLockoutInterval();
 
     /*
      *  Holistic validation.
diff --git a/opends/src/server/org/opends/server/core/PasswordPolicyConfig.java b/opends/src/server/org/opends/server/core/PasswordPolicyConfig.java
index 46c66e9..febcd4f 100644
--- a/opends/src/server/org/opends/server/core/PasswordPolicyConfig.java
+++ b/opends/src/server/org/opends/server/core/PasswordPolicyConfig.java
@@ -27,33 +27,20 @@
 package org.opends.server.core;
 
 import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
 import java.util.List;
 
-import org.opends.server.api.ConfigurableComponent;
-import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.config.BooleanConfigAttribute;
-import org.opends.server.config.ConfigAttribute;
-import org.opends.server.config.ConfigEntry;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.server.PasswordPolicyCfg;
 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.StringConfigAttribute;
-import org.opends.server.schema.GeneralizedTimeSyntax;
 import org.opends.server.types.ConfigChangeResult;
-import org.opends.server.types.DN;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.ResultCode;
 
-import static org.opends.server.config.ConfigConstants.*;
 import static org.opends.server.loggers.debug.DebugLogger.debugCaught;
 import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
 import org.opends.server.types.DebugLogLevel;
 import static org.opends.server.messages.CoreMessages.*;
 import static org.opends.server.messages.MessageHandler.getMessage;
-import static org.opends.server.util.ServerConstants.*;
 
 /**
  This class is the interface between the password policy configurable component
@@ -63,7 +50,7 @@
  valiadating any proposed modification and applying an accepted modification.
  */
 public class PasswordPolicyConfig
-        implements ConfigurableComponent
+        implements ConfigurationChangeListener<PasswordPolicyCfg>
 {
 
   /**
@@ -85,325 +72,22 @@
   public PasswordPolicyConfig(PasswordPolicy policy)
   {
     this.currentPolicy = policy;
-    DirectoryServer.registerConfigurableComponent(this);
   }
 
 
-
   /**
-   * Finalize a password policy configuration handler.
+   * {@inheritDoc}
    */
-  public void finalizePasswordPolicyConfig()
+  public boolean isConfigurationChangeAcceptable(
+      PasswordPolicyCfg configuration, List<String> unacceptableReasons)
   {
-    DirectoryServer.deregisterConfigurableComponent(this);
-  }
-
-
-
-  /**
-   * Retrieves the DN of the configuration entry with which this component is
-   * associated.
-   *
-   * @return  The DN of the configuration entry with which this component is
-   *          associated.
-   */
-  public DN getConfigurableComponentEntryDN()
-  {
-    return currentPolicy.getConfigEntryDN();
-  }
-
-
-
-  /**
-   * Retrieves the set of configuration attributes that are associated with this
-   * configurable component.
-   *
-   * @return  The set of configuration attributes that are associated with this
-   *          configurable component.
-   */
-  public List<ConfigAttribute> getConfigurationAttributes()
-  {
-    // Create a list of units and values that we can use to represent time
-    // periods.
-    LinkedHashMap<String,Double> timeUnits = new LinkedHashMap<String,Double>();
-    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));
-
-
-    PasswordPolicy policy = this.currentPolicy; // this field is volatile
-
-    LinkedList<ConfigAttribute> attrList = new LinkedList<ConfigAttribute>();
-
-    int msgID = MSGID_PWPOLICY_DESCRIPTION_PW_ATTR;
-    String pwAttr = (policy.getPasswordAttribute() == null)
-                    ? null
-                    : policy.getPasswordAttribute().getNameOrOID();
-    attrList.add(new StringConfigAttribute(ATTR_PWPOLICY_PASSWORD_ATTRIBUTE,
-                                           getMessage(msgID), false, false,
-                                           false, pwAttr));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_DEFAULT_STORAGE_SCHEMES;
-    ArrayList<String> schemes = new ArrayList<String>();
-    for (PasswordStorageScheme s : policy.getDefaultStorageSchemes())
-    {
-      schemes.add(s.getStorageSchemeName());
-    }
-    attrList.add(new StringConfigAttribute(ATTR_PWPOLICY_DEFAULT_SCHEME,
-                                           getMessage(msgID), false, true,
-                                           false, schemes));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_DEPRECATED_STORAGE_SCHEMES;
-    ArrayList<String> deprecatedSchemes = new ArrayList<String>();
-    deprecatedSchemes.addAll(policy.getDeprecatedStorageSchemes());
-    attrList.add(new StringConfigAttribute(ATTR_PWPOLICY_DEPRECATED_SCHEME,
-                                           getMessage(msgID), false, true,
-                                           false, deprecatedSchemes));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_PASSWORD_VALIDATORS;
-    ArrayList<DN> validatorDNs = new ArrayList<DN>();
-    validatorDNs.addAll(policy.getPasswordValidators().keySet());
-    attrList.add(new DNConfigAttribute(ATTR_PWPOLICY_PASSWORD_VALIDATOR,
-                                       getMessage(msgID), false, true, false,
-                                       validatorDNs));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_NOTIFICATION_HANDLERS;
-    ArrayList<DN> handlerDNs = new ArrayList<DN>();
-    handlerDNs.addAll(policy.getAccountStatusNotificationHandlers().keySet());
-    attrList.add(new DNConfigAttribute(ATTR_PWPOLICY_NOTIFICATION_HANDLER,
-                                       getMessage(msgID), false, true, false,
-                                       handlerDNs));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_ALLOW_USER_PW_CHANGES;
-    attrList.add(new BooleanConfigAttribute(ATTR_PWPOLICY_ALLOW_USER_CHANGE,
-                                            getMessage(msgID), false,
-                                            policy.allowUserPasswordChanges()));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_REQUIRE_CURRENT_PW;
-    attrList.add(new BooleanConfigAttribute(
-                             ATTR_PWPOLICY_REQUIRE_CURRENT_PASSWORD,
-                             getMessage(msgID), false,
-                             policy.requireCurrentPassword()));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_FORCE_CHANGE_ON_ADD;
-    attrList.add(new BooleanConfigAttribute(ATTR_PWPOLICY_FORCE_CHANGE_ON_ADD,
-                                            getMessage(msgID), false,
-                                            policy.forceChangeOnAdd()));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_FORCE_CHANGE_ON_RESET;
-    attrList.add(new BooleanConfigAttribute(ATTR_PWPOLICY_FORCE_CHANGE_ON_RESET,
-                                            getMessage(msgID), false,
-                                            policy.forceChangeOnReset()));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_SKIP_ADMIN_VALIDATION;
-    attrList.add(new BooleanConfigAttribute(
-                             ATTR_PWPOLICY_SKIP_ADMIN_VALIDATION,
-                             getMessage(msgID), false,
-                             policy.skipValidationForAdministrators()));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_PASSWORD_GENERATOR;
-    attrList.add(new DNConfigAttribute(ATTR_PWPOLICY_PASSWORD_GENERATOR,
-                                       getMessage(msgID), false, false, false,
-                                       policy.getPasswordGeneratorDN()));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_REQUIRE_SECURE_AUTH;
-    attrList.add(new BooleanConfigAttribute(
-                             ATTR_PWPOLICY_REQUIRE_SECURE_AUTHENTICATION,
-                             getMessage(msgID), false,
-                             policy.requireSecureAuthentication()));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_REQUIRE_SECURE_CHANGES;
-    attrList.add(new BooleanConfigAttribute(
-                             ATTR_PWPOLICY_REQUIRE_SECURE_PASSWORD_CHANGES,
-                             getMessage(msgID), false,
-                             policy.requireSecurePasswordChanges()));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_ALLOW_MULTIPLE_PW_VALUES;
-    attrList.add(new BooleanConfigAttribute(
-                             ATTR_PWPOLICY_ALLOW_MULTIPLE_PW_VALUES,
-                             getMessage(msgID), false,
-                             policy.allowMultiplePasswordValues()));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_ALLOW_PREENCODED;
-    attrList.add(new BooleanConfigAttribute(
-                             ATTR_PWPOLICY_ALLOW_PRE_ENCODED_PASSWORDS,
-                             getMessage(msgID), false,
-                             policy.allowPreEncodedPasswords()));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_MIN_AGE;
-    attrList.add(new IntegerWithUnitConfigAttribute(
-                          ATTR_PWPOLICY_MINIMUM_PASSWORD_AGE,
-                          getMessage(msgID), false, timeUnits, true, 0, true,
-                          Integer.MAX_VALUE, policy.getMinimumPasswordAge(),
-                          TIME_UNIT_SECONDS_FULL));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_MAX_AGE;
-    attrList.add(new IntegerWithUnitConfigAttribute(
-                          ATTR_PWPOLICY_MAXIMUM_PASSWORD_AGE,
-                          getMessage(msgID), false, timeUnits, true, 0, true,
-                          Integer.MAX_VALUE, policy.getMaximumPasswordAge(),
-                          TIME_UNIT_SECONDS_FULL));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_MAX_RESET_AGE;
-    attrList.add(new IntegerWithUnitConfigAttribute(
-                          ATTR_PWPOLICY_MAXIMUM_PASSWORD_RESET_AGE,
-                          getMessage(msgID), false, timeUnits, true, 0, true,
-                          Integer.MAX_VALUE,
-                          policy.getMaximumPasswordResetAge(),
-                          TIME_UNIT_SECONDS_FULL));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_WARNING_INTERVAL;
-    attrList.add(new IntegerWithUnitConfigAttribute(
-                          ATTR_PWPOLICY_WARNING_INTERVAL, getMessage(msgID),
-                          false, timeUnits, true, 0, true, Integer.MAX_VALUE,
-                          policy.getWarningInterval(), TIME_UNIT_SECONDS_FULL));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_EXPIRE_WITHOUT_WARNING;
-    attrList.add(new BooleanConfigAttribute(
-                          ATTR_PWPOLICY_EXPIRE_WITHOUT_WARNING,
-                          getMessage(msgID), false,
-                          policy.expirePasswordsWithoutWarning()));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_ALLOW_EXPIRED_CHANGES;
-    attrList.add(new BooleanConfigAttribute(
-                          ATTR_PWPOLICY_ALLOW_EXPIRED_CHANGES,
-                          getMessage(msgID), false,
-                          policy.allowExpiredPasswordChanges()));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_GRACE_LOGIN_COUNT;
-    attrList.add(new IntegerConfigAttribute(ATTR_PWPOLICY_GRACE_LOGIN_COUNT,
-                                            getMessage(msgID), false, false,
-                                            false, true, 0, true,
-                                            Integer.MAX_VALUE,
-                                            policy.getGraceLoginCount()));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_LOCKOUT_FAILURE_COUNT;
-    attrList.add(new IntegerConfigAttribute(ATTR_PWPOLICY_LOCKOUT_FAILURE_COUNT,
-                                            getMessage(msgID), false, false,
-                                            false, true, 0, true,
-                                            Integer.MAX_VALUE,
-                                            policy.getLockoutFailureCount()));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_LOCKOUT_DURATION;
-    attrList.add(new IntegerWithUnitConfigAttribute(
-                          ATTR_PWPOLICY_LOCKOUT_DURATION, getMessage(msgID),
-                          false, timeUnits, true, 0, true, Integer.MAX_VALUE,
-                          policy.getLockoutDuration(), TIME_UNIT_SECONDS_FULL));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_FAILURE_EXPIRATION;
-    attrList.add(new IntegerWithUnitConfigAttribute(
-                          ATTR_PWPOLICY_LOCKOUT_FAILURE_EXPIRATION_INTERVAL,
-                          getMessage(msgID), false, timeUnits, true, 0, true,
-                          Integer.MAX_VALUE,
-                          policy.getLockoutFailureExpirationInterval(),
-                          TIME_UNIT_SECONDS_FULL));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_REQUIRE_CHANGE_BY_TIME;
-    String timeStr = null;
-    if (policy.getRequireChangeByTime() > 0)
-    {
-      timeStr = GeneralizedTimeSyntax.createGeneralizedTimeValue(
-                     policy.getRequireChangeByTime()).getStringValue();
-    }
-    attrList.add(new StringConfigAttribute(ATTR_PWPOLICY_REQUIRE_CHANGE_BY_TIME,
-                                           getMessage(msgID), false, false,
-                                           false, timeStr));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_LAST_LOGIN_TIME_ATTR;
-    String loginTimeAttr = (policy.getLastLoginTimeAttribute() == null)
-                           ? null
-                           : policy.getLastLoginTimeAttribute().getNameOrOID();
-    attrList.add(new StringConfigAttribute(
-                          ATTR_PWPOLICY_LAST_LOGIN_TIME_ATTRIBUTE,
-                          getMessage(msgID), false, false, false,
-                          loginTimeAttr));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_LAST_LOGIN_TIME_FORMAT;
-    attrList.add(new StringConfigAttribute(ATTR_PWPOLICY_LAST_LOGIN_TIME_FORMAT,
-                                           getMessage(msgID), false, false,
-                                           false,
-                                           policy.getLastLoginTimeFormat()));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_PREVIOUS_LAST_LOGIN_TIME_FORMAT;
-    ArrayList<String> previousFormats = new ArrayList<String>();
-    previousFormats.addAll(policy.getPreviousLastLoginTimeFormats());
-    attrList.add(new StringConfigAttribute(
-                          ATTR_PWPOLICY_PREVIOUS_LAST_LOGIN_TIME_FORMAT,
-                          getMessage(msgID), false, false, false,
-                          previousFormats));
-
-
-    msgID = MSGID_PWPOLICY_DESCRIPTION_IDLE_LOCKOUT_INTERVAL;
-    attrList.add(new IntegerWithUnitConfigAttribute(
-                          ATTR_PWPOLICY_IDLE_LOCKOUT_INTERVAL,
-                          getMessage(msgID), false, timeUnits, true, 0, true,
-                          Integer.MAX_VALUE,  policy.getIdleLockoutInterval(),
-                          TIME_UNIT_SECONDS_FULL));
-
-    return attrList;
-  }
-
-
-
-  /**
-   * 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)
-  {
-    assert configEntry.getDN().equals(this.currentPolicy.getConfigEntryDN() )
+    assert configuration.dn().equals(this.currentPolicy.getConfigEntryDN() )
             : "Internal Error: mismatch between DN of configuration entry and"
               + "DN of current password policy." ;
 
     try
     {
-      new PasswordPolicy(configEntry);
+      new PasswordPolicy(configuration);
     }
     catch (ConfigException ce)
     {
@@ -433,25 +117,12 @@
 
 
   /**
-   * 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.
+   * {@inheritDoc}
    */
-  public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry,
-                                                  boolean detailedResults)
+  public ConfigChangeResult applyConfigurationChange(
+      PasswordPolicyCfg configuration)
   {
-    assert configEntry.getDN().equals(this.currentPolicy.getConfigEntryDN() )
+    assert configuration.dn().equals(this.currentPolicy.getConfigEntryDN() )
             : "Internal Error: mismatch between DN of configuration entry and"
               + "DN of current password policy." ;
 
@@ -459,7 +130,7 @@
 
     try
     {
-      p = new PasswordPolicy(configEntry);
+      p = new PasswordPolicy(configuration);
     }
     catch (ConfigException ce)
     {
@@ -489,11 +160,8 @@
     // If we've made it here, then everything is acceptable.  Apply the new
     // configuration.
     ArrayList<String> messages = new ArrayList<String>();
-    if (detailedResults)
-    {
-      int msgID = MSGID_PWPOLICY_UPDATED_POLICY;
-      messages.add(getMessage(msgID, String.valueOf(p.getConfigEntryDN())));
-    }
+    int msgID = MSGID_PWPOLICY_UPDATED_POLICY;
+    messages.add(getMessage(msgID, String.valueOf(p.getConfigEntryDN())));
 
     this.currentPolicy = p;
 
@@ -501,7 +169,6 @@
                                   /*adminActionRequired*/ false, messages);
   }
 
-
   /**
    * Retrieves the PasswordPolicy object representing the configuration entry
    * managed by this object.
diff --git a/opends/src/server/org/opends/server/core/PasswordPolicyConfigManager.java b/opends/src/server/org/opends/server/core/PasswordPolicyConfigManager.java
index 4daab18..c966af0 100644
--- a/opends/src/server/org/opends/server/core/PasswordPolicyConfigManager.java
+++ b/opends/src/server/org/opends/server/core/PasswordPolicyConfigManager.java
@@ -29,20 +29,19 @@
 
 
 import java.util.ArrayList;
+import java.util.List;
 
-import org.opends.server.api.ConfigAddListener;
-import org.opends.server.api.ConfigDeleteListener;
-import org.opends.server.config.ConfigEntry;
+import org.opends.server.admin.server.ConfigurationAddListener;
+import org.opends.server.admin.server.ConfigurationDeleteListener;
+import org.opends.server.admin.server.ServerManagementContext;
+import org.opends.server.admin.std.server.PasswordPolicyCfg;
+import org.opends.server.admin.std.server.RootCfg;
 import org.opends.server.config.ConfigException;
 import org.opends.server.types.ConfigChangeResult;
 import org.opends.server.types.DN;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.ResultCode;
 
-import static org.opends.server.config.ConfigConstants.*;
-import static org.opends.server.loggers.debug.DebugLogger.debugCaught;
-import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
-import org.opends.server.types.DebugLogLevel;
 import static org.opends.server.messages.ConfigMessages.*;
 import static org.opends.server.messages.MessageHandler.*;
 import static org.opends.server.util.StaticUtils.*;
@@ -56,7 +55,8 @@
  * the server is running.
  */
 public class PasswordPolicyConfigManager
-       implements ConfigAddListener, ConfigDeleteListener
+       implements ConfigurationAddListener<PasswordPolicyCfg>,
+       ConfigurationDeleteListener<PasswordPolicyCfg>
 {
 
 
@@ -85,44 +85,23 @@
   public void initializePasswordPolicies()
          throws ConfigException, InitializationException
   {
+    // Get the root configuration object.
+    ServerManagementContext managementContext =
+         ServerManagementContext.getInstance();
+    RootCfg rootConfiguration =
+         managementContext.getRootConfiguration();
+
+    // Register as an add and delete listener with the root configuration so we
+    // can be notified if any password ploicies entries are added or removed.
+    rootConfiguration.addPasswordPolicyAddListener(this);
+    rootConfiguration.addPasswordPolicyDeleteListener(this);
+
     // First, get the configuration base entry.
-    ConfigEntry baseEntry;
-    try
-    {
-      DN policyBase = DN.decode(DN_PWPOLICY_CONFIG_BASE);
-      baseEntry = DirectoryServer.getConfigHandler().getConfigEntry(policyBase);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int    msgID   = MSGID_CONFIG_PWPOLICY_CANNOT_GET_BASE;
-      String message = getMessage(msgID, String.valueOf(e));
-      throw new ConfigException(msgID, message, e);
-    }
-
-    if (baseEntry == null)
-    {
-      // The password policy base entry does not exist.  This is not
-      // acceptable, so throw an exception.
-      int    msgID   = MSGID_CONFIG_PWPOLICY_BASE_DOES_NOT_EXIST;
-      String message = getMessage(msgID);
-      throw new ConfigException(msgID, message);
-    }
-
-
-    // Register add and delete listeners with the policy base entry.  We
-    // don't care about modifications to it.
-    baseEntry.registerAddListener(this);
-    baseEntry.registerDeleteListener(this);
-
+    String[] passwordPoliciesName = rootConfiguration.listPasswordPolicys() ;
 
     // See if the base entry has any children.  If not, then that means that
     // there are no policies defined, so that's a problem.
-    if (! baseEntry.hasChildren())
+    if (passwordPoliciesName.length == 0)
     {
       int    msgID   = MSGID_CONFIG_PWPOLICY_NO_POLICIES;
       String message = getMessage(msgID);
@@ -141,32 +120,39 @@
 
     // Iterate through the child entries and process them as password policy
     // configuration entries.
-    for (ConfigEntry childEntry : baseEntry.getChildren().values())
+    for (String passwordPolicyName : passwordPoliciesName)
     {
+      PasswordPolicyCfg passwordPolicyConfiguration =
+        rootConfiguration.getPasswordPolicy(passwordPolicyName);
+
       try
       {
-        PasswordPolicy policy = new PasswordPolicy(childEntry);
-        DirectoryServer.registerPasswordPolicy(childEntry.getDN(), policy);
+        PasswordPolicy policy = new PasswordPolicy(passwordPolicyConfiguration);
+        PasswordPolicyConfig config = new PasswordPolicyConfig(policy);
+        DirectoryServer.registerPasswordPolicy(
+            passwordPolicyConfiguration.dn(), config);
+        passwordPolicyConfiguration.addChangeListener(config);
       }
       catch (ConfigException ce)
       {
-        int    msgID   = MSGID_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG;
-        String message = getMessage(msgID, String.valueOf(childEntry.getDN()),
-                                    ce.getMessage());
+        int msgID = MSGID_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG;
+        String message = getMessage(msgID, String
+            .valueOf(passwordPolicyConfiguration.dn()), ce.getMessage());
         throw new ConfigException(msgID, message, ce);
       }
       catch (InitializationException ie)
       {
         int    msgID   = MSGID_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG;
-        String message = getMessage(msgID, String.valueOf(childEntry.getDN()),
-                                    ie.getMessage());
+        String message = getMessage(msgID, String
+            .valueOf(passwordPolicyConfiguration.dn()), ie.getMessage());
         throw new InitializationException(msgID, message, ie);
       }
       catch (Exception e)
       {
         int    msgID   = MSGID_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG;
-        String message = getMessage(msgID, String.valueOf(childEntry.getDN()),
-                                    stackTraceToSingleLineString(e));
+        String message = getMessage(msgID, String
+            .valueOf(passwordPolicyConfiguration.dn()),
+            stackTraceToSingleLineString(e));
         throw new InitializationException(msgID, message, e);
       }
     }
@@ -186,49 +172,39 @@
 
 
   /**
-   * Indicates whether the configuration entry that will result from a proposed
-   * add is acceptable to this add listener.
-   *
-   * @param  configEntry         The configuration entry that will result from
-   *                             the requested add.
-   * @param  unacceptableReason  A buffer to which this method can append a
-   *                             human-readable message explaining why the
-   *                             proposed entry is not acceptable.
-   *
-   * @return  <CODE>true</CODE> if the proposed entry contains an acceptable
-   *          configuration, or <CODE>false</CODE> if it does not.
+   * {@inheritDoc}
    */
-  public boolean configAddIsAcceptable(ConfigEntry configEntry,
-                                       StringBuilder unacceptableReason)
+  public boolean isConfigurationAddAcceptable(PasswordPolicyCfg configuration,
+                                       List<String> unacceptableReason)
   {
     // See if we can create a password policy from the provided configuration
     // entry.  If so, then it's acceptable.
     try
     {
-      new PasswordPolicy(configEntry);
+      new PasswordPolicy(configuration);
     }
     catch (ConfigException ce)
     {
       int    msgID   = MSGID_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG;
-      String message = getMessage(msgID, String.valueOf(configEntry.getDN()),
+      String message = getMessage(msgID, String.valueOf(configuration.dn()),
                                   ce.getMessage());
-      unacceptableReason.append(message);
+      unacceptableReason.add(message);
       return false;
     }
     catch (InitializationException ie)
     {
       int    msgID   = MSGID_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG;
-      String message = getMessage(msgID, String.valueOf(configEntry.getDN()),
+      String message = getMessage(msgID, String.valueOf(configuration.dn()),
                                   ie.getMessage());
-      unacceptableReason.append(message);
+      unacceptableReason.add(message);
       return false;
     }
     catch (Exception e)
     {
       int    msgID   = MSGID_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG;
-      String message = getMessage(msgID, String.valueOf(configEntry.getDN()),
+      String message = getMessage(msgID, String.valueOf(configuration.dn()),
                                   stackTraceToSingleLineString(e));
-      unacceptableReason.append(message);
+      unacceptableReason.add(message);
       return false;
     }
 
@@ -240,17 +216,12 @@
 
 
   /**
-   * Attempts to apply a new configuration based on the provided added entry.
-   *
-   * @param  configEntry  The new configuration entry that contains the
-   *                      configuration to apply.
-   *
-   * @return  Information about the result of processing the configuration
-   *          change.
+   * {@inheritDoc}
    */
-  public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry)
+  public ConfigChangeResult applyConfigurationAdd(
+      PasswordPolicyCfg configuration)
   {
-    DN                configEntryDN       = configEntry.getDN();
+    DN                configEntryDN       = configuration.dn();
     ArrayList<String> messages            = new ArrayList<String>();
 
 
@@ -258,14 +229,17 @@
     // entry.  If so, then register it with the Directory Server.
     try
     {
-      PasswordPolicy policy = new PasswordPolicy(configEntry);
-      DirectoryServer.registerPasswordPolicy(configEntryDN, policy);
+      PasswordPolicy policy = new PasswordPolicy(configuration);
+      PasswordPolicyConfig config = new PasswordPolicyConfig(policy);
+
+      DirectoryServer.registerPasswordPolicy(configEntryDN, config);
+      configuration.addChangeListener(config);
       return new ConfigChangeResult(ResultCode.SUCCESS, false, messages);
     }
     catch (ConfigException ce)
     {
       int msgID = MSGID_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG;
-      messages.add(getMessage(msgID, String.valueOf(configEntry.getDN()),
+      messages.add(getMessage(msgID, String.valueOf(configuration.dn()),
                               ce.getMessage()));
 
       return new ConfigChangeResult(ResultCode.CONSTRAINT_VIOLATION, false,
@@ -274,7 +248,7 @@
     catch (InitializationException ie)
     {
       int msgID = MSGID_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG;
-      messages.add(getMessage(msgID, String.valueOf(configEntry.getDN()),
+      messages.add(getMessage(msgID, String.valueOf(configuration.dn()),
                               ie.getMessage()));
 
       return new ConfigChangeResult(DirectoryServer.getServerErrorResultCode(),
@@ -283,7 +257,7 @@
     catch (Exception e)
     {
       int msgID = MSGID_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG;
-      messages.add(getMessage(msgID, String.valueOf(configEntry.getDN()),
+      messages.add(getMessage(msgID, String.valueOf(configuration.dn()),
                               stackTraceToSingleLineString(e)));
 
       return new ConfigChangeResult(DirectoryServer.getServerErrorResultCode(),
@@ -294,20 +268,10 @@
 
 
   /**
-   * Indicates whether it is acceptable to remove the provided configuration
-   * entry.
-   *
-   * @param  configEntry         The configuration entry that will be removed
-   *                             from the configuration.
-   * @param  unacceptableReason  A buffer to which this method can append a
-   *                             human-readable message explaining why the
-   *                             proposed delete is not acceptable.
-   *
-   * @return  <CODE>true</CODE> if the proposed entry may be removed from the
-   *          configuration, or <CODE>false</CODE> if not.
+   * {@inheritDoc}
    */
-  public boolean configDeleteIsAcceptable(ConfigEntry configEntry,
-                                          StringBuilder unacceptableReason)
+  public boolean isConfigurationDeleteAcceptable(
+      PasswordPolicyCfg configuration, List<String> unacceptableReason)
   {
     // We'll allow the policy to be removed as long as it isn't the default.
     // FIXME: something like a referential integrity check is needed to ensure
@@ -315,11 +279,11 @@
     // directly or via a virtual attribute).
     DN defaultPolicyDN = DirectoryServer.getDefaultPasswordPolicyDN();
     if ((defaultPolicyDN != null) &&
-        defaultPolicyDN.equals(configEntry.getDN()))
+        defaultPolicyDN.equals(configuration.dn()))
     {
       int msgID = MSGID_CONFIG_PWPOLICY_CANNOT_DELETE_DEFAULT_POLICY;
       String message = getMessage(msgID, String.valueOf(defaultPolicyDN));
-      unacceptableReason.append(message);
+      unacceptableReason.add(message);
       return false;
     }
     else
@@ -331,21 +295,17 @@
 
 
   /**
-   * Attempts to apply a new configuration based on the provided deleted entry.
-   *
-   * @param  configEntry  The new configuration entry that has been deleted.
-   *
-   * @return  Information about the result of processing the configuration
-   *          change.
+   * {@inheritDoc}
    */
-  public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry)
+  public ConfigChangeResult applyConfigurationDelete(
+      PasswordPolicyCfg configuration)
   {
     // We'll allow the policy to be removed as long as it isn't the default.
     // FIXME: something like a referential integrity check is needed to ensure
     //  a policy is not removed when referenced by a user entry (either
     // directly or via a virtual attribute).
     ArrayList<String> messages = new ArrayList<String>(1);
-    DN policyDN = configEntry.getDN();
+    DN policyDN = configuration.dn();
     DN defaultPolicyDN = DirectoryServer.getDefaultPasswordPolicyDN();
     if ((defaultPolicyDN != null) && defaultPolicyDN.equals(policyDN))
     {
@@ -355,8 +315,13 @@
       return new ConfigChangeResult(ResultCode.CONSTRAINT_VIOLATION, false,
                                     messages);
     }
-
     DirectoryServer.deregisterPasswordPolicy(policyDN);
+    PasswordPolicyConfig config =
+      DirectoryServer.getPasswordPolicyConfig(policyDN);
+    if (config != null)
+    {
+      configuration.removeChangeListener(config);
+    }
 
     int msgID = MSGID_CONFIG_PWPOLICY_REMOVED_POLICY;
     messages.add(getMessage(msgID, String.valueOf(policyDN)));
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/core/PasswordPolicyTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/core/PasswordPolicyTestCase.java
index 548c320..72c2ead 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/core/PasswordPolicyTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/core/PasswordPolicyTestCase.java
@@ -38,6 +38,9 @@
 import org.testng.annotations.Test;
 
 import org.opends.server.TestCaseUtils;
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.PasswordPolicyCfgDefn;
+import org.opends.server.admin.std.server.PasswordPolicyCfg;
 import org.opends.server.api.PasswordStorageScheme;
 import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
@@ -2111,7 +2114,11 @@
     ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN);
     ConfigEntry configEntry = new ConfigEntry(e, parentEntry);
 
-    new PasswordPolicy(configEntry);
+    PasswordPolicyCfg configuration =
+      AdminTestCaseUtils.getConfiguration(PasswordPolicyCfgDefn.getInstance(),
+          configEntry.getEntry());
+
+    new PasswordPolicy(configuration);
   }
 
 

--
Gitblit v1.10.0