From bff247202b2e096249150884a93601b19e836c9a Mon Sep 17 00:00:00 2001
From: jdemendi <jdemendi@localhost>
Date: Wed, 02 May 2007 08:29:33 +0000
Subject: [PATCH] Issue #1560 - Migrate some objects to the new admin framework: - Entry Cache - Account Status Notification Handler - Password Storage Scheme

---
 opends/src/admin/defn/org/opends/server/admin/std/SoftReferenceEntryCacheConfiguration.xml                                   |   50 
 opends/src/server/org/opends/server/core/EntryCacheConfigManager.java                                                        |  676 +++---
 opends/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageScheme.java                                        |   10 
 opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageSchemeTestCase.java        |   12 
 opends/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageScheme.java                                        |   10 
 opends/src/server/org/opends/server/core/AccountStatusNotificationHandlerConfigManager.java                                  | 1083 ++-------
 opends/src/server/org/opends/server/extensions/ErrorLogAccountStatusNotificationHandler.java                                 |  414 +--
 opends/src/admin/defn/org/opends/server/admin/std/EntryCacheConfiguration.xml                                                |   60 
 opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml                                                      |   24 
 opends/src/admin/defn/org/opends/server/admin/std/AccountStatusNotificationHandlerConfiguration.xml                          |   65 
 opends/src/admin/defn/org/opends/server/admin/std/PasswordStorageSchemeConfiguration.xml                                     |   61 
 opends/src/server/org/opends/server/extensions/ClearPasswordStorageScheme.java                                               |   10 
 opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ClearPasswordStorageSchemeTestCase.java               |   12 
 opends/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java                                          |   10 
 opends/tests/unit-tests-testng/src/server/org/opends/server/schema/AuthPasswordEqualityMatchingRuleTest.java                 |   15 
 opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SHA1PasswordStorageSchemeTestCase.java                |   12 
 opends/src/server/org/opends/server/extensions/EntryCacheCommon.java                                                         |  333 +++
 opends/tests/unit-tests-testng/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRuleTest.java                 |   12 
 opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ErrorLogAccountStatusNotificationHandlerTestCase.java |   12 
 opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java                                                  |  866 +------
 opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageSchemeTestCase.java           |   14 
 opends/resource/FindJavaHome.class                                                                                           |    0 
 opends/src/admin/defn/org/opends/server/admin/std/ErrorLogAccountStatusNotificationHandlerConfiguration.xml                  |  135 +
 opends/src/server/org/opends/server/extensions/MD5PasswordStorageScheme.java                                                 |   10 
 opends/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java                                        |   10 
 opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/MD5PasswordStorageSchemeTestCase.java                 |   12 
 opends/src/server/org/opends/server/extensions/DefaultEntryCache.java                                                        |  167 -
 opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageSchemeTestCase.java        |   12 
 opends/src/admin/defn/org/opends/server/admin/std/Package.xml                                                                |   39 
 opends/src/server/org/opends/server/api/PasswordStorageScheme.java                                                           |   16 
 opends/src/server/org/opends/server/extensions/FIFOEntryCache.java                                                           | 1100 +--------
 opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/Base64PasswordStorageSchemeTestCase.java              |   12 
 opends/src/server/org/opends/server/api/AccountStatusNotificationHandler.java                                                |   18 
 opends/src/server/org/opends/server/core/PasswordStorageSchemeConfigManager.java                                             | 1072 ++-------
 opends/src/server/org/opends/server/extensions/Base64PasswordStorageScheme.java                                              |   10 
 opends/src/server/org/opends/server/extensions/SHA1PasswordStorageScheme.java                                                |   10 
 opends/resource/admin/abbreviations.xsl                                                                                      |    4 
 opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageSchemeTestCase.java        |   12 
 opends/src/server/org/opends/server/api/EntryCache.java                                                                      |   12 
 opends/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java                                           |   10 
 opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageSchemeTestCase.java          |   21 
 opends/src/admin/defn/org/opends/server/admin/std/FIFOEntryCacheConfiguration.xml                                            |  112 +
 42 files changed, 2,607 insertions(+), 3,948 deletions(-)

diff --git a/opends/resource/FindJavaHome.class b/opends/resource/FindJavaHome.class
index c0ae713..0a92e67 100644
--- a/opends/resource/FindJavaHome.class
+++ b/opends/resource/FindJavaHome.class
Binary files differ
diff --git a/opends/resource/admin/abbreviations.xsl b/opends/resource/admin/abbreviations.xsl
index 88c5fe4..eaa6876 100644
--- a/opends/resource/admin/abbreviations.xsl
+++ b/opends/resource/admin/abbreviations.xsl
@@ -47,6 +47,8 @@
               or $value = 'ldap' or $value = 'ldaps' or $value = 'ldif'
               or $value = 'jdbc' or $value = 'tcp' or $value = 'tls'
               or $value = 'pkcs11' or $value = 'sasl' or $value = 'gssapi'
-              or $value = 'md5' or $value = 'je' or $value = 'dse' " />
+              or $value = 'md5' or $value = 'je' or $value = 'dse'
+              or $value = 'fifo'
+             "/>
   </xsl:template>
 </xsl:stylesheet>
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/AccountStatusNotificationHandlerConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/AccountStatusNotificationHandlerConfiguration.xml
new file mode 100644
index 0000000..cdce93d
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/AccountStatusNotificationHandlerConfiguration.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adm:managed-object
+  name="account-status-notification-handler"
+  plural-name="account-status-notification-handlers"
+  package="org.opends.server.admin.std"
+  xmlns:adm="http://www.opends.org/admin"
+  xmlns:ldap="http://www.opends.org/admin-ldap"
+  >
+
+  <adm:synopsis>
+    <adm:user-friendly-name />
+    is invoked whenever certain types of events occur that could change
+    the status of a user account. The
+    <adm:user-friendly-name />
+    may be used to notify the user and/or administrators of the change.
+  </adm:synopsis>
+
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:oid>1.3.6.1.4.1.26027.1.2.75</ldap:oid>
+      <ldap:name>ds-cfg-account-status-notification-handler</ldap:name>
+      <ldap:superior>top</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+
+  <adm:property name="enabled" mandatory="true">
+    <adm:synopsis>
+      Indicate whether the
+      <adm:user-friendly-name />
+      is enabled for use.
+    </adm:synopsis>
+    <adm:syntax>
+      <adm:boolean />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.282</ldap:oid>
+        <ldap:name>ds-cfg-account-status-notification-handler-enabled</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="notification-handler-class" mandatory="true">
+    <adm:synopsis>
+      The fully-qualified name of the Java class that provides the
+      <adm:user-friendly-name />
+      implementation.
+    </adm:synopsis>
+    <adm:syntax>
+      <adm:java-class>
+        <adm:instance-of>
+          org.opends.server.api.AccountStatusNotificationHandler
+        </adm:instance-of>
+      </adm:java-class>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.281</ldap:oid>
+        <ldap:name>ds-cfg-account-status-notification-handler-class</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+</adm:managed-object>
+
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/EntryCacheConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/EntryCacheConfiguration.xml
new file mode 100644
index 0000000..78b0589
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/EntryCacheConfiguration.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adm:managed-object
+  name="entry-cache"
+  plural-name="entry-caches"
+  package="org.opends.server.admin.std"
+  xmlns:adm="http://www.opends.org/admin"
+  xmlns:ldap="http://www.opends.org/admin-ldap"
+  >
+  <adm:synopsis>
+    <adm:user-friendly-name />
+    defines a Directory Server entry cache.
+  </adm:synopsis>
+
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:oid>1.3.6.1.4.1.26027.1.2.15</ldap:oid>
+      <ldap:name>ds-cfg-entry-cache</ldap:name>
+      <ldap:superior>top</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+
+  <adm:property name="enabled" mandatory="true">
+    <adm:synopsis>
+      Indicate whether the
+      <adm:user-friendly-name />
+      is enabled for use.
+    </adm:synopsis>
+    <adm:syntax>
+      <adm:boolean />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.35</ldap:oid>
+        <ldap:name>ds-cfg-entry-cache-enabled</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="entry-cache-class" mandatory="true">
+    <adm:synopsis>
+      The fully-qualified name of the Java class that provides the
+      <adm:user-friendly-name />
+      implementation.
+    </adm:synopsis>
+    <adm:syntax>
+      <adm:java-class>
+        <adm:instance-of>
+          org.opends.server.api.EntryCache
+        </adm:instance-of>
+      </adm:java-class>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.34</ldap:oid>
+        <ldap:name>ds-cfg-entry-cache-class</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+</adm:managed-object>
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/ErrorLogAccountStatusNotificationHandlerConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/ErrorLogAccountStatusNotificationHandlerConfiguration.xml
new file mode 100644
index 0000000..dd96b93
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/ErrorLogAccountStatusNotificationHandlerConfiguration.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adm:managed-object
+  name="error-log-account-status-notification-handler"
+  plural-name="error-log-account-status-notification-handlers"
+  extends="account-status-notification-handler"
+  package="org.opends.server.admin.std"
+  xmlns:adm="http://www.opends.org/admin"
+  xmlns:ldap="http://www.opends.org/admin-ldap"
+  >
+
+  <adm:synopsis>
+    <adm:user-friendly-name />
+    is an account status notification handler that writes information
+    about status notifications using the Directory Server's error
+    logging facility.
+  </adm:synopsis>
+
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:oid>1.3.6.1.4.1.26027.1.2.76</ldap:oid>
+      <ldap:name>
+        ds-cfg-error-log-account-status-notification-handler
+      </ldap:name>
+      <ldap:superior>
+        ds-cfg-account-status-notification-handler
+      </ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+
+  <adm:property name="account-status-notification-type" mandatory="true"
+    multi-valued="true">
+    <adm:synopsis>
+      <adm:user-friendly-name />
+      is a possible event type that can trigger an account status
+      notification.
+    </adm:synopsis>
+    <adm:syntax>
+      <adm:enumeration>
+        <adm:value name="account-temporarily-locked">
+          <adm:synopsis>
+            Indicates that an account status message should be generated
+            whenever a user account has been temporarily locked after
+            too many failed attempts.
+          </adm:synopsis>
+        </adm:value>
+        <adm:value name="account-permanently-locked">
+          <adm:synopsis>
+            Indicates that an account status message should be generated
+            whenever a user account has been permanently locked after
+            too many failed attempts.
+          </adm:synopsis>
+        </adm:value>
+        <adm:value name="account-unlocked">
+          <adm:synopsis>
+            Indicates that an account status message should be generated
+            whenever a user account has been unlocked by an
+            administrator.
+          </adm:synopsis>
+        </adm:value>
+        <adm:value name="account-idle-locked">
+          <adm:synopsis>
+            Indicates that an account status message should be generated
+            whenever a user account has been locked because it was idle
+            for too long.
+          </adm:synopsis>
+        </adm:value>
+        <adm:value name="account-reset-locked">
+          <adm:synopsis>
+            Indicates that an account status message should be generated
+            whenever a user account has been locked because it the
+            password had been reset by an administrator but not changed
+            by the user within the required interval.
+          </adm:synopsis>
+        </adm:value>
+        <adm:value name="account-disabled">
+          <adm:synopsis>
+            Indicates that an account status message should be generated
+            whenever a user account has been disabled by an
+            administrator.
+          </adm:synopsis>
+        </adm:value>
+        <adm:value name="account-enabled">
+          <adm:synopsis>
+            Indicates that an account status message should be generated
+            whenever a user account has been enabled by an
+            administrator.
+          </adm:synopsis>
+        </adm:value>
+        <adm:value name="account-expired">
+          <adm:synopsis>
+            Indicates that an account status message should be generated
+            whenever a user authentication has failed because the
+            account has expired.
+          </adm:synopsis>
+        </adm:value>
+        <adm:value name="password-expired">
+          <adm:synopsis>
+            Indicates that an account status notification message should
+            be generated whenever a user authentication has failed
+            because the password has expired.
+          </adm:synopsis>
+        </adm:value>
+        <adm:value name="password-expiring">
+          <adm:synopsis>
+            Indicates that an account status notification message should
+            be generated the first time that a password expiration
+            warning is encountered for a user password.
+          </adm:synopsis>
+        </adm:value>
+        <adm:value name="password-reset">
+          <adm:synopsis>
+            Indicates that an account status notification message should
+            be generated whenever a user's password is reset by an
+            administrator.
+          </adm:synopsis>
+        </adm:value>
+        <adm:value name="password-changed">
+          <adm:synopsis>
+            Indicates whether an account status notification message
+            should be generated whenever a user changes his/her own
+            password.
+          </adm:synopsis>
+        </adm:value>
+      </adm:enumeration>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.283</ldap:oid>
+        <ldap:name>ds-cfg-account-status-notification-type</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+</adm:managed-object>
+
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/FIFOEntryCacheConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/FIFOEntryCacheConfiguration.xml
new file mode 100644
index 0000000..2b0d6c1
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/FIFOEntryCacheConfiguration.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adm:managed-object
+  name="fifo-entry-cache"
+  plural-name="fifo-entry-caches"
+  package="org.opends.server.admin.std"
+  extends="entry-cache"
+  xmlns:adm="http://www.opends.org/admin"
+  xmlns:ldap="http://www.opends.org/admin-ldap"
+  >
+
+  <adm:synopsis>
+    <adm:user-friendly-name />
+    defines a Directory Server entry cache that uses a FIFO to keep
+    track of the entries.  Entries that have been in the cache the longest are
+    the most likely candidates for purging if space is needed.  In contrast to
+    other cache structures, the selection of entries to purge is not based on
+    how frequently or recently the entries have been accessed.  This requires
+    significantly less locking (it will only be required when an entry is added
+    or removed from the cache, rather than each time an entry is accessed).
+
+    Cache sizing is based on the percentage of free memory within the JVM, such
+    that if enough memory is free, then adding an entry to the cache will not
+    require purging, but if more than a specified percentage of the available
+    memory within the JVM is already consumed, then one or more entries will need
+    to be removed in order to make room for a new entry.  It is also possible to
+    configure a maximum number of entries for the cache.  If this is specified,
+    then the number of entries will not be allowed to exceed this value, but it
+    may not be possible to hold this many entries if the available memory fills
+    up first.
+
+    Other configurable parameters for this cache include the maximum length of
+    time to block while waiting to acquire a lock, and a set of filters that may
+    be used to define criteria for determining which entries are stored in the
+    cache.  If a filter list is provided, then only entries matching at least
+    one of the given filters will be stored in the cache.
+  </adm:synopsis>
+
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:oid>1.3.6.1.4.1.26027.1.2.16</ldap:oid>
+      <ldap:name>ds-cfg-fifo-entry-cache</ldap:name>
+      <ldap:superior>ds-cfg-entry-cache</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+
+  <adm:property name="lock-timeout" mandatory="false">
+    <adm:synopsis>
+      The length of time in milliseconds to wait while
+      attempting to acquire a read or write lock.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>2000.0ms</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:duration base-unit="ms" lower-limit="0" allow-unlimited="true"/>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.58</ldap:oid>
+        <ldap:name>ds-cfg-lock-timeout</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="max-memory-percent" mandatory="false">
+    <adm:synopsis>
+      The maximum memory usage for the entry cache as a percentage
+      of the total JVM memory.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>90</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:size lower-limit="1" upper-limit="100"/>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.66</ldap:oid>
+        <ldap:name>ds-cfg-max-memory-percent</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="max-entries" mandatory="false">
+    <adm:synopsis>
+      The maximum number of entries that we will allow in the cache.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>0x7fffffffffffffffL</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:size lower-limit="0" allow-unlimited="true"/>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.65</ldap:oid>
+        <ldap:name>ds-cfg-max-entries</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property-reference name="include-filter" />
+  <adm:property-reference name="exclude-filter" />
+
+</adm:managed-object>
+
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/Package.xml b/opends/src/admin/defn/org/opends/server/admin/std/Package.xml
index 780c11f..0a6bb19 100644
--- a/opends/src/admin/defn/org/opends/server/admin/std/Package.xml
+++ b/opends/src/admin/defn/org/opends/server/admin/std/Package.xml
@@ -242,4 +242,43 @@
       </ldap:attribute>
     </adm:profile>
   </adm:property>
+
+  <adm:property name="include-filter" mandatory="false" multi-valued="true">
+    <adm:synopsis>
+      The set of filters that define the entries that should be
+      included in the cache.
+    </adm:synopsis>
+    <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.43</ldap:oid>
+        <ldap:name>ds-cfg-include-filter</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="exclude-filter" mandatory="false" multi-valued="true">
+    <adm:synopsis>
+      The set of filters that define the entries that should be
+      excluded from the cache.
+    </adm:synopsis>
+    <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.38</ldap:oid>
+        <ldap:name>ds-cfg-exclude-filter</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
 </adm:package>
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/PasswordStorageSchemeConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/PasswordStorageSchemeConfiguration.xml
new file mode 100644
index 0000000..2f26137
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/PasswordStorageSchemeConfiguration.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adm:managed-object
+  name="password-storage-scheme"
+  plural-name="password-storage-schemes"
+  package="org.opends.server.admin.std"
+  xmlns:adm="http://www.opends.org/admin"
+  xmlns:ldap="http://www.opends.org/admin-ldap"
+  >
+
+  <adm:synopsis>
+    <adm:user-friendly-name />
+    defines a module that implements a password storage scheme.
+  </adm:synopsis>
+
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:oid>1.3.6.1.4.1.26027.1.2.35</ldap:oid>
+      <ldap:name>ds-cfg-password-storage-scheme</ldap:name>
+      <ldap:superior>top</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+
+  <adm:property name="enabled" mandatory="true">
+    <adm:synopsis>
+      Indicate whether the
+      <adm:user-friendly-name />
+      is enabled for use.
+    </adm:synopsis>
+    <adm:syntax>
+      <adm:boolean />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.76</ldap:oid>
+        <ldap:name>ds-cfg-password-storage-scheme-enabled</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="scheme-class" mandatory="true">
+    <adm:synopsis>
+      The fully-qualified name of the Java class that provides the
+      <adm:user-friendly-name />
+      implementation.
+    </adm:synopsis>
+    <adm:syntax>
+      <adm:java-class>
+        <adm:instance-of>
+          org.opends.server.api.PasswordStorageScheme
+        </adm:instance-of>
+      </adm:java-class>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.75</ldap:oid>
+        <ldap:name>ds-cfg-password-storage-scheme-class</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+</adm:managed-object>
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 61bd1bd..3113858 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
@@ -99,6 +99,30 @@
       </ldap:rdn-sequence>
     </adm:profile>
   </adm:relation>
+  <adm:relation name="entry-cache">
+  	<adm:one-to-one />
+  	<adm:profile name="ldap">
+      <ldap:rdn-sequence>
+        cn=Entry Cache,cn=config
+      </ldap:rdn-sequence>
+    </adm:profile>
+  </adm:relation>
+  <adm:relation name="account-status-notification-handler">
+    <adm:one-to-many />
+    <adm:profile name="ldap">
+      <ldap:rdn-sequence>
+        cn=Account Status Notification Handlers,cn=config
+      </ldap:rdn-sequence>
+    </adm:profile>
+  </adm:relation>
+  <adm:relation name="password-storage-scheme">
+    <adm:one-to-many />
+    <adm:profile name="ldap">
+      <ldap:rdn-sequence>
+        cn=Password Storage Schemes,cn=config
+      </ldap:rdn-sequence>
+    </adm:profile>
+  </adm:relation>
   <adm:relation name="backend">
     <adm:one-to-many />
     <adm:profile name="ldap">
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/SoftReferenceEntryCacheConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/SoftReferenceEntryCacheConfiguration.xml
new file mode 100644
index 0000000..8394275
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/SoftReferenceEntryCacheConfiguration.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adm:managed-object
+  name="soft-reference-entry-cache"
+  plural-name="soft-reference-entry-caches"
+  package="org.opends.server.admin.std"
+  extends="entry-cache"
+  xmlns:adm="http://www.opends.org/admin"
+  xmlns:ldap="http://www.opends.org/admin-ldap"
+  >
+
+  <adm:synopsis>
+    <adm:user-friendly-name />
+    defines a Directory Server entry cache that uses soft references
+    to manage objects in a way that will allow them to be freed if the JVM is
+    running low on memory.
+  </adm:synopsis>
+
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:oid>1.3.6.1.4.1.26027.1.2.17</ldap:oid>
+      <ldap:name>ds-cfg-soft-reference-entry-cache</ldap:name>
+      <ldap:superior>ds-cfg-entry-cache</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+
+  <adm:property name="lock-timeout" mandatory="false">
+    <adm:synopsis>
+      The length of time in milliseconds to wait while
+      attempting to acquire a read or write lock.
+    </adm:synopsis>
+    <adm:default-behavior>
+    	<adm:defined>
+    		<adm:value>3000ms</adm:value>
+    	</adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:duration base-unit="ms" lower-limit="0" allow-unlimited="true"/>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.58</ldap:oid>
+        <ldap:name>ds-cfg-lock-timeout</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  
+  <adm:property-reference name="include-filter" />
+  <adm:property-reference name="exclude-filter" />
+
+</adm:managed-object>
diff --git a/opends/src/server/org/opends/server/api/AccountStatusNotificationHandler.java b/opends/src/server/org/opends/server/api/AccountStatusNotificationHandler.java
index 74d3405..3e6c7bb 100644
--- a/opends/src/server/org/opends/server/api/AccountStatusNotificationHandler.java
+++ b/opends/src/server/org/opends/server/api/AccountStatusNotificationHandler.java
@@ -28,7 +28,8 @@
 
 
 
-import org.opends.server.config.ConfigEntry;
+import org.opends.server.admin.std.server.
+       AccountStatusNotificationHandlerCfg;
 import org.opends.server.config.ConfigException;
 import org.opends.server.types.AccountStatusNotification;
 import org.opends.server.types.AccountStatusNotificationType;
@@ -44,16 +45,21 @@
  * the status of a user account.  The account status notification
  * handler may be used to notify the user and/or administrators of the
  * change.
+ *
+ * @param  <T>  The type of configuration handled by this notification
+ *              handler.
  */
-public abstract class AccountStatusNotificationHandler
+public abstract class
+       AccountStatusNotificationHandler
+       <T extends AccountStatusNotificationHandlerCfg>
 {
   /**
    * Initializes this account status notification handler based on the
    * information in the provided configuration entry.
    *
-   * @param  configEntry  The configuration entry that contains the
-   *                      information to use to initialize this
-   *                      account status notification handler.
+   * @param  configuration  The configuration entry that contains the
+   *                        information to use to initialize this
+   *                        account status notification handler.
    *
    * @throws  ConfigException  If the provided entry does not contain
    *                           a valid configuration for this account
@@ -65,7 +71,7 @@
    *                                   configuration.
    */
   public abstract void initializeStatusNotificationHandler(
-                            ConfigEntry configEntry)
+         T configuration)
          throws ConfigException, InitializationException;
 
 
diff --git a/opends/src/server/org/opends/server/api/EntryCache.java b/opends/src/server/org/opends/server/api/EntryCache.java
index 420b724..a7ae1c7 100644
--- a/opends/src/server/org/opends/server/api/EntryCache.java
+++ b/opends/src/server/org/opends/server/api/EntryCache.java
@@ -31,12 +31,12 @@
 import java.util.List;
 import java.util.concurrent.locks.Lock;
 
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.types.DN;
 import org.opends.server.types.Entry;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.LockType;
+import org.opends.server.admin.std.server.EntryCacheCfg;
 
 
 
@@ -62,15 +62,19 @@
  *       the behavior of the default cache that will be used if none
  *       is configured).</LI>
  * </UL>
+ *
+ * @param  <T>  The type of configuration handled by this entry
+ *              cache.
  */
 public abstract class EntryCache
+       <T extends EntryCacheCfg>
 {
   /**
    * Initializes this entry cache implementation so that it will be
    * available for storing and retrieving entries.
    *
-   * @param  configEntry  The configuration entry containing the
-   *                      settings to use for this entry cache.
+   * @param  configuration  The configuration to use to initialize
+   *                        the entry cache.
    *
    * @throws  ConfigException  If there is a problem with the provided
    *                           configuration entry that would prevent
@@ -81,7 +85,7 @@
    *                                   not related to the
    *                                   configuration.
    */
-  public abstract void initializeEntryCache(ConfigEntry configEntry)
+  public abstract void initializeEntryCache(T configuration)
          throws ConfigException, InitializationException;
 
 
diff --git a/opends/src/server/org/opends/server/api/PasswordStorageScheme.java b/opends/src/server/org/opends/server/api/PasswordStorageScheme.java
index fbaa4f3..a26bda7 100644
--- a/opends/src/server/org/opends/server/api/PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/api/PasswordStorageScheme.java
@@ -28,7 +28,7 @@
 
 
 
-import org.opends.server.config.ConfigEntry;
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.config.ConfigException;
 import org.opends.server.types.ByteString;
 import org.opends.server.types.DirectoryException;
@@ -41,8 +41,12 @@
  * implemented by a Directory Server module that implements a password
  * storage scheme.  Each subclass may only implement a single password
  * storage scheme type.
+ *
+ * @param  <T>  The type of configuration handled by this
+ *              password storage scheme
  */
-public abstract class PasswordStorageScheme
+public abstract class
+       PasswordStorageScheme <T extends PasswordStorageSchemeCfg>
 {
   /**
    * Initializes this password storage scheme handler based on the
@@ -50,9 +54,9 @@
    * register itself with the Directory Server for the particular
    * storage scheme that it will manage.
    *
-   * @param  configEntry  The configuration entry that contains the
-   *                      information to use to initialize this
-   *                      password storage scheme handler.
+   * @param  configuration  The configuration entry that contains the
+   *                        information to use to initialize this
+   *                        password storage scheme handler.
    *
    * @throws  ConfigException  If an unrecoverable problem arises in
    *                           the process of performing the
@@ -64,7 +68,7 @@
    *                                   configuration.
    */
   public abstract void initializePasswordStorageScheme(
-                            ConfigEntry configEntry)
+         T configuration)
          throws ConfigException, InitializationException;
 
 
diff --git a/opends/src/server/org/opends/server/core/AccountStatusNotificationHandlerConfigManager.java b/opends/src/server/org/opends/server/core/AccountStatusNotificationHandlerConfigManager.java
index 3b2d68d..bde3356 100644
--- a/opends/src/server/org/opends/server/core/AccountStatusNotificationHandlerConfigManager.java
+++ b/opends/src/server/org/opends/server/core/AccountStatusNotificationHandlerConfigManager.java
@@ -28,38 +28,30 @@
 
 
 
+import static org.opends.server.messages.ConfigMessages.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
+
+import java.lang.reflect.Method;
 import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 
+import org.opends.server.admin.ClassPropertyDefinition;
+import org.opends.server.admin.server.ConfigurationAddListener;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.server.ConfigurationDeleteListener;
+import org.opends.server.admin.server.ServerManagementContext;
+import org.opends.server.admin.std.meta.AccountStatusNotificationHandlerCfgDefn;
+import org.opends.server.admin.std.server.AccountStatusNotificationHandlerCfg;
+import org.opends.server.admin.std.server.RootCfg;
 import org.opends.server.api.AccountStatusNotificationHandler;
-import org.opends.server.api.ConfigAddListener;
-import org.opends.server.api.ConfigChangeListener;
-import org.opends.server.api.ConfigDeleteListener;
-import org.opends.server.api.ConfigHandler;
-import org.opends.server.api.ConfigurableComponent;
-import org.opends.server.config.BooleanConfigAttribute;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
-import org.opends.server.config.StringConfigAttribute;
 import org.opends.server.types.ConfigChangeResult;
 import org.opends.server.types.DN;
-import org.opends.server.types.ErrorLogCategory;
-import org.opends.server.types.ErrorLogSeverity;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.ResultCode;
 
-import static org.opends.server.config.ConfigConstants.*;
-import static org.opends.server.loggers.debug.DebugLogger.debugCaught;
-import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
-import org.opends.server.types.DebugLogLevel;
-import static org.opends.server.loggers.Error.*;
-import static org.opends.server.messages.ConfigMessages.*;
-import static org.opends.server.messages.MessageHandler.*;
-import static org.opends.server.util.ServerConstants.*;
-
 
 
 /**
@@ -70,19 +62,16 @@
  * server is running.
  */
 public class AccountStatusNotificationHandlerConfigManager
-       implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener
+       implements
+          ConfigurationChangeListener <AccountStatusNotificationHandlerCfg>,
+          ConfigurationAddListener    <AccountStatusNotificationHandlerCfg>,
+          ConfigurationDeleteListener <AccountStatusNotificationHandlerCfg>
 {
 
-
-
   // A mapping between the DNs of the config entries and the associated
   // notification handlers.
   private ConcurrentHashMap<DN,AccountStatusNotificationHandler>
-               notificationHandlers;
-
-  // The configuration handler for the Directory Server.
-  private ConfigHandler configHandler;
-
+          notificationHandlers;
 
 
   /**
@@ -91,7 +80,6 @@
    */
   public AccountStatusNotificationHandlerConfigManager()
   {
-    configHandler = DirectoryServer.getConfigHandler();
     notificationHandlers =
          new ConcurrentHashMap<DN,AccountStatusNotificationHandler>();
   }
@@ -115,823 +103,228 @@
   public void initializeNotificationHandlers()
          throws ConfigException, InitializationException
   {
-    // First, get the configuration base entry.
-    ConfigEntry baseEntry;
-    try
+    // 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 account status notification handler entry
+    // is added or removed.
+    rootConfiguration.addAccountStatusNotificationHandlerAddListener (this);
+    rootConfiguration.addAccountStatusNotificationHandlerDeleteListener (this);
+
+    // Initialize existing account status notification handlers.
+    for (String handlerName:
+         rootConfiguration.listAccountStatusNotificationHandlers())
     {
-      DN handlerBase = DN.decode(DN_ACCT_NOTIFICATION_HANDLER_CONFIG_BASE);
-      baseEntry = configHandler.getConfigEntry(handlerBase);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
+      // Get the account status notification handler's configuration.
+      AccountStatusNotificationHandlerCfg config =
+        rootConfiguration.getAccountStatusNotificationHandler (handlerName);
+
+      // Register as a change listener for this notification handler
+      // entry so that we will be notified of any changes that may be
+      // made to it.
+      config.addChangeListener (this);
+
+      // Ignore this notification handler if it is disabled.
+      if (config.isEnabled())
       {
-        debugCaught(DebugLogLevel.ERROR, e);
+        // Load the notification handler implementation class.
+        String className = config.getNotificationHandlerClass();
+        loadAndInstallNotificationHandler (className, config);
       }
-
-      int    msgID   = MSGID_CONFIG_ACCTNOTHANDLER_CANNOT_GET_BASE;
-      String message = getMessage(msgID, String.valueOf(e));
-      throw new ConfigException(msgID, message, e);
     }
+  }
 
-    if (baseEntry == null)
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationChangeAcceptable(
+      AccountStatusNotificationHandlerCfg configuration,
+      List<String>  unacceptableReasons
+      )
+  {
+    // returned status -- all is fine by default
+    boolean status = true;
+
+    if (configuration.isEnabled())
     {
-      // The notification handler base entry does not exist.  This is not
-      // acceptable, so throw an exception.
-      int    msgID   = MSGID_CONFIG_ACCTNOTHANDLER_BASE_DOES_NOT_EXIST;
-      String message = getMessage(msgID);
-      throw new ConfigException(msgID, message);
-    }
-
-
-    // Register add and delete listeners with the notification handler base
-    // entry.  We don't care about modifications to it.
-    baseEntry.registerAddListener(this);
-    baseEntry.registerDeleteListener(this);
-
-
-    // See if the base entry has any children.  If not, then we don't need to do
-    // anything else.
-    if (! baseEntry.hasChildren())
-    {
-      return;
-    }
-
-
-    // Iterate through the child entries and process them as account status
-    // notification handler configuration entries.
-    for (ConfigEntry childEntry : baseEntry.getChildren().values())
-    {
-      childEntry.registerChangeListener(this);
-
-      StringBuilder unacceptableReason = new StringBuilder();
-      if (! configAddIsAcceptable(childEntry, unacceptableReason))
-      {
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 MSGID_CONFIG_ACCTNOTHANDLER_ENTRY_UNACCEPTABLE,
-                 childEntry.getDN().toString(), unacceptableReason.toString());
-        continue;
-      }
-
+      // Get the name of the class and make sure we can instantiate it as an
+      // entry cache.
+      String className = configuration.getNotificationHandlerClass();
       try
       {
-        ConfigChangeResult result = applyConfigurationAdd(childEntry);
-        if (result.getResultCode() != ResultCode.SUCCESS)
-        {
-          StringBuilder buffer = new StringBuilder();
-
-          List<String> resultMessages = result.getMessages();
-          if ((resultMessages == null) || (resultMessages.isEmpty()))
-          {
-            buffer.append(getMessage(MSGID_CONFIG_UNKNOWN_UNACCEPTABLE_REASON));
-          }
-          else
-          {
-            Iterator<String> iterator = resultMessages.iterator();
-
-            buffer.append(iterator.next());
-            while (iterator.hasNext())
-            {
-              buffer.append(EOL);
-              buffer.append(iterator.next());
-            }
-          }
-
-          logError(ErrorLogCategory.CONFIGURATION,
-                   ErrorLogSeverity.SEVERE_ERROR,
-                   MSGID_CONFIG_ACCTNOTHANDLER_CANNOT_CREATE_HANDLER,
-                   childEntry.getDN().toString(), buffer.toString());
-        }
+        // Load the class but don't initialize it.
+        loadNotificationHandler(className, null);
       }
-      catch (Exception e)
+      catch (InitializationException ie)
       {
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 MSGID_CONFIG_ACCTNOTHANDLER_CANNOT_CREATE_HANDLER,
-                 childEntry.getDN().toString(), String.valueOf(e));
+        unacceptableReasons.add(ie.getMessage());
+        status = false;
       }
     }
+
+    return status;
   }
 
 
 
   /**
-   * Indicates whether the configuration entry that will result from a proposed
-   * modification is acceptable to this change listener.
-   *
-   * @param  configEntry         The configuration entry that will result from
-   *                             the requested update.
-   * @param  unacceptableReason  A buffer to which this method can append a
-   *                             human-readable message explaining why the
-   *                             proposed change is not acceptable.
-   *
-   * @return  <CODE>true</CODE> if the proposed entry contains an acceptable
-   *          configuration, or <CODE>false</CODE> if it does not.
+   * {@inheritDoc}
    */
-  public boolean configChangeIsAcceptable(ConfigEntry configEntry,
-                                          StringBuilder unacceptableReason)
+  public ConfigChangeResult applyConfigurationChange(
+      AccountStatusNotificationHandlerCfg configuration
+      )
   {
-    // Make sure that the entry has an appropriate objectclass for an account
-    // status notification handler.
-    if (! configEntry.hasObjectClass(OC_ACCT_NOTIFICATION_HANDLER))
+    // Returned result.
+    ConfigChangeResult changeResult = new ConfigChangeResult(
+        ResultCode.SUCCESS, false, new ArrayList<String>()
+        );
+
+    // Get the configuration entry DN and the associated handler class.
+    DN configEntryDN = configuration.dn();
+    AccountStatusNotificationHandler handler = notificationHandlers.get(
+        configEntryDN
+        );
+
+    // If the new configuration has the notification handler disabled,
+    // then remove it from the mapping list and clean it.
+    if (! configuration.isEnabled())
     {
-      int    msgID   = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_OBJECTCLASS;
-      String message = getMessage(msgID, configEntry.getDN().toString());
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // Make sure that the entry specifies the notification handler class name.
-    StringConfigAttribute classNameAttr;
-    try
-    {
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_DESCRIPTION_CLASS_NAME;
-      StringConfigAttribute classStub =
-           new StringConfigAttribute(ATTR_ACCT_NOTIFICATION_HANDLER_CLASS,
-                                     getMessage(msgID), true, false, true);
-      classNameAttr = (StringConfigAttribute)
-                      configEntry.getConfigAttribute(classStub);
-
-      if (classNameAttr == null)
+      if (handler != null)
       {
-        msgID = MSGID_CONFIG_ACCTNOTHANDLER_NO_CLASS_NAME;
-        String message = getMessage(msgID, configEntry.getDN().toString());
-        unacceptableReason.append(message);
-        return false;
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
+        uninstallNotificationHandler (configEntryDN);
       }
 
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS_NAME;
-      String message = getMessage(msgID, configEntry.getDN().toString(),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
+      return changeResult;
     }
 
-    Class handlerClass;
-    try
-    {
-      handlerClass = DirectoryServer.loadClass(classNameAttr.pendingValue());
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS_NAME;
-      String message = getMessage(msgID, configEntry.getDN().toString(),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-    try
-    {
-      AccountStatusNotificationHandler handler =
-           (AccountStatusNotificationHandler) handlerClass.newInstance();
-    }
-    catch(Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS;
-      String message = getMessage(msgID, handlerClass.getName(),
-                                  String.valueOf(configEntry.getDN()),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // See if this account status notification handler should be enabled.
-    BooleanConfigAttribute enabledAttr;
-    try
-    {
-      BooleanConfigAttribute enabledStub =
-           new BooleanConfigAttribute(ATTR_ACCT_NOTIFICATION_HANDLER_ENABLED,
-                    getMessage(MSGID_CONFIG_ACCTNOTHANDLER_DESCRIPTION_ENABLED),
-                               false);
-      enabledAttr = (BooleanConfigAttribute)
-                    configEntry.getConfigAttribute(enabledStub);
-
-      if (enabledAttr == null)
-      {
-        int msgID = MSGID_CONFIG_ACCTNOTHANDLER_NO_ENABLED_ATTR;
-        String message = getMessage(msgID, configEntry.getDN().toString());
-        unacceptableReason.append(message);
-        return false;
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_ENABLED_VALUE;
-      String message = getMessage(msgID, configEntry.getDN().toString(),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // If we've gotten here then the notification handler entry appears to be
-    // acceptable.
-    return true;
-  }
-
-
-
-  /**
-   * Attempts to apply a new configuration to this Directory Server component
-   * based on the provided changed entry.
-   *
-   * @param  configEntry  The configuration entry that containing the updated
-   *                      configuration for this component.
-   *
-   * @return  Information about the result of processing the configuration
-   *          change.
-   */
-  public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry)
-  {
-    DN                configEntryDN       = configEntry.getDN();
-    ResultCode        resultCode          = ResultCode.SUCCESS;
-    boolean           adminActionRequired = false;
-    ArrayList<String> messages            = new ArrayList<String>();
-
-
-    // Make sure that the entry has an appropriate objectclass for an account
-    // status notification handler.
-    if (! configEntry.hasObjectClass(OC_ACCT_NOTIFICATION_HANDLER))
-    {
-      int    msgID   = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_OBJECTCLASS;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-      resultCode = ResultCode.UNWILLING_TO_PERFORM;
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // Get the corresponding notification handler if it is active.
-    AccountStatusNotificationHandler handler =
-         notificationHandlers.get(configEntryDN);
-
-
-    // See if this handler should be enabled or disabled.
-    boolean needsEnabled = false;
-    BooleanConfigAttribute enabledAttr;
-    try
-    {
-      BooleanConfigAttribute enabledStub =
-           new BooleanConfigAttribute(ATTR_ACCT_NOTIFICATION_HANDLER_ENABLED,
-                    getMessage(MSGID_CONFIG_ACCTNOTHANDLER_DESCRIPTION_ENABLED),
-                               false);
-      enabledAttr = (BooleanConfigAttribute)
-                    configEntry.getConfigAttribute(enabledStub);
-
-      if (enabledAttr == null)
-      {
-        int msgID = MSGID_CONFIG_ACCTNOTHANDLER_NO_ENABLED_ATTR;
-        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-        resultCode = ResultCode.UNWILLING_TO_PERFORM;
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-
-      if (enabledAttr.activeValue())
-      {
-        if (handler == null)
-        {
-          needsEnabled = true;
-        }
-        else
-        {
-          // The handler is already active, so no action is required.
-        }
-      }
-      else
-      {
-        if (handler == null)
-        {
-          // The handler is already disabled, so no action is required and we
-          // can short-circuit out of this processing.
-          return new ConfigChangeResult(resultCode, adminActionRequired,
-                                        messages);
-        }
-        else
-        {
-          // The handler is active, so it needs to be disabled.  Do this and
-          // return that we were successful.
-          notificationHandlers.remove(configEntryDN);
-          handler.finalizeStatusNotificationHandler();
-
-          DirectoryServer.deregisterAccountStatusNotificationHandler(
-               configEntryDN);
-
-          return new ConfigChangeResult(resultCode, adminActionRequired,
-                                        messages);
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_ENABLED_VALUE;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              String.valueOf(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // Make sure that the entry specifies the notification handler class name.
-    // If it has changed, then we will not try to dynamically apply it.
-    String className;
-    try
-    {
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_DESCRIPTION_CLASS_NAME;
-      StringConfigAttribute classStub =
-           new StringConfigAttribute(ATTR_ACCT_NOTIFICATION_HANDLER_CLASS,
-                                     getMessage(msgID), true, false, true);
-      StringConfigAttribute classNameAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
-
-      if (classNameAttr == null)
-      {
-        msgID = MSGID_CONFIG_ACCTNOTHANDLER_NO_CLASS_NAME;
-        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-
-      className = classNameAttr.pendingValue();
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS_NAME;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              String.valueOf(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    boolean classChanged = false;
-    String  oldClassName = null;
+    // At this point, new configuration is enabled...
+    // If the current notification handler is already enabled then we
+    // don't do anything unless the class has changed in which case we
+    // should indicate that administrative action is required.
+    String newClassName = configuration.getNotificationHandlerClass();
     if (handler != null)
     {
-      oldClassName = handler.getClass().getName();
-      classChanged = (! className.equals(oldClassName));
+      String curClassName = handler.getClass().getName();
+      boolean classIsNew = (! newClassName.equals (curClassName));
+      if (classIsNew)
+      {
+        changeResult.setAdminActionRequired (true);
+      }
+      return changeResult;
     }
 
-
-    if (classChanged)
+    // New entry cache is enabled and there were no previous one.
+    // Instantiate the new class and initalize it.
+    try
     {
-      // This will not be applied dynamically.  Add a message to the response
-      // and indicate that admin action is required.
-      adminActionRequired = true;
-      messages.add(getMessage(MSGID_CONFIG_ACCTNOTHANDLER_CLASS_ACTION_REQUIRED,
-                              String.valueOf(oldClassName),
-                              String.valueOf(className),
-                              String.valueOf(configEntryDN)));
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+      loadAndInstallNotificationHandler (newClassName, configuration);
     }
-
-
-    if (needsEnabled)
+    catch (InitializationException ie)
     {
-      try
-      {
-        Class handlerClass = DirectoryServer.loadClass(className);
-        handler = (AccountStatusNotificationHandler) handlerClass.newInstance();
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS;
-        messages.add(getMessage(msgID, className,
-                                String.valueOf(configEntryDN),
-                                String.valueOf(e)));
-        resultCode = DirectoryServer.getServerErrorResultCode();
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-
-      try
-      {
-        handler.initializeStatusNotificationHandler(configEntry);
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INITIALIZATION_FAILED;
-        messages.add(getMessage(msgID, className,
-                                String.valueOf(configEntryDN),
-                                String.valueOf(e)));
-        resultCode = DirectoryServer.getServerErrorResultCode();
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-
-
-      notificationHandlers.put(configEntryDN, handler);
-      DirectoryServer.registerAccountStatusNotificationHandler(configEntryDN,
-                                                               handler);
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+      changeResult.addMessage (ie.getMessage());
+      changeResult.setResultCode (DirectoryServer.getServerErrorResultCode());
+      return changeResult;
     }
 
-
-    // If we've gotten here, then there haven't been any changes to anything
-    // that we care about.
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+    return changeResult;
   }
 
 
 
   /**
-   * 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(
+      AccountStatusNotificationHandlerCfg configuration,
+      List<String> unacceptableReasons
+      )
   {
+    // returned status -- all is fine by default
+    boolean status = true;
+
     // Make sure that no entry already exists with the specified DN.
-    DN configEntryDN = configEntry.getDN();
+    DN configEntryDN = configuration.dn();
     if (notificationHandlers.containsKey(configEntryDN))
     {
       int    msgID   = MSGID_CONFIG_ACCTNOTHANDLER_EXISTS;
       String message = getMessage(msgID, String.valueOf(configEntryDN));
-      unacceptableReason.append(message);
-      return false;
+      unacceptableReasons.add (message);
+      status = false;
     }
-
-
-    // Make sure that the entry has an appropriate objectclass for an account
-    // status notification handler.
-    if (! configEntry.hasObjectClass(OC_ACCT_NOTIFICATION_HANDLER))
+    // If configuration is enabled then check that notification class
+    // can be instantiated.
+    else if (configuration.isEnabled())
     {
-      int    msgID   = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_OBJECTCLASS;
-      String message = getMessage(msgID, configEntry.getDN().toString());
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // Make sure that the entry specifies the handler class.
-    StringConfigAttribute classNameAttr;
-    try
-    {
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_DESCRIPTION_CLASS_NAME;
-      StringConfigAttribute classStub =
-           new StringConfigAttribute(ATTR_ACCT_NOTIFICATION_HANDLER_CLASS,
-                                     getMessage(msgID), true, false, true);
-      classNameAttr = (StringConfigAttribute)
-                      configEntry.getConfigAttribute(classStub);
-
-      if (classNameAttr == null)
+      // Get the name of the class and make sure we can instantiate it as
+      // an entry cache.
+      String className = configuration.getNotificationHandlerClass();
+      try
       {
-        msgID = MSGID_CONFIG_ACCTNOTHANDLER_NO_CLASS_NAME;
-        String message = getMessage(msgID, configEntry.getDN().toString());
-        unacceptableReason.append(message);
-        return false;
+        // Load the class but don't initialize it.
+        loadNotificationHandler (className, null);
       }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
+      catch (InitializationException ie)
       {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS_NAME;
-      String message = getMessage(msgID, configEntry.getDN().toString(),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-    Class handlerClass;
-    try
-    {
-      handlerClass = DirectoryServer.loadClass(classNameAttr.pendingValue());
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS_NAME;
-      String message = getMessage(msgID, configEntry.getDN().toString(),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-    AccountStatusNotificationHandler handler;
-    try
-    {
-      handler = (AccountStatusNotificationHandler) handlerClass.newInstance();
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS;
-      String message = getMessage(msgID, handlerClass.getName(),
-                                  String.valueOf(configEntryDN),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // If the notofication handler is a configurable component, then make sure
-    // that its configuration is valid.
-    if (handler instanceof ConfigurableComponent)
-    {
-      ConfigurableComponent cc = (ConfigurableComponent) handler;
-      LinkedList<String> errorMessages = new LinkedList<String>();
-      if (! cc.hasAcceptableConfiguration(configEntry, errorMessages))
-      {
-        if (errorMessages.isEmpty())
-        {
-          int msgID = MSGID_CONFIG_ACCTNOTHANDLER_UNACCEPTABLE_CONFIG;
-          unacceptableReason.append(getMessage(msgID,
-                                               String.valueOf(configEntryDN)));
-        }
-        else
-        {
-          Iterator<String> iterator = errorMessages.iterator();
-          unacceptableReason.append(iterator.next());
-          while (iterator.hasNext())
-          {
-            unacceptableReason.append("  ");
-            unacceptableReason.append(iterator.next());
-          }
-        }
-
-        return false;
+        unacceptableReasons.add (ie.getMessage());
+        status = false;
       }
     }
 
-
-    // See if this notification handler should be enabled.
-    BooleanConfigAttribute enabledAttr;
-    try
-    {
-      BooleanConfigAttribute enabledStub =
-           new BooleanConfigAttribute(ATTR_ACCT_NOTIFICATION_HANDLER_ENABLED,
-                    getMessage(MSGID_CONFIG_ACCTNOTHANDLER_DESCRIPTION_ENABLED),
-                               false);
-      enabledAttr = (BooleanConfigAttribute)
-                    configEntry.getConfigAttribute(enabledStub);
-
-      if (enabledAttr == null)
-      {
-        int msgID = MSGID_CONFIG_ACCTNOTHANDLER_NO_ENABLED_ATTR;
-        String message = getMessage(msgID, configEntry.getDN().toString());
-        unacceptableReason.append(message);
-        return false;
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_ENABLED_VALUE;
-      String message = getMessage(msgID, configEntry.getDN().toString(),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // If we've gotten here then the notification handler entry appears to be
-    // acceptable.
-    return true;
+    return status;
   }
 
 
 
   /**
-   * 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(
+      AccountStatusNotificationHandlerCfg configuration
+      )
   {
-    DN                configEntryDN       = configEntry.getDN();
-    ResultCode        resultCode          = ResultCode.SUCCESS;
-    boolean           adminActionRequired = false;
-    ArrayList<String> messages            = new ArrayList<String>();
+    // Returned result.
+    ConfigChangeResult changeResult = new ConfigChangeResult(
+        ResultCode.SUCCESS, false, new ArrayList<String>()
+        );
 
+    // Register a change listener with it so we can be notified of changes
+    // to it over time.
+    configuration.addChangeListener(this);
 
-    // Make sure that the entry has an appropriate objectclass for an account
-    // status notification handler.
-    if (! configEntry.hasObjectClass(OC_ACCT_NOTIFICATION_HANDLER))
+    if (configuration.isEnabled())
     {
-      int    msgID   = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_OBJECTCLASS;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-      resultCode = ResultCode.UNWILLING_TO_PERFORM;
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // See if this notification handler should be enabled or disabled.
-    BooleanConfigAttribute enabledAttr;
-    try
-    {
-      BooleanConfigAttribute enabledStub =
-           new BooleanConfigAttribute(ATTR_ACCT_NOTIFICATION_HANDLER_ENABLED,
-                    getMessage(MSGID_CONFIG_ACCTNOTHANDLER_DESCRIPTION_ENABLED),
-                               false);
-      enabledAttr = (BooleanConfigAttribute)
-                    configEntry.getConfigAttribute(enabledStub);
-
-      if (enabledAttr == null)
+      // Instantiate the class as an entry cache and initialize it.
+      String className = configuration.getNotificationHandlerClass();
+      try
       {
-        // The attribute doesn't exist, so it will be disabled by default.
-        int msgID = MSGID_CONFIG_ACCTNOTHANDLER_NO_ENABLED_ATTR;
-        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-        resultCode = ResultCode.SUCCESS;
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
+        loadAndInstallNotificationHandler (className, configuration);
       }
-      else if (! enabledAttr.activeValue())
+      catch (InitializationException ie)
       {
-        // It is explicitly configured as disabled, so we don't need to do
-        // anything.
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
+        changeResult.addMessage (ie.getMessage());
+        changeResult.setResultCode (DirectoryServer.getServerErrorResultCode());
+        return changeResult;
       }
     }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
 
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_ENABLED_VALUE;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              String.valueOf(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // Make sure that the entry specifies the handler class name.
-    String className;
-    try
-    {
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_DESCRIPTION_CLASS_NAME;
-      StringConfigAttribute classStub =
-           new StringConfigAttribute(ATTR_ACCT_NOTIFICATION_HANDLER_CLASS,
-                                     getMessage(msgID), true, false, true);
-      StringConfigAttribute classNameAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
-
-      if (classNameAttr == null)
-      {
-        msgID = MSGID_CONFIG_ACCTNOTHANDLER_NO_CLASS_NAME;
-        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-
-      className = classNameAttr.pendingValue();
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS_NAME;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              String.valueOf(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // Load and initialize the notificationhandler class, and register it with
-    // the Directory Server.
-    AccountStatusNotificationHandler handler;
-    try
-    {
-      Class handlerClass = DirectoryServer.loadClass(className);
-      handler = (AccountStatusNotificationHandler) handlerClass.newInstance();
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS;
-      messages.add(getMessage(msgID, className, String.valueOf(configEntryDN),
-                              String.valueOf(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-    try
-    {
-      handler.initializeStatusNotificationHandler(configEntry);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INITIALIZATION_FAILED;
-      messages.add(getMessage(msgID, className, String.valueOf(configEntryDN),
-                              String.valueOf(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    notificationHandlers.put(configEntryDN, handler);
-    DirectoryServer.registerAccountStatusNotificationHandler(configEntryDN,
-                                                             handler);
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+    return changeResult;
   }
 
 
 
   /**
-   * 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(
+      AccountStatusNotificationHandlerCfg configuration,
+      List<String> unacceptableReasons
+      )
   {
     // A delete should always be acceptable, so just return true.
     return true;
@@ -940,33 +333,145 @@
 
 
   /**
-   * 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(
+      AccountStatusNotificationHandlerCfg configuration
+      )
   {
-    DN         configEntryDN       = configEntry.getDN();
-    ResultCode resultCode          = ResultCode.SUCCESS;
-    boolean    adminActionRequired = false;
+    // Returned result.
+    ConfigChangeResult changeResult = new ConfigChangeResult(
+        ResultCode.SUCCESS, false, new ArrayList<String>()
+        );
+
+    uninstallNotificationHandler (configuration.dn());
+
+    return changeResult;
+  }
 
 
-    // See if the entry is registered as an account status notification handler.
-    // If so, deregister it and stop the handler.
+  /**
+   * Loads the specified class, instantiates it as a notification handler,
+   * and optionally initializes that instance. Any initialized notification
+   * handler is registered in the server.
+   *
+   * @param  className      The fully-qualified name of the notification handler
+   *                        class to load, instantiate, and initialize.
+   * @param  configuration  The configuration to use to initialize the
+   *                        notification handler, or {@code null} if the
+   *                        notification handler should not be initialized.
+   *
+   * @throws  InitializationException  If a problem occurred while attempting
+   *                                   to initialize the notification handler.
+   */
+  private void loadAndInstallNotificationHandler(
+       String className,
+       AccountStatusNotificationHandlerCfg configuration
+       )
+       throws InitializationException
+  {
+    // Load the notification handler class...
+    AccountStatusNotificationHandler
+        <? extends AccountStatusNotificationHandlerCfg> handlerClass;
+    handlerClass = loadNotificationHandler (className, configuration);
+
+    // ... and install the entry cache in the server.
+    DN configEntryDN = configuration.dn();
+    notificationHandlers.put (configEntryDN, handlerClass);
+    DirectoryServer.registerAccountStatusNotificationHandler(
+        configEntryDN,
+        handlerClass
+        );
+  }
+
+
+  /**
+   * Loads the specified class, instantiates it as a notification handler,
+   * and optionally initializes that instance.
+   *
+   * @param  className      The fully-qualified name of the notification handler
+   *                        class to load, instantiate, and initialize.
+   * @param  configuration  The configuration to use to initialize the
+   *                        notification handler, or {@code null} if the
+   *                        notification handler should not be initialized.
+   *
+   * @return  The possibly initialized notification handler.
+   *
+   * @throws  InitializationException  If a problem occurred while attempting
+   *                                   to initialize the notification handler.
+   */
+  private
+    AccountStatusNotificationHandler
+       <? extends AccountStatusNotificationHandlerCfg>
+    loadNotificationHandler(
+       String className,
+       AccountStatusNotificationHandlerCfg configuration
+       )
+       throws InitializationException
+  {
+    try
+    {
+      AccountStatusNotificationHandlerCfgDefn definition;
+      ClassPropertyDefinition propertyDefinition;
+      Class<? extends AccountStatusNotificationHandler> handlerClass;
+      AccountStatusNotificationHandler
+         <? extends AccountStatusNotificationHandlerCfg> notificationHandler;
+
+      definition = AccountStatusNotificationHandlerCfgDefn.getInstance();
+      propertyDefinition =
+          definition.getNotificationHandlerClassPropertyDefinition();
+      handlerClass = propertyDefinition.loadClass(
+          className,
+          AccountStatusNotificationHandler.class
+          );
+      notificationHandler =
+        (AccountStatusNotificationHandler
+            <? extends AccountStatusNotificationHandlerCfg>)
+        handlerClass.newInstance();
+
+      if (configuration != null)
+      {
+        Method method = notificationHandler.getClass().getMethod(
+            "initializeStatusNotificationHandler",
+            configuration.definition().getServerConfigurationClass()
+            );
+        method.invoke(notificationHandler, configuration);
+      }
+
+      return notificationHandler;
+    }
+    catch (Exception e)
+    {
+      int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INITIALIZATION_FAILED;
+      String message = getMessage(
+          msgID, className,
+          String.valueOf(configuration.dn()),
+          stackTraceToSingleLineString(e)
+          );
+      throw new InitializationException(msgID, message, e);
+    }
+  }
+
+
+  /**
+   * Remove a notification handler that has been installed in the server.
+   *
+   * @param configEntryDN  the DN of the configuration enry associated to
+   *                       the notification handler to remove
+   */
+  private void uninstallNotificationHandler(
+      DN configEntryDN
+      )
+  {
     AccountStatusNotificationHandler handler =
-         notificationHandlers.remove(configEntryDN);
+        notificationHandlers.remove (configEntryDN);
     if (handler != null)
     {
-      DirectoryServer.deregisterAccountStatusNotificationHandler(configEntryDN);
-
+      DirectoryServer.deregisterAccountStatusNotificationHandler (
+          configEntryDN
+          );
       handler.finalizeStatusNotificationHandler();
     }
-
-
-    return new ConfigChangeResult(resultCode, adminActionRequired);
   }
 }
 
diff --git a/opends/src/server/org/opends/server/core/EntryCacheConfigManager.java b/opends/src/server/org/opends/server/core/EntryCacheConfigManager.java
index deda12d..b53d33b 100644
--- a/opends/src/server/org/opends/server/core/EntryCacheConfigManager.java
+++ b/opends/src/server/org/opends/server/core/EntryCacheConfigManager.java
@@ -28,24 +28,19 @@
 
 
 
+import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.List;
 
-import org.opends.server.api.ConfigAddListener;
-import org.opends.server.api.ConfigChangeListener;
-import org.opends.server.api.ConfigDeleteListener;
 import org.opends.server.api.EntryCache;
-import org.opends.server.config.BooleanConfigAttribute;
-import org.opends.server.config.ConfigEntry;
-import org.opends.server.config.StringConfigAttribute;
 import org.opends.server.extensions.DefaultEntryCache;
 import org.opends.server.types.ConfigChangeResult;
-import org.opends.server.types.DN;
 import org.opends.server.types.ErrorLogCategory;
 import org.opends.server.types.ErrorLogSeverity;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.ResultCode;
+import org.opends.server.config.ConfigException;
 
-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;
@@ -55,6 +50,16 @@
 import static org.opends.server.util.StaticUtils.*;
 
 
+import org.opends.server.admin.ClassPropertyDefinition;
+import org.opends.server.admin.server.ConfigurationAddListener;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.server.ConfigurationDeleteListener;
+import org.opends.server.admin.server.ServerManagementContext;
+import org.opends.server.admin.std.server.EntryCacheCfg;
+import org.opends.server.admin.std.server.RootCfg;
+import org.opends.server.admin.std.meta.EntryCacheCfgDefn;
+
+
 
 /**
  * This class defines a utility that will be used to manage the configuration
@@ -62,9 +67,17 @@
  * defined, but if it is absent or disabled, then a default cache will be used.
  */
 public class EntryCacheConfigManager
-       implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener
+       implements
+          ConfigurationChangeListener <EntryCacheCfg>,
+          ConfigurationAddListener    <EntryCacheCfg>,
+          ConfigurationDeleteListener <EntryCacheCfg>
 {
+  // The current entry cache registered in the server
+  private EntryCache _entryCache = null;
 
+  // The default entry cache to use when no entry cache has been configured
+  // or when the configured entry cache could not be initialized.
+  private EntryCache _defaultEntryCache = null;
 
 
   /**
@@ -76,19 +89,36 @@
   }
 
 
-
   /**
    * Initializes the configuration associated with the Directory Server entry
    * cache.  This should only be called at Directory Server startup.  If an
    * error occurs, then a message will be logged and the default entry cache
    * will be installed.
    *
+   * @throws  ConfigException  If a configuration problem causes the entry
+   *                           cache initialization process to fail.
+   *
    * @throws  InitializationException  If a problem occurs while trying to
    *                                   install the default entry cache.
    */
   public void initializeEntryCache()
-         throws InitializationException
+         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 entry cache entry is added or removed.
+    // If entry cache configuration is using a one-to-zero-or-one relation
+    // then uncomment the lines below (see issue #1558).
+    /*
+    // rootConfiguration.addEntryCacheAddListener(this);
+    // rootConfiguration.addEntryCacheDeleteListener(this);
+    */
+
     // First, install a default entry cache so that there will be one even if
     // we encounter a problem later.
     try
@@ -96,6 +126,7 @@
       DefaultEntryCache defaultCache = new DefaultEntryCache();
       defaultCache.initializeEntryCache(null);
       DirectoryServer.setEntryCache(defaultCache);
+      _defaultEntryCache = defaultCache;
     }
     catch (Exception e)
     {
@@ -109,377 +140,336 @@
       throw new InitializationException(msgID, message, e);
     }
 
+    // If the entry cache configuration is not present then keep the
+    // default entry cache already installed.
+    // If entry cache configuration is using a one-to-zero-or-one relation
+    // then uncomment the lines below (see issue #1558).
+    /*
+    //    if (!rootConfiguration.hasEntryCache())
+    //    {
+    //      logError(
+    //          ErrorLogCategory.CONFIGURATION,
+    //          ErrorLogSeverity.SEVERE_WARNING,
+    //          MSGID_CONFIG_ENTRYCACHE_NO_CONFIG_ENTRY
+    //          );
+    //      return;
+    //    }
+    */
 
-    // Get the entry cache configuration entry.  If it is not present, then
-    // register an add listener and install the default cache.
-    DN configEntryDN;
-    ConfigEntry configEntry;
-    try
+    // Get the entry cache configuration.
+    EntryCacheCfg configuration = rootConfiguration.getEntryCache();
+
+    // At this point, we have a configuration entry. Register a change
+    // listener with it so we can be notified of changes to it over time.
+    configuration.addChangeListener(this);
+
+    // Initialize the entry cache.
+    if (configuration.isEnabled())
     {
-      configEntryDN = DN.decode(DN_ENTRY_CACHE_CONFIG);
-      configEntry   = DirectoryServer.getConfigEntry(configEntryDN);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-               MSGID_CONFIG_ENTRYCACHE_CANNOT_GET_CONFIG_ENTRY,
-               stackTraceToSingleLineString(e));
-      return;
-    }
-
-    if (configEntry == null)
-    {
-      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING,
-               MSGID_CONFIG_ENTRYCACHE_NO_CONFIG_ENTRY);
-
+      // Load the entry cache implementation class and install the entry
+      // cache with the server.
+      String className = configuration.getEntryCacheClass();
       try
       {
-        ConfigEntry parentEntry = DirectoryServer
-            .getConfigEntry(configEntryDN.getParentDNInSuffix());
-        if (parentEntry != null)
-        {
-          parentEntry.registerAddListener(this);
-        }
+        loadAndInstallEntryCache (className, configuration);
       }
-      catch (Exception e)
+      catch (InitializationException ie)
       {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 MSGID_CONFIG_ENTRYCACHE_CANNOT_REGISTER_ADD_LISTENER,
-                 stackTraceToSingleLineString(e));
+        logError(
+            ErrorLogCategory.CONFIGURATION,
+            ErrorLogSeverity.SEVERE_ERROR,
+            ie.getMessage(),
+            ie.getMessageID());
       }
+    }
+  }
 
-      return;
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationChangeAcceptable(
+      EntryCacheCfg configuration,
+      List<String>  unacceptableReasons
+      )
+  {
+    // returned status -- all is fine by default
+    boolean status = true;
+
+    if (configuration.isEnabled())
+    {
+      // Get the name of the class and make sure we can instantiate it as an
+      // entry cache.
+      String className = configuration.getEntryCacheClass();
+      try
+      {
+        // Load the class but don't initialize it.
+        loadEntryCache(className, null);
+      }
+      catch (InitializationException ie)
+      {
+        unacceptableReasons.add(ie.getMessage());
+        status = false;
+      }
     }
 
+    return status;
+  }
 
-    // At this point, we have a configuration entry.  Register a change listener
-    // with it so we can be notified of changes to it over time.  We will also
-    // want to register a delete listener with its parent to allow us to
-    // determine if the entry is deleted.
-    configEntry.registerChangeListener(this);
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationChange(
+      EntryCacheCfg configuration
+      )
+  {
+    // Returned result.
+    ConfigChangeResult changeResult = new ConfigChangeResult(
+        ResultCode.SUCCESS, false, new ArrayList<String>()
+        );
+
+    // If the new configuration has the entry cache disabled, then install
+    // the default entry cache with the server.
+    if (! configuration.isEnabled())
+    {
+      DirectoryServer.setEntryCache (_defaultEntryCache);
+
+      // If an entry cache was installed then clean it.
+      if (_entryCache != null)
+      {
+        _entryCache.finalizeEntryCache();
+        _entryCache = null;
+      }
+      return changeResult;
+    }
+
+    // At this point, new configuration is enabled...
+    // If the current entry cache is already enabled then we don't do
+    // anything unless the class has changed in which case we should
+    // indicate that administrative action is required.
+    String newClassName = configuration.getEntryCacheClass();
+    if (_entryCache !=null)
+    {
+      String curClassName = _entryCache.getClass().getName();
+      boolean classIsNew = (! newClassName.equals (curClassName));
+      if (classIsNew)
+      {
+        changeResult.setAdminActionRequired (true);
+      }
+      return changeResult;
+    }
+
+    // New entry cache is enabled and there were no previous one.
+    // Instantiate the new class and initalize it.
     try
     {
-      DN parentDN = configEntryDN.getParentDNInSuffix();
-      ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN);
-      if (parentEntry != null)
+      loadAndInstallEntryCache (newClassName, configuration);
+    }
+    catch (InitializationException ie)
+    {
+      changeResult.addMessage (ie.getMessage());
+      changeResult.setResultCode (DirectoryServer.getServerErrorResultCode());
+      return changeResult;
+    }
+
+    return changeResult;
+  }
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationAddAcceptable(
+      EntryCacheCfg configuration,
+      List<String>  unacceptableReasons
+      )
+  {
+    // returned status -- all is fine by default
+    boolean status = true;
+
+    if (configuration.isEnabled())
+    {
+      // Get the name of the class and make sure we can instantiate it as
+      // an entry cache.
+      String className = configuration.getEntryCacheClass();
+      try
       {
-        parentEntry.registerDeleteListener(this);
+        // Load the class but don't initialize it.
+        loadEntryCache(className, null);
+      }
+      catch (InitializationException ie)
+      {
+        unacceptableReasons.add (ie.getMessage());
+        status = false;
       }
     }
-    catch (Exception e)
+
+    return status;
+  }
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationAdd(
+      EntryCacheCfg configuration
+      )
+  {
+    // Returned result.
+    ConfigChangeResult changeResult = new ConfigChangeResult(
+        ResultCode.SUCCESS, false, new ArrayList<String>()
+        );
+
+    // Register a change listener with it so we can be notified of changes
+    // to it over time.
+    configuration.addChangeListener(this);
+
+    if (configuration.isEnabled())
     {
-      if (debugEnabled())
+      // Instantiate the class as an entry cache and initialize it.
+      String className = configuration.getEntryCacheClass();
+      try
       {
-        debugCaught(DebugLogLevel.ERROR, e);
+        loadAndInstallEntryCache (className, configuration);
       }
-
-      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING,
-               MSGID_CONFIG_ENTRYCACHE_CANNOT_REGISTER_DELETE_LISTENER,
-               stackTraceToSingleLineString(e));
-    }
-
-
-    // See if the entry indicates whether the cache should be enabled.
-    int msgID = MSGID_CONFIG_ENTRYCACHE_DESCRIPTION_CACHE_ENABLED;
-    BooleanConfigAttribute enabledStub =
-         new BooleanConfigAttribute(ATTR_ENTRYCACHE_ENABLED, getMessage(msgID),
-                                    false);
-    try
-    {
-      BooleanConfigAttribute enabledAttr =
-           (BooleanConfigAttribute)
-           configEntry.getConfigAttribute(enabledStub);
-      if (enabledAttr == null)
+      catch (InitializationException ie)
       {
-        // The attribute is not present, so the entry cache will be disabled.
-        // Log a warning message and return.
-        logError(ErrorLogCategory.CONFIGURATION,
-                 ErrorLogSeverity.SEVERE_WARNING,
-                 MSGID_CONFIG_ENTRYCACHE_NO_ENABLED_ATTR);
-        return;
-      }
-      else if (! enabledAttr.activeValue())
-      {
-        // The entry cache is explicitly disabled.  Log a mild warning and
-        // return.
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_WARNING,
-                 MSGID_CONFIG_ENTRYCACHE_DISABLED);
-        return;
+        changeResult.addMessage (ie.getMessage());
+        changeResult.setResultCode (DirectoryServer.getServerErrorResultCode());
+        return changeResult;
       }
     }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
 
-      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-               MSGID_CONFIG_ENTRYCACHE_UNABLE_TO_DETERMINE_ENABLED_STATE,
-               stackTraceToSingleLineString(e));
-      return;
+    return changeResult;
+  }
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationDeleteAcceptable(
+      EntryCacheCfg configuration,
+      List<String>  unacceptableReasons
+      )
+  {
+    // NYI
+
+    // If we've gotten to this point, then it is acceptable as far as we are
+    // concerned.  If it is unacceptable according to the configuration, then
+    // the entry cache itself will make that determination.
+    return true;
+  }
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationDelete(
+      EntryCacheCfg configuration
+      )
+  {
+    // Returned result.
+    ConfigChangeResult changeResult = new ConfigChangeResult(
+        ResultCode.SUCCESS, false, new ArrayList<String>()
+        );
+
+    // If the entry cache was installed then replace it with the
+    // default entry cache, and clean it.
+    if (_entryCache != null)
+    {
+      DirectoryServer.setEntryCache (_defaultEntryCache);
+      _entryCache.finalizeEntryCache();
+      _entryCache = null;
     }
 
-
-    // See if it specifies the class name for the entry cache implementation.
-    String className;
-    msgID = MSGID_CONFIG_ENTRYCACHE_DESCRIPTION_CACHE_CLASS;
-    StringConfigAttribute classStub =
-         new StringConfigAttribute(ATTR_ENTRYCACHE_CLASS, getMessage(msgID),
-                                   true, false, false);
-    try
-    {
-      StringConfigAttribute classAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
-      if (classAttr == null)
-      {
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 MSGID_CONFIG_ENTRYCACHE_NO_CLASS_ATTR);
-        return;
-      }
-      else
-      {
-        className = classAttr.activeValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-               MSGID_CONFIG_ENTRYCACHE_CANNOT_DETERMINE_CLASS,
-               stackTraceToSingleLineString(e));
-      return;
-    }
+    return changeResult;
+  }
 
 
-    // Try to load the class and instantiate it as an entry cache.
-    Class cacheClass;
-    try
-    {
-      cacheClass = DirectoryServer.loadClass(className);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
+  /**
+   * Loads the specified class, instantiates it as an entry cache,
+   * and optionally initializes that instance. Any initialize entry
+   * cache is registered in the server.
+   *
+   * @param  className      The fully-qualified name of the entry cache
+   *                        class to load, instantiate, and initialize.
+   * @param  configuration  The configuration to use to initialize the
+   *                        entry cache, or {@code null} if the
+   *                        entry cache should not be initialized.
+   *
+   * @throws  InitializationException  If a problem occurred while attempting
+   *                                   to initialize the entry cache.
+   */
+  private void loadAndInstallEntryCache(
+    String        className,
+    EntryCacheCfg configuration
+    )
+    throws InitializationException
+  {
+    // Load the entry cache class...
+    EntryCache entryCache = loadEntryCache (className, configuration);
 
-      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-               MSGID_CONFIG_ENTRYCACHE_CANNOT_LOAD_CLASS,
-               String.valueOf(className), stackTraceToSingleLineString(e));
-      return;
-    }
-
-    EntryCache entryCache;
-    try
-    {
-      entryCache = (EntryCache) cacheClass.newInstance();
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-               MSGID_CONFIG_ENTRYCACHE_CANNOT_INSTANTIATE_CLASS,
-               String.valueOf(className), stackTraceToSingleLineString(e));
-      return;
-    }
-
-
-    // Try to initialize the cache with the contents of the configuration entry.
-    try
-    {
-      entryCache.initializeEntryCache(configEntry);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-               MSGID_CONFIG_ENTRYCACHE_CANNOT_INITIALIZE_CACHE,
-               String.valueOf(className), stackTraceToSingleLineString(e));
-      return;
-    }
-
-
-    // Install the new cache with the server.  We don't need to do anything to
-    // get rid of the previous default cache since it doesn't consume any
-    // resources.
+    // ... and install the entry cache in the server.
     DirectoryServer.setEntryCache(entryCache);
+    _entryCache = entryCache;
   }
 
 
-
   /**
-   * Indicates whether the configuration entry that will result from a proposed
-   * modification is acceptable to this change listener.
+   * Loads the specified class, instantiates it as an entry cache,
+   * and optionally initializes that instance.
    *
-   * @param  configEntry         The configuration entry that will result from
-   *                             the requested update.
-   * @param  unacceptableReason  A buffer to which this method can append a
-   *                             human-readable message explaining why the
-   *                             proposed change is not acceptable.
+   * @param  className      The fully-qualified name of the entry cache
+   *                        class to load, instantiate, and initialize.
+   * @param  configuration  The configuration to use to initialize the
+   *                        entry cache, or {@code null} if the
+   *                        entry cache should not be initialized.
    *
-   * @return  <CODE>true</CODE> if the proposed entry contains an acceptable
-   *          configuration, or <CODE>false</CODE> if it does not.
+   * @return  The possibly initialized entry cache.
+   *
+   * @throws  InitializationException  If a problem occurred while attempting
+   *                                   to initialize the entry cache.
    */
-  public boolean configChangeIsAcceptable(ConfigEntry configEntry,
-                                          StringBuilder unacceptableReason)
+  private EntryCache<? extends EntryCacheCfg> loadEntryCache(
+    String        className,
+    EntryCacheCfg configuration
+    )
+    throws InitializationException
   {
-    // NYI
+    try
+    {
+      EntryCacheCfgDefn                   definition;
+      ClassPropertyDefinition             propertyDefinition;
+      Class<? extends EntryCache>         cacheClass;
+      EntryCache<? extends EntryCacheCfg> cache;
 
+      definition = EntryCacheCfgDefn.getInstance();
+      propertyDefinition = definition.getEntryCacheClassPropertyDefinition();
+      cacheClass = propertyDefinition.loadClass(className, EntryCache.class);
+      cache = (EntryCache<? extends EntryCacheCfg>) cacheClass.newInstance();
 
-    // If we've gotten to this point, then it is acceptable as far as we are
-    // concerned.  If it is unacceptable according to the configuration, then
-    // the entry cache itself will make that determination.
-    return true;
+      if (configuration != null)
+      {
+        Method method = cache.getClass().getMethod(
+            "initializeEntryCache",
+            configuration.definition().getServerConfigurationClass()
+            );
+        method.invoke(cache, configuration);
+      }
+
+      return cache;
+    }
+    catch (Exception e)
+    {
+      int msgID = MSGID_CONFIG_ENTRYCACHE_CANNOT_INITIALIZE_CACHE;
+      String message = getMessage(
+          msgID, className,
+          String.valueOf(configuration.dn()),
+          stackTraceToSingleLineString(e)
+          );
+      throw new InitializationException(msgID, message, e);
+    }
   }
 
-
-
-  /**
-   * Attempts to apply a new configuration to this Directory Server component
-   * based on the provided changed entry.
-   *
-   * @param  configEntry  The configuration entry that containing the updated
-   *                      configuration for this component.
-   *
-   * @return  Information about the result of processing the configuration
-   *          change.
-   */
-  public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry)
-  {
-    ResultCode        resultCode          = ResultCode.SUCCESS;
-    boolean           adminActionRequired = false;
-    ArrayList<String> messages            = new ArrayList<String>();
-
-
-    // NYI
-
-
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-  }
-
-
-
-  /**
-   * Indicates whether the configuration entry that will result from a proposed
-   * add is acceptable to this add listener.
-   *
-   * @param  configEntry         The configuration entry that will result from
-   *                             the requested add.
-   * @param  unacceptableReason  A buffer to which this method can append a
-   *                             human-readable message explaining why the
-   *                             proposed entry is not acceptable.
-   *
-   * @return  <CODE>true</CODE> if the proposed entry contains an acceptable
-   *          configuration, or <CODE>false</CODE> if it does not.
-   */
-  public boolean configAddIsAcceptable(ConfigEntry configEntry,
-                                       StringBuilder unacceptableReason)
-  {
-    // NYI
-
-
-    // If we've gotten to this point, then it is acceptable as far as we are
-    // concerned.  If it is unacceptable according to the configuration, then
-    // the entry cache itself will make that determination.
-    return true;
-  }
-
-
-
-  /**
-   * Attempts to apply a new configuration based on the provided added entry.
-   *
-   * @param  configEntry  The new configuration entry that contains the
-   *                      configuration to apply.
-   *
-   * @return  Information about the result of processing the configuration
-   *          change.
-   */
-  public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry)
-  {
-    ResultCode        resultCode          = ResultCode.SUCCESS;
-    boolean           adminActionRequired = false;
-    ArrayList<String> messages            = new ArrayList<String>();
-
-
-    // NYI
-
-
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-  }
-
-
-
-  /**
-   * Indicates whether it is acceptable to remove the provided configuration
-   * entry.
-   *
-   * @param  configEntry         The configuration entry that will be removed
-   *                             from the configuration.
-   * @param  unacceptableReason  A buffer to which this method can append a
-   *                             human-readable message explaining why the
-   *                             proposed delete is not acceptable.
-   *
-   * @return  <CODE>true</CODE> if the proposed entry may be removed from the
-   *          configuration, or <CODE>false</CODE> if not.
-   */
-  public boolean configDeleteIsAcceptable(ConfigEntry configEntry,
-                                          StringBuilder unacceptableReason)
-  {
-    // NYI
-
-
-    // If we've gotten to this point, then it is acceptable as far as we are
-    // concerned.  If it is unacceptable according to the configuration, then
-    // the entry cache itself will make that determination.
-    return true;
-  }
-
-
-
-  /**
-   * Attempts to apply a new configuration based on the provided deleted entry.
-   *
-   * @param  configEntry  The new configuration entry that has been deleted.
-   *
-   * @return  Information about the result of processing the configuration
-   *          change.
-   */
-  public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry)
-  {
-    ResultCode        resultCode          = ResultCode.SUCCESS;
-    boolean           adminActionRequired = false;
-    ArrayList<String> messages            = new ArrayList<String>();
-
-
-    // NYI
-
-
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-  }
 }
-
diff --git a/opends/src/server/org/opends/server/core/PasswordStorageSchemeConfigManager.java b/opends/src/server/org/opends/server/core/PasswordStorageSchemeConfigManager.java
index da4632f..1081d4d 100644
--- a/opends/src/server/org/opends/server/core/PasswordStorageSchemeConfigManager.java
+++ b/opends/src/server/org/opends/server/core/PasswordStorageSchemeConfigManager.java
@@ -28,39 +28,30 @@
 
 
 
+import static org.opends.server.messages.ConfigMessages.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
+
+import java.lang.reflect.Method;
 import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 
-import org.opends.server.api.ConfigAddListener;
-import org.opends.server.api.ConfigChangeListener;
-import org.opends.server.api.ConfigDeleteListener;
-import org.opends.server.api.ConfigHandler;
-import org.opends.server.api.ConfigurableComponent;
+import org.opends.server.admin.ClassPropertyDefinition;
+import org.opends.server.admin.server.ConfigurationAddListener;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.server.ConfigurationDeleteListener;
+import org.opends.server.admin.server.ServerManagementContext;
+import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
+import org.opends.server.admin.std.server.RootCfg;
 import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.config.BooleanConfigAttribute;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
-import org.opends.server.config.StringConfigAttribute;
 import org.opends.server.types.ConfigChangeResult;
 import org.opends.server.types.DN;
-import org.opends.server.types.ErrorLogCategory;
-import org.opends.server.types.ErrorLogSeverity;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.ResultCode;
 
-import static org.opends.server.config.ConfigConstants.*;
-import static org.opends.server.loggers.debug.DebugLogger.debugCaught;
-import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
-import org.opends.server.types.DebugLogLevel;
-import static org.opends.server.loggers.Error.*;
-import static org.opends.server.messages.ConfigMessages.*;
-import static org.opends.server.messages.MessageHandler.*;
-import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
-
 
 
 /**
@@ -70,26 +61,21 @@
  * removals, or modifications to any schemes while the server is running.
  */
 public class PasswordStorageSchemeConfigManager
-       implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener
+       implements
+          ConfigurationChangeListener <PasswordStorageSchemeCfg>,
+          ConfigurationAddListener    <PasswordStorageSchemeCfg>,
+          ConfigurationDeleteListener <PasswordStorageSchemeCfg>
 {
-
-
-
   // A mapping between the DNs of the config entries and the associated password
   // storage schemes.
   private ConcurrentHashMap<DN,PasswordStorageScheme> storageSchemes;
 
-  // The configuration handler for the Directory Server.
-  private ConfigHandler configHandler;
-
-
 
   /**
    * Creates a new instance of this password storage scheme config manager.
    */
   public PasswordStorageSchemeConfigManager()
   {
-    configHandler  = DirectoryServer.getConfigHandler();
     storageSchemes = new ConcurrentHashMap<DN,PasswordStorageScheme>();
   }
 
@@ -110,99 +96,35 @@
   public void initializePasswordStorageSchemes()
          throws ConfigException, InitializationException
   {
-    // First, get the configuration base entry.
-    ConfigEntry baseEntry;
-    try
+    // 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 entry cache entry is added or removed.
+    rootConfiguration.addPasswordStorageSchemeAddListener (this);
+    rootConfiguration.addPasswordStorageSchemeDeleteListener (this);
+
+    // Initialize existing password storage schemes.
+    for (String schemeName: rootConfiguration.listPasswordStorageSchemes())
     {
-      DN schemeBase = DN.decode(DN_PWSCHEME_CONFIG_BASE);
-      baseEntry = configHandler.getConfigEntry(schemeBase);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
+      // Get the password storage scheme's configuration.
+      PasswordStorageSchemeCfg config =
+        rootConfiguration.getPasswordStorageScheme (schemeName);
+
+      // Register as a change listener for this password storage scheme
+      // entry so that we will be notified of any changes that may be
+      // made to it.
+      config.addChangeListener (this);
+
+      // Ignore this password storage scheme if it is disabled.
+      if (config.isEnabled())
       {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int    msgID   = MSGID_CONFIG_PWSCHEME_CANNOT_GET_BASE;
-      String message = getMessage(msgID, String.valueOf(e));
-      throw new ConfigException(msgID, message, e);
-    }
-
-    if (baseEntry == null)
-    {
-      // The password storage scheme base entry does not exist.  This is not
-      // acceptable, so throw an exception.
-      int    msgID   = MSGID_CONFIG_PWSCHEME_BASE_DOES_NOT_EXIST;
-      String message = getMessage(msgID);
-      throw new ConfigException(msgID, message);
-    }
-
-
-    // Register add and delete listeners with the storage scheme base entry.  We
-    // don't care about modifications to it.
-    baseEntry.registerAddListener(this);
-    baseEntry.registerDeleteListener(this);
-
-
-    // See if the base entry has any children.  If not, then we don't need to do
-    // anything else.
-    if (! baseEntry.hasChildren())
-    {
-      return;
-    }
-
-
-    // Iterate through the child entries and process them as password storage
-    // scheme configuration entries.
-    for (ConfigEntry childEntry : baseEntry.getChildren().values())
-    {
-      childEntry.registerChangeListener(this);
-
-      StringBuilder unacceptableReason = new StringBuilder();
-      if (! configAddIsAcceptable(childEntry, unacceptableReason))
-      {
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 MSGID_CONFIG_PWSCHEME_ENTRY_UNACCEPTABLE,
-                 childEntry.getDN().toString(), unacceptableReason.toString());
-        continue;
-      }
-
-      try
-      {
-        ConfigChangeResult result = applyConfigurationAdd(childEntry);
-        if (result.getResultCode() != ResultCode.SUCCESS)
-        {
-          StringBuilder buffer = new StringBuilder();
-
-          List<String> resultMessages = result.getMessages();
-          if ((resultMessages == null) || (resultMessages.isEmpty()))
-          {
-            buffer.append(getMessage(MSGID_CONFIG_UNKNOWN_UNACCEPTABLE_REASON));
-          }
-          else
-          {
-            Iterator<String> iterator = resultMessages.iterator();
-
-            buffer.append(iterator.next());
-            while (iterator.hasNext())
-            {
-              buffer.append(EOL);
-              buffer.append(iterator.next());
-            }
-          }
-
-          logError(ErrorLogCategory.CONFIGURATION,
-                   ErrorLogSeverity.SEVERE_ERROR,
-                   MSGID_CONFIG_PWSCHEME_CANNOT_CREATE_SCHEME,
-                   childEntry.getDN().toString(), buffer.toString());
-        }
-      }
-      catch (Exception e)
-      {
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 MSGID_CONFIG_PWSCHEME_CANNOT_CREATE_SCHEME,
-                 childEntry.getDN().toString(), String.valueOf(e));
+        // Load the password storage scheme implementation class.
+        String className = config.getSchemeClass();
+        loadAndInstallPasswordStorageScheme (className, config);
       }
     }
   }
@@ -210,720 +132,192 @@
 
 
   /**
-   * Indicates whether the configuration entry that will result from a proposed
-   * modification is acceptable to this change listener.
-   *
-   * @param  configEntry         The configuration entry that will result from
-   *                             the requested update.
-   * @param  unacceptableReason  A buffer to which this method can append a
-   *                             human-readable message explaining why the
-   *                             proposed change is not acceptable.
-   *
-   * @return  <CODE>true</CODE> if the proposed entry contains an acceptable
-   *          configuration, or <CODE>false</CODE> if it does not.
+   * {@inheritDoc}
    */
-  public boolean configChangeIsAcceptable(ConfigEntry configEntry,
-                                          StringBuilder unacceptableReason)
+  public boolean isConfigurationChangeAcceptable(
+      PasswordStorageSchemeCfg configuration,
+      List<String>             unacceptableReasons
+      )
   {
-    // Make sure that the entry has an appropriate objectclass for a password
-    // storage scheme.
-    if (! configEntry.hasObjectClass(OC_PASSWORD_STORAGE_SCHEME))
+    // returned status -- all is fine by default
+    boolean status = true;
+
+    if (configuration.isEnabled())
     {
-      int    msgID   = MSGID_CONFIG_PWSCHEME_INVALID_OBJECTCLASS;
-      String message = getMessage(msgID, configEntry.getDN().toString());
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // Make sure that the entry specifies the storage scheme class name.
-    StringConfigAttribute classNameAttr;
-    try
-    {
-      StringConfigAttribute classStub =
-           new StringConfigAttribute(ATTR_PWSCHEME_CLASS,
-                    getMessage(MSGID_CONFIG_PWSCHEME_DESCRIPTION_CLASS_NAME),
-                    true, false, true);
-      classNameAttr = (StringConfigAttribute)
-                      configEntry.getConfigAttribute(classStub);
-
-      if (classNameAttr == null)
+      // Get the name of the class and make sure we can instantiate it as
+      // a password storage scheme.
+      String className = configuration.getSchemeClass();
+      try
       {
-        int msgID = MSGID_CONFIG_PWSCHEME_NO_CLASS_NAME;
-        String message = getMessage(msgID, configEntry.getDN().toString());
-        unacceptableReason.append(message);
-        return false;
+        // Load the class but don't initialize it.
+        loadPasswordStorageScheme (className, null);
+      }
+      catch (InitializationException ie)
+      {
+        unacceptableReasons.add(ie.getMessage());
+        status = false;
       }
     }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
 
-      int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS_NAME;
-      String message = getMessage(msgID, configEntry.getDN().toString(),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-    Class schemeClass;
-    try
-    {
-      schemeClass = DirectoryServer.loadClass(classNameAttr.pendingValue());
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS_NAME;
-      String message = getMessage(msgID, configEntry.getDN().toString(),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-    try
-    {
-      PasswordStorageScheme scheme =
-           (PasswordStorageScheme) schemeClass.newInstance();
-    }
-    catch(Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS;
-      String message = getMessage(msgID, schemeClass.getName(),
-                                  String.valueOf(configEntry.getDN()),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // See if this password storage scheme should be enabled.
-    BooleanConfigAttribute enabledAttr;
-    try
-    {
-      BooleanConfigAttribute enabledStub =
-           new BooleanConfigAttribute(ATTR_PWSCHEME_ENABLED,
-                    getMessage(MSGID_CONFIG_PWSCHEME_DESCRIPTION_ENABLED),
-                               false);
-      enabledAttr = (BooleanConfigAttribute)
-                    configEntry.getConfigAttribute(enabledStub);
-
-      if (enabledAttr == null)
-      {
-        int msgID = MSGID_CONFIG_PWSCHEME_NO_ENABLED_ATTR;
-        String message = getMessage(msgID, configEntry.getDN().toString());
-        unacceptableReason.append(message);
-        return false;
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_PWSCHEME_INVALID_ENABLED_VALUE;
-      String message = getMessage(msgID, configEntry.getDN().toString(),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // If we've gotten here then the password storage scheme entry appears to be
-    // acceptable.
-    return true;
+    return status;
   }
 
 
 
   /**
-   * Attempts to apply a new configuration to this Directory Server component
-   * based on the provided changed entry.
-   *
-   * @param  configEntry  The configuration entry that containing the updated
-   *                      configuration for this component.
-   *
-   * @return  Information about the result of processing the configuration
-   *          change.
+   * {@inheritDoc}
    */
-  public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry)
+  public ConfigChangeResult applyConfigurationChange(
+      PasswordStorageSchemeCfg configuration
+      )
   {
-    DN                configEntryDN       = configEntry.getDN();
-    ResultCode        resultCode          = ResultCode.SUCCESS;
-    boolean           adminActionRequired = false;
-    ArrayList<String> messages            = new ArrayList<String>();
+    // Returned result.
+    ConfigChangeResult changeResult = new ConfigChangeResult(
+        ResultCode.SUCCESS, false, new ArrayList<String>()
+        );
 
+    // Get the configuration entry DN and the associated
+    // password storage scheme class.
+    DN configEntryDN = configuration.dn();
+    PasswordStorageScheme storageScheme = storageSchemes.get(
+        configEntryDN
+        );
 
-    // Make sure that the entry has an appropriate objectclass for a password
-    // storage scheme.
-    if (! configEntry.hasObjectClass(OC_PASSWORD_STORAGE_SCHEME))
+    // If the new configuration has the password storage scheme disabled,
+    // then remove it from the mapping list and clean it.
+    if (! configuration.isEnabled())
     {
-      int    msgID   = MSGID_CONFIG_PWSCHEME_INVALID_OBJECTCLASS;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-      resultCode = ResultCode.UNWILLING_TO_PERFORM;
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+      if (storageScheme != null)
+      {
+        uninstallPasswordStorageScheme (configEntryDN);
+      }
+
+      return changeResult;
     }
 
+    // At this point, new configuration is enabled...
+    // If the current password storage scheme is already enabled then we
+    // don't do anything unless the class has changed in which case we
+    // should indicate that administrative action is required.
+    String newClassName = configuration.getSchemeClass();
+    if (storageScheme != null)
+    {
+      String curClassName = storageScheme.getClass().getName();
+      boolean classIsNew = (! newClassName.equals (curClassName));
+      if (classIsNew)
+      {
+        changeResult.setAdminActionRequired (true);
+      }
+      return changeResult;
+    }
 
-    // Get the corresponding password storage scheme if it is active.
-    PasswordStorageScheme scheme = storageSchemes.get(configEntryDN);
-
-
-    // See if this scheme should be enabled or disabled.
-    boolean needsEnabled = false;
-    BooleanConfigAttribute enabledAttr;
+    // New entry cache is enabled and there were no previous one.
+    // Instantiate the new class and initalize it.
     try
     {
-      BooleanConfigAttribute enabledStub =
-           new BooleanConfigAttribute(ATTR_PWSCHEME_ENABLED,
-                    getMessage(MSGID_CONFIG_PWSCHEME_DESCRIPTION_ENABLED),
-                               false);
-      enabledAttr = (BooleanConfigAttribute)
-                    configEntry.getConfigAttribute(enabledStub);
-
-      if (enabledAttr == null)
-      {
-        int msgID = MSGID_CONFIG_PWSCHEME_NO_ENABLED_ATTR;
-        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-        resultCode = ResultCode.UNWILLING_TO_PERFORM;
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-
-      if (enabledAttr.activeValue())
-      {
-        if (scheme == null)
-        {
-          needsEnabled = true;
-        }
-        else
-        {
-          // The scheme is already active, so no action is required.
-        }
-      }
-      else
-      {
-        if (scheme == null)
-        {
-          // The scheme is already disabled, so no action is required and we
-          // can short-circuit out of this processing.
-          return new ConfigChangeResult(resultCode, adminActionRequired,
-                                        messages);
-        }
-        else
-        {
-          // The scheme is active, so it needs to be disabled.  Do this and
-          // return that we were successful.
-          storageSchemes.remove(configEntryDN);
-          scheme.finalizePasswordStorageScheme();
-
-          String lowerName = toLowerCase(scheme.getStorageSchemeName());
-          DirectoryServer.deregisterPasswordStorageScheme(lowerName);
-
-          return new ConfigChangeResult(resultCode, adminActionRequired,
-                                        messages);
-        }
-      }
+      loadAndInstallPasswordStorageScheme (newClassName, configuration);
     }
-    catch (Exception e)
+    catch (InitializationException ie)
     {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_PWSCHEME_INVALID_ENABLED_VALUE;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              String.valueOf(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+      changeResult.addMessage (ie.getMessage());
+      changeResult.setResultCode (DirectoryServer.getServerErrorResultCode());
+      return changeResult;
     }
 
-
-    // Make sure that the entry specifies the storage scheme class name.  If it
-    // has changed, then we will not try to dynamically apply it.
-    String className;
-    try
-    {
-      StringConfigAttribute classStub =
-           new StringConfigAttribute(ATTR_PWSCHEME_CLASS,
-                    getMessage(MSGID_CONFIG_PWSCHEME_DESCRIPTION_CLASS_NAME),
-                    true, false, true);
-      StringConfigAttribute classNameAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
-
-      if (classNameAttr == null)
-      {
-        int msgID = MSGID_CONFIG_PWSCHEME_NO_CLASS_NAME;
-        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-
-      className = classNameAttr.pendingValue();
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS_NAME;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              String.valueOf(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    boolean classChanged = false;
-    String  oldClassName = null;
-    if (scheme != null)
-    {
-      oldClassName = scheme.getClass().getName();
-      classChanged = (! className.equals(oldClassName));
-    }
-
-
-    if (classChanged)
-    {
-      // This will not be applied dynamically.  Add a message to the response
-      // and indicate that admin action is required.
-      adminActionRequired = true;
-      messages.add(getMessage(MSGID_CONFIG_PWSCHEME_CLASS_ACTION_REQUIRED,
-                              String.valueOf(oldClassName),
-                              String.valueOf(className),
-                              String.valueOf(configEntryDN)));
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    if (needsEnabled)
-    {
-      try
-      {
-        Class schemeClass = DirectoryServer.loadClass(className);
-        scheme = (PasswordStorageScheme) schemeClass.newInstance();
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS;
-        messages.add(getMessage(msgID, className,
-                                String.valueOf(configEntryDN),
-                                String.valueOf(e)));
-        resultCode = DirectoryServer.getServerErrorResultCode();
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-
-      try
-      {
-        scheme.initializePasswordStorageScheme(configEntry);
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        int msgID = MSGID_CONFIG_PWSCHEME_INITIALIZATION_FAILED;
-        messages.add(getMessage(msgID, className,
-                                String.valueOf(configEntryDN),
-                                String.valueOf(e)));
-        resultCode = DirectoryServer.getServerErrorResultCode();
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-
-
-      storageSchemes.put(configEntryDN, scheme);
-      DirectoryServer.registerPasswordStorageScheme(scheme);
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // If we've gotten here, then there haven't been any changes to anything
-    // that we care about.
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+    return changeResult;
   }
 
 
 
   /**
-   * 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(
+      PasswordStorageSchemeCfg configuration,
+      List<String>             unacceptableReasons
+      )
   {
+    // returned status -- all is fine by default
+    boolean status = true;
+
     // Make sure that no entry already exists with the specified DN.
-    DN configEntryDN = configEntry.getDN();
+    DN configEntryDN = configuration.dn();
     if (storageSchemes.containsKey(configEntryDN))
     {
       int    msgID   = MSGID_CONFIG_PWSCHEME_EXISTS;
       String message = getMessage(msgID, String.valueOf(configEntryDN));
-      unacceptableReason.append(message);
-      return false;
+      unacceptableReasons.add (message);
+      status = false;
     }
-
-
-    // Make sure that the entry has an appropriate objectclass for a password
-    // storage scheme.
-    if (! configEntry.hasObjectClass(OC_PASSWORD_STORAGE_SCHEME))
+    // If configuration is enabled then check that password storage scheme
+    // class can be instantiated.
+    else if (configuration.isEnabled())
     {
-      int    msgID   = MSGID_CONFIG_PWSCHEME_INVALID_OBJECTCLASS;
-      String message = getMessage(msgID, configEntry.getDN().toString());
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // Make sure that the entry specifies the password storage scheme class.
-    StringConfigAttribute classNameAttr;
-    try
-    {
-      StringConfigAttribute classStub =
-           new StringConfigAttribute(ATTR_PWSCHEME_CLASS,
-                    getMessage(MSGID_CONFIG_PWSCHEME_DESCRIPTION_CLASS_NAME),
-                    true, false, true);
-      classNameAttr = (StringConfigAttribute)
-                      configEntry.getConfigAttribute(classStub);
-
-      if (classNameAttr == null)
+      // Get the name of the class and make sure we can instantiate it as
+      // an entry cache.
+      String className = configuration.getSchemeClass();
+      try
       {
-        int msgID = MSGID_CONFIG_PWSCHEME_NO_CLASS_NAME;
-        String message = getMessage(msgID, configEntry.getDN().toString());
-        unacceptableReason.append(message);
-        return false;
+        // Load the class but don't initialize it.
+        loadPasswordStorageScheme (className, null);
       }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
+      catch (InitializationException ie)
       {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS_NAME;
-      String message = getMessage(msgID, configEntry.getDN().toString(),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-    Class schemeClass;
-    try
-    {
-      schemeClass = DirectoryServer.loadClass(classNameAttr.pendingValue());
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS_NAME;
-      String message = getMessage(msgID, configEntry.getDN().toString(),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-    PasswordStorageScheme storageScheme;
-    try
-    {
-      storageScheme = (PasswordStorageScheme) schemeClass.newInstance();
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS;
-      String message = getMessage(msgID, schemeClass.getName(),
-                                  String.valueOf(configEntryDN),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // If the storage scheme is a configurable component, then make sure that
-    // its configuration is valid.
-    if (storageScheme instanceof ConfigurableComponent)
-    {
-      ConfigurableComponent cc = (ConfigurableComponent) storageScheme;
-      LinkedList<String> errorMessages = new LinkedList<String>();
-      if (! cc.hasAcceptableConfiguration(configEntry, errorMessages))
-      {
-        if (errorMessages.isEmpty())
-        {
-          int msgID = MSGID_CONFIG_PWSCHEME_UNACCEPTABLE_CONFIG;
-          unacceptableReason.append(getMessage(msgID,
-                                               String.valueOf(configEntryDN)));
-        }
-        else
-        {
-          Iterator<String> iterator = errorMessages.iterator();
-          unacceptableReason.append(iterator.next());
-          while (iterator.hasNext())
-          {
-            unacceptableReason.append("  ");
-            unacceptableReason.append(iterator.next());
-          }
-        }
-
-        return false;
+        unacceptableReasons.add (ie.getMessage());
+        status = false;
       }
     }
 
-
-    // See if this storage scheme should be enabled.
-    BooleanConfigAttribute enabledAttr;
-    try
-    {
-      BooleanConfigAttribute enabledStub =
-           new BooleanConfigAttribute(ATTR_PWSCHEME_ENABLED,
-                    getMessage(MSGID_CONFIG_PWSCHEME_DESCRIPTION_ENABLED),
-                               false);
-      enabledAttr = (BooleanConfigAttribute)
-                    configEntry.getConfigAttribute(enabledStub);
-
-      if (enabledAttr == null)
-      {
-        int msgID = MSGID_CONFIG_PWSCHEME_NO_ENABLED_ATTR;
-        String message = getMessage(msgID, configEntry.getDN().toString());
-        unacceptableReason.append(message);
-        return false;
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_PWSCHEME_INVALID_ENABLED_VALUE;
-      String message = getMessage(msgID, configEntry.getDN().toString(),
-                                  String.valueOf(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // If we've gotten here then the storage scheme entry appears to be
-    // acceptable.
-    return true;
+    return status;
   }
 
 
 
   /**
-   * 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(
+      PasswordStorageSchemeCfg configuration
+      )
   {
-    DN                configEntryDN       = configEntry.getDN();
-    ResultCode        resultCode          = ResultCode.SUCCESS;
-    boolean           adminActionRequired = false;
-    ArrayList<String> messages            = new ArrayList<String>();
+    // Returned result.
+    ConfigChangeResult changeResult = new ConfigChangeResult(
+        ResultCode.SUCCESS, false, new ArrayList<String>()
+        );
 
+    // Register a change listener with it so we can be notified of changes
+    // to it over time.
+    configuration.addChangeListener(this);
 
-    // Make sure that the entry has an appropriate objectclass for a password
-    // storage scheme.
-    if (! configEntry.hasObjectClass(OC_PASSWORD_STORAGE_SCHEME))
+    if (configuration.isEnabled())
     {
-      int    msgID   = MSGID_CONFIG_PWSCHEME_INVALID_OBJECTCLASS;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-      resultCode = ResultCode.UNWILLING_TO_PERFORM;
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // See if this storage scheme should be enabled or disabled.
-    BooleanConfigAttribute enabledAttr;
-    try
-    {
-      BooleanConfigAttribute enabledStub =
-           new BooleanConfigAttribute(ATTR_PWSCHEME_ENABLED,
-                    getMessage(MSGID_CONFIG_PWSCHEME_DESCRIPTION_ENABLED),
-                               false);
-      enabledAttr = (BooleanConfigAttribute)
-                    configEntry.getConfigAttribute(enabledStub);
-
-      if (enabledAttr == null)
+      // Instantiate the class as password storage scheme
+      // and initialize it.
+      String className = configuration.getSchemeClass();
+      try
       {
-        // The attribute doesn't exist, so it will be disabled by default.
-        int msgID = MSGID_CONFIG_PWSCHEME_NO_ENABLED_ATTR;
-        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-        resultCode = ResultCode.SUCCESS;
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
+        loadAndInstallPasswordStorageScheme (className, configuration);
       }
-      else if (! enabledAttr.activeValue())
+      catch (InitializationException ie)
       {
-        // It is explicitly configured as disabled, so we don't need to do
-        // anything.
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
+        changeResult.addMessage (ie.getMessage());
+        changeResult.setResultCode (DirectoryServer.getServerErrorResultCode());
+        return changeResult;
       }
     }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
 
-      int msgID = MSGID_CONFIG_PWSCHEME_INVALID_ENABLED_VALUE;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              String.valueOf(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // Make sure that the entry specifies the storage scheme class name.
-    String className;
-    try
-    {
-      StringConfigAttribute classStub =
-           new StringConfigAttribute(ATTR_PWSCHEME_CLASS,
-                    getMessage(MSGID_CONFIG_PWSCHEME_DESCRIPTION_CLASS_NAME),
-                    true, false, true);
-      StringConfigAttribute classNameAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
-
-      if (classNameAttr == null)
-      {
-        int msgID = MSGID_CONFIG_PWSCHEME_NO_CLASS_NAME;
-        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
-        return new ConfigChangeResult(resultCode, adminActionRequired,
-                                      messages);
-      }
-
-      className = classNameAttr.pendingValue();
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS_NAME;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              String.valueOf(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    // Load and initialize the storage scheme class, and register it with the
-    // Directory Server.
-    PasswordStorageScheme storageScheme;
-    try
-    {
-      Class schemeClass = DirectoryServer.loadClass(className);
-      storageScheme = (PasswordStorageScheme) schemeClass.newInstance();
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS;
-      messages.add(getMessage(msgID, className, String.valueOf(configEntryDN),
-                              String.valueOf(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-    try
-    {
-      storageScheme.initializePasswordStorageScheme(configEntry);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_PWSCHEME_INITIALIZATION_FAILED;
-      messages.add(getMessage(msgID, className, String.valueOf(configEntryDN),
-                              String.valueOf(e)));
-      resultCode = DirectoryServer.getServerErrorResultCode();
-      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-    }
-
-
-    storageSchemes.put(configEntryDN, storageScheme);
-    DirectoryServer.registerPasswordStorageScheme(storageScheme);
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+    return changeResult;
   }
 
 
 
   /**
-   * 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(
+      PasswordStorageSchemeCfg configuration,
+      List<String>             unacceptableReasons
+      )
   {
     // A delete should always be acceptable, so just return true.
     return true;
@@ -932,33 +326,139 @@
 
 
   /**
-   * 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(
+      PasswordStorageSchemeCfg configuration
+      )
   {
-    DN         configEntryDN       = configEntry.getDN();
-    ResultCode resultCode          = ResultCode.SUCCESS;
-    boolean    adminActionRequired = false;
+    // Returned result.
+    ConfigChangeResult changeResult = new ConfigChangeResult(
+        ResultCode.SUCCESS, false, new ArrayList<String>()
+        );
+
+    uninstallPasswordStorageScheme (configuration.dn());
+
+    return changeResult;
+  }
 
 
-    // See if the entry is registered as a password storage scheme.  If so,
-    // deregister it and stop the storage scheme.
-    PasswordStorageScheme storageScheme = storageSchemes.remove(configEntryDN);
-    if (storageScheme != null)
+
+  /**
+   * Loads the specified class, instantiates it as a password storage scheme,
+   * and optionally initializes that instance. Any initialized password
+   * storage scheme is registered in the server.
+   *
+   * @param  className      The fully-qualified name of the password storage
+   *                        scheme class to load, instantiate, and initialize.
+   * @param  configuration  The configuration to use to initialize the
+   *                        password storage scheme, or {@code null} if the
+   *                        password storage scheme should not be initialized.
+   *
+   * @throws  InitializationException  If a problem occurred while attempting
+   *                                   to initialize the class.
+   */
+  private void loadAndInstallPasswordStorageScheme(
+       String className,
+       PasswordStorageSchemeCfg configuration
+       )
+       throws InitializationException
+  {
+    // Load the password storage scheme class...
+    PasswordStorageScheme
+        <? extends PasswordStorageSchemeCfg> schemeClass;
+    schemeClass = loadPasswordStorageScheme (className, configuration);
+
+    // ... and install the password storage scheme in the server.
+    DN configEntryDN = configuration.dn();
+    storageSchemes.put (configEntryDN, schemeClass);
+    DirectoryServer.registerPasswordStorageScheme (schemeClass);
+  }
+
+
+  /**
+   * Loads the specified class, instantiates it as a password storage scheme,
+   * and optionally initializes that instance.
+   *
+   * @param  className      The fully-qualified name of the class
+   *                        to load, instantiate, and initialize.
+   * @param  configuration  The configuration to use to initialize the
+   *                        class, or {@code null} if the
+   *                        class should not be initialized.
+   *
+   * @return  The possibly initialized password storage scheme.
+   *
+   * @throws  InitializationException  If a problem occurred while attempting
+   *                                   to initialize the class.
+   */
+  private PasswordStorageScheme <? extends PasswordStorageSchemeCfg>
+    loadPasswordStorageScheme(
+       String className,
+       PasswordStorageSchemeCfg configuration
+       )
+       throws InitializationException
+  {
+    try
     {
-      String lowerName = toLowerCase(storageScheme.getStorageSchemeName());
-      DirectoryServer.deregisterPasswordStorageScheme(lowerName);
+      PasswordStorageSchemeCfgDefn definition;
+      ClassPropertyDefinition propertyDefinition;
+      Class<? extends PasswordStorageScheme> schemeClass;
+      PasswordStorageScheme<? extends PasswordStorageSchemeCfg>
+          passwordStorageScheme;
 
-      storageScheme.finalizePasswordStorageScheme();
+      definition = PasswordStorageSchemeCfgDefn.getInstance();
+      propertyDefinition = definition.getSchemeClassPropertyDefinition();
+      schemeClass = propertyDefinition.loadClass(
+          className,
+          PasswordStorageScheme.class
+          );
+      passwordStorageScheme =
+        (PasswordStorageScheme<? extends PasswordStorageSchemeCfg>)
+            schemeClass.newInstance();
+
+      if (configuration != null)
+      {
+        Method method = passwordStorageScheme.getClass().getMethod(
+            "initializePasswordStorageScheme",
+            configuration.definition().getServerConfigurationClass()
+            );
+        method.invoke(passwordStorageScheme, configuration);
+      }
+
+      return passwordStorageScheme;
     }
+    catch (Exception e)
+    {
+      int msgID = MSGID_CONFIG_PWSCHEME_INITIALIZATION_FAILED;
+      String message = getMessage(
+          msgID, className,
+          String.valueOf(configuration.dn()),
+          stackTraceToSingleLineString(e)
+          );
+      throw new InitializationException(msgID, message, e);
+    }
+  }
 
 
-    return new ConfigChangeResult(resultCode, adminActionRequired);
+  /**
+   * Remove a password storage that has been installed in the server.
+   *
+   * @param configEntryDN  the DN of the configuration enry associated to
+   *                       the password storage scheme to remove
+   */
+  private void uninstallPasswordStorageScheme(
+      DN configEntryDN
+      )
+  {
+    PasswordStorageScheme scheme =
+        storageSchemes.remove (configEntryDN);
+    if (scheme != null)
+    {
+      DirectoryServer.deregisterPasswordStorageScheme (
+          scheme.getStorageSchemeName().toLowerCase()
+          );
+      scheme.finalizePasswordStorageScheme();
+    }
   }
 }
 
diff --git a/opends/src/server/org/opends/server/extensions/Base64PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/Base64PasswordStorageScheme.java
index bd88ec5..5901b3f 100644
--- a/opends/src/server/org/opends/server/extensions/Base64PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/Base64PasswordStorageScheme.java
@@ -28,8 +28,8 @@
 
 
 
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.types.ByteString;
 import org.opends.server.types.ByteStringFactory;
@@ -53,7 +53,7 @@
  * value from the casual observer.
  */
 public class Base64PasswordStorageScheme
-       extends PasswordStorageScheme
+       extends PasswordStorageScheme <PasswordStorageSchemeCfg>
 {
 
 
@@ -75,8 +75,10 @@
    * {@inheritDoc}
    */
   @Override()
-  public void initializePasswordStorageScheme(ConfigEntry configEntry)
-         throws ConfigException, InitializationException
+  public void initializePasswordStorageScheme(
+      PasswordStorageSchemeCfg configuration
+      )
+      throws ConfigException, InitializationException
   {
     // No initialization is required.
   }
diff --git a/opends/src/server/org/opends/server/extensions/ClearPasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/ClearPasswordStorageScheme.java
index 3ad7fd6..fbdb6d0 100644
--- a/opends/src/server/org/opends/server/extensions/ClearPasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/ClearPasswordStorageScheme.java
@@ -28,8 +28,8 @@
 
 
 
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.types.ByteString;
 import org.opends.server.types.ByteStringFactory;
@@ -52,7 +52,7 @@
  * applications.
  */
 public class ClearPasswordStorageScheme
-       extends PasswordStorageScheme
+       extends PasswordStorageScheme <PasswordStorageSchemeCfg>
 {
 
 
@@ -74,8 +74,10 @@
    * {@inheritDoc}
    */
   @Override()
-  public void initializePasswordStorageScheme(ConfigEntry configEntry)
-         throws ConfigException, InitializationException
+  public void initializePasswordStorageScheme(
+      PasswordStorageSchemeCfg configuration
+      )
+  throws ConfigException, InitializationException
   {
     // No initialization is required.
   }
diff --git a/opends/src/server/org/opends/server/extensions/DefaultEntryCache.java b/opends/src/server/org/opends/server/extensions/DefaultEntryCache.java
index f661d3f..0228b87 100644
--- a/opends/src/server/org/opends/server/extensions/DefaultEntryCache.java
+++ b/opends/src/server/org/opends/server/extensions/DefaultEntryCache.java
@@ -28,17 +28,21 @@
 
 
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.locks.Lock;
 
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.server.EntryCacheCfg;
 import org.opends.server.api.Backend;
 import org.opends.server.api.EntryCache;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
+import org.opends.server.types.ConfigChangeResult;
 import org.opends.server.types.DN;
 import org.opends.server.types.Entry;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.LockType;
+import org.opends.server.types.ResultCode;
 
 
 
@@ -50,7 +54,8 @@
  * <CODE>putEntry</CODE> will return immediately without doing anything.
  */
 public class DefaultEntryCache
-       extends EntryCache
+       extends EntryCache<EntryCacheCfg>
+       implements ConfigurationChangeListener<EntryCacheCfg>
 {
 
 
@@ -67,21 +72,9 @@
 
 
   /**
-   * Initializes this entry cache implementation so that it will be available
-   * for storing and retrieving entries.
-   *
-   * @param  configEntry  The configuration entry containing the settings to use
-   *                      for this entry cache.
-   *
-   * @throws  ConfigException  If there is a problem with the provided
-   *                           configuration entry that would prevent this
-   *                           entry cache from being used.
-   *
-   * @throws  InitializationException  If a problem occurs during the
-   *                                   initialization process that is not
-   *                                   related to the configuration.
+   * {@inheritDoc}
    */
-  public void initializeEntryCache(ConfigEntry configEntry)
+  public void initializeEntryCache(EntryCacheCfg configEntry)
          throws ConfigException, InitializationException
   {
     // No implementation required.
@@ -90,9 +83,7 @@
 
 
   /**
-   * Performs any necessary cleanup work (e.g., flushing all cached entries and
-   * releasing any other held resources) that should be performed when the
-   * server is to be shut down or the entry cache destroyed or replaced.
+   * {@inheritDoc}
    */
   public void finalizeEntryCache()
   {
@@ -102,14 +93,7 @@
 
 
   /**
-   * Indicates whether the entry cache currently contains the entry with the
-   * specified DN.  This method may be called without holding any locks if a
-   * point-in-time check is all that is required.
-   *
-   * @param  entryDN  The DN for which to make the determination.
-   *
-   * @return  <CODE>true</CODE> if the entry cache currently contains the entry
-   *          with the specified DN, or <CODE>false</CODE> if not.
+   * {@inheritDoc}
    */
   public boolean containsEntry(DN entryDN)
   {
@@ -120,14 +104,7 @@
 
 
   /**
-   * Retrieves the entry with the specified DN from the cache.  The caller
-   * should have already acquired a read or write lock for the entry if such
-   * protection is needed.
-   *
-   * @param  entryDN  The DN of the entry to retrieve.
-   *
-   * @return  The requested entry if it is present in the cache, or
-   *          <CODE>null</CODE> if it is not present.
+   * {@inheritDoc}
    */
   public Entry getEntry(DN entryDN)
   {
@@ -138,14 +115,7 @@
 
 
   /**
-   * Retrieves the entry ID for the entry with the specified DN from the cache.
-   * The caller should have already acquired a read or write lock for the entry
-   * if such protection is needed.
-   *
-   * @param  entryDN  The DN of the entry for which to retrieve the entry ID.
-   *
-   * @return  The entry ID for the requested entry, or -1 if it is not present
-   *          in the cache.
+   * {@inheritDoc}
    */
   public long getEntryID(DN entryDN)
   {
@@ -156,20 +126,7 @@
 
 
   /**
-   * Retrieves the entry with the specified DN from the cache, obtaining a lock
-   * on the entry before it is returned.  If the entry is present in the cache,
-   * then a lock will be obtained for that entry and appended to the provided
-   * list before the entry is returned.  If the entry is not present, then no
-   * lock will be obtained.
-   *
-   * @param  entryDN   The DN of the entry to retrieve.
-   * @param  lockType  The type of lock to obtain (it may be <CODE>NONE</CODE>).
-   * @param  lockList  The list to which the obtained lock will be added (note
-   *                   that no lock will be added if the lock type was
-   *                   <CODE>NONE</CODE>).
-   *
-   * @return  The requested entry if it is present in the cache, or
-   *          <CODE>null</CODE> if it is not present.
+   * {@inheritDoc}
    */
   public Entry getEntry(DN entryDN, LockType lockType, List<Lock> lockList)
   {
@@ -180,22 +137,7 @@
 
 
   /**
-   * Retrieves the requested entry if it is present in the cache, obtaining a
-   * lock on the entry before it is returned.  If the entry is present in the
-   * cache, then a lock  will be obtained for that entry and appended to the
-   * provided list before the entry is returned.  If the entry is not present,
-   * then no lock will be obtained.
-   *
-   * @param  backend   The backend associated with the entry to retrieve.
-   * @param  entryID   The entry ID within the provided backend for the
-   *                   specified entry.
-   * @param  lockType  The type of lock to obtain (it may be <CODE>NONE</CODE>).
-   * @param  lockList  The list to which the obtained lock will be added (note
-   *                   that no lock will be added if the lock type was
-   *                   <CODE>NONE</CODE>).
-   *
-   * @return  The requested entry if it is present in the cache, or
-   *          <CODE>null</CODE> if it is not present.
+   * {@inheritDoc}
    */
   public Entry getEntry(Backend backend, long entryID, LockType lockType,
                         List<Lock> lockList)
@@ -207,14 +149,7 @@
 
 
   /**
-   * Stores the provided entry in the cache.  Note that the mechanism that it
-   * uses to achieve this is implementation-dependent, and it is acceptable for
-   * the entry to not actually be stored in any cache.
-   *
-   * @param  entry    The entry to store in the cache.
-   * @param  backend  The backend with which the entry is associated.
-   * @param  entryID  The entry ID within the provided backend that uniquely
-   *                  identifies the specified entry.
+   * {@inheritDoc}
    */
   public void putEntry(Entry entry, Backend backend, long entryID)
   {
@@ -224,22 +159,7 @@
 
 
   /**
-   * Stores the provided entry in the cache only if it does not conflict with an
-   * entry that already exists.  Note that the mechanism that it uses to achieve
-   * this is implementation-dependent, and it is acceptable for the entry to not
-   * actually be stored in any cache.  However, this method must not overwrite
-   * an existing version of the entry.
-   *
-   * @param  entry    The entry to store in the cache.
-   * @param  backend  The backend with which the entry is associated.
-   * @param  entryID  The entry ID within the provided backend that uniquely
-   *                  identifies the specified entry.
-   *
-   * @return  <CODE>false</CODE> if an existing entry or some other problem
-   *          prevented the method from completing successfully, or
-   *          <CODE>true</CODE> if there was no conflict and the entry was
-   *          either stored or the cache determined that this entry should never
-   *          be cached for some reason.
+   * {@inheritDoc}
    */
   public boolean putEntryIfAbsent(Entry entry, Backend backend, long entryID)
   {
@@ -251,9 +171,7 @@
 
 
   /**
-   * Removes the specified entry from the cache.
-   *
-   * @param  entryDN  The DN of the entry to remove from the cache.
+   * {@inheritDoc}
    */
   public void removeEntry(DN entryDN)
   {
@@ -263,8 +181,7 @@
 
 
   /**
-   * Removes all entries from the cache.  The cache should still be available
-   * for future use.
+   * {@inheritDoc}
    */
   public void clear()
   {
@@ -274,10 +191,7 @@
 
 
   /**
-   * Removes all entries from the cache that are associated with the provided
-   * backend.
-   *
-   * @param  backend  The backend for which to flush the associated entries.
+   * {@inheritDoc}
    */
   public void clearBackend(Backend backend)
   {
@@ -287,9 +201,7 @@
 
 
   /**
-   * Removes all entries from the cache that are below the provided DN.
-   *
-   * @param  baseDN  The base DN below which all entries should be flushed.
+   * {@inheritDoc}
    */
   public void clearSubtree(DN baseDN)
   {
@@ -299,15 +211,44 @@
 
 
   /**
-   * Attempts to react to a scenario in which it is determined that the system
-   * is running low on available memory.  In this case, the entry cache should
-   * attempt to free some memory if possible to try to avoid out of memory
-   * errors.
+   * {@inheritDoc}
    */
   public void handleLowMemory()
   {
     // This implementation does not store entries, so there are no resources
     // that it can free.
   }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationChangeAcceptable(
+      EntryCacheCfg configuration,
+      List<String>  unacceptableReasons
+      )
+  {
+    // No implementation required.
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationChange(
+      EntryCacheCfg configuration
+      )
+  {
+    // No implementation required.
+
+    ConfigChangeResult changeResult = new ConfigChangeResult(
+        ResultCode.SUCCESS, false, new ArrayList<String>()
+        );
+
+    return changeResult;
+    }
 }
 
diff --git a/opends/src/server/org/opends/server/extensions/EntryCacheCommon.java b/opends/src/server/org/opends/server/extensions/EntryCacheCommon.java
new file mode 100644
index 0000000..703f188
--- /dev/null
+++ b/opends/src/server/org/opends/server/extensions/EntryCacheCommon.java
@@ -0,0 +1,333 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+import static org.opends.server.loggers.Error.logError;
+import static org.opends.server.messages.MessageHandler.getMessage;
+import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.SortedSet;
+
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.ErrorLogCategory;
+import org.opends.server.types.ErrorLogSeverity;
+import org.opends.server.types.ResultCode;
+import org.opends.server.types.SearchFilter;
+
+
+/**
+ * This class provides some common tools to all entry cache implementations.
+ */
+public class EntryCacheCommon
+{
+  /**
+   * Configuration phases. Each value identifies a configuration step:
+   * - PHASE_INIT       when invoking method initializeEntryCache()
+   * - PHASE_ACCEPTABLE when invoking method isConfigurationChangeAcceptable()
+   * - PHASE_APPLY      when invoking method applyConfigurationChange()
+   */
+  public static enum ConfigPhase
+  {
+    /**
+     * Indicates that entry cache is in initialization check phase.
+     */
+    PHASE_INIT,
+
+    /**
+     * Indicates that entry cache is in configuration check phase.
+     */
+    PHASE_ACCEPTABLE,
+
+    /**
+     * Indicates that entry cache is applying its configuration.
+     */
+    PHASE_APPLY
+  }
+
+  /**
+   * Error handler used by local methods to report configuration error.
+   * The error handler simplifies the code of initializeEntryCache(),
+   * isConfigurationChangeAcceptable() and applyConfigurationChanges() methods.
+   */
+  public class ConfigErrorHandler
+  {
+    // Configuration phase.
+    private EntryCacheCommon.ConfigPhase _configPhase;
+
+    // Unacceptable reasons. Used when _configPhase is PHASE_ACCEPTABLE.
+    private List<String> _unacceptableReasons;
+
+    // Error messages. Used when _configPhase is PHASE_APPLY.
+    private ArrayList<String> _errorMessages;
+
+    // Result code. Used when _configPhase is PHASE_APPLY.
+    private ResultCode _resultCode;
+
+    // Acceptable Configuration ? Used when _configPhase is PHASE_ACCEPTABLE
+    // or PHASE_APPLY.
+    private boolean _isAcceptable;
+
+    /**
+     * Create an error handler.
+     *
+     * @param configPhase          the configuration phase for which the
+     *                             error handler is used
+     * @param unacceptableReasons  the reasons why the configuration cannot
+     *                             be applied (during PHASE_ACCEPTABLE phase)
+     * @param errorMessages        the errors found when applying a new
+     *                             configuration (during PHASE_APPLY phase)
+     */
+    public ConfigErrorHandler (
+        EntryCacheCommon.ConfigPhase configPhase,
+        List<String>                 unacceptableReasons,
+        ArrayList<String>            errorMessages
+        )
+    {
+      _configPhase         = configPhase;
+      _unacceptableReasons = unacceptableReasons;
+      _errorMessages       = errorMessages;
+      _resultCode          = ResultCode.SUCCESS;
+      _isAcceptable        = true;
+    }
+
+    /**
+     * Report an error.
+     *
+     * @param category     the category of the error to report
+     * @param severity     the severity of the error to report
+     * @param errorID      the error ID of the error to report
+     * @param arg1         the first  argument of the error message
+     * @param arg2         the second argument of the error message
+     * @param arg3         the third  argument of the error message
+     * @param isAcceptable <code>true</code> if the configuration is acceptable
+     * @param resultCode   the change result for the current configuration
+     */
+    public void reportError(
+        ErrorLogCategory category,
+        ErrorLogSeverity severity,
+        int              errorID,
+        String           arg1,
+        String           arg2,
+        String           arg3,
+        boolean          isAcceptable,
+        ResultCode       resultCode
+        )
+    {
+      switch (_configPhase)
+      {
+      case PHASE_INIT:
+        {
+        logError (category, severity, errorID, arg1, arg2, arg3);
+        break;
+        }
+      case PHASE_ACCEPTABLE:
+        {
+        String message = getMessage (errorID, arg1, arg2, arg3);
+        _unacceptableReasons.add (message);
+        _isAcceptable = isAcceptable;
+        break;
+        }
+      case PHASE_APPLY:
+        {
+        String message = getMessage (errorID, arg1, arg2, arg3);
+        _errorMessages.add (message);
+        _isAcceptable = isAcceptable;
+        if (_resultCode == ResultCode.SUCCESS)
+        {
+          _resultCode = resultCode;
+        }
+        break;
+        }
+      }
+    }
+
+    /**
+     * Get the current result code that was elaborated right after a
+     * configuration has been applied.
+     *
+     * @return the current result code
+     */
+    public ResultCode getResultCode()
+    {
+      return _resultCode;
+    }
+
+    /**
+     * Get the current isAcceptable flag. The isAcceptable flag is elaborated
+     * right after the configuration was checked.
+     *
+     * @return the isAcceptable flag
+     */
+    public boolean getIsAcceptable()
+    {
+      return _isAcceptable;
+    }
+
+    /**
+     * Get the current unacceptable reasons. The unacceptable reasons are
+     * elaborated when the configuration is checked.
+     *
+     * @return the list of unacceptable reasons
+     */
+    public List<String> getUnacceptableReasons()
+    {
+      return _unacceptableReasons;
+    }
+
+    /**
+     * Get the current error messages. The error messages are elaborated
+     * when the configuration is applied.
+     *
+     * @return the list of error messages
+     */
+    public ArrayList<String> getErrorMessages()
+    {
+      return _errorMessages;
+    }
+
+    /**
+     * Get the current configuration phase. The configuration phase indicates
+     * whether the entry cache is in initialization step, or in configuration
+     * checking step or in configuration being applied step.
+     *
+     * @return the current configuration phase.
+     */
+    public ConfigPhase getConfigPhase()
+    {
+      return _configPhase;
+    }
+  } // ConfigErrorHandler
+
+
+  /**
+   * Reads a list of string filters and convert it to a list of search
+   * filters.
+   *
+   * @param filters  the list of string filter to convert to search filters
+   * @param decodeErrorMsgId  the error message ID to use in case of error
+   * @param errorHandler      an handler used to report errors
+   *                          during decoding of filter
+   * @param noFilterMsgId     the error message ID to use when none of the
+   *                          filters was decoded properly
+   * @param configEntryDN     the DN of the configuration entry for the
+   *                          entry cache
+   *
+   * @return the set of search filters
+   */
+  public static HashSet<SearchFilter> getFilters (
+      SortedSet<String>  filters,
+      int                decodeErrorMsgId,
+      int                noFilterMsgId,
+      ConfigErrorHandler errorHandler,
+      DN                 configEntryDN
+      )
+  {
+    // Returned value
+    HashSet<SearchFilter> searchFilters = new HashSet<SearchFilter>();
+
+    // Convert the string filters to search filters.
+    if (filters != null)
+    {
+      for (String curFilter: filters)
+      {
+        try
+        {
+          searchFilters.add (SearchFilter.createFilterFromString (curFilter));
+        }
+        catch (DirectoryException de)
+        {
+          // We couldn't decode this filter. Log a warning and continue.
+          errorHandler.reportError(
+              ErrorLogCategory.CONFIGURATION,
+              ErrorLogSeverity.SEVERE_WARNING,
+              decodeErrorMsgId,
+              String.valueOf(configEntryDN),
+              curFilter,
+              stackTraceToSingleLineString (de),
+              false,
+              ResultCode.INVALID_ATTRIBUTE_SYNTAX
+              );
+        }
+      }
+
+      // If none of the filters was decoded properly log an error message
+      // (only if we are in initialize phase).
+      if ((errorHandler.getConfigPhase() == ConfigPhase.PHASE_INIT)
+          && searchFilters.isEmpty())
+      {
+        errorHandler.reportError(
+            ErrorLogCategory.CONFIGURATION,
+            ErrorLogSeverity.SEVERE_ERROR,
+            noFilterMsgId,
+            null,
+            null,
+            null,
+            false,
+            null
+            );
+      }
+    }
+
+    // done
+    return searchFilters;
+  }
+
+
+  /**
+   * Create a new error handler.
+   *
+   * @param configPhase          the configuration phase for which the
+   *                             error handler is used
+   * @param unacceptableReasons  the reasons why the configuration cannot
+   *                             be applied (during PHASE_ACCEPTABLE phase)
+   * @param errorMessages        the errors found when applying a new
+   *                             configuration (during PHASE_APPLY phase)
+   *
+   * @return a new configuration error handler
+   */
+  public static ConfigErrorHandler getConfigErrorHandler (
+      EntryCacheCommon.ConfigPhase  configPhase,
+      List<String>                  unacceptableReasons,
+      ArrayList<String>             errorMessages
+      )
+  {
+    ConfigErrorHandler errorHandler = null;
+
+    EntryCacheCommon ec = new EntryCacheCommon();
+
+    errorHandler = ec.new ConfigErrorHandler (
+        configPhase, unacceptableReasons, errorMessages
+        );
+    return errorHandler;
+  }
+
+}
+
diff --git a/opends/src/server/org/opends/server/extensions/ErrorLogAccountStatusNotificationHandler.java b/opends/src/server/org/opends/server/extensions/ErrorLogAccountStatusNotificationHandler.java
index 6f4be0a..8ebc86d 100644
--- a/opends/src/server/org/opends/server/extensions/ErrorLogAccountStatusNotificationHandler.java
+++ b/opends/src/server/org/opends/server/extensions/ErrorLogAccountStatusNotificationHandler.java
@@ -28,18 +28,25 @@
 
 
 
+import static org.opends.server.config.ConfigConstants.*;
+import static org.opends.server.loggers.Error.logError;
+import static org.opends.server.messages.ExtensionsMessages.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.meta.
+       ErrorLogAccountStatusNotificationHandlerCfgDefn;
+import org.opends.server.admin.std.server.
+       ErrorLogAccountStatusNotificationHandlerCfg;
 import org.opends.server.api.AccountStatusNotificationHandler;
-import org.opends.server.api.ConfigurableComponent;
 import org.opends.server.config.ConfigAttribute;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.config.MultiChoiceConfigAttribute;
-import org.opends.server.core.DirectoryServer;
 import org.opends.server.types.AccountStatusNotificationType;
 import org.opends.server.types.ConfigChangeResult;
 import org.opends.server.types.DN;
@@ -48,15 +55,6 @@
 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.loggers.Error.*;
-import static org.opends.server.messages.ExtensionsMessages.*;
-import static org.opends.server.messages.MessageHandler.*;
-import static org.opends.server.util.StaticUtils.*;
-
 
 
 /**
@@ -65,12 +63,13 @@
  * logging facility.
  */
 public class ErrorLogAccountStatusNotificationHandler
-       extends AccountStatusNotificationHandler
-       implements ConfigurableComponent
+       extends
+          AccountStatusNotificationHandler
+          <ErrorLogAccountStatusNotificationHandlerCfg>
+       implements
+          ConfigurationChangeListener
+          <ErrorLogAccountStatusNotificationHandlerCfg>
 {
-
-
-
   /**
    * The set of names for the account status notification types that may be
    * logged by this notification handler.
@@ -78,17 +77,6 @@
   private static final HashSet<String> NOTIFICATION_TYPE_NAMES =
        new HashSet<String>();
 
-
-
-  // The DN of the configuration entry for this notification handler.
-  private DN configEntryDN;
-
-  // The set of notification types that should generate log messages.
-  private HashSet<AccountStatusNotificationType> notificationTypes;
-
-
-
-
   static
   {
     for (AccountStatusNotificationType t :
@@ -99,88 +87,34 @@
   }
 
 
+  // The DN of the configuration entry for this notification handler.
+  private DN configEntryDN;
+
+  // The set of notification types that should generate log messages.
+  private HashSet<AccountStatusNotificationType> notificationTypes;
+
+
 
   /**
-   * Initializes this account status notification handler based on the
-   * information in the provided configuration entry.
-   *
-   * @param  configEntry  The configuration entry that contains the information
-   *                      to use to initialize this account status notification
-   *                      handler.
-   *
-   * @throws  ConfigException  If the provided entry does not contain a valid
-   *                           configuration for this account status
-   *                           notification handler.
-   *
-   * @throws  InitializationException  If a problem occurs during initialization
-   *                                   that is not related to the server
-   *                                   configuration.
+   * {@inheritDoc}
    */
-  public void initializeStatusNotificationHandler(ConfigEntry configEntry)
-       throws ConfigException, InitializationException
+  public void initializeStatusNotificationHandler(
+      ErrorLogAccountStatusNotificationHandlerCfg configuration
+      )
+      throws ConfigException, InitializationException
   {
-    configEntryDN = configEntry.getDN();
+    configuration.addErrorLogChangeListener (this);
+    configEntryDN = configuration.dn();
 
-
-    // Initialize the set of notification types that should generate log
-    // messages.
-    int msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_DESCRIPTION_NOTIFICATION_TYPES;
-    MultiChoiceConfigAttribute typesStub =
-         new MultiChoiceConfigAttribute(ATTR_ACCT_NOTIFICATION_TYPE,
-                                        getMessage(msgID), true, true, false,
-                                        NOTIFICATION_TYPE_NAMES);
-    try
-    {
-      MultiChoiceConfigAttribute typesAttr =
-           (MultiChoiceConfigAttribute)
-           configEntry.getConfigAttribute(typesStub);
-      notificationTypes = new HashSet<AccountStatusNotificationType>();
-      for (String s : typesAttr.activeValues())
-      {
-        AccountStatusNotificationType t =
-             AccountStatusNotificationType.typeForName(s);
-        if (t == null)
-        {
-          msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_INVALID_TYPE;
-          String message = getMessage(msgID, String.valueOf(configEntryDN), s);
-          throw new ConfigException(msgID, message);
-        }
-        else
-        {
-          notificationTypes.add(t);
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_CANNOT_GET_NOTIFICATION_TYPES;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    DirectoryServer.registerConfigurableComponent(this);
-    DirectoryServer.registerAccountStatusNotificationHandler(configEntryDN,
-                                                             this);
+    // Read configuration and apply changes.
+    boolean applyChanges = true;
+    processNotificationHandlerConfig (configuration, applyChanges);
   }
 
 
 
   /**
-   * Performs any processing that may be necessary in conjunction with the
-   * provided account status notification type.
-   *
-   * @param  notificationType  The type for this account status notification.
-   * @param  userDN            The DN of the user entry to which this
-   *                           notification applies.
-   * @param  messageID         The unique ID for this notification.
-   * @param  message           The human-readable message for this notification.
+   * {@inheritDoc}
    */
   public void handleStatusNotification(AccountStatusNotificationType
                                             notificationType,
@@ -240,158 +174,172 @@
 
 
   /**
-   * 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.
+   * {@inheritDoc}
    */
-  public boolean hasAcceptableConfiguration(ConfigEntry configEntry,
-                      List<String> unacceptableReasons)
+  public boolean isConfigurationChangeAcceptable(
+      ErrorLogAccountStatusNotificationHandlerCfg configuration,
+      List<String> unacceptableReasons
+      )
   {
-    // Initialize the set of notification types that should generate log
-    // messages.
-    int msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_DESCRIPTION_NOTIFICATION_TYPES;
-    MultiChoiceConfigAttribute typesStub =
-         new MultiChoiceConfigAttribute(ATTR_ACCT_NOTIFICATION_TYPE,
-                                        getMessage(msgID), true, true, false,
-                                        NOTIFICATION_TYPE_NAMES);
-    try
-    {
-      MultiChoiceConfigAttribute typesAttr =
-           (MultiChoiceConfigAttribute)
-           configEntry.getConfigAttribute(typesStub);
-      HashSet<AccountStatusNotificationType> types =
-           new HashSet<AccountStatusNotificationType>();
-      for (String s : typesAttr.activeValues())
-      {
-        AccountStatusNotificationType t =
-             AccountStatusNotificationType.typeForName(s);
-        if (t == null)
-        {
-          msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_INVALID_TYPE;
-          String message = getMessage(msgID, String.valueOf(configEntryDN), s);
-          unacceptableReasons.add(message);
-          return false;
-        }
-        else
-        {
-          types.add(t);
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
+    // Make sure that we can process the defined notification handler.
+    // If so, then we'll accept the new configuration.
+    boolean applyChanges = false;
+    boolean isAcceptable = processNotificationHandlerConfig (
+        configuration, applyChanges
+        );
 
-      msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_CANNOT_GET_NOTIFICATION_TYPES;
-      String message = getMessage(msgID, String.valueOf(configEntryDN),
-                                  getExceptionMessage(e));
-      unacceptableReasons.add(message);
-      return false;
-    }
-
-
-    // If we've gotten here, then everything is OK.
-    return true;
+    return isAcceptable;
   }
 
 
 
   /**
-   * 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.
+   * 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.
+   * @param  configuration    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.
+   * @return  Information about the result of the configuration update.
    */
-  public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry,
-                                                  boolean detailedResults)
+  public ConfigChangeResult applyConfigurationChange (
+      ErrorLogAccountStatusNotificationHandlerCfg configuration,
+      boolean detailedResults
+      )
+  {
+    ConfigChangeResult changeResult = applyConfigurationChange (configuration);
+    return changeResult;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationChange (
+      ErrorLogAccountStatusNotificationHandlerCfg configuration
+      )
   {
     ResultCode resultCode = ResultCode.SUCCESS;
     boolean adminActionRequired = false;
     ArrayList<String> messages = new ArrayList<String>();
-
+    ConfigChangeResult changeResult = new ConfigChangeResult(
+        resultCode, adminActionRequired, messages
+        );
 
     // Initialize the set of notification types that should generate log
     // messages.
-    HashSet<AccountStatusNotificationType> types =
-         new HashSet<AccountStatusNotificationType>();
-    int msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_DESCRIPTION_NOTIFICATION_TYPES;
-    MultiChoiceConfigAttribute typesStub =
-         new MultiChoiceConfigAttribute(ATTR_ACCT_NOTIFICATION_TYPE,
-                                        getMessage(msgID), true, true, false,
-                                        NOTIFICATION_TYPE_NAMES);
-    try
-    {
-      MultiChoiceConfigAttribute typesAttr =
-           (MultiChoiceConfigAttribute)
-           configEntry.getConfigAttribute(typesStub);
-      for (String s : typesAttr.activeValues())
-      {
-        AccountStatusNotificationType t =
-             AccountStatusNotificationType.typeForName(s);
-        if (t == null)
-        {
-          resultCode = ResultCode.UNWILLING_TO_PERFORM;
+    boolean applyChanges = false;
+    processNotificationHandlerConfig (
+        configuration, applyChanges
+        );
 
-          msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_INVALID_TYPE;
-          messages.add(getMessage(msgID, String.valueOf(configEntryDN), s));
-        }
-        else
-        {
-          types.add(t);
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      resultCode = DirectoryServer.getServerErrorResultCode();
-
-      msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_CANNOT_GET_NOTIFICATION_TYPES;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              getExceptionMessage(e)));
-    }
-
-
-    if (resultCode == ResultCode.SUCCESS)
-    {
-      this.notificationTypes = types;
-    }
-
-
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+    return changeResult;
   }
+
+
+  /**
+   * Parses the provided configuration and configure the notification handler.
+   *
+   * @param configuration  The new configuration containing the changes.
+   * @param applyChanges   If true then take into account the new configuration.
+   *
+   * @return  The mapping between strings of character set values and the
+   *          minimum number of characters required from those sets.
+   */
+  public boolean processNotificationHandlerConfig(
+      ErrorLogAccountStatusNotificationHandlerCfg configuration,
+      boolean                                     applyChanges
+      )
+  {
+    // false if the configuration is not acceptable
+    boolean isAcceptable = true;
+
+    // The set of notification types that should generate log messages.
+    HashSet<AccountStatusNotificationType> newNotificationTypes =
+        new HashSet<AccountStatusNotificationType>();
+
+    // Initialize the set of notification types that should generate log
+    // messages.
+    for (ErrorLogAccountStatusNotificationHandlerCfgDefn.
+         AccountStatusNotificationType configNotificationType:
+         configuration.getAccountStatusNotificationType())
+    {
+      newNotificationTypes.add (getNotificationType (configNotificationType));
+    }
+
+    if (applyChanges && isAcceptable)
+    {
+      notificationTypes = newNotificationTypes;
+    }
+
+    return isAcceptable;
+  }
+
+
+  /**
+   * Gets the OpenDS notification type object that corresponds to the
+   * configuration counterpart.
+   *
+   * @param  notificationType  The configuration notification type for which
+   *                           to retrieve the OpenDS notification type.
+   */
+  private AccountStatusNotificationType getNotificationType(
+      ErrorLogAccountStatusNotificationHandlerCfgDefn.
+         AccountStatusNotificationType configNotificationType
+      )
+  {
+    AccountStatusNotificationType nt = null;
+
+    switch (configNotificationType)
+    {
+    case ACCOUNT_TEMPORARILY_LOCKED:
+         nt = AccountStatusNotificationType.ACCOUNT_TEMPORARILY_LOCKED;
+         break;
+    case ACCOUNT_PERMANENTLY_LOCKED:
+         nt = AccountStatusNotificationType.ACCOUNT_PERMANENTLY_LOCKED;
+         break;
+    case ACCOUNT_UNLOCKED:
+         nt = AccountStatusNotificationType.ACCOUNT_UNLOCKED;
+         break;
+    case ACCOUNT_IDLE_LOCKED:
+         nt = AccountStatusNotificationType.ACCOUNT_IDLE_LOCKED;
+         break;
+    case ACCOUNT_RESET_LOCKED:
+         nt = AccountStatusNotificationType.ACCOUNT_RESET_LOCKED;
+         break;
+    case ACCOUNT_DISABLED:
+         nt = AccountStatusNotificationType.ACCOUNT_DISABLED;
+         break;
+    case ACCOUNT_ENABLED:
+         nt = AccountStatusNotificationType.ACCOUNT_ENABLED;
+         break;
+    case ACCOUNT_EXPIRED:
+         nt = AccountStatusNotificationType.ACCOUNT_EXPIRED;
+         break;
+    case PASSWORD_EXPIRED:
+         nt = AccountStatusNotificationType.PASSWORD_EXPIRED;
+         break;
+    case PASSWORD_EXPIRING:
+         nt = AccountStatusNotificationType.PASSWORD_EXPIRING;
+         break;
+    case PASSWORD_RESET:
+         nt = AccountStatusNotificationType.PASSWORD_RESET;
+         break;
+    case PASSWORD_CHANGED:
+         nt = AccountStatusNotificationType.PASSWORD_CHANGED;
+         break;
+    }
+
+    return nt;
+  }
+
 }
 
diff --git a/opends/src/server/org/opends/server/extensions/FIFOEntryCache.java b/opends/src/server/org/opends/server/extensions/FIFOEntryCache.java
index 70c174f..53bfa87 100644
--- a/opends/src/server/org/opends/server/extensions/FIFOEntryCache.java
+++ b/opends/src/server/org/opends/server/extensions/FIFOEntryCache.java
@@ -41,10 +41,10 @@
 import java.util.concurrent.locks.ReentrantLock;
 
 import org.opends.server.api.Backend;
-import org.opends.server.api.ConfigurableComponent;
 import org.opends.server.api.EntryCache;
+import org.opends.server.admin.std.server.FIFOEntryCacheCfg;
+import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.config.ConfigAttribute;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.config.IntegerConfigAttribute;
 import org.opends.server.config.IntegerWithUnitConfigAttribute;
@@ -54,8 +54,6 @@
 import org.opends.server.types.ConfigChangeResult;
 import org.opends.server.types.DN;
 import org.opends.server.types.Entry;
-import org.opends.server.types.ErrorLogCategory;
-import org.opends.server.types.ErrorLogSeverity;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.LockManager;
 import org.opends.server.types.LockType;
@@ -66,11 +64,9 @@
 import static org.opends.server.loggers.debug.DebugLogger.debugCaught;
 import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
 import org.opends.server.types.DebugLogLevel;
-import static org.opends.server.loggers.Error.*;
 import static org.opends.server.messages.ExtensionsMessages.*;
 import static org.opends.server.messages.MessageHandler.*;
 import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
 
 
 
@@ -100,8 +96,8 @@
  * of the given filters will be stored in the cache.
  */
 public class FIFOEntryCache
-       extends EntryCache
-       implements ConfigurableComponent
+       extends EntryCache <FIFOEntryCacheCfg>
+       implements ConfigurationChangeListener<FIFOEntryCacheCfg>
 {
 
 
@@ -179,291 +175,35 @@
 
 
   /**
-   * Initializes this entry cache implementation so that it will be available
-   * for storing and retrieving entries.
-   *
-   * @param  configEntry  The configuration entry containing the settings to use
-   *                      for this entry cache.
-   *
-   * @throws  ConfigException  If there is a problem with the provided
-   *                           configuration entry that would prevent this
-   *                           entry cache from being used.
-   *
-   * @throws  InitializationException  If a problem occurs during the
-   *                                   initialization process that is not
-   *                                   related to the configuration.
+   * {@inheritDoc}
    */
-  public void initializeEntryCache(ConfigEntry configEntry)
-         throws ConfigException, InitializationException
+  public void initializeEntryCache(
+      FIFOEntryCacheCfg configuration
+      )
+      throws ConfigException, InitializationException
   {
-    configEntryDN = configEntry.getDN();
-
+    configuration.addFIFOChangeListener (this);
+    configEntryDN = configuration.dn();
 
     // Initialize the cache structures.
     idMap     = new HashMap<Backend,HashMap<Long,CacheEntry>>();
     dnMap     = new LinkedHashMap<DN,CacheEntry>();
     cacheLock = new ReentrantLock();
-    runtime   = Runtime.getRuntime();
 
 
-    // Determine the maximum memory usage as a percentage of the total JVM
-    // memory.
-    maxMemoryPercent = DEFAULT_FIFOCACHE_MAX_MEMORY_PCT;
-    int msgID = MSGID_FIFOCACHE_DESCRIPTION_MAX_MEMORY_PCT;
-    IntegerConfigAttribute maxMemoryPctStub =
-         new IntegerConfigAttribute(ATTR_FIFOCACHE_MAX_MEMORY_PCT,
-                                    getMessage(msgID), true, false, false, true,
-                                    1, true, 100);
-    try
-    {
-      IntegerConfigAttribute maxMemoryPctAttr =
-           (IntegerConfigAttribute)
-           configEntry.getConfigAttribute(maxMemoryPctStub);
-      if (maxMemoryPctAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-      }
-      else
-      {
-        maxMemoryPercent = maxMemoryPctAttr.activeIntValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // Log an error message.
-      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-               MSGID_FIFOCACHE_CANNOT_DETERMINE_MAX_MEMORY_PCT,
-               String.valueOf(configEntryDN), getExceptionMessage(e),
-               maxMemoryPercent);
-    }
-
-    maxAllowedMemory = runtime.maxMemory() / 100 * maxMemoryPercent;
-
-
-    // Determine the maximum number of entries that we will allow in the cache.
-    maxEntries = DEFAULT_FIFOCACHE_MAX_ENTRIES;
-    msgID = MSGID_FIFOCACHE_DESCRIPTION_MAX_ENTRIES;
-    IntegerConfigAttribute maxEntriesStub =
-         new IntegerConfigAttribute(ATTR_FIFOCACHE_MAX_ENTRIES,
-                                    getMessage(msgID), true, false, false,
-                                    true, 0, false, 0);
-    try
-    {
-      IntegerConfigAttribute maxEntriesAttr =
-           (IntegerConfigAttribute)
-           configEntry.getConfigAttribute(maxEntriesStub);
-      if (maxEntriesAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-      }
-      else
-      {
-        maxEntries = maxEntriesAttr.activeValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // Log an error message.
-      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-               MSGID_FIFOCACHE_CANNOT_DETERMINE_MAX_ENTRIES,
-               String.valueOf(configEntryDN), getExceptionMessage(e));
-    }
-
-
-    // Determine the lock timeout to use when interacting with the lock manager.
-    lockTimeout = DEFAULT_FIFOCACHE_LOCK_TIMEOUT;
-    msgID = MSGID_FIFOCACHE_DESCRIPTION_LOCK_TIMEOUT;
-    IntegerWithUnitConfigAttribute lockTimeoutStub =
-         new IntegerWithUnitConfigAttribute(ATTR_FIFOCACHE_LOCK_TIMEOUT,
-                                            getMessage(msgID), false, timeUnits,
-                                            true, 0, false, 0);
-    try
-    {
-      IntegerWithUnitConfigAttribute lockTimeoutAttr =
-             (IntegerWithUnitConfigAttribute)
-             configEntry.getConfigAttribute(lockTimeoutStub);
-      if (lockTimeoutAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-      }
-      else
-      {
-        lockTimeout = lockTimeoutAttr.activeCalculatedValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // Log an error message.
-      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-               MSGID_FIFOCACHE_CANNOT_DETERMINE_LOCK_TIMEOUT,
-               String.valueOf(configEntryDN), getExceptionMessage(e),
-               lockTimeout);
-    }
-
-
-    // Determine the set of cache filters that can be used to control the
-    // entries that should be included in the cache.
-    includeFilters = new HashSet<SearchFilter>();
-    msgID = MSGID_FIFOCACHE_DESCRIPTION_INCLUDE_FILTERS;
-    StringConfigAttribute includeStub =
-         new StringConfigAttribute(ATTR_FIFOCACHE_INCLUDE_FILTER,
-                                   getMessage(msgID), false, true, false);
-    try
-    {
-      StringConfigAttribute includeAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(includeStub);
-      if (includeAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-      }
-      else
-      {
-        List<String> filterStrings = includeAttr.activeValues();
-        if ((filterStrings == null) || filterStrings.isEmpty())
-        {
-          // There are no include filters, so we'll allow anything by default.
-        }
-        else
-        {
-          for (String filterString : filterStrings)
-          {
-            try
-            {
-              includeFilters.add(
-                   SearchFilter.createFilterFromString(filterString));
-            }
-            catch (Exception e)
-            {
-              if (debugEnabled())
-              {
-                debugCaught(DebugLogLevel.ERROR, e);
-              }
-
-              // We couldn't decode this filter.  Log a warning and continue.
-              logError(ErrorLogCategory.CONFIGURATION,
-                       ErrorLogSeverity.SEVERE_WARNING,
-                       MSGID_FIFOCACHE_CANNOT_DECODE_INCLUDE_FILTER,
-                       String.valueOf(configEntryDN), filterString,
-                       getExceptionMessage(e));
-            }
-          }
-
-          if (includeFilters.isEmpty())
-          {
-            logError(ErrorLogCategory.CONFIGURATION,
-                     ErrorLogSeverity.SEVERE_ERROR,
-                     MSGID_FIFOCACHE_CANNOT_DECODE_ANY_INCLUDE_FILTERS,
-                     String.valueOf(configEntryDN));
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // Log an error message.
-      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-               MSGID_FIFOCACHE_CANNOT_DETERMINE_INCLUDE_FILTERS,
-               String.valueOf(configEntryDN), getExceptionMessage(e));
-    }
-
-
-    // Determine the set of cache filters that can be used to control the
-    // entries that should be excluded from the cache.
-    excludeFilters = new HashSet<SearchFilter>();
-    msgID = MSGID_FIFOCACHE_DESCRIPTION_EXCLUDE_FILTERS;
-    StringConfigAttribute excludeStub =
-         new StringConfigAttribute(ATTR_FIFOCACHE_EXCLUDE_FILTER,
-                                   getMessage(msgID), false, true, false);
-    try
-    {
-      StringConfigAttribute excludeAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(excludeStub);
-      if (excludeAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-      }
-      else
-      {
-        List<String> filterStrings = excludeAttr.activeValues();
-        if ((filterStrings == null) || filterStrings.isEmpty())
-        {
-          // There are no exclude filters, so we'll allow anything by default.
-        }
-        else
-        {
-          for (String filterString : filterStrings)
-          {
-            try
-            {
-              excludeFilters.add(
-                   SearchFilter.createFilterFromString(filterString));
-            }
-            catch (Exception e)
-            {
-              if (debugEnabled())
-              {
-                debugCaught(DebugLogLevel.ERROR, e);
-              }
-
-              // We couldn't decode this filter.  Log a warning and continue.
-              logError(ErrorLogCategory.CONFIGURATION,
-                       ErrorLogSeverity.SEVERE_WARNING,
-                       MSGID_FIFOCACHE_CANNOT_DECODE_EXCLUDE_FILTER,
-                       String.valueOf(configEntryDN), filterString,
-                       getExceptionMessage(e));
-            }
-          }
-
-          if (excludeFilters.isEmpty())
-          {
-            logError(ErrorLogCategory.CONFIGURATION,
-                     ErrorLogSeverity.SEVERE_ERROR,
-                     MSGID_FIFOCACHE_CANNOT_DECODE_ANY_EXCLUDE_FILTERS,
-                     String.valueOf(configEntryDN));
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // Log an error message.
-      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-               MSGID_FIFOCACHE_CANNOT_DETERMINE_EXCLUDE_FILTERS,
-               String.valueOf(configEntryDN), getExceptionMessage(e));
-    }
+    // Read configuration and apply changes.
+    boolean applyChanges = true;
+    EntryCacheCommon.ConfigErrorHandler errorHandler =
+      EntryCacheCommon.getConfigErrorHandler (
+          EntryCacheCommon.ConfigPhase.PHASE_INIT, null, null
+          );
+    processEntryCacheConfig (configuration, applyChanges, errorHandler);
   }
 
 
 
   /**
-   * Performs any necessary cleanup work (e.g., flushing all cached entries and
-   * releasing any other held resources) that should be performed when the
-   * server is to be shut down or the entry cache destroyed or replaced.
+   * {@inheritDoc}
    */
   public void finalizeEntryCache()
   {
@@ -492,14 +232,7 @@
 
 
   /**
-   * Indicates whether the entry cache currently contains the entry with the
-   * specified DN.  This method may be called without holding any locks if a
-   * point-in-time check is all that is required.
-   *
-   * @param  entryDN  The DN for which to make the determination.
-   *
-   * @return  <CODE>true</CODE> if the entry cache currently contains the entry
-   *          with the specified DN, or <CODE>false</CODE> if not.
+   * {@inheritDoc}
    */
   public boolean containsEntry(DN entryDN)
   {
@@ -510,14 +243,7 @@
 
 
   /**
-   * Retrieves the entry with the specified DN from the cache.  The caller
-   * should have already acquired a read or write lock for the entry if such
-   * protection is needed.
-   *
-   * @param  entryDN  The DN of the entry to retrieve.
-   *
-   * @return  The requested entry if it is present in the cache, or
-   *          <CODE>null</CODE> if it is not present.
+   * {@inheritDoc}
    */
   public Entry getEntry(DN entryDN)
   {
@@ -536,14 +262,7 @@
 
 
   /**
-   * Retrieves the entry ID for the entry with the specified DN from the cache.
-   * The caller should have already acquired a read or write lock for the entry
-   * if such protection is needed.
-   *
-   * @param  entryDN  The DN of the entry for which to retrieve the entry ID.
-   *
-   * @return  The entry ID for the requested entry, or -1 if it is not present
-   *          in the cache.
+   * {@inheritDoc}
    */
   public long getEntryID(DN entryDN)
   {
@@ -562,20 +281,7 @@
 
 
   /**
-   * Retrieves the entry with the specified DN from the cache, obtaining a lock
-   * on the entry before it is returned.  If the entry is present in the cache,
-   * then a lock will be obtained for that entry and appended to the provided
-   * list before the entry is returned.  If the entry is not present, then no
-   * lock will be obtained.
-   *
-   * @param  entryDN   The DN of the entry to retrieve.
-   * @param  lockType  The type of lock to obtain (it may be <CODE>NONE</CODE>).
-   * @param  lockList  The list to which the obtained lock will be added (note
-   *                   that no lock will be added if the lock type was
-   *                   <CODE>NONE</CODE>).
-   *
-   * @return  The requested entry if it is present in the cache, or
-   *          <CODE>null</CODE> if it is not present.
+   * {@inheritDoc}
    */
   public Entry getEntry(DN entryDN, LockType lockType, List<Lock> lockList)
   {
@@ -684,22 +390,7 @@
 
 
   /**
-   * Retrieves the requested entry if it is present in the cache, obtaining a
-   * lock on the entry before it is returned.  If the entry is present in the
-   * cache, then a lock  will be obtained for that entry and appended to the
-   * provided list before the entry is returned.  If the entry is not present,
-   * then no lock will be obtained.
-   *
-   * @param  backend   The backend associated with the entry to retrieve.
-   * @param  entryID   The entry ID within the provided backend for the
-   *                   specified entry.
-   * @param  lockType  The type of lock to obtain (it may be <CODE>NONE</CODE>).
-   * @param  lockList  The list to which the obtained lock will be added (note
-   *                   that no lock will be added if the lock type was
-   *                   <CODE>NONE</CODE>).
-   *
-   * @return  The requested entry if it is present in the cache, or
-   *          <CODE>null</CODE> if it is not present.
+   * {@inheritDoc}
    */
   public Entry getEntry(Backend backend, long entryID, LockType lockType,
                         List<Lock> lockList)
@@ -820,14 +511,7 @@
 
 
   /**
-   * Stores the provided entry in the cache.  Note that the mechanism that it
-   * uses to achieve this is implementation-dependent, and it is acceptable for
-   * the entry to not actually be stored in any cache.
-   *
-   * @param  entry    The entry to store in the cache.
-   * @param  backend  The backend with which the entry is associated.
-   * @param  entryID  The entry ID within the provided backend that uniquely
-   *                  identifies the specified entry.
+   * {@inheritDoc}
    */
   public void putEntry(Entry entry, Backend backend, long entryID)
   {
@@ -999,22 +683,7 @@
 
 
   /**
-   * Stores the provided entry in the cache only if it does not conflict with an
-   * entry that already exists.  Note that the mechanism that it uses to achieve
-   * this is implementation-dependent, and it is acceptable for the entry to not
-   * actually be stored in any cache.  However, this method must not overwrite
-   * an existing version of the entry.
-   *
-   * @param  entry    The entry to store in the cache.
-   * @param  backend  The backend with which the entry is associated.
-   * @param  entryID  The entry ID within the provided backend that uniquely
-   *                  identifies the specified entry.
-   *
-   * @return  <CODE>false</CODE> if an existing entry or some other problem
-   *          prevented the method from completing successfully, or
-   *          <CODE>true</CODE> if there was no conflict and the entry was
-   *          either stored or the cache determined that this entry should never
-   *          be cached for some reason.
+   * {@inheritDoc}
    */
   public boolean putEntryIfAbsent(Entry entry, Backend backend, long entryID)
   {
@@ -1201,9 +870,7 @@
 
 
   /**
-   * Removes the specified entry from the cache.
-   *
-   * @param  entryDN  The DN of the entry to remove from the cache.
+   * {@inheritDoc}
    */
   public void removeEntry(DN entryDN)
   {
@@ -1257,8 +924,7 @@
 
 
   /**
-   * Removes all entries from the cache.  The cache should still be available
-   * for future use.
+   * {@inheritDoc}
    */
   public void clear()
   {
@@ -1295,10 +961,7 @@
 
 
   /**
-   * Removes all entries from the cache that are associated with the provided
-   * backend.
-   *
-   * @param  backend  The backend for which to flush the associated entries.
+   * {@inheritDoc}
    */
   public void clearBackend(Backend backend)
   {
@@ -1359,9 +1022,7 @@
 
 
   /**
-   * Removes all entries from the cache that are below the provided DN.
-   *
-   * @param  baseDN  The base DN below which all entries should be flushed.
+   * {@inheritDoc}
    */
   public void clearSubtree(DN baseDN)
   {
@@ -1403,11 +1064,7 @@
 
 
   /**
-   * Clears all entries at or below the specified base DN that are associated
-   * with the given backend.  The caller must already hold the cache lock.
-   *
-   * @param  baseDN   The base DN below which all entries should be flushed.
-   * @param  backend  The backend for which to remove the appropriate entries.
+   * {@inheritDoc}
    */
   private void clearSubtree(DN baseDN, Backend backend)
   {
@@ -1474,10 +1131,7 @@
 
 
   /**
-   * Attempts to react to a scenario in which it is determined that the system
-   * is running low on available memory.  In this case, the entry cache should
-   * attempt to free some memory if possible to try to avoid out of memory
-   * errors.
+   * {@inheritDoc}
    */
   public void handleLowMemory()
   {
@@ -1618,235 +1272,55 @@
 
 
   /**
-   * 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.
+   * {@inheritDoc}
    */
-  public boolean hasAcceptableConfiguration(ConfigEntry configEntry,
-                                            List<String> unacceptableReasons)
+  public boolean isConfigurationChangeAcceptable(
+      FIFOEntryCacheCfg configuration,
+      List<String>      unacceptableReasons
+      )
   {
-    // Start out assuming that the configuration is valid.
-    boolean configIsAcceptable = true;
+    // Make sure that we can process the defined character sets.  If so, then
+    // we'll accept the new configuration.
+    boolean applyChanges = false;
+    EntryCacheCommon.ConfigErrorHandler errorHandler =
+      EntryCacheCommon.getConfigErrorHandler (
+          EntryCacheCommon.ConfigPhase.PHASE_ACCEPTABLE,
+          unacceptableReasons,
+          null
+        );
+    processEntryCacheConfig (configuration, applyChanges, errorHandler);
+
+    return errorHandler.getIsAcceptable();
+  }
 
 
-    // Determine the maximum memory usage as a percentage of the total JVM
-    // memory.
-    int msgID = MSGID_FIFOCACHE_DESCRIPTION_MAX_MEMORY_PCT;
-    IntegerConfigAttribute maxMemoryPctStub =
-         new IntegerConfigAttribute(ATTR_FIFOCACHE_MAX_MEMORY_PCT,
-                                    getMessage(msgID), true, false, false, true,
-                                    1, true, 100);
-    try
-    {
-      IntegerConfigAttribute maxMemoryPctAttr =
-           (IntegerConfigAttribute)
-           configEntry.getConfigAttribute(maxMemoryPctStub);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
 
-      // An error occurred, so the provided value must not be valid.
-      msgID = MSGID_FIFOCACHE_INVALID_MAX_MEMORY_PCT;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         getExceptionMessage(e)));
-      configIsAcceptable = false;
-    }
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationChange(
+      FIFOEntryCacheCfg configuration
+      )
+  {
+    // Make sure that we can process the defined character sets.  If so, then
+    // activate the new configuration.
+    boolean applyChanges = false;
+    ArrayList<String> errorMessages = new ArrayList<String>();
+    EntryCacheCommon.ConfigErrorHandler errorHandler =
+      EntryCacheCommon.getConfigErrorHandler (
+          EntryCacheCommon.ConfigPhase.PHASE_APPLY, null, errorMessages
+          );
+    processEntryCacheConfig (configuration, applyChanges, errorHandler);
 
 
-    // Determine the maximum number of entries that we will allow in the cache.
-    msgID = MSGID_FIFOCACHE_DESCRIPTION_MAX_ENTRIES;
-    IntegerConfigAttribute maxEntriesStub =
-         new IntegerConfigAttribute(ATTR_FIFOCACHE_MAX_ENTRIES,
-                                    getMessage(msgID), true, false, false,
-                                    true, 0, false, 0);
-    try
-    {
-      IntegerConfigAttribute maxEntriesAttr =
-           (IntegerConfigAttribute)
-           configEntry.getConfigAttribute(maxEntriesStub);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
+    boolean adminActionRequired = false;
+    ConfigChangeResult changeResult = new ConfigChangeResult(
+        errorHandler.getResultCode(),
+        adminActionRequired,
+        errorHandler.getErrorMessages()
+        );
 
-      // An error occurred, so the provided value must not be valid.
-      msgID = MSGID_FIFOCACHE_INVALID_MAX_ENTRIES;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         getExceptionMessage(e)));
-      configIsAcceptable = false;
-    }
-
-
-    // Determine the lock timeout to use when interacting with the lock manager.
-    msgID = MSGID_FIFOCACHE_DESCRIPTION_LOCK_TIMEOUT;
-    IntegerWithUnitConfigAttribute lockTimeoutStub =
-         new IntegerWithUnitConfigAttribute(ATTR_FIFOCACHE_LOCK_TIMEOUT,
-                                            getMessage(msgID), false, timeUnits,
-                                            true, 0, false, 0);
-    try
-    {
-      IntegerWithUnitConfigAttribute lockTimeoutAttr =
-             (IntegerWithUnitConfigAttribute)
-             configEntry.getConfigAttribute(lockTimeoutStub);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // An error occurred, so the provided value must not be valid.
-      msgID = MSGID_FIFOCACHE_INVALID_LOCK_TIMEOUT;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         getExceptionMessage(e)));
-      configIsAcceptable = false;
-    }
-
-
-    // Determine the set of cache filters that can be used to control the
-    // entries that should be included in the cache.
-    msgID = MSGID_FIFOCACHE_DESCRIPTION_INCLUDE_FILTERS;
-    StringConfigAttribute includeStub =
-         new StringConfigAttribute(ATTR_FIFOCACHE_INCLUDE_FILTER,
-                                   getMessage(msgID), false, true, false);
-    try
-    {
-      StringConfigAttribute includeAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(includeStub);
-      if (includeAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-      }
-      else
-      {
-        List<String> filterStrings = includeAttr.activeValues();
-        if ((filterStrings == null) || filterStrings.isEmpty())
-        {
-          // There are no include filters, so we'll allow anything by default.
-        }
-        else
-        {
-          for (String filterString : filterStrings)
-          {
-            try
-            {
-              SearchFilter.createFilterFromString(filterString);
-            }
-            catch (Exception e)
-            {
-              if (debugEnabled())
-              {
-                debugCaught(DebugLogLevel.ERROR, e);
-              }
-
-              // We couldn't decode this filter, so it isn't valid.
-              msgID = MSGID_FIFOCACHE_INVALID_INCLUDE_FILTER;
-              unacceptableReasons.add(getMessage(msgID,
-                                           String.valueOf(configEntryDN),
-                                            filterString,
-                                            getExceptionMessage(e)));
-              configIsAcceptable = false;
-            }
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // An error occurred, so the provided value must not be valid.
-      msgID = MSGID_FIFOCACHE_INVALID_INCLUDE_FILTERS;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         getExceptionMessage(e)));
-      configIsAcceptable = false;
-    }
-
-
-    // Determine the set of cache filters that can be used to control the
-    // entries that should be excluded from the cache.
-    msgID = MSGID_FIFOCACHE_DESCRIPTION_EXCLUDE_FILTERS;
-    StringConfigAttribute excludeStub =
-         new StringConfigAttribute(ATTR_FIFOCACHE_EXCLUDE_FILTER,
-                                   getMessage(msgID), false, true, false);
-    try
-    {
-      StringConfigAttribute excludeAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(excludeStub);
-      if (excludeAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-      }
-      else
-      {
-        List<String> filterStrings = excludeAttr.activeValues();
-        if ((filterStrings == null) || filterStrings.isEmpty())
-        {
-          // There are no exclude filters, so we'll allow anything by default.
-        }
-        else
-        {
-          for (String filterString : filterStrings)
-          {
-            try
-            {
-              SearchFilter.createFilterFromString(filterString);
-            }
-            catch (Exception e)
-            {
-              if (debugEnabled())
-              {
-                debugCaught(DebugLogLevel.ERROR, e);
-              }
-
-              // We couldn't decode this filter, so it isn't valid.
-              msgID = MSGID_FIFOCACHE_INVALID_EXCLUDE_FILTER;
-              unacceptableReasons.add(getMessage(msgID,
-                                           String.valueOf(configEntryDN),
-                                            filterString,
-                                            getExceptionMessage(e)));
-              configIsAcceptable = false;
-            }
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // An error occurred, so the provided value must not be valid.
-      msgID = MSGID_FIFOCACHE_INVALID_EXCLUDE_FILTERS;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         getExceptionMessage(e)));
-      configIsAcceptable = false;
-    }
-
-
-    return configIsAcceptable;
+    return changeResult;
   }
 
 
@@ -1860,335 +1334,159 @@
    * successfully (and optionally about parameters that were not changed) should
    * also be included.
    *
-   * @param  configEntry      The entry containing the new configuration to
+   * @param  configuration    The entry containing the new configuration to
    *                          apply for this component.
    * @param  detailedResults  Indicates whether detailed information about the
    *                          processing should be added to the list.
    *
    * @return  Information about the result of the configuration update.
    */
-  public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry,
-                                                  boolean detailedResults)
+  public ConfigChangeResult applyNewConfiguration(
+      FIFOEntryCacheCfg configuration,
+      boolean           detailedResults
+      )
   {
-    // Create a set of variables to use for the result.
-    ResultCode        resultCode          = ResultCode.SUCCESS;
-    boolean           adminActionRequired = false;
-    ArrayList<String> messages            = new ArrayList<String>();
-    boolean           configIsAcceptable  = true;
+    // Store the current value to detect changes.
+    long                  prevLockTimeout      = lockTimeout;
+    long                  prevMaxEntries       = maxEntries;
+    int                   prevMaxMemoryPercent = maxMemoryPercent;
+    HashSet<SearchFilter> prevIncludeFilters   = includeFilters;
+    HashSet<SearchFilter> prevExcludeFilters   = excludeFilters;
 
+    // Activate the new configuration.
+    ConfigChangeResult changeResult = applyConfigurationChange(configuration);
 
-    // Determine the maximum memory usage as a percentage of the total JVM
-    // memory.
-    int newMaxMemoryPercent = DEFAULT_FIFOCACHE_MAX_MEMORY_PCT;
-    int msgID = MSGID_FIFOCACHE_DESCRIPTION_MAX_MEMORY_PCT;
-    IntegerConfigAttribute maxMemoryPctStub =
-         new IntegerConfigAttribute(ATTR_FIFOCACHE_MAX_MEMORY_PCT,
-                                    getMessage(msgID), true, false, false, true,
-                                    1, true, 100);
-    try
+    // Add detailed messages if needed.
+    ResultCode resultCode = changeResult.getResultCode();
+    boolean configIsAcceptable = (resultCode == ResultCode.SUCCESS);
+    if (detailedResults && configIsAcceptable)
     {
-      IntegerConfigAttribute maxMemoryPctAttr =
-           (IntegerConfigAttribute)
-           configEntry.getConfigAttribute(maxMemoryPctStub);
-      if (maxMemoryPctAttr != null)
+      if (maxMemoryPercent != prevMaxMemoryPercent)
       {
-        newMaxMemoryPercent = maxMemoryPctAttr.pendingIntValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
+        changeResult.addMessage(
+            getMessage(
+                MSGID_FIFOCACHE_UPDATED_MAX_MEMORY_PCT,
+                maxMemoryPercent,
+                maxAllowedMemory));
       }
 
-      // An error occurred, so the provided value must not be valid.
-      msgID = MSGID_FIFOCACHE_INVALID_MAX_MEMORY_PCT;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              getExceptionMessage(e)));
-      resultCode = ResultCode.CONSTRAINT_VIOLATION;
-      configIsAcceptable = false;
-    }
 
-
-    // Determine the maximum number of entries that we will allow in the cache.
-    long newMaxEntries = DEFAULT_FIFOCACHE_MAX_ENTRIES;
-    msgID = MSGID_FIFOCACHE_DESCRIPTION_MAX_ENTRIES;
-    IntegerConfigAttribute maxEntriesStub =
-         new IntegerConfigAttribute(ATTR_FIFOCACHE_MAX_ENTRIES,
-                                    getMessage(msgID), true, false, false,
-                                    true, 0, false, 0);
-    try
-    {
-      IntegerConfigAttribute maxEntriesAttr =
-           (IntegerConfigAttribute)
-           configEntry.getConfigAttribute(maxEntriesStub);
-      if (maxEntriesAttr != null)
+      if (maxEntries != prevMaxEntries)
       {
-        newMaxEntries = maxEntriesAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
+        changeResult.addMessage(
+            getMessage (MSGID_FIFOCACHE_UPDATED_MAX_ENTRIES, maxEntries));
       }
 
-      // An error occurred, so the provided value must not be valid.
-      msgID = MSGID_FIFOCACHE_INVALID_MAX_ENTRIES;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              getExceptionMessage(e)));
-
-      if (resultCode == ResultCode.SUCCESS)
+      if (lockTimeout != prevLockTimeout)
       {
-        resultCode = ResultCode.CONSTRAINT_VIOLATION;
+        changeResult.addMessage(
+            getMessage (MSGID_FIFOCACHE_UPDATED_LOCK_TIMEOUT, lockTimeout));
       }
 
-      configIsAcceptable = false;
-    }
-
-
-    // Determine the lock timeout to use when interacting with the lock manager.
-    long newLockTimeout = DEFAULT_FIFOCACHE_LOCK_TIMEOUT;
-    msgID = MSGID_FIFOCACHE_DESCRIPTION_LOCK_TIMEOUT;
-    IntegerWithUnitConfigAttribute lockTimeoutStub =
-         new IntegerWithUnitConfigAttribute(ATTR_FIFOCACHE_LOCK_TIMEOUT,
-                                            getMessage(msgID), false, timeUnits,
-                                            true, 0, false, 0);
-    try
-    {
-      IntegerWithUnitConfigAttribute lockTimeoutAttr =
-             (IntegerWithUnitConfigAttribute)
-             configEntry.getConfigAttribute(lockTimeoutStub);
-      if (lockTimeoutAttr != null)
+      if (!includeFilters.equals(prevIncludeFilters))
       {
-        newLockTimeout = lockTimeoutAttr.pendingCalculatedValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
+        changeResult.addMessage(
+            getMessage (MSGID_FIFOCACHE_UPDATED_INCLUDE_FILTERS));
       }
 
-      // An error occurred, so the provided value must not be valid.
-      msgID = MSGID_FIFOCACHE_INVALID_LOCK_TIMEOUT;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              getExceptionMessage(e)));
-
-      if (resultCode == ResultCode.SUCCESS)
+      if (!excludeFilters.equals(prevExcludeFilters))
       {
-        resultCode = ResultCode.CONSTRAINT_VIOLATION;
-      }
-
-      configIsAcceptable = false;
-    }
-
-
-    // Determine the set of cache filters that can be used to control the
-    // entries that should be included in the cache.
-    HashSet<SearchFilter> newIncludeFilters = new HashSet<SearchFilter>();
-    msgID = MSGID_FIFOCACHE_DESCRIPTION_INCLUDE_FILTERS;
-    StringConfigAttribute includeStub =
-         new StringConfigAttribute(ATTR_FIFOCACHE_INCLUDE_FILTER,
-                                   getMessage(msgID), false, true, false);
-    try
-    {
-      StringConfigAttribute includeAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(includeStub);
-      if (includeAttr != null)
-      {
-        List<String> filterStrings = includeAttr.activeValues();
-        if ((filterStrings == null) || filterStrings.isEmpty())
-        {
-          // There are no include filters, so we'll allow anything by default.
-        }
-        else
-        {
-          for (String filterString : filterStrings)
-          {
-            try
-            {
-              newIncludeFilters.add(
-                   SearchFilter.createFilterFromString(filterString));
-            }
-            catch (Exception e)
-            {
-              if (debugEnabled())
-              {
-                debugCaught(DebugLogLevel.ERROR, e);
-              }
-
-              // We couldn't decode this filter, so it isn't valid.
-              msgID = MSGID_FIFOCACHE_INVALID_INCLUDE_FILTER;
-              messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                      filterString,
-                                      getExceptionMessage(e)));
-
-              if (resultCode == ResultCode.SUCCESS)
-              {
-                resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
-              }
-
-              configIsAcceptable = false;
-            }
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // An error occurred, so the provided value must not be valid.
-      msgID = MSGID_FIFOCACHE_INVALID_INCLUDE_FILTERS;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              getExceptionMessage(e)));
-
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = ResultCode.CONSTRAINT_VIOLATION;
-      }
-
-      configIsAcceptable = false;
-    }
-
-
-    // Determine the set of cache filters that can be used to control the
-    // entries that should be exclude from the cache.
-    HashSet<SearchFilter> newExcludeFilters = new HashSet<SearchFilter>();
-    msgID = MSGID_FIFOCACHE_DESCRIPTION_EXCLUDE_FILTERS;
-    StringConfigAttribute excludeStub =
-         new StringConfigAttribute(ATTR_FIFOCACHE_EXCLUDE_FILTER,
-                                   getMessage(msgID), false, true, false);
-    try
-    {
-      StringConfigAttribute excludeAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(excludeStub);
-      if (excludeAttr != null)
-      {
-        List<String> filterStrings = excludeAttr.activeValues();
-        if ((filterStrings == null) || filterStrings.isEmpty())
-        {
-          // There are no exclude filters, so we'll allow anything by default.
-        }
-        else
-        {
-          for (String filterString : filterStrings)
-          {
-            try
-            {
-              newExcludeFilters.add(
-                   SearchFilter.createFilterFromString(filterString));
-            }
-            catch (Exception e)
-            {
-              if (debugEnabled())
-              {
-                debugCaught(DebugLogLevel.ERROR, e);
-              }
-
-              // We couldn't decode this filter, so it isn't valid.
-              msgID = MSGID_FIFOCACHE_INVALID_EXCLUDE_FILTER;
-              messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                      filterString, getExceptionMessage(e)));
-
-              if (resultCode == ResultCode.SUCCESS)
-              {
-                resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
-              }
-
-              configIsAcceptable = false;
-            }
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // An error occurred, so the provided value must not be valid.
-      msgID = MSGID_FIFOCACHE_INVALID_EXCLUDE_FILTERS;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              getExceptionMessage(e)));
-
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = ResultCode.CONSTRAINT_VIOLATION;
-      }
-
-      configIsAcceptable = false;
-    }
-
-
-    if (configIsAcceptable)
-    {
-      if (maxMemoryPercent != newMaxMemoryPercent)
-      {
-        maxMemoryPercent = newMaxMemoryPercent;
-        maxAllowedMemory = runtime.maxMemory() / 100 * maxMemoryPercent;
-
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_FIFOCACHE_UPDATED_MAX_MEMORY_PCT,
-                                  maxMemoryPercent, maxAllowedMemory));
-        }
-      }
-
-      if (maxEntries != newMaxEntries)
-      {
-        maxEntries = newMaxEntries;
-
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_FIFOCACHE_UPDATED_MAX_ENTRIES,
-                                  maxEntries));
-        }
-      }
-
-      if (lockTimeout != newLockTimeout)
-      {
-        lockTimeout = newLockTimeout;
-
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_FIFOCACHE_UPDATED_LOCK_TIMEOUT,
-                                  lockTimeout));
-        }
-      }
-
-      if (!includeFilters.equals(newIncludeFilters))
-      {
-        includeFilters = newIncludeFilters;
-
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_FIFOCACHE_UPDATED_INCLUDE_FILTERS));
-        }
-      }
-
-      if (!excludeFilters.equals(newExcludeFilters))
-      {
-        excludeFilters = newExcludeFilters;
-
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_FIFOCACHE_UPDATED_EXCLUDE_FILTERS));
-        }
+        changeResult.addMessage(
+            getMessage (MSGID_FIFOCACHE_UPDATED_EXCLUDE_FILTERS));
       }
     }
 
-
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+    return changeResult;
   }
+
+
+
+  /**
+   * Parses the provided configuration and configure the entry cache.
+   *
+   * @param configuration  The new configuration containing the changes.
+   * @param applyChanges   If true then take into account the new configuration.
+   * @param errorHandler   An handler used to report errors.
+   *
+   * @return  The mapping between strings of character set values and the
+   *          minimum number of characters required from those sets.
+   */
+  public boolean processEntryCacheConfig(
+      FIFOEntryCacheCfg                   configuration,
+      boolean                             applyChanges,
+      EntryCacheCommon.ConfigErrorHandler errorHandler
+      )
+  {
+    // Local variables to read configuration.
+    DN                    newConfigEntryDN;
+    long                  newLockTimeout;
+    long                  newMaxEntries;
+    int                   newMaxMemoryPercent;
+    long                  newMaxAllowedMemory;
+    HashSet<SearchFilter> newIncludeFilters = null;
+    HashSet<SearchFilter> newExcludeFilters = null;
+
+    // Read configuration.
+    newConfigEntryDN = configuration.dn();
+    newLockTimeout   = configuration.getLockTimeout();
+    newMaxEntries    = configuration.getMaxEntries();
+
+    // Maximum memory the cache can use.
+    newMaxMemoryPercent = (int) configuration.getMaxMemoryPercent();
+    long maxJvmHeapSize = Runtime.getRuntime().maxMemory();
+    newMaxAllowedMemory = (maxJvmHeapSize / 100) * newMaxMemoryPercent;
+
+    // Get include and exclude filters.
+    switch (errorHandler.getConfigPhase())
+    {
+    case PHASE_INIT:
+      newIncludeFilters = EntryCacheCommon.getFilters (
+          configuration.getIncludeFilter(),
+          MSGID_FIFOCACHE_INVALID_INCLUDE_FILTER,
+          MSGID_FIFOCACHE_CANNOT_DECODE_ANY_INCLUDE_FILTERS,
+          errorHandler,
+          configEntryDN
+          );
+      newExcludeFilters = EntryCacheCommon.getFilters (
+          configuration.getExcludeFilter(),
+          MSGID_FIFOCACHE_CANNOT_DECODE_EXCLUDE_FILTER,
+          MSGID_FIFOCACHE_CANNOT_DECODE_ANY_EXCLUDE_FILTERS,
+          errorHandler,
+          configEntryDN
+          );
+      break;
+    case PHASE_ACCEPTABLE:  // acceptable and apply are using the same
+    case PHASE_APPLY:       // error ID codes
+      newIncludeFilters = EntryCacheCommon.getFilters (
+          configuration.getIncludeFilter(),
+          MSGID_FIFOCACHE_INVALID_INCLUDE_FILTER,
+          0,
+          errorHandler,
+          configEntryDN
+          );
+      newExcludeFilters = EntryCacheCommon.getFilters (
+          configuration.getExcludeFilter(),
+          MSGID_FIFOCACHE_INVALID_EXCLUDE_FILTER,
+          0,
+          errorHandler,
+          configEntryDN
+          );
+      break;
+    }
+
+    if (applyChanges && errorHandler.getIsAcceptable())
+    {
+      configEntryDN    = newConfigEntryDN;
+      lockTimeout      = newLockTimeout;
+      maxEntries       = newMaxEntries;
+      maxMemoryPercent = newMaxMemoryPercent;
+      maxAllowedMemory = newMaxAllowedMemory;
+      includeFilters   = newIncludeFilters;
+      excludeFilters   = newExcludeFilters;
+    }
+
+    return errorHandler.getIsAcceptable();
+  }
+
 }
 
diff --git a/opends/src/server/org/opends/server/extensions/MD5PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/MD5PasswordStorageScheme.java
index 17e69d8..45990df 100644
--- a/opends/src/server/org/opends/server/extensions/MD5PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/MD5PasswordStorageScheme.java
@@ -32,8 +32,8 @@
 import java.util.Arrays;
 import java.util.concurrent.locks.ReentrantLock;
 
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.types.ByteString;
@@ -66,7 +66,7 @@
  * vulnerable to dictionary attacks than salted variants.
  */
 public class MD5PasswordStorageScheme
-       extends PasswordStorageScheme
+       extends PasswordStorageScheme <PasswordStorageSchemeCfg>
 {
   /**
    * The fully-qualified name of this class.
@@ -101,8 +101,10 @@
    * {@inheritDoc}
    */
   @Override()
-  public void initializePasswordStorageScheme(ConfigEntry configEntry)
-         throws ConfigException, InitializationException
+  public void initializePasswordStorageScheme(
+      PasswordStorageSchemeCfg configuration
+      )
+      throws ConfigException, InitializationException
   {
     try
     {
diff --git a/opends/src/server/org/opends/server/extensions/SHA1PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/SHA1PasswordStorageScheme.java
index a5fc58e..d09ff37 100644
--- a/opends/src/server/org/opends/server/extensions/SHA1PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/SHA1PasswordStorageScheme.java
@@ -32,8 +32,8 @@
 import java.util.Arrays;
 import java.util.concurrent.locks.ReentrantLock;
 
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.types.ByteString;
@@ -66,7 +66,7 @@
  * vulnerable to dictionary attacks than salted variants.
  */
 public class SHA1PasswordStorageScheme
-       extends PasswordStorageScheme
+       extends PasswordStorageScheme <PasswordStorageSchemeCfg>
 {
   /**
    * The fully-qualified name of this class.
@@ -101,8 +101,10 @@
    * {@inheritDoc}
    */
   @Override()
-  public void initializePasswordStorageScheme(ConfigEntry configEntry)
-         throws ConfigException, InitializationException
+  public void initializePasswordStorageScheme(
+      PasswordStorageSchemeCfg configuration
+      )
+      throws ConfigException, InitializationException
   {
     try
     {
diff --git a/opends/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java
index fb6b42c..ccc3a51 100644
--- a/opends/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java
@@ -33,8 +33,8 @@
 import java.util.Arrays;
 import java.util.concurrent.locks.ReentrantLock;
 
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.types.ByteString;
@@ -69,7 +69,7 @@
  * appended to the hash, and then the entire value is base64-encoded.
  */
 public class SaltedMD5PasswordStorageScheme
-       extends PasswordStorageScheme
+       extends PasswordStorageScheme <PasswordStorageSchemeCfg>
 {
   /**
    * The fully-qualified name of this class.
@@ -115,8 +115,10 @@
    * {@inheritDoc}
    */
   @Override()
-  public void initializePasswordStorageScheme(ConfigEntry configEntry)
-         throws ConfigException, InitializationException
+  public void initializePasswordStorageScheme(
+      PasswordStorageSchemeCfg configuration
+      )
+      throws ConfigException, InitializationException
   {
     try
     {
diff --git a/opends/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java
index 75ef462..e7b685e 100644
--- a/opends/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java
@@ -33,8 +33,8 @@
 import java.util.Arrays;
 import java.util.concurrent.locks.ReentrantLock;
 
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.types.ByteString;
@@ -69,7 +69,7 @@
  * appended to the hash, and then the entire value is base64-encoded.
  */
 public class SaltedSHA1PasswordStorageScheme
-       extends PasswordStorageScheme
+       extends PasswordStorageScheme <PasswordStorageSchemeCfg>
 {
   /**
    * The fully-qualified name of this class.
@@ -115,8 +115,10 @@
    * {@inheritDoc}
    */
   @Override()
-  public void initializePasswordStorageScheme(ConfigEntry configEntry)
-         throws ConfigException, InitializationException
+  public void initializePasswordStorageScheme(
+      PasswordStorageSchemeCfg configuration
+      )
+      throws ConfigException, InitializationException
   {
     try
     {
diff --git a/opends/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageScheme.java
index d701e81..7315e4b 100644
--- a/opends/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageScheme.java
@@ -33,8 +33,8 @@
 import java.util.Arrays;
 import java.util.concurrent.locks.ReentrantLock;
 
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.types.ByteString;
@@ -69,7 +69,7 @@
  * is appended to the hash, and then the entire value is base64-encoded.
  */
 public class SaltedSHA256PasswordStorageScheme
-       extends PasswordStorageScheme
+       extends PasswordStorageScheme <PasswordStorageSchemeCfg>
 {
   /**
    * The fully-qualified name of this class.
@@ -116,8 +116,10 @@
    * {@inheritDoc}
    */
   @Override()
-  public void initializePasswordStorageScheme(ConfigEntry configEntry)
-         throws ConfigException, InitializationException
+  public void initializePasswordStorageScheme(
+      PasswordStorageSchemeCfg configuration
+      )
+      throws ConfigException, InitializationException
   {
     try
     {
diff --git a/opends/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageScheme.java
index 9ebc35f..62290e9 100644
--- a/opends/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageScheme.java
@@ -33,8 +33,8 @@
 import java.util.Arrays;
 import java.util.concurrent.locks.ReentrantLock;
 
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.types.ByteString;
@@ -69,7 +69,7 @@
  * is appended to the hash, and then the entire value is base64-encoded.
  */
 public class SaltedSHA384PasswordStorageScheme
-       extends PasswordStorageScheme
+       extends PasswordStorageScheme <PasswordStorageSchemeCfg>
 {
   /**
    * The fully-qualified name of this class.
@@ -116,8 +116,10 @@
    * {@inheritDoc}
    */
   @Override()
-  public void initializePasswordStorageScheme(ConfigEntry configEntry)
-         throws ConfigException, InitializationException
+  public void initializePasswordStorageScheme(
+      PasswordStorageSchemeCfg configuration
+      )
+      throws ConfigException, InitializationException
   {
     try
     {
diff --git a/opends/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java
index 912bfe6..a852301 100644
--- a/opends/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java
@@ -33,8 +33,8 @@
 import java.util.Arrays;
 import java.util.concurrent.locks.ReentrantLock;
 
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.types.ByteString;
@@ -69,7 +69,7 @@
  * is appended to the hash, and then the entire value is base64-encoded.
  */
 public class SaltedSHA512PasswordStorageScheme
-       extends PasswordStorageScheme
+       extends PasswordStorageScheme <PasswordStorageSchemeCfg>
 {
   /**
    * The fully-qualified name of this class.
@@ -116,8 +116,10 @@
    * {@inheritDoc}
    */
   @Override()
-  public void initializePasswordStorageScheme(ConfigEntry configEntry)
-         throws ConfigException, InitializationException
+  public void initializePasswordStorageScheme(
+      PasswordStorageSchemeCfg configuration
+      )
+      throws ConfigException, InitializationException
   {
     try
     {
diff --git a/opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java b/opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java
index 538cb3d..ee2a1b7 100644
--- a/opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java
+++ b/opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java
@@ -39,10 +39,10 @@
 import java.util.concurrent.locks.Lock;
 
 import org.opends.server.api.Backend;
-import org.opends.server.api.ConfigurableComponent;
 import org.opends.server.api.EntryCache;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.server.SoftReferenceEntryCacheCfg;
 import org.opends.server.config.ConfigAttribute;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.config.IntegerWithUnitConfigAttribute;
 import org.opends.server.config.StringConfigAttribute;
@@ -51,23 +51,19 @@
 import org.opends.server.types.ConfigChangeResult;
 import org.opends.server.types.DN;
 import org.opends.server.types.Entry;
-import org.opends.server.types.ErrorLogCategory;
-import org.opends.server.types.ErrorLogSeverity;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.LockManager;
 import org.opends.server.types.LockType;
-import org.opends.server.types.ResultCode;
 import org.opends.server.types.SearchFilter;
 
+
 import static org.opends.server.config.ConfigConstants.*;
 import static org.opends.server.loggers.debug.DebugLogger.debugCaught;
 import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
 import org.opends.server.types.DebugLogLevel;
-import static org.opends.server.loggers.Error.*;
 import static org.opends.server.messages.ExtensionsMessages.*;
 import static org.opends.server.messages.MessageHandler.*;
 import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
 
 
 
@@ -77,21 +73,18 @@
  * running low on memory.
  */
 public class SoftReferenceEntryCache
-       extends EntryCache
-       implements ConfigurableComponent, Runnable
+    extends EntryCache <SoftReferenceEntryCacheCfg>
+    implements
+        ConfigurationChangeListener<SoftReferenceEntryCacheCfg>,
+        Runnable
 {
 
 
-
-  /**
-   * The set of time units that will be used for expressing the task retention
-   * time.
-   */
+  // The set of time units that will be used for expressing the task retention
+  // time.
   private static final LinkedHashMap<String,Double> timeUnits =
        new LinkedHashMap<String,Double>();
 
-
-
   // The mapping between entry DNs and their corresponding entries.
   private ConcurrentHashMap<DN,SoftReference<CacheEntry>> dnMap;
 
@@ -158,213 +151,32 @@
 
 
   /**
-   * Initializes this entry cache implementation so that it will be available
-   * for storing and retrieving entries.
-   *
-   * @param  configEntry  The configuration entry containing the settings to use
-   *                      for this entry cache.
-   *
-   * @throws  ConfigException  If there is a problem with the provided
-   *                           configuration entry that would prevent this
-   *                           entry cache from being used.
-   *
-   * @throws  InitializationException  If a problem occurs during the
-   *                                   initialization process that is not
-   *                                   related to the configuration.
+   * {@inheritDoc}
    */
-  public void initializeEntryCache(ConfigEntry configEntry)
-         throws ConfigException, InitializationException
+  public void initializeEntryCache(
+      SoftReferenceEntryCacheCfg configuration
+      )
+      throws ConfigException, InitializationException
   {
+    configuration.addSoftReferenceChangeListener (this);
+    configEntryDN = configuration.dn();
+
     dnMap.clear();
     idMap.clear();
 
-
-    configEntryDN = configEntry.getDN();
-
-
-    // Determine the lock timeout to use when interacting with the lock manager.
-    int msgID = MSGID_SOFTREFCACHE_DESCRIPTION_LOCK_TIMEOUT;
-    IntegerWithUnitConfigAttribute lockTimeoutStub =
-         new IntegerWithUnitConfigAttribute(ATTR_SOFTREFCACHE_LOCK_TIMEOUT,
-                                            getMessage(msgID), false, timeUnits,
-                                            true, 0, false, 0);
-    try
-    {
-      IntegerWithUnitConfigAttribute lockTimeoutAttr =
-             (IntegerWithUnitConfigAttribute)
-             configEntry.getConfigAttribute(lockTimeoutStub);
-      if (lockTimeoutAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-      }
-      else
-      {
-        lockTimeout = lockTimeoutAttr.activeCalculatedValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // Log an error message.
-      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-               MSGID_SOFTREFCACHE_CANNOT_DETERMINE_LOCK_TIMEOUT,
-               String.valueOf(configEntryDN), getExceptionMessage(e),
-               lockTimeout);
-    }
-
-
-    // Determine the set of cache filters that can be used to control the
-    // entries that should be included in the cache.
-    includeFilters = new HashSet<SearchFilter>();
-    msgID = MSGID_SOFTREFCACHE_DESCRIPTION_INCLUDE_FILTERS;
-    StringConfigAttribute includeStub =
-         new StringConfigAttribute(ATTR_SOFTREFCACHE_INCLUDE_FILTER,
-                                   getMessage(msgID), false, true, false);
-    try
-    {
-      StringConfigAttribute includeAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(includeStub);
-      if (includeAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-      }
-      else
-      {
-        List<String> filterStrings = includeAttr.activeValues();
-        if ((filterStrings == null) || filterStrings.isEmpty())
-        {
-          // There are no include filters, so we'll allow anything by default.
-        }
-        else
-        {
-          for (String filterString : filterStrings)
-          {
-            try
-            {
-              includeFilters.add(
-                   SearchFilter.createFilterFromString(filterString));
-            }
-            catch (Exception e)
-            {
-              if (debugEnabled())
-              {
-                debugCaught(DebugLogLevel.ERROR, e);
-              }
-
-              // We couldn't decode this filter.  Log a warning and continue.
-              logError(ErrorLogCategory.CONFIGURATION,
-                       ErrorLogSeverity.SEVERE_WARNING,
-                       MSGID_SOFTREFCACHE_CANNOT_DECODE_INCLUDE_FILTER,
-                       String.valueOf(configEntryDN), filterString,
-                       getExceptionMessage(e));
-            }
-          }
-
-          if (includeFilters.isEmpty())
-          {
-            logError(ErrorLogCategory.CONFIGURATION,
-                     ErrorLogSeverity.SEVERE_ERROR,
-                     MSGID_SOFTREFCACHE_CANNOT_DECODE_ANY_INCLUDE_FILTERS,
-                     String.valueOf(configEntryDN));
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // Log an error message.
-      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-               MSGID_SOFTREFCACHE_CANNOT_DETERMINE_INCLUDE_FILTERS,
-               String.valueOf(configEntryDN), getExceptionMessage(e));
-    }
-
-
-    // Determine the set of cache filters that can be used to control the
-    // entries that should be excluded from the cache.
-    excludeFilters = new HashSet<SearchFilter>();
-    msgID = MSGID_SOFTREFCACHE_DESCRIPTION_EXCLUDE_FILTERS;
-    StringConfigAttribute excludeStub =
-         new StringConfigAttribute(ATTR_SOFTREFCACHE_EXCLUDE_FILTER,
-                                   getMessage(msgID), false, true, false);
-    try
-    {
-      StringConfigAttribute excludeAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(excludeStub);
-      if (excludeAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-      }
-      else
-      {
-        List<String> filterStrings = excludeAttr.activeValues();
-        if ((filterStrings == null) || filterStrings.isEmpty())
-        {
-          // There are no exclude filters, so we'll allow anything by default.
-        }
-        else
-        {
-          for (String filterString : filterStrings)
-          {
-            try
-            {
-              excludeFilters.add(
-                   SearchFilter.createFilterFromString(filterString));
-            }
-            catch (Exception e)
-            {
-              if (debugEnabled())
-              {
-                debugCaught(DebugLogLevel.ERROR, e);
-              }
-
-              // We couldn't decode this filter.  Log a warning and continue.
-              logError(ErrorLogCategory.CONFIGURATION,
-                       ErrorLogSeverity.SEVERE_WARNING,
-                       MSGID_SOFTREFCACHE_CANNOT_DECODE_EXCLUDE_FILTER,
-                       String.valueOf(configEntryDN), filterString,
-                       getExceptionMessage(e));
-            }
-          }
-
-          if (excludeFilters.isEmpty())
-          {
-            logError(ErrorLogCategory.CONFIGURATION,
-                     ErrorLogSeverity.SEVERE_ERROR,
-                     MSGID_SOFTREFCACHE_CANNOT_DECODE_ANY_EXCLUDE_FILTERS,
-                     String.valueOf(configEntryDN));
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // Log an error message.
-      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-               MSGID_SOFTREFCACHE_CANNOT_DETERMINE_EXCLUDE_FILTERS,
-               String.valueOf(configEntryDN), getExceptionMessage(e));
-    }
+    // Read configuration and apply changes.
+    boolean applyChanges = true;
+    EntryCacheCommon.ConfigErrorHandler errorHandler =
+      EntryCacheCommon.getConfigErrorHandler (
+          EntryCacheCommon.ConfigPhase.PHASE_INIT, null, null
+          );
+    processEntryCacheConfig (configuration, applyChanges, errorHandler);
   }
 
 
 
   /**
-   * Performs any necessary cleanup work (e.g., flushing all cached entries and
-   * releasing any other held resources) that should be performed when the
-   * server is to be shut down or the entry cache destroyed or replaced.
+   * {@inheritDoc}
    */
   public void finalizeEntryCache()
   {
@@ -375,14 +187,7 @@
 
 
   /**
-   * Indicates whether the entry cache currently contains the entry with the
-   * specified DN.  This method may be called without holding any locks if a
-   * point-in-time check is all that is required.
-   *
-   * @param  entryDN  The DN for which to make the determination.
-   *
-   * @return  <CODE>true</CODE> if the entry cache currently contains the entry
-   *          with the specified DN, or <CODE>false</CODE> if not.
+   * {@inheritDoc}
    */
   public boolean containsEntry(DN entryDN)
   {
@@ -393,14 +198,7 @@
 
 
   /**
-   * Retrieves the entry with the specified DN from the cache.  The caller
-   * should have already acquired a read or write lock for the entry if such
-   * protection is needed.
-   *
-   * @param  entryDN  The DN of the entry to retrieve.
-   *
-   * @return  The requested entry if it is present in the cache, or
-   *          <CODE>null</CODE> if it is not present.
+   * {@inheritDoc}
    */
   public Entry getEntry(DN entryDN)
   {
@@ -426,14 +224,7 @@
 
 
   /**
-   * Retrieves the entry ID for the entry with the specified DN from the cache.
-   * The caller should have already acquired a read or write lock for the entry
-   * if such protection is needed.
-   *
-   * @param  entryDN  The DN of the entry for which to retrieve the entry ID.
-   *
-   * @return  The entry ID for the requested entry, or -1 if it is not present
-   *          in the cache.
+   * {@inheritDoc}
    */
   public long getEntryID(DN entryDN)
   {
@@ -459,20 +250,7 @@
 
 
   /**
-   * Retrieves the entry with the specified DN from the cache, obtaining a lock
-   * on the entry before it is returned.  If the entry is present in the cache,
-   * then a lock will be obtained for that entry and appended to the provided
-   * list before the entry is returned.  If the entry is not present, then no
-   * lock will be obtained.
-   *
-   * @param  entryDN   The DN of the entry to retrieve.
-   * @param  lockType  The type of lock to obtain (it may be <CODE>NONE</CODE>).
-   * @param  lockList  The list to which the obtained lock will be added (note
-   *                   that no lock will be added if the lock type was
-   *                   <CODE>NONE</CODE>).
-   *
-   * @return  The requested entry if it is present in the cache, or
-   *          <CODE>null</CODE> if it is not present.
+   * {@inheritDoc}
    */
   public Entry getEntry(DN entryDN, LockType lockType,
                         List<Lock> lockList)
@@ -590,22 +368,7 @@
 
 
   /**
-   * Retrieves the requested entry if it is present in the cache, obtaining a
-   * lock on the entry before it is returned.  If the entry is present in the
-   * cache, then a lock  will be obtained for that entry and appended to the
-   * provided list before the entry is returned.  If the entry is not present,
-   * then no lock will be obtained.
-   *
-   * @param  backend   The backend associated with the entry to retrieve.
-   * @param  entryID   The entry ID within the provided backend for the
-   *                   specified entry.
-   * @param  lockType  The type of lock to obtain (it may be <CODE>NONE</CODE>).
-   * @param  lockList  The list to which the obtained lock will be added (note
-   *                   that no lock will be added if the lock type was
-   *                   <CODE>NONE</CODE>).
-   *
-   * @return  The requested entry if it is present in the cache, or
-   *          <CODE>null</CODE> if it is not present.
+   * {@inheritDoc}
    */
   public Entry getEntry(Backend backend, long entryID,
                         LockType lockType, List<Lock> lockList)
@@ -725,14 +488,7 @@
 
 
   /**
-   * Stores the provided entry in the cache.  Note that the mechanism that it
-   * uses to achieve this is implementation-dependent, and it is acceptable for
-   * the entry to not actually be stored in any cache.
-   *
-   * @param  entry    The entry to store in the cache.
-   * @param  backend  The backend with which the entry is associated.
-   * @param  entryID  The entry ID within the provided backend that uniquely
-   *                  identifies the specified entry.
+   * {@inheritDoc}
    */
   public void putEntry(Entry entry, Backend backend, long entryID)
   {
@@ -827,22 +583,7 @@
 
 
   /**
-   * Stores the provided entry in the cache only if it does not conflict with an
-   * entry that already exists.  Note that the mechanism that it uses to achieve
-   * this is implementation-dependent, and it is acceptable for the entry to not
-   * actually be stored in any cache.  However, this method must not overwrite
-   * an existing version of the entry.
-   *
-   * @param  entry    The entry to store in the cache.
-   * @param  backend  The backend with which the entry is associated.
-   * @param  entryID  The entry ID within the provided backend that uniquely
-   *                  identifies the specified entry.
-   *
-   * @return  <CODE>false</CODE> if an existing entry or some other problem
-   *          prevented the method from completing successfully, or
-   *          <CODE>true</CODE> if there was no conflict and the entry was
-   *          either stored or the cache determined that this entry should never
-   *          be cached for some reason.
+   * {@inheritDoc}
    */
   public boolean putEntryIfAbsent(Entry entry, Backend backend,
                                   long entryID)
@@ -940,9 +681,7 @@
 
 
   /**
-   * Removes the specified entry from the cache.
-   *
-   * @param  entryDN  The DN of the entry to remove from the cache.
+   * {@inheritDoc}
    */
   public void removeEntry(DN entryDN)
   {
@@ -973,8 +712,7 @@
 
 
   /**
-   * Removes all entries from the cache.  The cache should still be available
-   * for future use.
+   * {@inheritDoc}
    */
   public void clear()
   {
@@ -985,10 +723,7 @@
 
 
   /**
-   * Removes all entries from the cache that are associated with the provided
-   * backend.
-   *
-   * @param  backend  The backend for which to flush the associated entries.
+   * {@inheritDoc}
    */
   public void clearBackend(Backend backend)
   {
@@ -1015,9 +750,7 @@
 
 
   /**
-   * Removes all entries from the cache that are below the provided DN.
-   *
-   * @param  baseDN  The base DN below which all entries should be flushed.
+   * {@inheritDoc}
    */
   public void clearSubtree(DN baseDN)
   {
@@ -1037,10 +770,7 @@
 
 
   /**
-   * Attempts to react to a scenario in which it is determined that the system
-   * is running low on available memory.  In this case, the entry cache should
-   * attempt to free some memory if possible to try to avoid out of memory
-   * errors.
+   * {@inheritDoc}
    */
   public void handleLowMemory()
   {
@@ -1120,431 +850,135 @@
 
 
   /**
-   * 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.
+   * {@inheritDoc}
    */
-  public boolean hasAcceptableConfiguration(ConfigEntry configEntry,
-                                            List<String> unacceptableReasons)
+  public boolean isConfigurationChangeAcceptable(
+      SoftReferenceEntryCacheCfg configuration,
+      List<String>               unacceptableReasons)
   {
-    // Start out assuming that the configuration is valid.
-    boolean configIsAcceptable = true;
+    // Make sure that we can process the defined character sets.  If so, then
+    // we'll accept the new configuration.
+    boolean applyChanges = false;
+    EntryCacheCommon.ConfigErrorHandler errorHandler =
+      EntryCacheCommon.getConfigErrorHandler (
+          EntryCacheCommon.ConfigPhase.PHASE_ACCEPTABLE,
+          unacceptableReasons,
+          null
+        );
+    processEntryCacheConfig (configuration, applyChanges, errorHandler);
 
-
-    // Determine the lock timeout to use when interacting with the lock manager.
-    int msgID = MSGID_SOFTREFCACHE_DESCRIPTION_LOCK_TIMEOUT;
-    IntegerWithUnitConfigAttribute lockTimeoutStub =
-         new IntegerWithUnitConfigAttribute(ATTR_SOFTREFCACHE_LOCK_TIMEOUT,
-                                            getMessage(msgID), false, timeUnits,
-                                            true, 0, false, 0);
-    try
-    {
-      IntegerWithUnitConfigAttribute lockTimeoutAttr =
-             (IntegerWithUnitConfigAttribute)
-             configEntry.getConfigAttribute(lockTimeoutStub);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // An error occurred, so the provided value must not be valid.
-      msgID = MSGID_SOFTREFCACHE_INVALID_LOCK_TIMEOUT;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         getExceptionMessage(e)));
-      configIsAcceptable = false;
-    }
-
-
-    // Determine the set of cache filters that can be used to control the
-    // entries that should be included in the cache.
-    msgID = MSGID_SOFTREFCACHE_DESCRIPTION_INCLUDE_FILTERS;
-    StringConfigAttribute includeStub =
-         new StringConfigAttribute(ATTR_SOFTREFCACHE_INCLUDE_FILTER,
-                                   getMessage(msgID), false, true, false);
-    try
-    {
-      StringConfigAttribute includeAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(includeStub);
-      if (includeAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-      }
-      else
-      {
-        List<String> filterStrings = includeAttr.activeValues();
-        if ((filterStrings == null) || filterStrings.isEmpty())
-        {
-          // There are no include filters, so we'll allow anything by default.
-        }
-        else
-        {
-          for (String filterString : filterStrings)
-          {
-            try
-            {
-              SearchFilter.createFilterFromString(filterString);
-            }
-            catch (Exception e)
-            {
-              if (debugEnabled())
-              {
-                debugCaught(DebugLogLevel.ERROR, e);
-              }
-
-              // We couldn't decode this filter, so it isn't valid.
-              msgID = MSGID_SOFTREFCACHE_INVALID_INCLUDE_FILTER;
-              unacceptableReasons.add(getMessage(msgID,
-                                           String.valueOf(configEntryDN),
-                                            filterString,
-                                            getExceptionMessage(e)));
-              configIsAcceptable = false;
-            }
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // An error occurred, so the provided value must not be valid.
-      msgID = MSGID_SOFTREFCACHE_INVALID_INCLUDE_FILTERS;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         getExceptionMessage(e)));
-      configIsAcceptable = false;
-    }
-
-
-    // Determine the set of cache filters that can be used to control the
-    // entries that should be excluded from the cache.
-    msgID = MSGID_SOFTREFCACHE_DESCRIPTION_EXCLUDE_FILTERS;
-    StringConfigAttribute excludeStub =
-         new StringConfigAttribute(ATTR_SOFTREFCACHE_EXCLUDE_FILTER,
-                                   getMessage(msgID), false, true, false);
-    try
-    {
-      StringConfigAttribute excludeAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(excludeStub);
-      if (excludeAttr == null)
-      {
-        // This is fine -- we'll just use the default.
-      }
-      else
-      {
-        List<String> filterStrings = excludeAttr.activeValues();
-        if ((filterStrings == null) || filterStrings.isEmpty())
-        {
-          // There are no exclude filters, so we'll allow anything by default.
-        }
-        else
-        {
-          for (String filterString : filterStrings)
-          {
-            try
-            {
-              SearchFilter.createFilterFromString(filterString);
-            }
-            catch (Exception e)
-            {
-              if (debugEnabled())
-              {
-                debugCaught(DebugLogLevel.ERROR, e);
-              }
-
-              // We couldn't decode this filter, so it isn't valid.
-              msgID = MSGID_SOFTREFCACHE_INVALID_EXCLUDE_FILTER;
-              unacceptableReasons.add(getMessage(msgID,
-                                           String.valueOf(configEntryDN),
-                                           filterString,
-                                           getExceptionMessage(e)));
-              configIsAcceptable = false;
-            }
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // An error occurred, so the provided value must not be valid.
-      msgID = MSGID_SOFTREFCACHE_INVALID_EXCLUDE_FILTERS;
-      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                         getExceptionMessage(e)));
-      configIsAcceptable = false;
-    }
-
-
-    return configIsAcceptable;
+    return errorHandler.getIsAcceptable();
   }
 
 
 
   /**
-   * 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(
+      SoftReferenceEntryCacheCfg configuration
+      )
   {
-    // Create a set of variables to use for the result.
-    ResultCode        resultCode          = ResultCode.SUCCESS;
-    boolean           adminActionRequired = false;
-    ArrayList<String> messages            = new ArrayList<String>();
-    boolean           configIsAcceptable  = true;
+    // Make sure that we can process the defined character sets.  If so, then
+    // activate the new configuration.
+    boolean applyChanges = false;
+    ArrayList<String> errorMessages = new ArrayList<String>();
+    EntryCacheCommon.ConfigErrorHandler errorHandler =
+      EntryCacheCommon.getConfigErrorHandler (
+          EntryCacheCommon.ConfigPhase.PHASE_APPLY, null, errorMessages
+          );
+    processEntryCacheConfig (configuration, applyChanges, errorHandler);
 
-
-    // Determine the lock timeout to use when interacting with the lock manager.
-    long newLockTimeout = LockManager.DEFAULT_TIMEOUT;
-    int msgID = MSGID_SOFTREFCACHE_DESCRIPTION_LOCK_TIMEOUT;
-    IntegerWithUnitConfigAttribute lockTimeoutStub =
-         new IntegerWithUnitConfigAttribute(ATTR_SOFTREFCACHE_LOCK_TIMEOUT,
-                                            getMessage(msgID), false, timeUnits,
-                                            true, 0, false, 0);
-    try
-    {
-      IntegerWithUnitConfigAttribute lockTimeoutAttr =
-             (IntegerWithUnitConfigAttribute)
-             configEntry.getConfigAttribute(lockTimeoutStub);
-      if (lockTimeoutAttr != null)
-      {
-        newLockTimeout = lockTimeoutAttr.pendingCalculatedValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // An error occurred, so the provided value must not be valid.
-      msgID = MSGID_SOFTREFCACHE_INVALID_LOCK_TIMEOUT;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              getExceptionMessage(e)));
-
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = ResultCode.CONSTRAINT_VIOLATION;
-      }
-
-      configIsAcceptable = false;
-    }
-
-
-    // Determine the set of cache filters that can be used to control the
-    // entries that should be included in the cache.
-    HashSet<SearchFilter> newIncludeFilters = new HashSet<SearchFilter>();
-    msgID = MSGID_SOFTREFCACHE_DESCRIPTION_INCLUDE_FILTERS;
-    StringConfigAttribute includeStub =
-         new StringConfigAttribute(ATTR_SOFTREFCACHE_INCLUDE_FILTER,
-                                   getMessage(msgID), false, true, false);
-    try
-    {
-      StringConfigAttribute includeAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(includeStub);
-      if (includeAttr != null)
-      {
-        List<String> filterStrings = includeAttr.activeValues();
-        if ((filterStrings == null) || filterStrings.isEmpty())
-        {
-          // There are no include filters, so we'll allow anything by default.
-        }
-        else
-        {
-          for (String filterString : filterStrings)
-          {
-            try
-            {
-              newIncludeFilters.add(
-                   SearchFilter.createFilterFromString(filterString));
-            }
-            catch (Exception e)
-            {
-              if (debugEnabled())
-              {
-                debugCaught(DebugLogLevel.ERROR, e);
-              }
-
-              // We couldn't decode this filter, so it isn't valid.
-              msgID = MSGID_SOFTREFCACHE_INVALID_INCLUDE_FILTER;
-              messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                      filterString, getExceptionMessage(e)));
-
-              if (resultCode == ResultCode.SUCCESS)
-              {
-                resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
-              }
-
-              configIsAcceptable = false;
-            }
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // An error occurred, so the provided value must not be valid.
-      msgID = MSGID_SOFTREFCACHE_INVALID_INCLUDE_FILTERS;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              getExceptionMessage(e)));
-
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = ResultCode.CONSTRAINT_VIOLATION;
-      }
-
-      configIsAcceptable = false;
-    }
-
-
-    // Determine the set of cache filters that can be used to control the
-    // entries that should be exclude from the cache.
-    HashSet<SearchFilter> newExcludeFilters = new HashSet<SearchFilter>();
-    msgID = MSGID_SOFTREFCACHE_DESCRIPTION_EXCLUDE_FILTERS;
-    StringConfigAttribute excludeStub =
-         new StringConfigAttribute(ATTR_SOFTREFCACHE_EXCLUDE_FILTER,
-                                   getMessage(msgID), false, true, false);
-    try
-    {
-      StringConfigAttribute excludeAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(excludeStub);
-      if (excludeAttr != null)
-      {
-        List<String> filterStrings = excludeAttr.activeValues();
-        if ((filterStrings == null) || filterStrings.isEmpty())
-        {
-          // There are no exclude filters, so we'll allow anything by default.
-        }
-        else
-        {
-          for (String filterString : filterStrings)
-          {
-            try
-            {
-              newExcludeFilters.add(
-                   SearchFilter.createFilterFromString(filterString));
-            }
-            catch (Exception e)
-            {
-              if (debugEnabled())
-              {
-                debugCaught(DebugLogLevel.ERROR, e);
-              }
-
-              // We couldn't decode this filter, so it isn't valid.
-              msgID = MSGID_SOFTREFCACHE_INVALID_EXCLUDE_FILTER;
-              messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                      filterString, getExceptionMessage(e)));
-
-              if (resultCode == ResultCode.SUCCESS)
-              {
-                resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
-              }
-
-              configIsAcceptable = false;
-            }
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      // An error occurred, so the provided value must not be valid.
-      msgID = MSGID_SOFTREFCACHE_INVALID_EXCLUDE_FILTERS;
-      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                              getExceptionMessage(e)));
-
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = ResultCode.CONSTRAINT_VIOLATION;
-      }
-
-      configIsAcceptable = false;
-    }
-
-
-    if (configIsAcceptable)
-    {
-      if (lockTimeout != newLockTimeout)
-      {
-        lockTimeout = newLockTimeout;
-
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_SOFTREFCACHE_UPDATED_LOCK_TIMEOUT,
-                                  lockTimeout));
-        }
-      }
-
-      if (!includeFilters.equals(newIncludeFilters))
-      {
-        includeFilters = newIncludeFilters;
-
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_SOFTREFCACHE_UPDATED_INCLUDE_FILTERS));
-        }
-      }
-
-      if (!excludeFilters.equals(newExcludeFilters))
-      {
-        excludeFilters = newExcludeFilters;
-
-        if (detailedResults)
-        {
-          messages.add(getMessage(MSGID_SOFTREFCACHE_UPDATED_EXCLUDE_FILTERS));
-        }
-      }
-    }
-
-
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+    boolean adminActionRequired = false;
+    ConfigChangeResult changeResult = new ConfigChangeResult(
+        errorHandler.getResultCode(),
+        adminActionRequired,
+        errorHandler.getErrorMessages()
+        );
+    return changeResult;
   }
 
 
 
   /**
+   * Parses the provided configuration and configure the entry cache.
+   *
+   * @param configuration  The new configuration containing the changes.
+   * @param applyChanges   If true then take into account the new configuration.
+   * @param errorHandler   An handler used to report errors.
+   *
+   * @return  The mapping between strings of character set values and the
+   *          minimum number of characters required from those sets.
+   */
+  public boolean processEntryCacheConfig(
+      SoftReferenceEntryCacheCfg          configuration,
+      boolean                             applyChanges,
+      EntryCacheCommon.ConfigErrorHandler errorHandler
+      )
+  {
+    // Local variables to read configuration.
+    DN                    newConfigEntryDN;
+    long                  newLockTimeout;
+    HashSet<SearchFilter> newIncludeFilters = null;
+    HashSet<SearchFilter> newExcludeFilters = null;
+
+    // Read configuration.
+    newConfigEntryDN = configuration.dn();
+    newLockTimeout   = configuration.getLockTimeout();
+
+    // Get include and exclude filters.
+    switch (errorHandler.getConfigPhase())
+    {
+    case PHASE_INIT:
+      newIncludeFilters = EntryCacheCommon.getFilters (
+          configuration.getIncludeFilter(),
+          MSGID_SOFTREFCACHE_INVALID_INCLUDE_FILTER,
+          MSGID_SOFTREFCACHE_CANNOT_DECODE_ANY_INCLUDE_FILTERS,
+          errorHandler,
+          configEntryDN
+          );
+      newExcludeFilters = EntryCacheCommon.getFilters (
+          configuration.getExcludeFilter(),
+          MSGID_SOFTREFCACHE_CANNOT_DECODE_EXCLUDE_FILTER,
+          MSGID_SOFTREFCACHE_CANNOT_DECODE_ANY_EXCLUDE_FILTERS,
+          errorHandler,
+          configEntryDN
+          );
+      break;
+    case PHASE_ACCEPTABLE:  // acceptable and apply are using the same
+    case PHASE_APPLY:       // error ID codes
+      newIncludeFilters = EntryCacheCommon.getFilters (
+          configuration.getIncludeFilter(),
+          MSGID_SOFTREFCACHE_INVALID_INCLUDE_FILTER,
+          0,
+          errorHandler,
+          configEntryDN
+          );
+      newExcludeFilters = EntryCacheCommon.getFilters (
+          configuration.getExcludeFilter(),
+          MSGID_SOFTREFCACHE_INVALID_EXCLUDE_FILTER,
+          0,
+          errorHandler,
+          configEntryDN
+          );
+      break;
+    }
+
+    if (applyChanges && errorHandler.getIsAcceptable())
+    {
+      configEntryDN  = newConfigEntryDN;
+      lockTimeout    = newLockTimeout;
+      includeFilters = newIncludeFilters;
+      excludeFilters = newExcludeFilters;
+    }
+
+    return errorHandler.getIsAcceptable();
+  }
+
+
+
+
+  /**
    * Operate in a loop, receiving notification of soft references that have been
    * freed and removing the corresponding entries from the cache.
    */
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/Base64PasswordStorageSchemeTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/Base64PasswordStorageSchemeTestCase.java
index 7891fae..b4d64c7 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/Base64PasswordStorageSchemeTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/Base64PasswordStorageSchemeTestCase.java
@@ -28,6 +28,9 @@
 
 
 
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
 
 
@@ -62,7 +65,14 @@
          throws Exception
   {
     Base64PasswordStorageScheme scheme = new Base64PasswordStorageScheme();
-    scheme.initializePasswordStorageScheme(configEntry);
+
+    PasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          PasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry()
+          );
+
+    scheme.initializePasswordStorageScheme(configuration);
     return scheme;
   }
 }
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ClearPasswordStorageSchemeTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ClearPasswordStorageSchemeTestCase.java
index 8058e5b..96bbecb 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ClearPasswordStorageSchemeTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ClearPasswordStorageSchemeTestCase.java
@@ -28,6 +28,9 @@
 
 
 
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
 
 
@@ -62,7 +65,14 @@
          throws Exception
   {
     ClearPasswordStorageScheme scheme = new ClearPasswordStorageScheme();
-    scheme.initializePasswordStorageScheme(configEntry);
+
+    PasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          PasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry()
+          );
+
+    scheme.initializePasswordStorageScheme(configuration);
     return scheme;
   }
 }
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ErrorLogAccountStatusNotificationHandlerTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ErrorLogAccountStatusNotificationHandlerTestCase.java
index c1774d4..99de3d8 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ErrorLogAccountStatusNotificationHandlerTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ErrorLogAccountStatusNotificationHandlerTestCase.java
@@ -36,6 +36,11 @@
 
 import org.opends.server.TestCaseUtils;
 import org.opends.server.api.AccountStatusNotificationHandler;
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.
+       ErrorLogAccountStatusNotificationHandlerCfgDefn;
+import org.opends.server.admin.std.server.
+       ErrorLogAccountStatusNotificationHandlerCfg;
 import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.core.DirectoryServer;
@@ -149,7 +154,12 @@
 
     ErrorLogAccountStatusNotificationHandler handler =
          new ErrorLogAccountStatusNotificationHandler();
-    handler.initializeStatusNotificationHandler(configEntry);
+    ErrorLogAccountStatusNotificationHandlerCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          ErrorLogAccountStatusNotificationHandlerCfgDefn.getInstance(),
+          configEntry.getEntry()
+          );
+    handler.initializeStatusNotificationHandler(configuration);
   }
 
 
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/MD5PasswordStorageSchemeTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/MD5PasswordStorageSchemeTestCase.java
index 6ab7ff7..0d61951 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/MD5PasswordStorageSchemeTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/MD5PasswordStorageSchemeTestCase.java
@@ -28,6 +28,9 @@
 
 
 
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
 
 
@@ -62,7 +65,14 @@
          throws Exception
   {
     MD5PasswordStorageScheme scheme = new MD5PasswordStorageScheme();
-    scheme.initializePasswordStorageScheme(configEntry);
+
+    PasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          PasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry()
+          );
+
+    scheme.initializePasswordStorageScheme(configuration);
     return scheme;
   }
 }
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SHA1PasswordStorageSchemeTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SHA1PasswordStorageSchemeTestCase.java
index 3737c2d..cfff9d7 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SHA1PasswordStorageSchemeTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SHA1PasswordStorageSchemeTestCase.java
@@ -28,6 +28,9 @@
 
 
 
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
 
 
@@ -62,7 +65,14 @@
          throws Exception
   {
     SHA1PasswordStorageScheme scheme = new SHA1PasswordStorageScheme();
-    scheme.initializePasswordStorageScheme(configEntry);
+
+    PasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          PasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry()
+          );
+
+    scheme.initializePasswordStorageScheme(configuration);
     return scheme;
   }
 }
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageSchemeTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageSchemeTestCase.java
index b27b56b..bbb72d0 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageSchemeTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageSchemeTestCase.java
@@ -28,6 +28,11 @@
 
 
 
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.ErrorLogAccountStatusNotificationHandlerCfgDefn;
+import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.ErrorLogAccountStatusNotificationHandlerCfg;
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
 
 
@@ -63,7 +68,14 @@
   {
     SaltedMD5PasswordStorageScheme scheme =
          new SaltedMD5PasswordStorageScheme();
-    scheme.initializePasswordStorageScheme(configEntry);
+
+    PasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          PasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry()
+          );
+
+    scheme.initializePasswordStorageScheme(configuration);
     return scheme;
   }
 }
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageSchemeTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageSchemeTestCase.java
index b5be590..a188d1d 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageSchemeTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageSchemeTestCase.java
@@ -30,6 +30,9 @@
 
 import org.testng.annotations.Test;
 
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
 import org.opends.server.protocols.asn1.ASN1OctetString;
 import org.opends.server.schema.UserPasswordSyntax;
@@ -70,7 +73,14 @@
   {
     SaltedSHA1PasswordStorageScheme scheme =
          new SaltedSHA1PasswordStorageScheme();
-    scheme.initializePasswordStorageScheme(configEntry);
+
+    PasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          PasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry()
+          );
+
+    scheme.initializePasswordStorageScheme(configuration);
     return scheme;
   }
 
@@ -89,7 +99,14 @@
   {
     SaltedSHA1PasswordStorageScheme scheme =
          new SaltedSHA1PasswordStorageScheme();
-    scheme.initializePasswordStorageScheme(configEntry);
+
+    PasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          PasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry()
+          );
+
+    scheme.initializePasswordStorageScheme(configuration);
 
     String passwordString = scheme.encodeOffline(plaintext.value());
     String[] pwComps = UserPasswordSyntax.decodeUserPassword(passwordString);
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageSchemeTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageSchemeTestCase.java
index beea4f2..94f39bc 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageSchemeTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageSchemeTestCase.java
@@ -28,6 +28,9 @@
 
 
 
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
 
 
@@ -63,7 +66,14 @@
   {
     SaltedSHA256PasswordStorageScheme scheme =
          new SaltedSHA256PasswordStorageScheme();
-    scheme.initializePasswordStorageScheme(configEntry);
+
+    PasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          PasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry()
+          );
+
+    scheme.initializePasswordStorageScheme(configuration);
     return scheme;
   }
 }
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageSchemeTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageSchemeTestCase.java
index dc15470..23ccc03 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageSchemeTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageSchemeTestCase.java
@@ -28,6 +28,9 @@
 
 
 
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
 
 
@@ -63,7 +66,14 @@
   {
     SaltedSHA384PasswordStorageScheme scheme =
          new SaltedSHA384PasswordStorageScheme();
-    scheme.initializePasswordStorageScheme(configEntry);
+
+    PasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          PasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry()
+          );
+
+    scheme.initializePasswordStorageScheme(configuration);
     return scheme;
   }
 }
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageSchemeTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageSchemeTestCase.java
index 30ae73c..5d018eb 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageSchemeTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageSchemeTestCase.java
@@ -28,6 +28,9 @@
 
 
 
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
 
 
@@ -63,7 +66,14 @@
   {
     SaltedSHA512PasswordStorageScheme scheme =
          new SaltedSHA512PasswordStorageScheme();
-    scheme.initializePasswordStorageScheme(configEntry);
+
+    PasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          PasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry()
+          );
+
+    scheme.initializePasswordStorageScheme(configuration);
     return scheme;
   }
 }
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/AuthPasswordEqualityMatchingRuleTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/AuthPasswordEqualityMatchingRuleTest.java
index 8410ff9..e092b01 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/AuthPasswordEqualityMatchingRuleTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/AuthPasswordEqualityMatchingRuleTest.java
@@ -26,6 +26,9 @@
  */
 package org.opends.server.schema;
 
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.EqualityMatchingRule;
 import org.opends.server.config.ConfigEntry;
 import org.opends.server.core.DirectoryServer;
@@ -73,8 +76,16 @@
     SaltedMD5PasswordStorageScheme scheme = new SaltedMD5PasswordStorageScheme();
     
     ConfigEntry configEntry =
-       DirectoryServer.getConfigEntry(DN.decode("cn=Salted MD5,cn=Password Storage Schemes,cn=config"));
-    scheme.initializePasswordStorageScheme(configEntry);
+       DirectoryServer.getConfigEntry(
+           DN.decode("cn=Salted MD5,cn=Password Storage Schemes,cn=config"));
+
+    PasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          PasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry()
+          );
+
+    scheme.initializePasswordStorageScheme(configuration);
     
     ByteString encodedAuthPassword = scheme.encodeAuthPassword(bytePassword);
     StringBuilder[] authPWComponents =
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRuleTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRuleTest.java
index 61e81ed..e3d2dd8 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRuleTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRuleTest.java
@@ -26,6 +26,9 @@
  */
 package org.opends.server.schema;
 
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.PasswordStorageSchemeCfg;
 import org.opends.server.api.EqualityMatchingRule;
 import org.opends.server.config.ConfigEntry;
 import org.opends.server.core.DirectoryServer;
@@ -74,7 +77,14 @@
     ConfigEntry configEntry =
        DirectoryServer.getConfigEntry(
            DN.decode("cn=Salted MD5,cn=Password Storage Schemes,cn=config"));
-    scheme.initializePasswordStorageScheme(configEntry);
+
+    PasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          PasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry()
+          );
+
+    scheme.initializePasswordStorageScheme(configuration);
     
     ByteString encodedAuthPassword =
          scheme.encodePasswordWithScheme(bytePassword);

--
Gitblit v1.10.0