From 1b29f765bdfe3705c1b88fcdbb4fa923682e9678 Mon Sep 17 00:00:00 2001
From: gbellato <gbellato@localhost>
Date: Mon, 23 Apr 2007 13:38:48 +0000
Subject: [PATCH] This integrates the multi-master synchronization with the new admin framework (issue 1477) and makes possible to dynamically add or remove changelog server and synchronization domains in a running server (issue 639).

---
 opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ProtocolWindowTest.java                   |   11 
 opends/src/server/org/opends/server/synchronization/plugin/ChangelogListener.java                                     |  136 ++
 opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml                                               |   14 
 opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SchemaSynchronizationTest.java            |   14 
 opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/HistoricalTest.java                |   18 
 opends/src/server/org/opends/server/synchronization/common/LogMessages.java                                           |   18 
 opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/InitOnLineTest.java                       |   59 
 opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/UpdateOperationTest.java                  |   21 
 opends/src/admin/defn/org/opends/server/admin/std/MultimasterSynchronizationProviderConfiguration.xml                 |   33 
 opends/src/server/org/opends/server/api/SynchronizationProvider.java                                                  |   15 
 opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ReSyncTest.java                           |   11 
 opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogTest.java              |   54 
 opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/dbHandlerTest.java              |   17 
 opends/resource/schema/02-config.ldif                                                                                 |    4 
 opends/resource/config/synchronization.ldif                                                                           |   16 
 opends/src/server/org/opends/server/synchronization/plugin/SynchronizationDomain.java                                 |  448 +------
 opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/ModifyConflictTest.java            |    1 
 opends/src/admin/defn/org/opends/server/admin/std/MultimasterDomainConfiguration.xml                                  |  211 +++
 opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/StressTest.java                           |   10 
 opends/src/server/org/opends/server/synchronization/changelog/Changelog.java                                          |  299 +---
 opends/src/server/org/opends/server/core/DirectoryServer.java                                                         |   16 
 opends/src/server/org/opends/server/core/SynchronizationProviderConfigManager.java                                    | 1061 ++++++------------
 opends/src/server/org/opends/server/tasks/AddSchemaFileTask.java                                                      |    3 
 opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogFakeConfiguration.java |  190 +++
 opends/src/server/org/opends/server/synchronization/plugin/ChangelogBroker.java                                       |   40 
 opends/src/server/org/opends/server/synchronization/plugin/MultimasterSynchronization.java                            |  240 +--
 opends/src/admin/defn/org/opends/server/admin/std/SynchronizationProviderConfiguration.xml                            |   56 +
 opends/src/admin/defn/org/opends/server/admin/std/ChangelogServerConfiguration.xml                                    |  172 +++
 opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationTestCase.java              |  141 +-
 29 files changed, 1,588 insertions(+), 1,741 deletions(-)

diff --git a/opends/resource/config/synchronization.ldif b/opends/resource/config/synchronization.ldif
index 8924b3c..c2944fd 100644
--- a/opends/resource/config/synchronization.ldif
+++ b/opends/resource/config/synchronization.ldif
@@ -13,16 +13,22 @@
 dn: cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
 objectClass: top
 objectClass: ds-cfg-synchronization-provider
+objectClass: ds-cfg-multimaster-synchronization-provider
 ds-cfg-synchronization-provider-enabled: true
 ds-cfg-synchronization-provider-class: org.opends.server.synchronization.plugin.MultimasterSynchronization
 
-dn: cn=example, cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
+dn: cn=domains, cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
+objectClass: top
+objectClass: ds-cfg-branch
+cn: domains
+
+dn: cn=example, cn=domains, cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
 objectClass: top
 objectClass: ds-cfg-synchronization-provider-config
 cn: example
 ds-cfg-synchronization-dn: dc=example,dc=com
-ds-cfg-changelog-server: host1:8989
-ds-cfg-changelog-server: host2:8989
+ds-cfg-changelog-server: localhost:8989
+ds-cfg-changelog-server: localhost:8990
 ds-cfg-directory-server-id: 1
 ds-cfg-receive-status: true
 
@@ -31,7 +37,7 @@
 objectClass: ds-cfg-synchronization-changelog-server-config
 cn: Changelog Server
 ds-cfg-changelog-port: 8989
-ds-cfg-changelog-server: host1:8989
-ds-cfg-changelog-server: host2:8989
+ds-cfg-changelog-server: localhost:8989
+ds-cfg-changelog-server: localhost:8990
 ds-cfg-changelog-server-id: 1
 
diff --git a/opends/resource/schema/02-config.ldif b/opends/resource/schema/02-config.ldif
index c5b4b8b..e0ee545 100644
--- a/opends/resource/schema/02-config.ldif
+++ b/opends/resource/schema/02-config.ldif
@@ -1634,6 +1634,10 @@
   MUST ( ds-task-initialize-domain-dn $ ds-task-initialize-replica-server-id )
   MAY ( ds-task-processed-entry-count $ ds-task-unprocessed-entry-count )
   X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.94
+  NAME 'ds-cfg-multimaster-synchronization-provider'
+  SUP ds-cfg-synchronization-provider STRUCTURAL
+  X-ORIGIN 'OpenDS Directory Server' )
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.95
   NAME 'ds-cfg-dictionary-password-validator' SUP ds-cfg-password-validator
   STRUCTURAL MUST ( ds-cfg-dictionary-file $ ds-cfg-case-sensitive-validation $
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/ChangelogServerConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/ChangelogServerConfiguration.xml
new file mode 100644
index 0000000..a6e8aae
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/ChangelogServerConfiguration.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adm:managed-object name="changelog-server"
+  plural-name="changelog-servers" package="org.opends.server.admin.std"
+  xmlns:adm="http://www.opends.org/admin"
+  xmlns:ldap="http://www.opends.org/admin-ldap">
+  <adm:synopsis>
+    The
+    <adm:user-friendly-name />
+    is the server to which Multimaster Domain connects to publish and
+    receive changes to or from other Multimaster Domains.
+  </adm:synopsis>
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:oid>1.3.6.1.4.1.26027.1.2.65</ldap:oid>
+      <ldap:name>
+        ds-cfg-synchronization-changelog-server-config
+      </ldap:name>
+      <ldap:superior>top</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+  <adm:property name="changelog-server" multi-valued="true"
+    mandatory="false">
+    <adm:synopsis>
+      Specifies the addresses of the changelog server to which this
+      <adm:user-friendly-name />
+      should try to connect at startup time.
+    </adm:synopsis>
+    <adm:description>
+      Adresses must be specified using the syntax: hostname:port
+    </adm:description>
+    <adm:requires-admin-action>
+      <adm:none />
+    </adm:requires-admin-action>
+    <adm:default-behavior>
+      <adm:undefined />
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:string></adm:string>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.160</ldap:oid>
+        <ldap:name>ds-cfg-changelog-server</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="changelog-server-id" multi-valued="false"
+    mandatory="true" read-only="true">
+    <adm:synopsis>
+      Specifies the server ID of this Changelog Server
+    </adm:synopsis>
+    <adm:description>
+      Each Changelog Server must have a different server ID.
+    </adm:description>
+    <adm:requires-admin-action>
+      <adm:none />
+    </adm:requires-admin-action>
+    <adm:syntax>
+      <adm:integer></adm:integer>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.278</ldap:oid>
+        <ldap:name>ds-cfg-changelog-server-id</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="window-size" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the window size that will this Domain must use when
+      communicating with changelog servers.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>100</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:integer></adm:integer>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.288</ldap:oid>
+        <ldap:name>ds-cfg-window-size</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="queue-size" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the number of changes that will be kept in memory for
+      each LDAP server in the topology.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>10000</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:integer></adm:integer>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.290</ldap:oid>
+        <ldap:name>ds-cfg-changelog-max-queue-size</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="changelog-db-directory" mandatory="false"
+    hidden="false" multi-valued="false" read-only="true">
+    <adm:synopsis>
+      The path where the
+      <adm:user-friendly-name />
+      will store all persistent information.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:undefined />
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:string></adm:string>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.306</ldap:oid>
+        <ldap:name>ds-cfg-changelog-db-directory</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="changelog-purge-delay" multi-valued="false">
+    <adm:synopsis>
+      The time (in seconds) after which the
+      <adm:user-friendly-name />
+      will erase all persistent information.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>86400s</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:duration base-unit="s" allow-unlimited="false" />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.319</ldap:oid>
+        <ldap:name>ds-cfg-changelog-purge-delay</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="changelog-port" mandatory="true"
+    multi-valued="false">
+    <adm:synopsis>
+      The port on which this
+      <adm:user-friendly-name></adm:user-friendly-name>
+      will wait for connections from other Changelog Servers or LDAP
+      Servers or from LDAP servers.
+    </adm:synopsis>
+    <adm:requires-admin-action>
+      <adm:none />
+    </adm:requires-admin-action>
+    <adm:syntax>
+      <adm:integer></adm:integer>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.158</ldap:oid>
+        <ldap:name>ds-cfg-changelog-port</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+</adm:managed-object>
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/MultimasterDomainConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/MultimasterDomainConfiguration.xml
new file mode 100644
index 0000000..feb79e7
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/MultimasterDomainConfiguration.xml
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adm:managed-object name="multimaster-domain"
+  plural-name="multimaster-domains"
+  package="org.opends.server.admin.std"
+  xmlns:adm="http://www.opends.org/admin"
+  xmlns:ldap="http://www.opends.org/admin-ldap">
+  <adm:synopsis>
+    The
+    <adm:user-friendly-name />
+    is used to provide Multimaster Replication of several OpenDS copies
+    of the same data
+  </adm:synopsis>
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:oid>1.3.6.1.4.1.26027.1.2.58</ldap:oid>
+      <ldap:name>ds-cfg-synchronization-provider-config</ldap:name>
+      <ldap:superior>top</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+  <adm:property name="changelog-server" multi-valued="true"
+    mandatory="true">
+    <adm:synopsis>
+      Specifies the addresses of the changelog server to which this
+      <adm:user-friendly-name />
+      should try to connect at startup time.
+    </adm:synopsis>
+    <adm:description>
+      Adresses must be specified using the syntax: hostname:port
+    </adm:description>
+    <adm:requires-admin-action>
+      <adm:none />
+    </adm:requires-admin-action>
+    <adm:syntax>
+      <adm:string></adm:string>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.160</ldap:oid>
+        <ldap:name>ds-cfg-changelog-server</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="server-id" multi-valued="false" mandatory="true"
+    read-only="true">
+    <adm:synopsis>
+      Specifies the server ID of this multimaster provider.
+    </adm:synopsis>
+    <adm:description>
+      Each multimaster provider must have a different server ID.
+    </adm:description>
+    <adm:requires-admin-action>
+      <adm:none />
+    </adm:requires-admin-action>
+    <adm:syntax>
+      <adm:integer></adm:integer>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.279</ldap:oid>
+        <ldap:name>ds-cfg-directory-server-id</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="synchronization-dn" mandatory="true"
+    multi-valued="false" read-only="true">
+    <adm:synopsis>
+      Specifies the base dn of the Multimaster Domain
+    </adm:synopsis>
+    <adm:syntax>
+      <adm:dn></adm:dn>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.226</ldap:oid>
+        <ldap:name>ds-cfg-synchronization-dn</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="max-receive-queue" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the maximum length of the receive queue on the changelog
+      server before flow control must be activated.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>0</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:integer></adm:integer>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.164</ldap:oid>
+        <ldap:name>ds-cfg-max-receive-queue</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="max-receive-delay" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the maximum delay on the changelog server before flow
+      control must be activated.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>0s</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:duration base-unit="s" allow-unlimited="false"
+        upper-limit="2147483647" lower-limit="0" />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.165</ldap:oid>
+        <ldap:name>ds-cfg-max-receive-delay</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="max-send-queue" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the maximum length of the send queue on the changelog
+      server before flow control must be activated.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>0</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:integer></adm:integer>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.166</ldap:oid>
+        <ldap:name>ds-cfg-max-send-queue</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="max-send-delay" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the maximum send delay on the changelog server before
+      flow control must be activated.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>0s</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:duration upper-limit="2147483647" allow-unlimited="false"
+        lower-limit="0" base-unit="s" />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.167</ldap:oid>
+        <ldap:name>ds-cfg-max-send-delay</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="window-size" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the window size that will this Domain must use when
+      communicating with changelog servers.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>100</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:integer></adm:integer>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.288</ldap:oid>
+        <ldap:name>ds-cfg-window-size</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="heartbeat-interval" mandatory="false"
+    multi-valued="false">
+    <adm:synopsis>
+      Specifies the heartbeat interval that this Domain must use when
+      communicating with changelog servers. The Domain will expect
+      regular heatbeat coming from the changelog server with this
+      interval if they are not received it will close its connection and
+      connect to another changelog server.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>1000s</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:duration base-unit="ms" allow-unlimited="false"
+        lower-limit="100" />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.305</ldap:oid>
+        <ldap:name>ds-cfg-heartbeat-interval</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+</adm:managed-object>
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/MultimasterSynchronizationProviderConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/MultimasterSynchronizationProviderConfiguration.xml
new file mode 100644
index 0000000..efc764a
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/MultimasterSynchronizationProviderConfiguration.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adm:managed-object name="multimaster-synchronization-provider"
+  plural-name="multimaster-synchronization-providers"
+  package="org.opends.server.admin.std"
+  extends="synchronization-provider"
+  xmlns:adm="http://www.opends.org/admin"
+  xmlns:ldap="http://www.opends.org/admin-ldap" abstract="false">
+  <adm:synopsis>
+    The
+    <adm:user-friendly-name />
+    is used to provide Multimaster Replication of several OpenDS copies
+    of the same data
+  </adm:synopsis>
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:oid>1.3.6.1.4.1.26027.1.2.91</ldap:oid>
+      <ldap:name>ds-cfg-multimaster-synchronization-provider</ldap:name>
+      <ldap:superior>ds-cfg-synchronization-provider</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+  <adm:relation name="multimaster-domain">
+    <adm:one-to-many />
+    <adm:profile name="ldap">
+      <ldap:rdn-sequence>cn=domains</ldap:rdn-sequence>
+    </adm:profile>
+  </adm:relation>
+  <adm:relation name="changelog-server">
+    <adm:one-to-zero-or-one />
+    <adm:profile name="ldap">
+      <ldap:rdn-sequence>cn=changelog server</ldap:rdn-sequence>
+    </adm:profile>
+  </adm:relation>
+</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 01da02b..9f68116 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
@@ -21,7 +21,15 @@
       </ldap:rdn-sequence>
     </adm:profile>
   </adm:relation>
-    <adm:relation name="access-control-handler">
+  <adm:relation name="synchronization-provider">
+    <adm:one-to-many />
+    <adm:profile name="ldap">
+      <ldap:rdn-sequence>
+        cn=Synchronization Providers, cn=config
+      </ldap:rdn-sequence>
+    </adm:profile>
+  </adm:relation>
+  <adm:relation name="access-control-handler">
     <adm:one-to-one />
     <adm:profile name="ldap">
       <ldap:rdn-sequence>
@@ -72,9 +80,7 @@
   <adm:relation name="plugin">
     <adm:one-to-many />
     <adm:profile name="ldap">
-      <ldap:rdn-sequence>
-        cn=Plugins,cn=config
-      </ldap:rdn-sequence>
+      <ldap:rdn-sequence>cn=Plugins,cn=config</ldap:rdn-sequence>
     </adm:profile>
   </adm:relation>
   <adm:relation name="virtual-attribute">
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/SynchronizationProviderConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/SynchronizationProviderConfiguration.xml
new file mode 100644
index 0000000..f532aab
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/SynchronizationProviderConfiguration.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adm:managed-object name="synchronization-provider"
+  plural-name="synchronization-providers"
+  package="org.opends.server.admin.std" abstract="true"
+  xmlns:adm="http://www.opends.org/admin"
+  xmlns:ldap="http://www.opends.org/admin-ldap">
+  <adm:synopsis>
+    <adm:user-friendly-plural-name />
+    are responsible for handling Synchronization of the Directory Server
+    datas with other OpenDS instances or other data repositories.
+  </adm:synopsis>
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:oid>1.3.6.1.4.1.26027.1.2.57</ldap:oid>
+      <ldap:name>ds-cfg-synchronization-provider</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.155</ldap:oid>
+        <ldap:name>ds-cfg-synchronization-provider-enabled</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="java-implementation-class" mandatory="true"
+    multi-valued="false">
+    <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.SynchronizationProvider
+        </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.154</ldap:oid>
+        <ldap:name>ds-cfg-synchronization-provider-class</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+</adm:managed-object>
diff --git a/opends/src/server/org/opends/server/api/SynchronizationProvider.java b/opends/src/server/org/opends/server/api/SynchronizationProvider.java
index 3305807..063857f 100644
--- a/opends/src/server/org/opends/server/api/SynchronizationProvider.java
+++ b/opends/src/server/org/opends/server/api/SynchronizationProvider.java
@@ -30,7 +30,7 @@
 
 import java.util.List;
 
-import org.opends.server.config.ConfigEntry;
+import org.opends.server.admin.std.server.SynchronizationProviderCfg;
 import org.opends.server.config.ConfigException;
 import org.opends.server.core.AddOperation;
 import org.opends.server.core.DeleteOperation;
@@ -51,8 +51,11 @@
  * the Directory Server are properly communicated to other instances,
  * and potentially to other kinds of applications, so that they can be
  * updated accordingly.
+ *
+ * @param <T> the configuration for the synchronization provider.
  */
-public abstract class SynchronizationProvider
+public abstract class
+  SynchronizationProvider<T extends SynchronizationProviderCfg>
 {
 
 
@@ -61,9 +64,8 @@
    * Performs any initialization that might be necessary for this
    * synchronization provider.
    *
-   * @param  configEntry  The entry containing the configuration
-   *                      information for this synchronization
-   *                      provider.
+   * @param  config  The configuration information for this
+   *                 synchronization provider.
    *
    * @throws  ConfigException  If the provided entry does not contain
    *                           a valid configuration for this
@@ -75,8 +77,7 @@
    *                                   is not related to the server
    *                                   configuration.
    */
-  public abstract void initializeSynchronizationProvider(
-                            ConfigEntry configEntry)
+  public abstract void initializeSynchronizationProvider(T config)
          throws ConfigException, InitializationException;
 
 
diff --git a/opends/src/server/org/opends/server/core/DirectoryServer.java b/opends/src/server/org/opends/server/core/DirectoryServer.java
index 2472675..64dd31c 100644
--- a/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -49,6 +49,7 @@
 
 import org.opends.server.admin.ClassLoaderProvider;
 import org.opends.server.admin.std.server.PasswordValidatorCfg;
+import org.opends.server.admin.std.server.SynchronizationProviderCfg;
 import org.opends.server.api.*;
 import org.opends.server.api.plugin.PluginType;
 import org.opends.server.api.plugin.StartupPluginResult;
@@ -334,7 +335,8 @@
 
   // The set of synchronization providers that have been registered with the
   // Directory Server.
-  private CopyOnWriteArrayList<SynchronizationProvider>
+  private
+    CopyOnWriteArrayList<SynchronizationProvider<SynchronizationProviderCfg>>
                synchronizationProviders;
 
   // The set of virtual attributes defined in the server.
@@ -630,7 +632,8 @@
     directoryServer.shutdownListeners =
          new CopyOnWriteArrayList<ServerShutdownListener>();
     directoryServer.synchronizationProviders =
-         new CopyOnWriteArrayList<SynchronizationProvider>();
+         new CopyOnWriteArrayList<SynchronizationProvider
+                                 <SynchronizationProviderCfg>>();
     directoryServer.supportedControls = new TreeSet<String>();
     directoryServer.supportedFeatures = new TreeSet<String>();
     directoryServer.virtualAttributes =
@@ -7187,8 +7190,9 @@
    * @return  The set of synchronization providers that have been registered
    *          with the Directory Server.
    */
-  public static CopyOnWriteArrayList<SynchronizationProvider>
-              getSynchronizationProviders()
+  public static
+    CopyOnWriteArrayList<SynchronizationProvider<SynchronizationProviderCfg>>
+      getSynchronizationProviders()
   {
     return directoryServer.synchronizationProviders;
   }
@@ -7200,8 +7204,8 @@
    *
    * @param  provider  The synchronization provider to register.
    */
-  public static void registerSynchronizationProvider(SynchronizationProvider
-                                                          provider)
+  public static void registerSynchronizationProvider(
+      SynchronizationProvider<SynchronizationProviderCfg> provider)
   {
     directoryServer.synchronizationProviders.add(provider);
   }
diff --git a/opends/src/server/org/opends/server/core/SynchronizationProviderConfigManager.java b/opends/src/server/org/opends/server/core/SynchronizationProviderConfigManager.java
index d8186e9..659b148 100644
--- a/opends/src/server/org/opends/server/core/SynchronizationProviderConfigManager.java
+++ b/opends/src/server/org/opends/server/core/SynchronizationProviderConfigManager.java
@@ -28,33 +28,31 @@
 
 
 
-import java.util.ArrayList;
-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.SynchronizationProvider;
-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 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.ConfigMessages.*;
-import static org.opends.server.messages.MessageHandler.*;
-import static org.opends.server.util.StaticUtils.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
+
+import java.util.ArrayList;
+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.SynchronizationProviderCfgDefn;
+import org.opends.server.admin.std.server.RootCfg;
+import org.opends.server.admin.std.server.SynchronizationProviderCfg;
+import org.opends.server.api.SynchronizationProvider;
+import org.opends.server.config.ConfigException;
+import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.DN;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.ResultCode;
 
 
 
@@ -66,17 +64,20 @@
  * to them while the server is running.
  */
 public class SynchronizationProviderConfigManager
-       implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener
+       implements ConfigurationChangeListener<SynchronizationProviderCfg>,
+       ConfigurationAddListener<SynchronizationProviderCfg>,
+       ConfigurationDeleteListener<SynchronizationProviderCfg>
 {
 
 
 
   // The mapping between configuration entry DNs and their corresponding
   // synchronization provider implementations.
-  private ConcurrentHashMap<DN,SynchronizationProvider> registeredProviders;
+  private ConcurrentHashMap<DN,
+    SynchronizationProvider<SynchronizationProviderCfg>> registeredProviders =
+      new ConcurrentHashMap<DN,
+        SynchronizationProvider<SynchronizationProviderCfg>>();
 
-  // The DN of the associated configuration entry.
-  private DN configEntryDN;
 
 
 
@@ -107,765 +108,407 @@
   public void initializeSynchronizationProviders()
          throws ConfigException, InitializationException
   {
-    registeredProviders = new ConcurrentHashMap<DN,SynchronizationProvider>();
+    // Create an internal server management context and retrieve
+    // the root configuration which has the synchronization provider relation.
+    ServerManagementContext context = ServerManagementContext.getInstance();
+    RootCfg root = context.getRootConfiguration();
 
+    // Register as an add and delete listener so that we can
+    // be notified when new synchronization providers are added or existing
+    // sycnhronization providers are removed.
+    root.addSynchronizationProviderAddListener(this);
+    root.addSynchronizationProviderDeleteListener(this);
 
-    // Get the configuration entry that is the parent for all synchronization
-    // providers in the server.
-    ConfigEntry providerRoot;
-    try
+    // Initialize existing synchronization providers.
+    for (String name : root.listSynchronizationProviders())
     {
-      configEntryDN = DN.decode(DN_SYNCHRONIZATION_PROVIDER_BASE);
-      providerRoot  = DirectoryServer.getConfigEntry(configEntryDN);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
+      // Get the synchronization provider's configuration.
+      // This will automatically decode and validate its properties.
+      SynchronizationProviderCfg config = root.getSynchronizationProvider(name);
+
+      // Register as a change listener for this synchronization provider
+      // entry so that we can be notified when it is disabled or enabled.
+      config.addChangeListener(this);
+
+      // Ignore this synchronization provider if it is disabled.
+      if (config.isEnabled())
       {
-        debugCaught(DebugLogLevel.ERROR, e);
+        // Perform initialization, load the synchronization provider's
+        // implementation class and initialize it.
+        SynchronizationProvider<SynchronizationProviderCfg> provider =
+          getSynchronizationProvider(config);
+
+        // Register the synchronization provider with the Directory Server.
+        DirectoryServer.registerSynchronizationProvider(provider);
+
+        // Put this synchronization provider in the hash map so that we will be
+        // able to find it if it is deleted or disabled.
+        registeredProviders.put(config.dn(), provider);
       }
-
-      int    msgID   = MSGID_CONFIG_SYNCH_CANNOT_GET_CONFIG_BASE;
-      String message = getMessage(msgID, stackTraceToSingleLineString(e));
-      throw new ConfigException(msgID, message, e);
-    }
-
-
-    // If the configuration root entry is null, then assume it doesn't exist.
-    // In that case, then fail.  At least that entry must exist in the
-    // configuration, even if there are no synchronization providers defined
-    // below it.
-    if (providerRoot == null)
-    {
-      int    msgID   = MSGID_CONFIG_SYNCH_BASE_DOES_NOT_EXIST;
-      String message = getMessage(msgID);
-      throw new ConfigException(msgID, message);
-    }
-
-
-    // Register as an add and delete listener for the base entry so that we can
-    // be notified if new providers are added or existing providers are removed.
-    providerRoot.registerAddListener(this);
-    providerRoot.registerDeleteListener(this);
-
-
-    // Iterate through the set of immediate children below the provider root
-    // entry and register those providers.
-    for (ConfigEntry providerEntry : providerRoot.getChildren().values())
-    {
-      DN providerDN = providerEntry.getDN();
-
-
-      // Register as a change listener for this provider entry so that we will
-      // be notified of any changes that may be made to it.
-      providerEntry.registerChangeListener(this);
-
-
-      // Check to see if this entry appears to contain a synchronization
-      // provider configuration.  If not, then fail.
-      try
-      {
-        SearchFilter providerFilter =
-          SearchFilter.createFilterFromString("(objectClass=" +
-                                              OC_SYNCHRONIZATION_PROVIDER +
-                                              ")");
-
-        if (! providerFilter.matchesEntry(providerEntry.getEntry()))
-        {
-          int msgID = MSGID_CONFIG_SYNCH_ENTRY_DOES_NOT_HAVE_PROVIDER_CONFIG;
-          String message = getMessage(msgID, String.valueOf(providerDN));
-          throw new ConfigException(msgID, message);
-        }
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        int    msgID   = MSGID_CONFIG_SYNCH_CANNOT_CHECK_FOR_PROVIDER_CONFIG_OC;
-        String message = getMessage(msgID, String.valueOf(providerDN),
-                                    stackTraceToSingleLineString(e));
-        throw new InitializationException(msgID, message, e);
-      }
-
-
-      // See if the entry contains an attribute that indicates whether the
-      // synchronization provider should be enabled.  If it does not, then fail.
-      // If it is present but set to false, then log a warning and skip it.
-      int msgID = MSGID_CONFIG_SYNCH_DESCRIPTION_PROVIDER_ENABLED;
-      BooleanConfigAttribute enabledStub =
-           new BooleanConfigAttribute(ATTR_SYNCHRONIZATION_PROVIDER_ENABLED,
-                                      getMessage(msgID), true);
-      try
-      {
-        BooleanConfigAttribute enabledAttr =
-             (BooleanConfigAttribute)
-             providerEntry.getConfigAttribute(enabledStub);
-        if (enabledAttr == null)
-        {
-          msgID = MSGID_CONFIG_SYNCH_PROVIDER_NO_ENABLED_ATTR;
-          String message = getMessage(msgID, String.valueOf(providerDN));
-          throw new ConfigException(msgID, message);
-        }
-        else if (! enabledAttr.activeValue())
-        {
-          msgID = MSGID_CONFIG_SYNCH_PROVIDER_DISABLED;
-          String message = getMessage(msgID, String.valueOf(providerDN));
-          logError(ErrorLogCategory.CONFIGURATION,
-                   ErrorLogSeverity.SEVERE_WARNING, message, msgID);
-          continue;
-        }
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_DETERMINE_ENABLED_STATE;
-        String message = getMessage(msgID, String.valueOf(providerDN),
-                                    stackTraceToSingleLineString(e));
-        throw new InitializationException(msgID, message, e);
-      }
-
-
-      // See if the entry contains an attribute that specifies the class name
-      // for the synchronization provider implementation.  If there  is no such
-      // attribute, then fail.
-      String providerClassName;
-      msgID = MSGID_CONFIG_SYNCH_DESCRIPTION_PROVIDER_CLASS;
-      StringConfigAttribute classStub =
-           new StringConfigAttribute(ATTR_SYNCHRONIZATION_PROVIDER_CLASS,
-                                     getMessage(msgID), true, false, true);
-      try
-      {
-        StringConfigAttribute classAttr =
-             (StringConfigAttribute)
-             providerEntry.getConfigAttribute(classStub);
-        if (classAttr == null)
-        {
-          msgID = MSGID_CONFIG_SYNCH_NO_CLASS_ATTR;
-          String message = getMessage(msgID, String.valueOf(providerDN));
-          throw new ConfigException(msgID, message);
-        }
-        else
-        {
-          providerClassName = classAttr.activeValue();
-        }
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_DETERMINE_CLASS;
-        String message = getMessage(msgID, String.valueOf(providerDN),
-                                    stackTraceToSingleLineString(e));
-        throw new InitializationException(msgID, message, e);
-      }
-
-
-      // Load the specified provider class.  If an error occurs, then fail.
-      Class providerClass;
-      try
-      {
-        providerClass = DirectoryServer.loadClass(providerClassName);
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_LOAD_PROVIDER_CLASS;
-        String message = getMessage(msgID, String.valueOf(providerClassName),
-                                    String.valueOf(providerDN),
-                                    stackTraceToSingleLineString(e));
-        throw new InitializationException(msgID, message, e);
-      }
-
-
-      // Make sure that the specified class is a valid synchronization provider.
-      // If not, then fail.
-      SynchronizationProvider provider;
-      try
-      {
-        provider = (SynchronizationProvider) providerClass.newInstance();
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_INSTANTIATE_PROVIDER;
-        String message = getMessage(msgID, String.valueOf(providerClassName),
-                                    String.valueOf(providerDN),
-                                    stackTraceToSingleLineString(e));
-        throw new InitializationException(msgID, message, e);
-      }
-
-
-      // Perform the necessary initialization for the synchronization provider.
-      // If a problem occurs, then fail.
-      try
-      {
-        provider.initializeSynchronizationProvider(providerEntry);
-      }
-      catch (ConfigException ce)
-      {
-        msgID = MSGID_CONFIG_SYNCH_ERROR_INITIALIZING_PROVIDER;
-        String message = getMessage(msgID, String.valueOf(providerDN),
-                                    ce.getMessage());
-        throw new ConfigException(msgID, message, ce);
-      }
-      catch (InitializationException ie)
-      {
-        msgID = MSGID_CONFIG_SYNCH_ERROR_INITIALIZING_PROVIDER;
-        String message = getMessage(msgID, String.valueOf(providerDN),
-                                    ie.getMessage());
-        throw new InitializationException(msgID, message, ie);
-      }
-      catch (Exception e)
-      {
-        msgID = MSGID_CONFIG_SYNCH_ERROR_INITIALIZING_PROVIDER;
-        String message = getMessage(msgID, String.valueOf(providerDN),
-                                    stackTraceToSingleLineString(e));
-        throw new ConfigException(msgID, message, e);
-      }
-
-
-      // Register the synchronization provider with the Directory Server.
-      DirectoryServer.registerSynchronizationProvider(provider);
-
-
-      // Put this provider in the hash so that we will be able to find it if it
-      // is altered.
-      registeredProviders.put(providerDN, provider);
     }
   }
 
 
 
   /**
-   * 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(
+      SynchronizationProviderCfg configuration)
   {
-    DN providerDN = configEntry.getDN();
-    SynchronizationProvider provider = registeredProviders.get(providerDN);
-
-
-    // Check to see if this entry appears to contain a backend configuration.
-    // If not, then reject it.
-    try
-    {
-      SearchFilter providerFilter =
-           SearchFilter.createFilterFromString("(objectClass=" +
-                                               OC_SYNCHRONIZATION_PROVIDER +
-                                               ")");
-      if (! providerFilter.matchesEntry(configEntry.getEntry()))
-      {
-        int msgID = MSGID_CONFIG_SYNCH_ENTRY_DOES_NOT_HAVE_PROVIDER_CONFIG;
-        unacceptableReason.append(getMessage(msgID,
-                                             String.valueOf(providerDN)));
-        return false;
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_SYNCH_CANNOT_CHECK_FOR_PROVIDER_CONFIG_OC;
-      unacceptableReason.append(getMessage(msgID, String.valueOf(providerDN),
-                                           stackTraceToSingleLineString(e)));
-      return false;
-    }
-
-
-    // See if the entry contains an attribute that indicates whether the
-    // provider should be enabled.  If it does not, then reject it.
-    int msgID = MSGID_CONFIG_SYNCH_DESCRIPTION_PROVIDER_ENABLED;
-    BooleanConfigAttribute enabledStub =
-         new BooleanConfigAttribute(ATTR_SYNCHRONIZATION_PROVIDER_ENABLED,
-                                    getMessage(msgID), true);
-    try
-    {
-      BooleanConfigAttribute enabledAttr =
-           (BooleanConfigAttribute) configEntry.getConfigAttribute(enabledStub);
-      if (enabledAttr == null)
-      {
-        msgID = MSGID_CONFIG_SYNCH_PROVIDER_NO_ENABLED_ATTR;
-        unacceptableReason.append(getMessage(msgID,
-                                             String.valueOf(providerDN)));
-        return false;
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_DETERMINE_ENABLED_STATE;
-      unacceptableReason.append(getMessage(msgID,
-                                           String.valueOf(providerDN),
-                                           stackTraceToSingleLineString(e)));
-      return false;
-    }
-
-
-    // See if the entry contains an attribute that specifies the provider class.
-    // If it does not, then fail.
-    String className;
-    msgID = MSGID_CONFIG_SYNCH_DESCRIPTION_PROVIDER_CLASS;
-    StringConfigAttribute classStub =
-         new StringConfigAttribute(ATTR_SYNCHRONIZATION_PROVIDER_CLASS,
-                                   getMessage(msgID), true, false, true);
-    try
-    {
-      StringConfigAttribute classAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
-      if (classAttr == null)
-      {
-        msgID = MSGID_CONFIG_SYNCH_NO_CLASS_ATTR;
-        unacceptableReason.append(getMessage(msgID,
-                                             String.valueOf(providerDN)));
-        return false;
-      }
-      else
-      {
-        className = classAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_DETERMINE_CLASS;
-      unacceptableReason.append(getMessage(msgID,
-                                           String.valueOf(providerDN),
-                                           stackTraceToSingleLineString(e)));
-      return false;
-    }
-
-
-    // If the provider is currently disabled, or if the class is different from
-    // the one used by the running provider, then make sure that it is
-    // acceptable.
-    if ((provider == null) ||
-        (! className.equals(provider.getClass().getName())))
-    {
-      Class providerClass;
-      try
-      {
-        providerClass = DirectoryServer.loadClass(className);
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_LOAD_PROVIDER_CLASS;
-        unacceptableReason.append(getMessage(msgID, String.valueOf(className),
-                                             String.valueOf(providerDN),
-                                             stackTraceToSingleLineString(e)));
-        return false;
-      }
-
-      try
-      {
-        SynchronizationProvider newProvider =
-             (SynchronizationProvider) providerClass.newInstance();
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_INSTANTIATE_PROVIDER;
-        unacceptableReason.append(getMessage(msgID, String.valueOf(className),
-                                             String.valueOf(providerDN),
-                                             stackTraceToSingleLineString(e)));
-        return false;
-      }
-    }
-
-
-    // If we've gotten to this point, then it is acceptable as far as we are
-    // concerned.  If it is unacceptable according to the configuration for that
-    // synchronization provider, then the provider itself will need to make that
-    // determination.
-    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 providerDN = configEntry.getDN();
-    SynchronizationProvider provider = registeredProviders.get(providerDN);
+    // Default result code.
     ResultCode resultCode = ResultCode.SUCCESS;
     boolean adminActionRequired = false;
     ArrayList<String> messages = new ArrayList<String>();
 
+    // Attempt to get the existing synchronization provider. This will only
+    // succeed if it is currently enabled.
+    DN dn = configuration.dn();
+    SynchronizationProvider<SynchronizationProviderCfg> provider =
+      registeredProviders.get(dn);
 
-    // Check to see if this entry appears to contain a synchronization provider
-    // configuration.  If not, then fail.
-    try
+    // See whether the synchronization provider should be enabled.
+    if (provider == null)
     {
-      SearchFilter providerFilter =
-           SearchFilter.createFilterFromString("(objectClass=" +
-                                               OC_SYNCHRONIZATION_PROVIDER +
-                                               ")");
-      if (! providerFilter.matchesEntry(configEntry.getEntry()))
+      if (configuration.isEnabled())
       {
-        int msgID = MSGID_CONFIG_SYNCH_ENTRY_DOES_NOT_HAVE_PROVIDER_CONFIG;
-        messages.add(getMessage(msgID, String.valueOf(providerDN)));
-
-        if (resultCode == ResultCode.SUCCESS)
+        // The synchronization provider needs to be enabled. Load, initialize,
+        // and register the synchronization provider as per the add listener
+        // method.
+        try
         {
-          resultCode = ResultCode.CONSTRAINT_VIOLATION;
+          // Perform initialization, load the synchronization provider's
+          // implementation class and initialize it.
+          provider = getSynchronizationProvider(configuration);
+
+          // Register the synchronization provider with the Directory Server.
+          DirectoryServer.registerSynchronizationProvider(provider);
+
+          // Put this synchronization provider in the hash map so that we will
+          // be able to find it if it is deleted or disabled.
+          registeredProviders.put(configuration.dn(), provider);
+        }
+        catch (ConfigException e)
+        {
+          if (debugEnabled())
+          {
+            debugCaught(DebugLogLevel.ERROR, e);
+            messages.add(e.getMessage());
+            resultCode = DirectoryServer.getServerErrorResultCode();
+          }
+        }
+        catch (Exception e)
+        {
+          if (debugEnabled())
+          {
+            debugCaught(DebugLogLevel.ERROR, e);
+          }
+          int msgID = MSGID_CONFIG_SYNCH_ERROR_INITIALIZING_PROVIDER;
+          messages.add(getMessage(msgID, String.valueOf(
+                             configuration.getJavaImplementationClass()),
+                             String.valueOf(configuration.dn()),
+                             stackTraceToSingleLineString(e)));
+          resultCode = DirectoryServer.getServerErrorResultCode();
         }
       }
     }
-    catch (Exception e)
+    else
     {
-      if (debugEnabled())
+      if (configuration.isEnabled())
       {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = MSGID_CONFIG_SYNCH_CANNOT_CHECK_FOR_PROVIDER_CONFIG_OC;
-      messages.add(getMessage(msgID, String.valueOf(providerDN),
-                              stackTraceToSingleLineString(e)));
-
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-    }
-
-
-    // See if the entry contains an attribute that indicates whether the
-    // provider should be enabled.  If it does not, then reject it.
-    boolean shouldEnable = false;
-    int msgID = MSGID_CONFIG_SYNCH_DESCRIPTION_PROVIDER_ENABLED;
-    BooleanConfigAttribute enabledStub =
-         new BooleanConfigAttribute(ATTR_SYNCHRONIZATION_PROVIDER_ENABLED,
-                                    getMessage(msgID), true);
-    try
-    {
-      BooleanConfigAttribute enabledAttr =
-           (BooleanConfigAttribute) configEntry.getConfigAttribute(enabledStub);
-      if (enabledAttr == null)
-      {
-        msgID = MSGID_CONFIG_SYNCH_PROVIDER_NO_ENABLED_ATTR;
-        messages.add(getMessage(msgID, String.valueOf(providerDN)));
-
-        if (resultCode == ResultCode.SUCCESS)
+        // The synchronization provider is currently active, so we don't
+        // need to do anything. Changes to the class name cannot be
+        // applied dynamically, so if the class name did change then
+        // indicate that administrative action is required for that
+        // change to take effect.
+        String className = configuration.getJavaImplementationClass();
+        if (!className.equals(provider.getClass().getName()))
         {
-          resultCode = ResultCode.CONSTRAINT_VIOLATION;
+          adminActionRequired = true;
         }
       }
       else
       {
-        shouldEnable = enabledAttr.pendingValue();
+        // The connection handler is being disabled so remove it from
+        // the DirectorySerevr list, shut it down and  remove it from the
+        // hash map.
+        DirectoryServer.deregisterSynchronizationProvider(provider);
+        provider.finalizeSynchronizationProvider();
+        registeredProviders.remove(dn);
       }
     }
-    catch (Exception e)
+    // Return the configuration result.
+    return new ConfigChangeResult(resultCode, adminActionRequired,
+        messages);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationChangeAcceptable(
+      SynchronizationProviderCfg configuration,
+      List<String> unacceptableReasons)
+  {
+    if (configuration.isEnabled())
     {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_DETERMINE_ENABLED_STATE;
-      messages.add(getMessage(msgID, String.valueOf(providerDN),
-                              stackTraceToSingleLineString(e)));
-
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
+      // It's enabled so always validate the class.
+      return isJavaClassAcceptable(configuration, unacceptableReasons);
+    } else
+    {
+      // It's disabled so ignore it.
+      return true;
     }
+  }
 
 
-    // See if the entry contains an attribute that specifies the provider class.
-    // If it does not, then reject it.
-    String className = null;
-    msgID = MSGID_CONFIG_SYNCH_DESCRIPTION_PROVIDER_CLASS;
-    StringConfigAttribute classStub =
-         new StringConfigAttribute(ATTR_SYNCHRONIZATION_PROVIDER_CLASS,
-                                   getMessage(msgID), true, false, true);
-    try
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationAdd(
+    SynchronizationProviderCfg configuration)
+  {
+    // Default result code.
+    ResultCode resultCode = ResultCode.SUCCESS;
+    boolean adminActionRequired = false;
+    ArrayList<String> messages = new ArrayList<String>();
+
+    // Register as a change listener for this synchronization provider entry
+    // so that we will be notified if when it is disabled or enabled.
+    configuration.addChangeListener(this);
+
+    // Ignore this synchronization provider if it is disabled.
+    if (configuration.isEnabled())
     {
-      StringConfigAttribute classAttr =
-           (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
-      if (classAttr == null)
-      {
-        msgID = MSGID_CONFIG_SYNCH_NO_CLASS_ATTR;
-        messages.add(getMessage(msgID, String.valueOf(providerDN)));
-
-        if (resultCode == ResultCode.SUCCESS)
-        {
-          resultCode = ResultCode.CONSTRAINT_VIOLATION;
-        }
-      }
-      else
-      {
-        className = classAttr.pendingValue();
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_DETERMINE_CLASS;
-      messages.add(getMessage(msgID, String.valueOf(providerDN),
-                              stackTraceToSingleLineString(e)));
-
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-    }
-
-
-    // If the provider is currently disabled, or if the class is different from
-    // the one used by the running provider, then make sure that it is
-    // acceptable.
-    SynchronizationProvider newProvider = null;
-    if ((resultCode == ResultCode.SUCCESS) &&
-        ((provider == null) ||
-         (! provider.getClass().getName().equals(className))))
-    {
-      Class providerClass = null;
       try
       {
-        providerClass = DirectoryServer.loadClass(className);
+        // Perform initialization, load the synchronization provider's
+        // implementation class and initialize it.
+        SynchronizationProvider<SynchronizationProviderCfg> provider =
+          getSynchronizationProvider(configuration);
+
+        // Register the synchronization provider with the Directory Server.
+        DirectoryServer.registerSynchronizationProvider(provider);
+
+        // Put this synchronization provider in the hash map so that we will be
+        // able to find it if it is deleted or disabled.
+        registeredProviders.put(configuration.dn(), provider);
       }
-      catch (Exception e)
+      catch (ConfigException e)
       {
         if (debugEnabled())
         {
           debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_LOAD_PROVIDER_CLASS;
-        messages.add(getMessage(msgID, String.valueOf(className),
-                                String.valueOf(providerDN),
-                                stackTraceToSingleLineString(e)));
-
-        if (resultCode == ResultCode.SUCCESS)
-        {
+          messages.add(e.getMessage());
           resultCode = DirectoryServer.getServerErrorResultCode();
         }
       }
-
-      try
-      {
-        if (providerClass != null)
-        {
-          newProvider = (SynchronizationProvider) providerClass.newInstance();
-        }
-      }
       catch (Exception e)
       {
         if (debugEnabled())
         {
           debugCaught(DebugLogLevel.ERROR, e);
         }
-
-        msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_INSTANTIATE_PROVIDER;
-        messages.add(getMessage(msgID, String.valueOf(className),
-                                String.valueOf(providerDN),
-                                stackTraceToSingleLineString(e)));
-
-        if (resultCode == ResultCode.SUCCESS)
-        {
-          resultCode = DirectoryServer.getServerErrorResultCode();
-        }
+        int msgID = MSGID_CONFIG_SYNCH_ERROR_INITIALIZING_PROVIDER;
+        messages.add(getMessage(msgID, String.valueOf(
+                           configuration.getJavaImplementationClass()),
+                           String.valueOf(configuration.dn()),
+                           stackTraceToSingleLineString(e)));
+        resultCode = DirectoryServer.getServerErrorResultCode();
       }
     }
 
+    // Return the configuration result.
+    return new ConfigChangeResult(resultCode, adminActionRequired,
+        messages);
+  }
 
-    // If everything looks OK, then process the configuration change.
-    if (resultCode == ResultCode.SUCCESS)
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationAddAcceptable(
+      SynchronizationProviderCfg configuration,
+      List<String> unacceptableReasons)
+  {
+    if (configuration.isEnabled())
     {
-      // If the provider is currently disabled but should be enabled, then do
-      // so now.
-      if (provider == null)
-      {
-        if (shouldEnable && (newProvider != null))
-        {
-          try
-          {
-            newProvider.initializeSynchronizationProvider(configEntry);
-            registeredProviders.put(configEntryDN, newProvider);
-          }
-          catch (Exception e)
-          {
-            if (debugEnabled())
-            {
-              debugCaught(DebugLogLevel.ERROR, e);
-            }
-
-            msgID = MSGID_CONFIG_SYNCH_ERROR_INITIALIZING_PROVIDER;
-            messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                    stackTraceToSingleLineString(e)));
-
-            if (resultCode == ResultCode.SUCCESS)
-            {
-              resultCode = DirectoryServer.getServerErrorResultCode();
-            }
-          }
-        }
-      }
+      // It's enabled so always validate the class.
+      return isJavaClassAcceptable(configuration, unacceptableReasons);
+    } else
+    {
+      // It's disabled so ignore it.
+      return true;
+    }
+  }
 
 
-      // Otherwise, see if the enabled flag or class name changed and indicate
-      // that it will require a restart to take effect.
-      else
-      {
-        if (! shouldEnable)
-        {
-          msgID = MSGID_CONFIG_SYNCH_PROVIDER_HAS_BEEN_DISABLED;
-          messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
-          adminActionRequired = true;
-        }
 
-        if (! provider.getClass().getName().equals(className))
-        {
-          msgID = MSGID_CONFIG_SYNCH_PROVIDER_CLASS_CHANGED;
-          messages.add(getMessage(msgID, String.valueOf(configEntryDN),
-                                  String.valueOf(provider.getClass().getName()),
-                                  String.valueOf(className)));
-          adminActionRequired = true;
-        }
-      }
+  /**
+   * Check if the class provided in the configuration is an acceptable
+   * java class for a synchronization provider.
+   *
+   * @param configuration       The configuration for which the class must be
+   *                            checked.
+   * @param unacceptableReasons A list containing the reasons why the class is
+   *                            not acceptable.
+   *
+   * @return                    true if the class is acceptable or false if not.
+   */
+  @SuppressWarnings("unchecked")
+  private SynchronizationProvider<SynchronizationProviderCfg>
+    getSynchronizationProvider(SynchronizationProviderCfg configuration)
+    throws ConfigException
+  {
+    String className = configuration.getJavaImplementationClass();
+    SynchronizationProviderCfgDefn d =
+      SynchronizationProviderCfgDefn.getInstance();
+    ClassPropertyDefinition pd =
+      d.getJavaImplementationClassPropertyDefinition();
+
+    // Load the class
+    Class<? extends SynchronizationProvider> theClass;
+    SynchronizationProvider<SynchronizationProviderCfg> provider;
+    try
+    {
+       theClass = pd.loadClass(className, SynchronizationProvider.class);
+    } catch (Exception e)
+    {
+       // Handle the exception: put a message in the unacceptable reasons.
+       int msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_LOAD_PROVIDER_CLASS;
+       String message = getMessage(msgID, String.valueOf(className),
+                                   String.valueOf(configuration.dn()),
+                                   stackTraceToSingleLineString(e));
+       throw new ConfigException(msgID, message, e);
+    }
+    try
+    {
+      // Instantiate the class.
+      provider = theClass.newInstance();
+    } catch (Exception e)
+    {
+      // Handle the exception: put a message in the unacceptable reasons.
+      int msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_INSTANTIATE_PROVIDER;
+      String message = getMessage(msgID, String.valueOf(className),
+                                  String.valueOf(configuration.dn()),
+                                  stackTraceToSingleLineString(e));
+      throw new ConfigException(msgID, message, e);
+    }
+    try
+    {
+      // Initialize the Synchronization Provider.
+      provider.initializeSynchronizationProvider(configuration);
+    } catch (Exception e)
+    {
+      // Handle the exception: put a message in the unacceptable reasons.
+      int msgID = MSGID_CONFIG_SYNCH_ERROR_INITIALIZING_PROVIDER;
+      String message = getMessage(msgID, String.valueOf(className),
+                                  String.valueOf(configuration.dn()),
+                                  stackTraceToSingleLineString(e));
+      throw new ConfigException(msgID, message, e);
+    }
+    return provider;
+  }
+
+  /**
+   * Check if the class provided in the configuration is an acceptable
+   * java class for a synchronization provider.
+   *
+   * @param configuration       The configuration for which the class must be
+   *                            checked.
+   * @param unacceptableReasons A list containing the reasons why the class is
+   *                            not acceptable.
+   *
+   * @return                    true if the class is acceptable or false if not.
+   */
+  private boolean isJavaClassAcceptable(
+      SynchronizationProviderCfg configuration,
+      List<String> unacceptableReasons)
+  {
+    String className = configuration.getJavaImplementationClass();
+    SynchronizationProviderCfgDefn d =
+      SynchronizationProviderCfgDefn.getInstance();
+    ClassPropertyDefinition pd =
+      d.getJavaImplementationClassPropertyDefinition();
+
+    // Load the class and cast it to a synchronizationProvider.
+    Class<? extends SynchronizationProvider> theClass;
+    try
+    {
+       theClass = pd.loadClass(className, SynchronizationProvider.class);
+       theClass.newInstance();
+    } catch (Exception e)
+    {
+       // Handle the exception: put a message in the unacceptable reasons.
+       int msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_LOAD_PROVIDER_CLASS;
+       String message = getMessage(msgID, String.valueOf(className),
+                                   String.valueOf(configuration.dn()),
+                                   stackTraceToSingleLineString(e));
+       unacceptableReasons.add(message);
+       return false;
+    }
+    // Check that the implementation class implements the correct interface.
+    try
+    {
+      // Determine the initialization method to use: it must take a
+      // single parameter which is the exact type of the configuration
+      // object.
+      theClass.getMethod("initializeSynchronizationProvider",
+                     configuration.definition().getServerConfigurationClass());
+    } catch (Exception e)
+    {
+      // Handle the exception: put a message in the unacceptable reasons.
+      int msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_INSTANTIATE_PROVIDER;
+      String message = getMessage(msgID, String.valueOf(className),
+                                  String.valueOf(configuration.dn()),
+                                  stackTraceToSingleLineString(e));
+      unacceptableReasons.add(message);
+      return false;
     }
 
-    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
+    // The class is valid as far as we can tell.
     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.
+   * {@inheritDoc}
    */
-  public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry)
+  public ConfigChangeResult applyConfigurationDelete(
+      SynchronizationProviderCfg configuration)
   {
-    // NYI
-    return null;
+    //  Default result code.
+    ResultCode resultCode = ResultCode.SUCCESS;
+    boolean adminActionRequired = false;
+
+    // See if the entry is registered as a synchronization provider. If so,
+    // deregister and stop it.
+    DN dn = configuration.dn();
+    SynchronizationProvider provider = registeredProviders.get(dn);
+    if (provider != null)
+    {
+      DirectoryServer.deregisterSynchronizationProvider(provider);
+      provider.finalizeSynchronizationProvider();
+    }
+    return new ConfigChangeResult(resultCode, adminActionRequired);
   }
 
 
 
   /**
-   * 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(
+      SynchronizationProviderCfg configuration,
+      List<String> unacceptableReasons)
   {
-    // NYI
+    // A delete should always be acceptable, so just return true.
     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)
-  {
-    // NYI
-    return null;
-  }
 }
 
+
+
+
diff --git a/opends/src/server/org/opends/server/synchronization/changelog/Changelog.java b/opends/src/server/org/opends/server/synchronization/changelog/Changelog.java
index 531569c..e813bd6 100644
--- a/opends/src/server/org/opends/server/synchronization/changelog/Changelog.java
+++ b/opends/src/server/org/opends/server/synchronization/changelog/Changelog.java
@@ -40,26 +40,24 @@
 import java.net.Socket;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Set;
 
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.server.ChangelogServerCfg;
 import org.opends.server.api.ConfigurableComponent;
 import org.opends.server.api.DirectoryThread;
 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;
-import org.opends.server.config.StringConfigAttribute;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.messages.MessageHandler;
 import org.opends.server.synchronization.protocol.SocketSession;
 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.ResultCode;
 
 import com.sleepycat.je.DatabaseException;
 
@@ -73,7 +71,9 @@
  *
  * It is responsible for creating the changelog cache and managing it
  */
-public class Changelog implements Runnable, ConfigurableComponent
+public class Changelog
+  implements Runnable, ConfigurableComponent,
+             ConfigurationChangeListener<ChangelogServerCfg>
 {
   private short serverId;
   private String serverURL;
@@ -85,7 +85,7 @@
   private boolean runListen = true;
 
   /* The list of changelog servers configured by the administrator */
-  private List<String> changelogServers;
+  private Collection<String> changelogServers;
 
   /* This table is used to store the list of dn for which we are currently
    * handling servers.
@@ -106,212 +106,30 @@
   private long trimAge; // the time (in sec) after which the  changes must
                         // de deleted from the persistent storage.
 
-  static final String CHANGELOG_SERVER_ATTR = "ds-cfg-changelog-server";
-  static final String SERVER_ID_ATTR = "ds-cfg-changelog-server-id";
-  static final String CHANGELOG_PORT_ATTR = "ds-cfg-changelog-port";
-  static final String WINDOW_SIZE_ATTR = "ds-cfg-window-size";
-  static final String QUEUE_SIZE_ATTR = "ds-cfg-changelog-max-queue-size";
-  static final String CHANGELOG_DIR_PATH_ATTR = "ds-cfg-changelog-db-directory";
-  static final String PURGE_DELAY_ATTR = "ds-cfg-changelog-purge-delay";
-
-
-  static final IntegerConfigAttribute changelogPortStub =
-    new IntegerConfigAttribute(CHANGELOG_PORT_ATTR, "changelog port",
-      true, false, false, true, 0, true, 65535);
-
-  static final IntegerConfigAttribute serverIdStub =
-    new IntegerConfigAttribute(SERVER_ID_ATTR, "server ID", true, false,
-        false, true, 0, true, 65535);
-
-  static final StringConfigAttribute changelogStub =
-    new StringConfigAttribute(CHANGELOG_SERVER_ATTR,
-        "changelog server information", true, true, false);
-
-  static final IntegerConfigAttribute windowStub =
-    new IntegerConfigAttribute(WINDOW_SIZE_ATTR, "window size",
-                               false, false, false, true, 0, false, 0);
-
-  static final IntegerConfigAttribute queueSizeStub =
-    new IntegerConfigAttribute(QUEUE_SIZE_ATTR, "changelog queue size",
-                               false, false, false, true, 0, false, 0);
-
-  static final StringConfigAttribute dbDirnameStub =
-    new StringConfigAttribute(CHANGELOG_DIR_PATH_ATTR,
-        "changelog storage directory path", false, false, true);
-
-  /**
-   * The set of time units that will be used for expressing the
-   * changelog purge delay.
-   */
-  private static final LinkedHashMap<String,Double> purgeTimeUnits =
-       new LinkedHashMap<String,Double>();
-
-  static
-  {
-    purgeTimeUnits.put(TIME_UNIT_SECONDS_ABBR, 1D);
-    purgeTimeUnits.put(TIME_UNIT_SECONDS_FULL, 1D);
-    purgeTimeUnits.put(TIME_UNIT_MINUTES_ABBR, 60D);
-    purgeTimeUnits.put(TIME_UNIT_MINUTES_FULL, 1D);
-    purgeTimeUnits.put(TIME_UNIT_HOURS_ABBR, 60*60D);
-    purgeTimeUnits.put(TIME_UNIT_HOURS_FULL, 60*60D);
-    purgeTimeUnits.put(TIME_UNIT_DAYS_ABBR, 24*60*60D);
-    purgeTimeUnits.put(TIME_UNIT_DAYS_FULL, 24*60*60D);
-  }
-
-  static final IntegerWithUnitConfigAttribute purgeDelayStub =
-    new IntegerWithUnitConfigAttribute(PURGE_DELAY_ATTR,
-        "changelog purge delay", false, purgeTimeUnits, true, 0, false, 0);
-
-  /**
-   * Check if a ConfigEntry is valid.
-   * @param config The config entry that needs to be checked.
-   * @param unacceptableReason A description of the reason why the config entry
-   *                           is not acceptable (if return is false).
-   * @return a boolean indicating if the configEntry is valid.
-   */
-  public static boolean checkConfigEntry(ConfigEntry config,
-      StringBuilder unacceptableReason)
-  {
-    try
-    {
-      IntegerConfigAttribute changelogPortAttr;
-      changelogPortAttr =
-        (IntegerConfigAttribute) config.getConfigAttribute(changelogPortStub);
-
-      /* The config must provide a changelog port number
-       */
-      if (changelogPortAttr == null)
-      {
-        unacceptableReason.append(
-            MessageHandler.getMessage(MSGID_NEED_CHANGELOG_PORT,
-            config.getDN().toString())  );
-      }
-
-      /*
-       * read the server Id information
-       * this is a single valued integer, its value must fit on a
-       * short integer
-       */
-      IntegerConfigAttribute serverIdAttr =
-        (IntegerConfigAttribute) config.getConfigAttribute(serverIdStub);
-
-      if (serverIdAttr == null)
-      {
-        unacceptableReason.append(
-            MessageHandler.getMessage(MSGID_NEED_SERVER_ID,
-            config.getDN().toString()) );
-      }
-
-      return true;
-    } catch (ConfigException e)
-    {
-      return false;
-    }
-  }
-
   /**
    * Creates a new Changelog using the provided configuration entry.
    *
-   * @param config The configuration entry where configuration can be found.
-   * @throws ConfigException When Configuration entry is invalid.
+   * @param configuration The configuration of this changelog.
+   * @throws ConfigException When Configuration is invalid.
    */
-  public Changelog(ConfigEntry config) throws ConfigException
+  public Changelog(ChangelogServerCfg configuration) throws ConfigException
   {
     shutdown = false;
     runListen = true;
-
-    IntegerConfigAttribute changelogPortAttr =
-      (IntegerConfigAttribute) config.getConfigAttribute(changelogPortStub);
-    /* if there is no changelog port configured, this process must not be a
-     * changelog server
-     */
-    if (changelogPortAttr == null)
-    {
-      throw new ConfigException(MSGID_NEED_CHANGELOG_PORT,
-          MessageHandler.getMessage(MSGID_NEED_CHANGELOG_PORT,
-              config.getDN().toString())  );
-    }
-    int changelogPort = changelogPortAttr.activeIntValue();
-    configAttributes.add(changelogPortAttr);
-
-    /*
-     * read the server Id information
-     * this is a single valued integer, its value must fit on a
-     * short integer
-     */
-    IntegerConfigAttribute serverIdAttr =
-      (IntegerConfigAttribute) config.getConfigAttribute(serverIdStub);
-
-    if (serverIdAttr == null)
-    {
-      throw new ConfigException(MSGID_NEED_SERVER_ID,
-          MessageHandler.getMessage(MSGID_NEED_SERVER_ID,
-              config.getDN().toString())  );
-    }
-    changelogServerId = (short) serverIdAttr.activeIntValue();
-    configAttributes.add(serverIdAttr);
-
-    /*
-     * read the centralized changelog server configuration
-     * this is a multivalued attribute
-     */
-    StringConfigAttribute changelogServer =
-      (StringConfigAttribute) config.getConfigAttribute(changelogStub);
-    changelogServers = new ArrayList<String>();
-    if (changelogServer != null)
-    {
-      for (String serverURL : changelogServer.activeValues())
-      {
-        String[] splitStrings = serverURL.split(":");
-        try
-        {
-          changelogServers.add(
-              InetAddress.getByName(splitStrings[0]).getHostAddress()
-              + ":" + splitStrings[1]);
-        } catch (UnknownHostException e)
-        {
-          throw new ConfigException(MSGID_UNKNOWN_HOSTNAME,
-              e.getLocalizedMessage());
-        }
-      }
-    }
-    configAttributes.add(changelogServer);
-
-    IntegerConfigAttribute windowAttr =
-      (IntegerConfigAttribute) config.getConfigAttribute(windowStub);
-    if (windowAttr == null)
-      rcvWindow = 100;  // Attribute is not present : use the default value
-    else
-    {
-      rcvWindow = windowAttr.activeIntValue();
-      configAttributes.add(windowAttr);
-    }
-
-    IntegerConfigAttribute queueSizeAttr =
-      (IntegerConfigAttribute) config.getConfigAttribute(queueSizeStub);
-    if (queueSizeAttr == null)
-      queueSize = 10000;  // Attribute is not present : use the default value
-    else
-    {
-      queueSize = queueSizeAttr.activeIntValue();
-      configAttributes.add(queueSizeAttr);
-    }
-
-    /*
-     * read the storage directory path attribute
-     */
-    StringConfigAttribute dbDirnameAttr =
-      (StringConfigAttribute) config.getConfigAttribute(dbDirnameStub);
-    if (dbDirnameAttr == null)
+    int changelogPort = configuration.getChangelogPort();
+    changelogServerId = (short) configuration.getChangelogServerId();
+    changelogServers = configuration.getChangelogServer();
+    if (changelogServers == null)
+      changelogServers = new ArrayList<String>();
+    queueSize = configuration.getQueueSize();
+    trimAge = configuration.getChangelogPurgeDelay();
+    dbDirname = configuration.getChangelogDbDirectory();
+    rcvWindow = configuration.getWindowSize();
+    if (dbDirname == null)
     {
       dbDirname = "changelogDb";
     }
-    else
-    {
-      dbDirname = dbDirnameAttr.activeValue();
-      configAttributes.add(changelogServer);
-    }
-    // Exists or Create
+    // Chech that this path exists or create it.
     File f = getFileForPath(dbDirname);
     try
     {
@@ -326,24 +144,8 @@
           e.getMessage() + " " + getFileForPath(dbDirname));
     }
 
-    /*
-     * Read the Purge Delay (trim age) attribute
-     */
-    IntegerWithUnitConfigAttribute purgeDelayAttr =
-      (IntegerWithUnitConfigAttribute) config.getConfigAttribute(
-          purgeDelayStub);
-    if (purgeDelayAttr == null)
-      trimAge = 24*60*60;  // not present : use the default value : 1 day
-    else
-    {
-      trimAge = purgeDelayAttr.activeCalculatedValue();
-      configAttributes.add(purgeDelayAttr);
-    }
-
     initialize(changelogServerId, changelogPort);
-
-    configDn = config.getDN();
-    DirectoryServer.registerConfigurableComponent(this);
+    configuration.addChangeListener(this);
   }
 
   /**
@@ -452,7 +254,7 @@
          */
         for (String serverURL : changelogServers)
         {
-          if ((serverURL.compareTo(localURL) != 0) &&
+          if ((serverURL.compareTo(this.serverURL) != 0) &&
               (!connectedChangelogs.contains(serverURL)))
           {
             this.connect(serverURL, changelogCache.getBaseDn());
@@ -629,7 +431,6 @@
     }
 
     dbEnv.shutdown();
-    DirectoryServer.deregisterConfigurableComponent(this);
   }
 
 
@@ -659,4 +460,56 @@
   {
     return trimAge * 1000;
   }
+
+  /**
+   * Check if the provided configuration is acceptable for add.
+   *
+   * @param configuration The configuration to check.
+   * @param unacceptableReasons When the configuration is not acceptable, this
+   *                            table is use to return the reasons why this
+   *                            configuration is not acceptbale.
+   *
+   * @return true if the configuration is acceptable, false other wise.
+   */
+  public static boolean isConfigurationAcceptable(
+      ChangelogServerCfg configuration, List<String> unacceptableReasons)
+  {
+    int port = configuration.getChangelogPort();
+
+    try
+    {
+      ServerSocket tmpSocket = new ServerSocket();
+      tmpSocket.bind(new InetSocketAddress(port));
+      tmpSocket.close();
+    }
+    catch (Exception e)
+    {
+      String message = getMessage(MSGID_COULD_NOT_BIND_CHANGELOG, port,
+                                  e.getMessage());
+      unacceptableReasons.add(message);
+      return false;
+    }
+
+    return true;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationChange(
+      ChangelogServerCfg configuration)
+  {
+    // TODO : implement this
+    return new ConfigChangeResult(ResultCode.SUCCESS, false);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationChangeAcceptable(
+      ChangelogServerCfg configuration, List<String> unacceptableReasons)
+  {
+    // TODO : implement this
+    return true;
+  }
 }
diff --git a/opends/src/server/org/opends/server/synchronization/common/LogMessages.java b/opends/src/server/org/opends/server/synchronization/common/LogMessages.java
index d2fc088..da1e49f 100644
--- a/opends/src/server/org/opends/server/synchronization/common/LogMessages.java
+++ b/opends/src/server/org/opends/server/synchronization/common/LogMessages.java
@@ -48,18 +48,6 @@
        CATEGORY_MASK_SYNC | SEVERITY_MASK_MILD_ERROR | 1;
 
   /**
-   * Need at least one Changelog Server.
-   */
-  public static final int MSGID_NEED_CHANGELOG_SERVER =
-    CATEGORY_MASK_SYNC | SEVERITY_MASK_MILD_ERROR | 2;
-
-  /**
-   * Need to have a server ID.
-   */
-  public static final int MSGID_NEED_SERVER_ID =
-    CATEGORY_MASK_SYNC | SEVERITY_MASK_MILD_ERROR | 3;
-
-  /**
    * Invalid Changelog Server.
    */
   public static final int MSGID_INVALID_CHANGELOG_SERVER =
@@ -380,11 +368,7 @@
   public static void registerMessages()
   {
     MessageHandler.registerMessage(MSGID_SYNC_INVALID_DN,
-       "The Synchronization configuration DN is invalid");
-    MessageHandler.registerMessage(MSGID_NEED_CHANGELOG_SERVER,
-        "At least one changelog server must be declared");
-    MessageHandler.registerMessage(MSGID_NEED_SERVER_ID,
-        "The Server Id must be defined");
+       "The configured DN is already used by another domain.");
     MessageHandler.registerMessage(MSGID_INVALID_CHANGELOG_SERVER,
         "Invalid changelog server configuration");
     MessageHandler.registerMessage(MSGID_UNKNOWN_HOSTNAME,
diff --git a/opends/src/server/org/opends/server/synchronization/plugin/ChangelogBroker.java b/opends/src/server/org/opends/server/synchronization/plugin/ChangelogBroker.java
index a985e6b..674d94a 100644
--- a/opends/src/server/org/opends/server/synchronization/plugin/ChangelogBroker.java
+++ b/opends/src/server/org/opends/server/synchronization/plugin/ChangelogBroker.java
@@ -33,8 +33,8 @@
 import static org.opends.server.synchronization.common.LogMessages.*;
 import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
 
+import java.util.Collection;
 import java.util.LinkedHashSet;
-import java.util.List;
 import java.util.TreeSet;
 import java.util.concurrent.Semaphore;
 import java.io.IOException;
@@ -75,7 +75,7 @@
 public class ChangelogBroker implements InternalSearchListener
 {
   private boolean shutdown = false;
-  private List<String> servers;
+  private Collection<String> servers;
   private boolean connected = false;
   private final Object lock = new Object();
   private String changelogServer = "Not connected";
@@ -158,7 +158,7 @@
    * @param servers list of servers used
    * @throws Exception : in case of errors
    */
-  public void start(List<String> servers)
+  public void start(Collection<String> servers)
                     throws Exception
   {
     /*
@@ -504,7 +504,6 @@
       try
       {
         SynchronizationMessage msg = session.receive();
-
         if (msg instanceof WindowMessage)
         {
           WindowMessage windowMsg = (WindowMessage) msg;
@@ -556,7 +555,8 @@
         debugInfo("ChangelogBroker Stop Closing session");
       }
 
-      session.close();
+      if (session != null)
+        session.close();
     } catch (IOException e)
     {}
   }
@@ -695,11 +695,31 @@
     return numLostConnections;
   }
 
-  private void log(String message)
+
+  /**
+   * Change some config parameters.
+   *
+   * @param changelogServers    The new list of changelog servers.
+   * @param maxReceiveQueue     The max size of receive queue.
+   * @param maxReceiveDelay     The max receive delay.
+   * @param maxSendQueue        The max send queue.
+   * @param maxSendDelay        The max Send Delay.
+   * @param window              The max window size.
+   * @param heartbeatInterval   The heartbeat interval.
+   */
+  public void changeConfig(Collection<String> changelogServers,
+      int maxReceiveQueue, int maxReceiveDelay, int maxSendQueue,
+      int maxSendDelay, int window, long heartbeatInterval)
   {
-    int    msgID   = MSGID_UNKNOWN_TYPE;
-    logError(ErrorLogCategory.SYNCHRONIZATION,
-           ErrorLogSeverity.SEVERE_ERROR,
-           message, msgID);
+    this.servers = changelogServers;
+    this.maxRcvWindow = window;
+    this.heartbeatInterval = heartbeatInterval;
+    this.maxReceiveDelay = maxReceiveDelay;
+    this.maxReceiveQueue = maxReceiveQueue;
+    this.maxSendDelay = maxSendDelay;
+    this.maxSendQueue = maxSendQueue;
+    // TODO : Changing those parameters requires to either restart a new
+    // session with the changelog server or renegociate the parameters that
+    // were sent in the ServerStart message
   }
 }
diff --git a/opends/src/server/org/opends/server/synchronization/plugin/ChangelogListener.java b/opends/src/server/org/opends/server/synchronization/plugin/ChangelogListener.java
new file mode 100644
index 0000000..68e50c8
--- /dev/null
+++ b/opends/src/server/org/opends/server/synchronization/plugin/ChangelogListener.java
@@ -0,0 +1,136 @@
+/*
+ * 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 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.synchronization.plugin;
+
+import java.util.List;
+
+import org.opends.server.admin.server.ConfigurationAddListener;
+import org.opends.server.admin.server.ConfigurationDeleteListener;
+import org.opends.server.admin.std.server.ChangelogServerCfg;
+import org.opends.server.admin.std.server.MultimasterSynchronizationProviderCfg;
+import org.opends.server.config.ConfigException;
+import org.opends.server.synchronization.changelog.Changelog;
+import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.ResultCode;
+
+/**
+ * This class is used to create and object that can
+ * register in the admin framework as a listener for changes, add and delete
+ * on the Changelog Server configuration objects.
+ *
+ */
+public class ChangelogListener
+       implements ConfigurationAddListener<ChangelogServerCfg>,
+       ConfigurationDeleteListener<ChangelogServerCfg>
+{
+  Changelog changelog = null;
+
+  /**
+   * Build a Changelog Listener from the given Multimaster configuration.
+   *
+   * @param configuration The configuration that will be used to listen
+   *                      for changelog configuration changes.
+   *
+   * @throws ConfigException if the ChangelogListener can't register for
+   *                         listening to changes on the provided configuration
+   *                         object.
+   */
+  public ChangelogListener(
+      MultimasterSynchronizationProviderCfg configuration)
+      throws ConfigException
+  {
+    configuration.addChangelogServerAddListener(this);
+    configuration.addChangelogServerDeleteListener(this);
+
+    if (configuration.hasChangelogServer())
+    {
+      ChangelogServerCfg server = configuration.getChangelogServer();
+      changelog = new Changelog(server);
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationAdd(
+      ChangelogServerCfg configuration)
+  {
+    try
+    {
+      changelog = new Changelog(configuration);
+      return new ConfigChangeResult(ResultCode.SUCCESS, false);
+    } catch (ConfigException e)
+    {
+      // we should never get to this point because the configEntry has
+      // already been validated in configAddisAcceptable
+      return new ConfigChangeResult(ResultCode.CONSTRAINT_VIOLATION, false);
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationAddAcceptable(
+      ChangelogServerCfg configuration, List<String> unacceptableReasons)
+  {
+    return Changelog.isConfigurationAcceptable(
+      configuration, unacceptableReasons);
+  }
+
+  /**
+   * Shutdown the Changelog servers.
+   */
+  public void shutdown()
+  {
+    if (changelog != null)
+      changelog.shutdown();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationDelete(
+      ChangelogServerCfg configuration)
+  {
+    // There can be only one changelog, just shutdown the changelog
+    // currently configured.
+    if (changelog != null)
+    {
+      changelog.shutdown();
+    }
+    return new ConfigChangeResult(ResultCode.SUCCESS, false);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationDeleteAcceptable(
+      ChangelogServerCfg configuration, List<String> unacceptableReasons)
+  {
+    return true;
+  }
+}
diff --git a/opends/src/server/org/opends/server/synchronization/plugin/MultimasterSynchronization.java b/opends/src/server/org/opends/server/synchronization/plugin/MultimasterSynchronization.java
index edbb868..0637e48 100644
--- a/opends/src/server/org/opends/server/synchronization/plugin/MultimasterSynchronization.java
+++ b/opends/src/server/org/opends/server/synchronization/plugin/MultimasterSynchronization.java
@@ -26,34 +26,35 @@
  */
 package org.opends.server.synchronization.plugin;
 
+import static org.opends.server.synchronization.common.LogMessages.HISTORICAL;
+
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.opends.server.admin.server.ConfigurationAddListener;
+import org.opends.server.admin.server.ConfigurationDeleteListener;
+import org.opends.server.admin.std.server.MultimasterDomainCfg;
+import org.opends.server.admin.std.server.MultimasterSynchronizationProviderCfg;
 import org.opends.server.api.Backend;
 import org.opends.server.api.BackupTaskListener;
-import org.opends.server.api.ConfigAddListener;
-import org.opends.server.api.ConfigChangeListener;
-import org.opends.server.api.ConfigDeleteListener;
 import org.opends.server.api.ExportTaskListener;
 import org.opends.server.api.ImportTaskListener;
 import org.opends.server.api.RestoreTaskListener;
 import org.opends.server.api.SynchronizationProvider;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.core.AddOperation;
-import org.opends.server.synchronization.changelog.Changelog;
-import org.opends.server.synchronization.common.LogMessages;
-import org.opends.server.types.DN;
 import org.opends.server.core.DeleteOperation;
-import org.opends.server.types.DirectoryException;
 import org.opends.server.core.DirectoryServer;
-import org.opends.server.types.Entry;
 import org.opends.server.core.ModifyDNOperation;
 import org.opends.server.core.ModifyOperation;
 import org.opends.server.core.Operation;
+import org.opends.server.synchronization.common.LogMessages;
 import org.opends.server.types.BackupConfig;
 import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
 import org.opends.server.types.LDIFExportConfig;
 import org.opends.server.types.LDIFImportConfig;
 import org.opends.server.types.Modification;
@@ -61,8 +62,6 @@
 import org.opends.server.types.ResultCode;
 import org.opends.server.types.SynchronizationProviderResult;
 
-import static org.opends.server.synchronization.common.LogMessages.*;
-
 /**
  * This class is used to load the Synchronization code inside the JVM
  * and to trigger initialization of the synchronization.
@@ -71,19 +70,19 @@
  * synchronization code running during the operation process
  * as pre-op, conflictRsolution, and post-op.
  */
-public class MultimasterSynchronization extends SynchronizationProvider
-       implements ConfigAddListener, ConfigDeleteListener, ConfigChangeListener,
-       BackupTaskListener, RestoreTaskListener, ImportTaskListener,
-       ExportTaskListener
-
+public class MultimasterSynchronization
+       extends SynchronizationProvider<MultimasterSynchronizationProviderCfg>
+       implements ConfigurationAddListener<MultimasterDomainCfg>,
+                  ConfigurationDeleteListener<MultimasterDomainCfg>,
+                  BackupTaskListener, RestoreTaskListener, ImportTaskListener,
+                  ExportTaskListener
 {
   static String CHANGELOG_DN = "cn=Changelog Server," +
     "cn=Multimaster Synchronization, cn=Synchronization Providers, cn=config";
   static String SYNCHRONIZATION_CLASS =
     "ds-cfg-synchronization-provider-config";
 
-  private DN changelogConfigEntryDn = null;
-  private Changelog changelog = null;
+  private ChangelogListener changelog = null;
   private static Map<DN, SynchronizationDomain> domains =
     new HashMap<DN, SynchronizationDomain>() ;
 
@@ -91,46 +90,25 @@
   /**
    * {@inheritDoc}
    */
-  public void initializeSynchronizationProvider(ConfigEntry configEntry)
+  @Override
+  public void initializeSynchronizationProvider(
+      MultimasterSynchronizationProviderCfg configuration)
   throws ConfigException
   {
     LogMessages.registerMessages();
 
-    configEntry.registerAddListener(this);
-    configEntry.registerDeleteListener(this);
+    changelog = new ChangelogListener(configuration);
 
-    /*
-     * Read changelog server the changelog configuration entry
-     */
-    try
-    {
-      changelogConfigEntryDn = DN.decode(CHANGELOG_DN);
-      ConfigEntry config =
-        DirectoryServer.getConfigEntry(changelogConfigEntryDn);
-      /*
-       * If there is no such entry, this process must not be a changelog server
-       */
-      if (config != null)
-      {
-        changelog = new Changelog(config);
-      }
-    } catch (DirectoryException e)
-    {
-      /* never happens */
-      throw new ConfigException(MSGID_SYNC_INVALID_DN,
-      "Invalid Changelog configuration DN");
-    }
+    // Register as an add and delete listener with the root configuration so we
+    // can be notified if Multimaster domain entries are added or removed.
+    configuration.addMultimasterDomainAddListener(this);
+    configuration.addMultimasterDomainDeleteListener(this);
 
-    /*
-     * Parse the list of entries below configEntry,
-     * create one synchronization domain for each child
-     */
-    for (ConfigEntry domainEntry : configEntry.getChildren().values())
+    //  Create the list of domains that are already defined.
+    for (String name : configuration.listMultimasterDomains())
     {
-      if (domainEntry.hasObjectClass(SYNCHRONIZATION_CLASS))
-      {
-        createNewSynchronizationDomain(domainEntry);
-      }
+      MultimasterDomainCfg domain = configuration.getMultimasterDomain(name);
+      createNewSynchronizationDomain(domain);
     }
 
     /*
@@ -151,124 +129,46 @@
   }
 
   /**
-   * 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 isConfigurationAddAcceptable(
+      MultimasterDomainCfg configuration, List<String> unacceptableReasons)
   {
-    return false; // TODO :NYI
-  }
-
-  /**
-   * 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)
-  {
-    // TODO implement this method
-    return new ConfigChangeResult(ResultCode.SUCCESS, false);
+    return SynchronizationDomain.isConfigurationAcceptable(
+      configuration, unacceptableReasons);
   }
 
   /**
    * {@inheritDoc}
    */
-  public boolean configAddIsAcceptable(ConfigEntry configEntry,
-      StringBuilder unacceptableReason)
+  public ConfigChangeResult applyConfigurationAdd(
+     MultimasterDomainCfg configuration)
   {
-    // Check if the added entry is the changelog config entry
     try
     {
-      if (configEntry.getDN().equals(DN.decode(CHANGELOG_DN)))
-      {
-        return Changelog.checkConfigEntry(configEntry, unacceptableReason);
-      }
-    } catch (DirectoryException e)
+      createNewSynchronizationDomain(configuration);
+      return new ConfigChangeResult(ResultCode.SUCCESS, false);
+    } catch (ConfigException e)
     {
-      /* never happens */
-       unacceptableReason.append("Invalid Changelog configuration DN");
-       return false;
+      // we should never get to this point because the configEntry has
+      // already been validated in configAddisAcceptable
+      return new ConfigChangeResult(ResultCode.CONSTRAINT_VIOLATION, false);
     }
-
-    // otherwise it must be a Synchronization domain, check for
-    // presence of the Synchronization configuration object class
-    if (configEntry.hasObjectClass(SYNCHRONIZATION_CLASS))
-    {
-      return SynchronizationDomain.checkConfigEntry(configEntry,
-          unacceptableReason);
-    }
-
-    return false;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry)
-  {
-    // check if the entry is the changelog configuration entry
-    if (configEntry.getDN().equals(changelogConfigEntryDn))
-    {
-      try
-      {
-        changelog = new Changelog(configEntry);
-        return new ConfigChangeResult(ResultCode.SUCCESS, false);
-      } catch (ConfigException e)
-      {
-        // we should never get to this point because the configEntry has
-        // already been validated in configAddisAcceptable
-        return new ConfigChangeResult(ResultCode.SUCCESS, false);
-      }
-    }
-
-    // otherwise it must be a synchronization domain, check for
-    // presence of the Synchronization configuration object class
-    if (configEntry.hasObjectClass(SYNCHRONIZATION_CLASS))
-    {
-      try
-      {
-        createNewSynchronizationDomain(configEntry);
-        return new ConfigChangeResult(ResultCode.SUCCESS, false);
-      } catch (ConfigException e)
-      {
-        // we should never get to this point because the configEntry has
-        // already been validated in configAddisAcceptable
-        return new ConfigChangeResult(ResultCode.SUCCESS, false);
-      }
-    }
-
-    // we should never get to this point because the configEntry has
-    // already been validated in configAddisAcceptable
-    return new ConfigChangeResult(ResultCode.SUCCESS, false);
   }
 
   /**
    * Creates a New Synchronization domain from its configEntry, do the
    * necessary initialization and starts it so that it is
    * fully operational when this method returns.
-   * @param configEntry The entry whith the configuration of this domain.
+   * @param configuration The entry whith the configuration of this domain.
    * @throws ConfigException When the configuration is not valid.
    */
-  private void createNewSynchronizationDomain(ConfigEntry configEntry)
-          throws ConfigException
+  private void createNewSynchronizationDomain(
+      MultimasterDomainCfg configuration)
+      throws ConfigException
   {
     SynchronizationDomain domain;
-    domain = new SynchronizationDomain(configEntry);
+    domain = new SynchronizationDomain(configuration);
     domains.put(domain.getBaseDN(), domain);
     domain.start();
   }
@@ -276,25 +176,7 @@
   /**
    * {@inheritDoc}
    */
-  public boolean configDeleteIsAcceptable(ConfigEntry configEntry,
-      StringBuilder unacceptableReason)
-  {
-    // TODO Auto-generated method stub
-    return true;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry)
-  {
-    // TODO Auto-generated method stub
-    return null;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
+  @Override
   public void doPostOperation(AddOperation addOperation)
   {
     DN dn = addOperation.getEntryDN();
@@ -305,6 +187,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public void doPostOperation(DeleteOperation deleteOperation)
   {
     DN dn = deleteOperation.getEntryDN();
@@ -314,6 +197,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public void doPostOperation(ModifyDNOperation modifyDNOperation)
   {
     DN dn = modifyDNOperation.getEntryDN();
@@ -536,6 +420,7 @@
    *                                      applied to the schema.
    *
    */
+  @Override
   public void processSchemaChange(List<Modification> modifications)
   {
     SynchronizationDomain domain =
@@ -651,6 +536,29 @@
         domain.backupEnd();
     }
   }
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationDelete(
+      MultimasterDomainCfg configuration)
+  {
+    DN dn = configuration.getSynchronizationDN();
+    SynchronizationDomain domain = domains.remove(dn);
+    if (domain != null)
+      domain.shutdown();
+
+    return new ConfigChangeResult(ResultCode.SUCCESS, false);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationDeleteAcceptable(
+      MultimasterDomainCfg configuration, List<String> unacceptableReasons)
+  {
+    return true;
+  }
 }
 
 
diff --git a/opends/src/server/org/opends/server/synchronization/plugin/SynchronizationDomain.java b/opends/src/server/org/opends/server/synchronization/plugin/SynchronizationDomain.java
index 743d24d..c597f18 100644
--- a/opends/src/server/org/opends/server/synchronization/plugin/SynchronizationDomain.java
+++ b/opends/src/server/org/opends/server/synchronization/plugin/SynchronizationDomain.java
@@ -39,14 +39,13 @@
 import static org.opends.server.synchronization.common.LogMessages.*;
 import static org.opends.server.synchronization.plugin.Historical.ENTRYUIDNAME;
 import static org.opends.server.synchronization.protocol.OperationContext.*;
-import static org.opends.server.util.ServerConstants.*;
 import static org.opends.server.util.StaticUtils.createEntry;
 import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
 
 import java.io.IOException;
 import java.net.SocketTimeoutException;
 import java.util.ArrayList;
-import java.util.LinkedHashMap;
+import java.util.Collection;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
@@ -55,20 +54,18 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.zip.DataFormatException;
 
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.server.MultimasterDomainCfg;
 import org.opends.server.api.Backend;
-import org.opends.server.api.ConfigurableComponent;
 import org.opends.server.api.DirectoryThread;
 import org.opends.server.api.SynchronizationProvider;
 import org.opends.server.backends.jeb.BackendImpl;
 import org.opends.server.backends.task.Task;
 import org.opends.server.backends.task.TaskState;
-import org.opends.server.config.BooleanConfigAttribute;
 import org.opends.server.config.ConfigAttribute;
 import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.config.DNConfigAttribute;
-import org.opends.server.config.IntegerConfigAttribute;
-import org.opends.server.config.IntegerWithUnitConfigAttribute;
 import org.opends.server.config.StringConfigAttribute;
 import org.opends.server.core.AddOperation;
 import org.opends.server.core.DeleteOperation;
@@ -77,7 +74,6 @@
 import org.opends.server.core.ModifyDNOperation;
 import org.opends.server.core.ModifyOperation;
 import org.opends.server.core.Operation;
-import org.opends.server.messages.MessageHandler;
 import org.opends.server.protocols.asn1.ASN1Exception;
 import org.opends.server.protocols.internal.InternalClientConnection;
 import org.opends.server.protocols.internal.InternalSearchOperation;
@@ -130,7 +126,7 @@
  *  handle protocol messages from the changelog server.
  */
 public class SynchronizationDomain extends DirectoryThread
-       implements ConfigurableComponent
+       implements ConfigurationChangeListener<MultimasterDomainCfg>
 {
   private SynchronizationMonitor monitor;
 
@@ -254,7 +250,7 @@
   private int listenerThreadNumber = 10;
   private boolean receiveStatus = true;
 
-  private List<String> changelogServers;
+  private Collection<String> changelogServers;
 
   private DN baseDN;
 
@@ -263,8 +259,6 @@
 
   private boolean shutdown = false;
 
-  private DN configDn;
-
   private InternalClientConnection conn =
       InternalClientConnection.getRootConnection();
 
@@ -273,102 +267,30 @@
   private boolean disabled = false;
   private boolean stateSavingDisabled = false;
 
-  static final String CHANGELOG_SERVER_ATTR = "ds-cfg-changelog-server";
-  static final String BASE_DN_ATTR = "ds-cfg-synchronization-dn";
-  static final String SERVER_ID_ATTR = "ds-cfg-directory-server-id";
-  static final String RECEIVE_STATUS = "ds-cfg-receive-status";
-  static final String MAX_RECEIVE_QUEUE = "ds-cfg-max-receive-queue";
-  static final String MAX_RECEIVE_DELAY = "ds-cfg-max-receive-delay";
-  static final String MAX_SEND_QUEUE = "ds-cfg-max-send-queue";
-  static final String MAX_SEND_DELAY = "ds-cfg-max-send-delay";
-  static final String WINDOW_SIZE = "ds-cfg-window-size";
-  static final String HEARTBEAT_INTERVAL = "ds-cfg-heartbeat-interval";
+  private int window = 100;
 
-  private static final StringConfigAttribute changelogStub =
-    new StringConfigAttribute(CHANGELOG_SERVER_ATTR,
-        "changelog server information", true, true, false);
-
-  private static final IntegerConfigAttribute serverIdStub =
-    new IntegerConfigAttribute(SERVER_ID_ATTR, "server ID", true, false,
-                               false, true, 0, true, 65535);
-
-  private static final DNConfigAttribute baseDnStub =
-    new DNConfigAttribute(BASE_DN_ATTR, "synchronization base DN",
-                          true, false, false);
-
-  private static final BooleanConfigAttribute receiveStatusStub =
-    new BooleanConfigAttribute(RECEIVE_STATUS, "receive status", false);
-
-
-  /**
-   * The set of time units that will be used for expressing the heartbeat
-   * interval.
-   */
-  private static final LinkedHashMap<String,Double> timeUnits =
-       new LinkedHashMap<String,Double>();
-
-
-
-  static
-  {
-    timeUnits.put(TIME_UNIT_MILLISECONDS_ABBR, 1D);
-    timeUnits.put(TIME_UNIT_MILLISECONDS_FULL, 1D);
-    timeUnits.put(TIME_UNIT_SECONDS_ABBR, 1000D);
-    timeUnits.put(TIME_UNIT_SECONDS_FULL, 1000D);
-  }
 
   /**
    * Creates a new SynchronizationDomain using configuration from configEntry.
    *
-   * @param configEntry The ConfigEntry to use to read the configuration of this
-   *                    SynchronizationDomain.
+   * @param configuration    The configuration of this SynchronizationDomain.
    * @throws ConfigException In case of invalid configuration.
    */
-  public SynchronizationDomain(ConfigEntry configEntry) throws ConfigException
+  public SynchronizationDomain(MultimasterDomainCfg configuration)
+    throws ConfigException
   {
     super("Synchronization flush");
 
-    /*
-     * read the centralized changelog server configuration
-     * this is a multivalued attribute
-     */
-    StringConfigAttribute changelogServer =
-      (StringConfigAttribute) configEntry.getConfigAttribute(changelogStub);
-
-    if (changelogServer == null)
-    {
-      throw new ConfigException(MSGID_NEED_CHANGELOG_SERVER,
-          MessageHandler.getMessage(MSGID_NEED_CHANGELOG_SERVER,
-              configEntry.getDN().toString()) );
-    }
-    changelogServers = changelogServer.activeValues();
-    configAttributes.add(changelogServer);
-
-    /*
-     * read the server Id information
-     * this is a single valued integer, its value must fit on a short integer
-     */
-    IntegerConfigAttribute serverIdAttr =
-      (IntegerConfigAttribute) configEntry.getConfigAttribute(serverIdStub);
-    if (serverIdAttr == null)
-    {
-      throw new ConfigException(MSGID_NEED_SERVER_ID,
-          MessageHandler.getMessage(MSGID_NEED_SERVER_ID,
-              configEntry.getDN().toString())  );
-    }
-    serverId = (short) serverIdAttr.activeIntValue();
-    configAttributes.add(serverIdAttr);
-
-    /*
-     * read the base DN
-     */
-    DNConfigAttribute baseDn =
-      (DNConfigAttribute) configEntry.getConfigAttribute(baseDnStub);
-    if (baseDn == null)
-      baseDN = null;  // Attribute is not present : don't set a limit
-    else
-      baseDN = baseDn.activeValue();
-    configAttributes.add(baseDn);
+    // Read the configuration parameters.
+    changelogServers = configuration.getChangelogServer();
+    serverId = (short) configuration.getServerId();
+    baseDN = configuration.getSynchronizationDN();
+    maxReceiveQueue = configuration.getMaxReceiveQueue();
+    maxReceiveDelay = (int) configuration.getMaxReceiveDelay();
+    maxSendQueue = configuration.getMaxSendQueue();
+    maxSendDelay = (int) configuration.getMaxSendDelay();
+    window  = configuration.getWindowSize();
+    heartbeatInterval = configuration.getHeartbeatInterval();
 
     /*
      * Modify conflicts are solved for all suffixes but the schema suffix
@@ -386,114 +308,25 @@
       solveConflictFlag = true;
     }
 
+    /*
+     * Create a new Persistent Server State that will be used to store
+     * the last ChangeNmber seen from all LDAP servers in the topology.
+     */
     state = new PersistentServerState(baseDN);
 
     /*
-     * Read the Receive Status.
+     * Create a Synchronization monitor object responsible for publishing
+     * monitoring information below cn=monitor.
      */
-    BooleanConfigAttribute receiveStatusAttr = (BooleanConfigAttribute)
-          configEntry.getConfigAttribute(receiveStatusStub);
-    if (receiveStatusAttr != null)
-    {
-      receiveStatus = receiveStatusAttr.activeValue();
-      configAttributes.add(receiveStatusAttr);
-    }
-
-    /*
-     * read the synchronization flow control configuration.
-     */
-    IntegerConfigAttribute maxReceiveQueueStub =
-      new IntegerConfigAttribute(MAX_RECEIVE_QUEUE, "max receive queue",
-                                 false, false, false, true, 0,false, 0);
-
-    IntegerConfigAttribute maxReceiveQueueAttr = (IntegerConfigAttribute)
-              configEntry.getConfigAttribute(maxReceiveQueueStub);
-    if (maxReceiveQueueAttr == null)
-      maxReceiveQueue = 0;  // Attribute is not present : don't set a limit
-    else
-    {
-      maxReceiveQueue = maxReceiveQueueAttr.activeIntValue();
-      configAttributes.add(maxReceiveQueueAttr);
-    }
-
-    IntegerConfigAttribute maxReceiveDelayStub =
-      new IntegerConfigAttribute(MAX_RECEIVE_DELAY, "max receive delay",
-                                 false, false, false, true, 0, false, 0);
-    IntegerConfigAttribute maxReceiveDelayAttr = (IntegerConfigAttribute)
-              configEntry.getConfigAttribute(maxReceiveDelayStub);
-    if (maxReceiveDelayAttr == null)
-      maxReceiveDelay = 0;  // Attribute is not present : don't set a limit
-    else
-    {
-      maxReceiveDelay = maxReceiveDelayAttr.activeIntValue();
-      configAttributes.add(maxReceiveDelayAttr);
-    }
-
-    IntegerConfigAttribute maxSendQueueStub =
-      new IntegerConfigAttribute(MAX_SEND_QUEUE, "max send queue",
-                                 false, false, false, true, 0, false, 0);
-    IntegerConfigAttribute maxSendQueueAttr =
-      (IntegerConfigAttribute) configEntry.getConfigAttribute(maxSendQueueStub);
-    if (maxSendQueueAttr == null)
-      maxSendQueue = 0;  // Attribute is not present : don't set a limit
-    else
-    {
-      maxSendQueue = maxSendQueueAttr.activeIntValue();
-      configAttributes.add(maxSendQueueAttr);
-    }
-
-    IntegerConfigAttribute maxSendDelayStub =
-      new IntegerConfigAttribute(MAX_SEND_DELAY, "max send delay",
-                                 false, false, false, true, 0, false, 0);
-    IntegerConfigAttribute maxSendDelayAttr =
-      (IntegerConfigAttribute) configEntry.getConfigAttribute(maxSendDelayStub);
-    if (maxSendDelayAttr == null)
-      maxSendDelay = 0;  // Attribute is not present : don't set a limit
-    else
-    {
-      maxSendDelay = maxSendDelayAttr.activeIntValue();
-      configAttributes.add(maxSendDelayAttr);
-    }
-
-    Integer window;
-    IntegerConfigAttribute windowStub =
-      new IntegerConfigAttribute(WINDOW_SIZE, "window size",
-                                 false, false, false, true, 0, false, 0);
-    IntegerConfigAttribute windowAttr =
-      (IntegerConfigAttribute) configEntry.getConfigAttribute(windowStub);
-    if (windowAttr == null)
-      window = 100;  // Attribute is not present : use the default value
-    else
-    {
-      window = windowAttr.activeIntValue();
-      configAttributes.add(windowAttr);
-    }
-
-    IntegerWithUnitConfigAttribute heartbeatStub =
-      new IntegerWithUnitConfigAttribute(HEARTBEAT_INTERVAL,
-                                         "heartbeat interval",
-                                         false, timeUnits, true, 0, false, 0);
-    IntegerWithUnitConfigAttribute heartbeatAttr =
-      (IntegerWithUnitConfigAttribute)
-           configEntry.getConfigAttribute(heartbeatStub);
-    if (heartbeatAttr == null)
-    {
-      // Attribute is not present : use the default value
-      heartbeatInterval = 1000;
-    }
-    else
-    {
-      heartbeatInterval = heartbeatAttr.activeCalculatedValue();
-      configAttributes.add(heartbeatAttr);
-    }
-
-    configDn = configEntry.getDN();
-    DirectoryServer.registerConfigurableComponent(this);
-
     monitor = new SynchronizationMonitor(this);
     DirectoryServer.registerMonitorProvider(monitor);
 
+    /*
+     * ChangeNumberGenerator is used to create new unique ChangeNumbers
+     * for each operation done on the synchronization domain.
+     */
     changeNumberGenerator = new ChangeNumberGenerator(serverId, state);
+
     /*
      * create the broker object used to publish and receive changes
      */
@@ -519,14 +352,9 @@
       * should we stop the modifications ?
       */
     }
-  }
 
-  /**
-   * {@inheritDoc}
-   */
-  public DN getConfigurableComponentEntryDN()
-  {
-    return configDn;
+    // listen for changes on the configuration
+    configuration.addChangeListener(this);
   }
 
   /**
@@ -537,112 +365,6 @@
     return configAttributes;
   }
 
-  /**
-   * {@inheritDoc}
-   */
-  public boolean hasAcceptableConfiguration(ConfigEntry configEntry,
-      List<String> unacceptableReasons)
-  {
-    boolean acceptable = true;
-    StringConfigAttribute changelog = null;
-    try
-    {
-      changelog = (StringConfigAttribute)
-                                  configEntry.getConfigAttribute(changelogStub);
-    } catch (ConfigException e)
-    {
-      acceptable = false;
-      unacceptableReasons.add("Need at least one changelog server.");
-    }
-    if (changelog == null)
-    {
-      acceptable = false;
-      unacceptableReasons.add("Need at least one changelog server.");
-    }
-    return acceptable;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry,
-      boolean detailedResults)
-  {
-    StringConfigAttribute changelog = null;
-    List<String> newChangelogServers;
-    boolean newReceiveStatus;
-
-    try
-    {
-      /*
-       *  check if changelog server list changed
-       */
-      changelog = (StringConfigAttribute)
-                                  configEntry.getConfigAttribute(changelogStub);
-
-      newChangelogServers = changelog.activeValues();
-
-      boolean sameConf = true;
-      for (String s :newChangelogServers)
-        if (!changelogServers.contains(s))
-          sameConf = false;
-      for (String s : changelogServers)
-        if (!newChangelogServers.contains(s))
-          sameConf = false;
-
-      if (!sameConf)
-      {
-        broker.stop();
-        changelogServers = newChangelogServers;
-        broker.start(changelogServers);
-      }
-
-      /*
-       * check if reception should be disabled
-       */
-      newReceiveStatus = ((BooleanConfigAttribute)
-               configEntry.getConfigAttribute(receiveStatusStub)).activeValue();
-      if (newReceiveStatus != receiveStatus)
-      {
-        /*
-         * was disabled and moved to enabled
-         */
-        if (newReceiveStatus)
-        {
-          broker.restartReceive();
-          for (int i=0; i<listenerThreadNumber; i++)
-          {
-            ListenerThread myThread = new ListenerThread(this);
-            myThread.start();
-            synchroThreads.add(myThread);
-          }
-        }
-        else
-        {
-          /* was enabled and moved to disabled */
-          broker.suspendReceive();
-          // FIXME Need a way to stop these threads.
-          // Setting the shutdown flag does not stop them until they have
-          // consumed and discarded one more message each.
-//          for (ListenerThread thread : synchroThreads)
-//          {
-//            thread.shutdown();
-//          }
-          synchroThreads.clear();
-        }
-        receiveStatus = newReceiveStatus;
-      }
-
-    } catch (Exception e)
-    {
-      /* this should never happen because the parameters have been
-       * validated by hasAcceptableConfiguration
-       */
-      return new ConfigChangeResult(ResultCode.OPERATIONS_ERROR, false);
-    }
-
-    return new ConfigChangeResult(ResultCode.SUCCESS, false);
-  }
 
   /**
    * Returns the base DN of this SynchronizationDomain.
@@ -1041,9 +763,7 @@
   public void receiveAck(AckMessage ack)
   {
     UpdateMessage update;
-    ChangeNumber changeNumber;
-
-    changeNumber = ack.getChangeNumber();
+    ChangeNumber changeNumber = ack.getChangeNumber();
 
     synchronized (pendingChanges)
     {
@@ -1933,51 +1653,6 @@
   }
 
   /**
-   * Check if a ConfigEntry is valid.
-   * @param configEntry The config entry that needs to be checked.
-   * @param unacceptableReason A description of the reason why the config entry
-   *                           is not acceptable (if return is false).
-   * @return a boolean indicating if the configEntry is valid.
-   */
-  public static boolean checkConfigEntry(ConfigEntry configEntry,
-      StringBuilder unacceptableReason)
-  {
-    try
-    {
-    StringConfigAttribute changelogServer =
-      (StringConfigAttribute) configEntry.getConfigAttribute(changelogStub);
-
-    if (changelogServer == null)
-    {
-      unacceptableReason.append(
-          MessageHandler.getMessage(MSGID_NEED_CHANGELOG_SERVER,
-          configEntry.getDN().toString()) );
-      return false;
-    }
-
-    /*
-     * read the server Id information
-     * this is a single valued integer, its value must fit on a short integer
-     */
-    IntegerConfigAttribute serverIdAttr =
-      (IntegerConfigAttribute) configEntry.getConfigAttribute(serverIdStub);
-    if (serverIdAttr == null)
-    {
-      unacceptableReason.append(
-          MessageHandler.getMessage(MSGID_NEED_SERVER_ID,
-              configEntry.getDN().toString()) );
-      return false;
-    }
-    }
-    catch (ConfigException e)
-    {
-      unacceptableReason.append(e.getMessage());
-      return false;
-    }
-    return true;
-  }
-
-  /**
    * Get the maximum receive window size.
    *
    * @return The maximum receive window size.
@@ -2026,7 +1701,6 @@
     return broker.getNumLostConnections();
   }
 
-
   /**
    * Check if the domain solve conflicts.
    *
@@ -3109,4 +2783,60 @@
     op.setResultCode(ResultCode.SUCCESS);
     synchronize(op);
   }
+
+  /**
+   * Check if the provided configuration is acceptable for add.
+   *
+   * @param configuration The configuration to check.
+   * @param unacceptableReasons When the configuration is not acceptable, this
+   *                            table is use to return the reasons why this
+   *                            configuration is not acceptbale.
+   *
+   * @return true if the configuration is acceptable, false other wise.
+   */
+  public static boolean isConfigurationAcceptable(
+      MultimasterDomainCfg configuration, List<String> unacceptableReasons)
+  {
+    // Check that there is not already a domain with the same DN
+    // TODO : Check that the server id is a short
+    DN dn = configuration.getSynchronizationDN();
+    if (MultimasterSynchronization.findDomain(dn,null) != null)
+    {
+      String message = getMessage(MSGID_SYNC_INVALID_DN, dn.toString());
+      unacceptableReasons.add(message);
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationChange(
+         MultimasterDomainCfg configuration)
+  {
+    // server id and base dn are readonly.
+    // The other parameters needs to be renegociated with the Changelog Server.
+    // so that requires restarting the session with the Changelog Server.
+    changelogServers = configuration.getChangelogServer();
+    maxReceiveQueue = configuration.getMaxReceiveQueue();
+    maxReceiveDelay = (int) configuration.getMaxReceiveDelay();
+    maxSendQueue = configuration.getMaxSendQueue();
+    maxSendDelay = (int) configuration.getMaxSendDelay();
+    window = configuration.getWindowSize();
+    heartbeatInterval = configuration.getHeartbeatInterval();
+    broker.changeConfig(changelogServers, maxReceiveQueue, maxReceiveDelay,
+                        maxSendQueue, maxSendDelay, window, heartbeatInterval);
+
+    return new ConfigChangeResult(ResultCode.SUCCESS, false);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationChangeAcceptable(
+         MultimasterDomainCfg configuration, List<String> unacceptableReasons)
+  {
+    return true;
+  }
 }
diff --git a/opends/src/server/org/opends/server/tasks/AddSchemaFileTask.java b/opends/src/server/org/opends/server/tasks/AddSchemaFileTask.java
index 44c33ce..5d97b38 100644
--- a/opends/src/server/org/opends/server/tasks/AddSchemaFileTask.java
+++ b/opends/src/server/org/opends/server/tasks/AddSchemaFileTask.java
@@ -35,6 +35,7 @@
 import java.util.TreeSet;
 import java.util.concurrent.locks.Lock;
 
+import org.opends.server.admin.std.server.SynchronizationProviderCfg;
 import org.opends.server.api.ClientConnection;
 import org.opends.server.api.SynchronizationProvider;
 import org.opends.server.backends.task.Task;
@@ -298,7 +299,7 @@
 
       if (! mods.isEmpty())
       {
-        for (SynchronizationProvider provider :
+        for (SynchronizationProvider<SynchronizationProviderCfg> provider :
              DirectoryServer.getSynchronizationProviders())
         {
           try
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/InitOnLineTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/InitOnLineTest.java
index a6d43a0..521afec 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/InitOnLineTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/InitOnLineTest.java
@@ -26,11 +26,7 @@
  */
 package org.opends.server.synchronization;
 
-import static org.opends.server.config.ConfigConstants.ATTR_TASK_COMPLETION_TIME;
-import static org.opends.server.config.ConfigConstants.ATTR_TASK_INITIALIZE_DONE;
-import static org.opends.server.config.ConfigConstants.ATTR_TASK_INITIALIZE_LEFT;
-import static org.opends.server.config.ConfigConstants.ATTR_TASK_LOG_MESSAGES;
-import static org.opends.server.config.ConfigConstants.ATTR_TASK_STATE;
+import static org.opends.server.config.ConfigConstants.*;
 import static org.opends.server.loggers.Error.logError;
 import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
 import static org.opends.server.loggers.debug.DebugLogger.debugInfo;
@@ -40,49 +36,35 @@
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
 import java.util.ArrayList;
-import java.util.LinkedHashSet;
-import java.util.List;
 import java.util.UUID;
 
 import org.opends.server.TestCaseUtils;
 import org.opends.server.backends.task.TaskState;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.core.AddOperation;
 import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.ModifyOperation;
 import org.opends.server.messages.TaskMessages;
 import org.opends.server.protocols.internal.InternalClientConnection;
 import org.opends.server.protocols.internal.InternalSearchOperation;
 import org.opends.server.schema.DirectoryStringSyntax;
 import org.opends.server.synchronization.changelog.Changelog;
+import org.opends.server.synchronization.changelog.ChangelogFakeConfiguration;
 import org.opends.server.synchronization.common.LogMessages;
-import org.opends.server.synchronization.common.ServerState;
 import org.opends.server.synchronization.plugin.ChangelogBroker;
 import org.opends.server.synchronization.plugin.SynchronizationDomain;
-import org.opends.server.synchronization.protocol.ChangelogStartMessage;
 import org.opends.server.synchronization.protocol.DoneMessage;
 import org.opends.server.synchronization.protocol.EntryMessage;
 import org.opends.server.synchronization.protocol.ErrorMessage;
 import org.opends.server.synchronization.protocol.InitializeRequestMessage;
 import org.opends.server.synchronization.protocol.InitializeTargetMessage;
 import org.opends.server.synchronization.protocol.RoutableMessage;
-import org.opends.server.synchronization.protocol.ServerStartMessage;
 import org.opends.server.synchronization.protocol.SocketSession;
 import org.opends.server.synchronization.protocol.SynchronizationMessage;
-import org.opends.server.types.Attribute;
 import org.opends.server.types.AttributeType;
-import org.opends.server.types.AttributeValue;
 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.Modification;
-import org.opends.server.types.ModificationType;
 import org.opends.server.types.ResultCode;
 import org.opends.server.types.SearchFilter;
 import org.opends.server.types.SearchScope;
@@ -193,14 +175,6 @@
     // Synchro multi-master
     synchroPluginStringDN = "cn=Multimaster Synchronization, "
       + synchroStringDN;
-    String synchroPluginLdif = "dn: "
-      + synchroPluginStringDN
-      + "\n"
-      + "objectClass: top\n"
-      + "objectClass: ds-cfg-synchronization-provider\n"
-      + "ds-cfg-synchronization-provider-enabled: true\n"
-      + "ds-cfg-synchronization-provider-class: org.opends.server.synchronization.MultimasterSynchronization\n";
-    synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
 
     // Synchro suffix
     synchroServerEntry = null;
@@ -762,26 +736,10 @@
       {
         int chPort = getChangelogPort(changelogId);
         
-        // Create a changelog server
-        String changelogLdif = "dn: cn=Changelog Server\n"
-          + "objectClass: top\n"
-          + "objectClass: ds-cfg-synchronization-changelog-server-config\n"
-          + "cn: Changelog Server\n"
-          + "ds-cfg-changelog-port: " + chPort + "\n"
-          + "ds-cfg-changelog-server-id: " + changelogId + "\n"
-//        + "ds-cfg-heartbeat-interval: 0 ms\n"
-          + "ds-cfg-window-size: 100" + "\n";
-        
-        if (changelogId==changelog2ID)
-        {
-          changelogLdif += new String(
-              "ds-cfg-changelog-server: localhost:"
-              + getChangelogPort(changelog1ID)+"\n");
-        }
-        Entry tmp = TestCaseUtils.entryFromLdifString(changelogLdif);
-        ConfigEntry changelogConfig = new ConfigEntry(tmp, null);
-        Changelog changelog = new Changelog(changelogConfig);
-        
+        ChangelogFakeConfiguration conf =
+          new ChangelogFakeConfiguration(chPort, null, 0, changelogId, 0, 100,
+                                         null); 
+        Changelog changelog = new Changelog(conf);
         Thread.sleep(1000);
 
         return changelog;
@@ -806,7 +764,8 @@
     {
       // suffix synchronized
       String synchroServerStringDN = synchroPluginStringDN;
-      String synchroServerLdif = "dn: cn=example," + synchroServerStringDN + "\n"
+      String synchroServerLdif =
+        "dn: cn=example, cn=domains" + synchroServerStringDN + "\n"
       + "objectClass: top\n"
       + "objectClass: ds-cfg-synchronization-provider-config\n"
       + "cn: example\n"
@@ -1483,6 +1442,6 @@
       // fromthe changelog server.
       server2 = null;
     }
-    super.cleanEntries();
+    super.cleanRealEntries();
   }
 }
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ProtocolWindowTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ProtocolWindowTest.java
index 1478b9c..7cd2c2b 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ProtocolWindowTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ProtocolWindowTest.java
@@ -273,14 +273,6 @@
     // Multimaster Synchro plugin
     synchroPluginStringDN = "cn=Multimaster Synchronization, "
         + synchroStringDN;
-    String synchroPluginLdif = "dn: "
-        + synchroPluginStringDN
-        + "\n"
-        + "objectClass: top\n"
-        + "objectClass: ds-cfg-synchronization-provider\n"
-        + "ds-cfg-synchronization-provider-enabled: true\n"
-        + "ds-cfg-synchronization-provider-class: org.opends.server.synchronization.MultimasterSynchronization\n";
-    synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
 
     // Change log
     String changeLogStringDN = "cn=Changelog Server, " + synchroPluginStringDN;
@@ -294,7 +286,8 @@
     changeLogEntry = TestCaseUtils.entryFromLdifString(changeLogLdif);
 
     // suffix synchronized
-    String synchroServerStringDN = "cn=example, " + synchroPluginStringDN;
+    String synchroServerStringDN =
+      "cn=example, cn=domains, " + synchroPluginStringDN;
     String synchroServerLdif = "dn: " + synchroServerStringDN + "\n"
         + "objectClass: top\n"
         + "objectClass: ds-cfg-synchronization-provider-config\n"
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ReSyncTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ReSyncTest.java
index 95917ec..b4bf994 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ReSyncTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ReSyncTest.java
@@ -89,14 +89,6 @@
     // Multimaster Synchro plugin
     synchroPluginStringDN = "cn=Multimaster Synchronization, "
         + synchroStringDN;
-    String synchroPluginLdif = "dn: "
-        + synchroPluginStringDN
-        + "\n"
-        + "objectClass: top\n"
-        + "objectClass: ds-cfg-synchronization-provider\n"
-        + "ds-cfg-synchronization-provider-enabled: true\n"
-        + "ds-cfg-synchronization-provider-class: org.opends.server.synchronization.MultimasterSynchronization\n";
-    synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
 
     // Change log
     String changeLogStringDN = "cn=Changelog Server, " + synchroPluginStringDN;
@@ -109,7 +101,8 @@
     changeLogEntry = TestCaseUtils.entryFromLdifString(changeLogLdif);
 
     // suffix synchronized
-    String synchroServerLdif = "dn: cn=example, " + synchroPluginStringDN + "\n"
+    String synchroServerLdif =
+      "dn: cn=example, cn=domains, " + synchroPluginStringDN + "\n"
         + "objectClass: top\n"
         + "objectClass: ds-cfg-synchronization-provider-config\n"
         + "cn: example\n"
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SchemaSynchronizationTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SchemaSynchronizationTest.java
index 561cf3e..142bcf1 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SchemaSynchronizationTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SchemaSynchronizationTest.java
@@ -38,6 +38,7 @@
 import java.util.List;
 
 import org.opends.server.TestCaseUtils;
+import org.opends.server.admin.std.server.SynchronizationProviderCfg;
 import org.opends.server.api.SynchronizationProvider;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.ModifyOperation;
@@ -98,14 +99,6 @@
     // Multimaster Synchro plugin
     synchroPluginStringDN = "cn=Multimaster Synchronization, "
         + synchroStringDN;
-    String synchroPluginLdif = "dn: "
-        + synchroPluginStringDN
-        + "\n"
-        + "objectClass: top\n"
-        + "objectClass: ds-cfg-synchronization-provider\n"
-        + "ds-cfg-synchronization-provider-enabled: true\n"
-        + "ds-cfg-synchronization-provider-class: org.opends.server.synchronization.MultimasterSynchronization\n";
-    synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
 
     // Change log
     String changeLogStringDN = "cn=Changelog Server, " + synchroPluginStringDN;
@@ -118,7 +111,8 @@
     changeLogEntry = TestCaseUtils.entryFromLdifString(changeLogLdif);
 
     // suffix synchronized
-    String synchroServerLdif = "dn: cn=example, " + synchroPluginStringDN + "\n"
+    String synchroServerLdif =
+      "dn: cn=example, cn=domains, " + synchroPluginStringDN + "\n"
         + "objectClass: top\n"
         + "objectClass: ds-cfg-synchronization-provider-config\n"
         + "cn: example\n"
@@ -276,7 +270,7 @@
     Modification mod = new Modification(ModificationType.ADD, attr);
     mods.add(mod);
 
-    for (SynchronizationProvider provider :
+    for (SynchronizationProvider<SynchronizationProviderCfg> provider :
          DirectoryServer.getSynchronizationProviders())
     {
       provider.processSchemaChange(mods);
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/StressTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/StressTest.java
index 44b8188..9f91a5a 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/StressTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/StressTest.java
@@ -231,14 +231,6 @@
     // Multimaster Synchro plugin
     synchroPluginStringDN = "cn=Multimaster Synchronization, "
         + synchroStringDN;
-    String synchroPluginLdif = "dn: "
-        + synchroPluginStringDN
-        + "\n"
-        + "objectClass: top\n"
-        + "objectClass: ds-cfg-synchronization-provider\n"
-        + "ds-cfg-synchronization-provider-enabled: true\n"
-        + "ds-cfg-synchronization-provider-class: org.opends.server.synchronization.MultimasterSynchronization\n";
-    synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
 
     // Change log
     changeLogStringDN = "cn=Changelog Server, " + synchroPluginStringDN;
@@ -250,7 +242,7 @@
     changeLogEntry = TestCaseUtils.entryFromLdifString(changeLogLdif);
 
     // suffix synchronized
-    synchroServerStringDN = "cn=example, " + synchroPluginStringDN;
+    synchroServerStringDN = "cn=example, cn=domains, " + synchroPluginStringDN;
     String synchroServerLdif = "dn: " + synchroServerStringDN + "\n"
         + "objectClass: top\n"
         + "objectClass: ds-cfg-synchronization-provider-config\n"
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationTestCase.java
index 7374e38..da0c40b 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationTestCase.java
@@ -28,7 +28,6 @@
 
 import static org.opends.server.loggers.Error.logError;
 import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
 import java.net.SocketException;
@@ -41,8 +40,6 @@
 import org.opends.server.DirectoryServerTestCase;
 import org.opends.server.TestCaseUtils;
 import org.opends.server.schema.IntegerSyntax;
-import org.opends.server.config.ConfigEntry;
-import org.opends.server.config.ConfigException;
 import org.opends.server.core.DeleteOperation;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.protocols.internal.InternalClientConnection;
@@ -50,7 +47,6 @@
 import org.opends.server.protocols.ldap.LDAPFilter;
 import org.opends.server.synchronization.common.ServerState;
 import org.opends.server.synchronization.plugin.ChangelogBroker;
-import org.opends.server.synchronization.plugin.MultimasterSynchronization;
 import org.opends.server.synchronization.plugin.PersistentServerState;
 import org.opends.server.types.DN;
 import org.opends.server.types.Entry;
@@ -84,8 +80,7 @@
    * Created entries that need to be deleted for cleanup
    */
   protected LinkedList<DN> entryList = new LinkedList<DN>();
-
-  protected Entry synchroPluginEntry;
+  protected LinkedList<DN> configEntryList = new LinkedList<DN>();
 
   protected Entry synchroServerEntry;
 
@@ -97,14 +92,10 @@
   protected boolean schemaCheck;
 
   /**
-   *
-   */
-  MultimasterSynchronization mms = null;
-
-  /**
    * The synchronization plugin entry
    */
-  protected String synchroPluginStringDN;
+  protected String synchroPluginStringDN =
+    "cn=Multimaster Synchronization, cn=Synchronization Providers,cn=config";
 
   /**
    * Set up the environment for performing the tests in this suite.
@@ -228,20 +219,19 @@
         }
       }
       catch (Exception e)
-      { 
-      }
+      { }
     }
     return broker;
   }
 
   /**
-   * suppress all the entries created by the tests in this class
+   * suppress all the config entries created by the tests in this class
    */
-  protected void cleanEntries()
+  protected void cleanConfigEntries()
   {
     logError(ErrorLogCategory.SYNCHRONIZATION,
         ErrorLogSeverity.NOTICE,
-        "SynchronizationTestCase/Cleaning entries" , 1);
+        "SynchronizationTestCase/Cleaning config entries" , 1);
 
     DeleteOperation op;
     // Delete entries
@@ -249,6 +239,38 @@
     {
       while (true)
       {
+        DN dn = configEntryList.removeLast();
+             logError(ErrorLogCategory.SYNCHRONIZATION,
+            ErrorLogSeverity.NOTICE,
+            "cleaning config entry " + dn, 1);
+        
+        op = new DeleteOperation(connection, InternalClientConnection
+            .nextOperationID(), InternalClientConnection.nextMessageID(), null,
+            dn);
+
+        op.run();
+      }
+    }
+    catch (NoSuchElementException e) {
+      // done
+    }
+  }
+  
+  /**
+   * suppress all the real entries created by the tests in this class
+   */
+  protected void cleanRealEntries()
+  {
+  	logError(ErrorLogCategory.SYNCHRONIZATION,
+        ErrorLogSeverity.NOTICE,
+        "SynchronizationTestCase/Cleaning entries" , 1);
+  
+    DeleteOperation op;
+    // Delete entries
+    try
+    {
+      while (true)
+      {
         DN dn = entryList.removeLast();
         logError(ErrorLogCategory.SYNCHRONIZATION,
             ErrorLogSeverity.NOTICE,
@@ -277,20 +299,8 @@
   {
     DirectoryServer.setCheckSchema(schemaCheck);
 
-    // WORKAROUND FOR BUG #639 - BEGIN -
-    if (mms != null)
-    {
-      logError(ErrorLogCategory.SYNCHRONIZATION,
-          ErrorLogSeverity.NOTICE,
-          "SynchronizationTestCase/FinalizeSynchronization Provider" , 1);
-
-      DirectoryServer.deregisterSynchronizationProvider(mms);
-      mms.finalizeSynchronizationProvider();
-      mms = null;
-    }
-    // WORKAROUND FOR BUG #639 - END -
-
-    cleanEntries();
+    cleanConfigEntries();
+    cleanRealEntries();
   }
 
   /**
@@ -298,48 +308,45 @@
    */
   protected void configureSynchronization() throws Exception
   {
-    //
     // Add the Multimaster synchronization plugin
+    String synchroPluginLdif = "dn: " + synchroPluginStringDN + "\n"
+         + "objectClass: top\n"
+         + "objectClass: ds-cfg-synchronization-provider\n"
+         + "objectClass: ds-cfg-multimaster-synchronization-provider\n"
+         + "ds-cfg-synchronization-provider-enabled: true\n"
+         + "ds-cfg-synchronization-provider-class: " +
+         "org.opends.server.synchronization.plugin.MultimasterSynchronization\n";
+    Entry synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
     DirectoryServer.getConfigHandler().addEntry(synchroPluginEntry, null);
-    entryList.add(synchroPluginEntry.getDN());
+    configEntryList.add(synchroPluginEntry.getDN());
     assertNotNull(DirectoryServer.getConfigEntry(DN
         .decode(synchroPluginStringDN)),
         "Unable to add the Multimaster synchronization plugin");
-
-    // WORKAROUND FOR BUG #639 - BEGIN -
-    DN dn = DN.decode(synchroPluginStringDN);
-    ConfigEntry mmsConfigEntry = DirectoryServer.getConfigEntry(dn);
-    mms = new MultimasterSynchronization();
-    try
-    {
-      mms.initializeSynchronizationProvider(mmsConfigEntry);
-    }
-    catch (ConfigException e)
-    {
-      assertTrue(false,
-          "Unable to initialize the Multimaster synchronization plugin");
-    }
-    DirectoryServer.registerSynchronizationProvider(mms);
-    // WORKAROUND FOR BUG #639 - END -
-
-    //
-    // Add the changelog server
-    if (changeLogEntry!=null)
-    {
-      DirectoryServer.getConfigHandler().addEntry(changeLogEntry, null);
-      assertNotNull(DirectoryServer.getConfigEntry(changeLogEntry.getDN()),
-        "Unable to add the changeLog server");
-      entryList.add(changeLogEntry.getDN());
-    }
     
-    if (synchroServerEntry!=null)
-    {
-      // We also have a replicated suffix (synchronization domain)
-      DirectoryServer.getConfigHandler().addEntry(synchroServerEntry, null);
-      assertNotNull(DirectoryServer.getConfigEntry(synchroServerEntry.getDN()),
-      "Unable to add the synchronized suffix");
-      entryList.add(synchroServerEntry.getDN());
-    }
+    // domains container entry.
+    String domainsLdif = "dn: "
+      + "cn=domains," + synchroPluginStringDN + "\n"
+      + "objectClass: top\n"
+      + "objectClass: ds-cfg-branch\n";
+    Entry domainsEntry = TestCaseUtils.entryFromLdifString(domainsLdif);
+    DirectoryServer.getConfigHandler().addEntry(domainsEntry, null);
+    configEntryList.add(domainsEntry.getDN());
+    assertNotNull(DirectoryServer.getConfigEntry(
+      DN.decode(synchroPluginStringDN)),
+      "Unable to add the Multimaster synchronization plugin");
+      
+
+    // Add the changelog server
+    DirectoryServer.getConfigHandler().addEntry(changeLogEntry, null);
+    assertNotNull(DirectoryServer.getConfigEntry(changeLogEntry.getDN()),
+       "Unable to add the changeLog server");
+    configEntryList.add(changeLogEntry.getDN());
+
+    // We also have a replicated suffix (synchronization domain)
+    DirectoryServer.getConfigHandler().addEntry(synchroServerEntry, null);
+    assertNotNull(DirectoryServer.getConfigEntry(synchroServerEntry.getDN()),
+        "Unable to add the synchronized server");
+    configEntryList.add(synchroServerEntry.getDN());
   }
 
   /**
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/UpdateOperationTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/UpdateOperationTest.java
index 7e7411e..95cb27d 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/UpdateOperationTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/UpdateOperationTest.java
@@ -133,14 +133,6 @@
     // Multimaster Synchro plugin
     synchroPluginStringDN = "cn=Multimaster Synchronization, "
         + synchroStringDN;
-    String synchroPluginLdif = "dn: "
-        + synchroPluginStringDN
-        + "\n"
-        + "objectClass: top\n"
-        + "objectClass: ds-cfg-synchronization-provider\n"
-        + "ds-cfg-synchronization-provider-enabled: true\n"
-        + "ds-cfg-synchronization-provider-class: org.opends.server.synchronization.MultimasterSynchronization\n";
-    synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
 
     // Change log
     String changeLogStringDN = "cn=Changelog Server, " + synchroPluginStringDN;
@@ -152,7 +144,8 @@
     changeLogEntry = TestCaseUtils.entryFromLdifString(changeLogLdif);
 
     // suffix synchronized
-    String synchroServerStringDN = "cn=example, " + synchroPluginStringDN;
+    String synchroServerStringDN =
+      "cn=example, cn=domains, " + synchroPluginStringDN;
     String synchroServerLdif = "dn: " + synchroServerStringDN + "\n"
         + "objectClass: top\n"
         + "objectClass: ds-cfg-synchronization-provider-config\n"
@@ -318,7 +311,7 @@
         ErrorLogSeverity.NOTICE,
         "Starting synchronization test : lostHeartbeatFailover" , 1);
 
-    cleanEntries();
+    cleanRealEntries();
 
     final DN baseDn = DN.decode("ou=People,dc=example,dc=com");
 
@@ -831,7 +824,7 @@
 
     final DN baseDn = DN.decode("ou=People,dc=example,dc=com");
 
-    cleanEntries();
+    cleanRealEntries();
 
     ChangelogBroker broker =
       openChangelogSession(baseDn, (short) 27, 100, 8989, 1000, true);
@@ -886,7 +879,7 @@
       "The received synchronization message is not a MODIFY msg");
       ModifyMsg modMsg = (ModifyMsg) msg;
 
-      Operation receivedOp = modMsg.createOperation(connection);
+      modMsg.createOperation(connection);
       assertTrue(DN.decode(modMsg.getDn()).compareTo(personEntry.getDN()) == 0,
       "The received MODIFY synchronization message is not for the excepted DN");
 
@@ -908,7 +901,7 @@
       assertTrue(msg instanceof ModifyDNMsg,
       "The received synchronization message is not a MODIFY DN msg");
       ModifyDNMsg moddnMsg = (ModifyDNMsg) msg;
-      receivedOp = moddnMsg.createOperation(connection);
+      moddnMsg.createOperation(connection);
 
       assertTrue(DN.decode(moddnMsg.getDn()).compareTo(personEntry.getDN()) == 0,
       "The received MODIFY_DN message is not for the excepted DN");
@@ -927,7 +920,7 @@
       assertTrue(msg instanceof DeleteMsg,
       "The received synchronization message is not a MODIFY DN msg");
       DeleteMsg delMsg = (DeleteMsg) msg;
-      receivedOp = delMsg.createOperation(connection);
+      delMsg.createOperation(connection);
       assertTrue(DN.decode(delMsg.getDn()).compareTo(DN
           .decode("uid= new person,ou=People,dc=example,dc=com")) == 0,
       "The received DELETE message is not for the excepted DN");
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogFakeConfiguration.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogFakeConfiguration.java
new file mode 100644
index 0000000..1ff7a5e
--- /dev/null
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogFakeConfiguration.java
@@ -0,0 +1,190 @@
+/*
+ * 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 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.synchronization.changelog;
+
+import java.util.SortedSet;
+
+import org.opends.server.admin.ManagedObjectDefinition;
+import org.opends.server.admin.PropertyProvider;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.client.ChangelogServerCfgClient;
+import org.opends.server.admin.std.server.ChangelogServerCfg;
+import org.opends.server.types.DN;
+
+/**
+ * This Class implements an object that can be used to instantiate
+ * The Changelog class for tests purpose.
+ */
+public class ChangelogFakeConfiguration implements ChangelogServerCfg
+{
+  int port;
+  String dirName;
+  int purgeDelay;
+  int serverId;
+  int queueSize;
+  int windowSize;
+  private SortedSet<String> servers;
+
+  public ChangelogFakeConfiguration(
+      int port, String dirName, int purgeDelay, int serverId,
+      int queueSize, int windowSize, SortedSet<String> servers)
+  {
+    this.port    = port;
+    this.dirName = dirName;
+    
+    if (purgeDelay == 0)
+    {
+      this.purgeDelay = 24*60*60;
+    }
+    else
+    {
+      this.purgeDelay = purgeDelay;
+    }
+
+    this.serverId = serverId;
+    
+    if (queueSize == 0)
+    {
+      this.queueSize = 10000;
+    }
+    else
+    {
+      this.queueSize = queueSize;
+    }
+
+    if (windowSize == 0)
+    {
+      this.windowSize = 100;
+    }
+    else
+    {
+      this.windowSize = windowSize;
+    }
+
+    this.servers = servers;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void addChangeListener(
+      ConfigurationChangeListener<ChangelogServerCfg> listener)
+  {
+
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public ManagedObjectDefinition<? extends ChangelogServerCfgClient,
+                                 ? extends ChangelogServerCfg> definition()
+  {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getChangelogDbDirectory()
+  {
+    return dirName;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public int getChangelogPort()
+  {
+    return port;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public long getChangelogPurgeDelay()
+  {
+    return purgeDelay;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public SortedSet<String> getChangelogServer()
+  {
+     return servers;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public int getChangelogServerId()
+  {
+    return serverId;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public int getQueueSize()
+  {
+    return queueSize;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public int getWindowSize()
+  {
+    return windowSize;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void removeChangeListener(
+      ConfigurationChangeListener<ChangelogServerCfg> listener)
+  {
+
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public DN dn()
+  {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public PropertyProvider properties()
+  {
+    return null;
+  }
+
+}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogTest.java
index dcf23e0..27e5382 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogTest.java
@@ -34,9 +34,10 @@
 import java.net.ServerSocket;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
 
 import org.opends.server.TestCaseUtils;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.core.ModifyDNOperation;
 import org.opends.server.synchronization.SynchronizationTestCase;
 import org.opends.server.synchronization.common.ChangeNumber;
@@ -98,17 +99,9 @@
     changelogPort = socket.getLocalPort();
     socket.close();
 
-    String changelogLdif =
-      "dn: cn=Changelog Server\n"
-        + "objectClass: top\n"
-        + "objectClass: ds-cfg-synchronization-changelog-server-config\n"
-        + "cn: Changelog Server\n"
-        + "ds-cfg-changelog-port: "+ changelogPort + "\n"
-        + "ds-cfg-changelog-server-id: 1\n"
-        + "ds-cfg-window-size: 100";
-    Entry tmp = TestCaseUtils.entryFromLdifString(changelogLdif);
-    ConfigEntry changelogConfig = new ConfigEntry(tmp, null);
-    changelog = new Changelog(changelogConfig);
+    ChangelogFakeConfiguration conf =
+      new ChangelogFakeConfiguration(changelogPort, null, 0, 1, 0, 0, null); 
+    changelog = new Changelog(conf);
   }
 
   /**
@@ -602,19 +595,13 @@
         // for itest=0, create the 2 connected changelog servers
         // for itest=1, create the 1rst changelog server, the second
         // one will be created later
-
-        String changelogLdif = "dn: cn=Changelog Server\n"
-          + "objectClass: top\n"
-          + "objectClass: ds-cfg-synchronization-changelog-server-config\n"
-          + "cn: Changelog Server\n"
-          + "ds-cfg-changelog-port: " + changelogPorts[i] + "\n"
-          + "ds-cfg-changelog-server: localhost:" + ((i == 0) ? changelogPorts[1] : changelogPorts[0]) + "\n"
-          + "ds-cfg-changelog-server-id: " + changelogIds[0] + "\n"
-          + "ds-cfg-window-size: 100" + "\n"
-          + "ds-cfg-changelog-db-directory: changelogDb"+i;
-        Entry tmp = TestCaseUtils.entryFromLdifString(changelogLdif);
-        ConfigEntry changelogConfig = new ConfigEntry(tmp, null);
-        changelogs[i] = new Changelog(changelogConfig);
+        SortedSet<String> servers = new TreeSet<String>();
+        servers.add(
+          "localhost:" + ((i == 0) ? changelogPorts[1] : changelogPorts[0]));
+        ChangelogFakeConfiguration conf =
+          new ChangelogFakeConfiguration(changelogPorts[i], "changelogDb"+i, 0,
+                                         changelogIds[i], 0, 100, servers); 
+        changelog = new Changelog(conf);
       }
 
       ChangelogBroker broker1 = null;
@@ -681,16 +668,13 @@
         if (itest > 0)
         {
           socket.close();
-          String changelogLdif = "dn: cn=Changelog Server\n"
-            + "objectClass: top\n"
-            + "objectClass: ds-cfg-synchronization-changelog-server-config\n"
-            + "cn: Changelog Server\n"
-            + "ds-cfg-changelog-port: " + changelogPorts[1] + "\n"
-            + "ds-cfg-changelog-server: localhost:" + changelogPorts[0] + "\n"
-            + "ds-cfg-changelog-server-id: " + changelogIds[1] + "\n";
-          Entry tmp = TestCaseUtils.entryFromLdifString(changelogLdif);
-          ConfigEntry changelogConfig = new ConfigEntry(tmp, null);
-          changelogs[1] = new Changelog(changelogConfig);
+          
+          SortedSet<String> servers = new TreeSet<String>();
+          servers.add("localhost:"+changelogPorts[0]);
+          ChangelogFakeConfiguration conf =
+            new ChangelogFakeConfiguration(changelogPorts[1], null, 0,
+                                           changelogIds[1], 0, 0, null); 
+          changelogs[1] = new Changelog(conf);
 
           // Connect broker 2 to changelog2
           broker2 = openChangelogSession(DN.decode("dc=example,dc=com"),
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/dbHandlerTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/dbHandlerTest.java
index 5c13f9a..00174da 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/dbHandlerTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/dbHandlerTest.java
@@ -30,13 +30,11 @@
 import java.net.ServerSocket;
 
 import org.opends.server.TestCaseUtils;
-import org.opends.server.config.ConfigEntry;
 import org.opends.server.synchronization.SynchronizationTestCase;
 import org.opends.server.synchronization.common.ChangeNumber;
 import org.opends.server.synchronization.common.ChangeNumberGenerator;
 import org.opends.server.synchronization.protocol.DeleteMsg;
 import org.opends.server.types.DN;
-import org.opends.server.types.Entry;
 import org.testng.annotations.Test;
 import static org.testng.Assert.*;
 
@@ -56,17 +54,10 @@
     socket.close();
 
     // configure a Changelog server.
-    String changelogLdif =
-      "dn: cn=Changelog Server\n"
-        + "objectClass: top\n"
-        + "objectClass: ds-cfg-synchronization-changelog-server-config\n"
-        + "cn: Changelog Server\n"
-        + "ds-cfg-changelog-port: "+ changelogPort + "\n"
-        + "ds-cfg-changelog-server-id: 2\n"
-        + "ds-cfg-changelog-purge-delay: 0 d";
-    Entry tmp = TestCaseUtils.entryFromLdifString(changelogLdif);
-    ConfigEntry changelogConfig = new ConfigEntry(tmp, null);
-    Changelog changelog = new Changelog(changelogConfig);
+    ChangelogFakeConfiguration conf =
+      new ChangelogFakeConfiguration(changelogPort, null, 0,
+                                     2, 0, 100, null); 
+    Changelog changelog = new Changelog(conf);
 
     // create or clean a directory for the dbHandler
     String buildRoot = System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT);
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/HistoricalTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/HistoricalTest.java
index 08ad95f..95b54a8 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/HistoricalTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/HistoricalTest.java
@@ -67,22 +67,6 @@
     // Create an internal connection.
     connection = InternalClientConnection.getRootConnection();
 
-    // Top level synchronization provider.
-    String synchroStringDN = "cn=Synchronization Providers,cn=config";
-
-    // Multimaster synchronization plugin.
-    synchroPluginStringDN = "cn=Multimaster Synchronization, "
-         + synchroStringDN;
-    String synchroPluginLdif = "dn: "
-         + synchroPluginStringDN
-         + "\n"
-         + "objectClass: top\n"
-         + "objectClass: ds-cfg-synchronization-provider\n"
-         + "ds-cfg-synchronization-provider-enabled: true\n"
-         + "ds-cfg-synchronization-provider-class: " +
-         "org.opends.server.synchronization.MultimasterSynchronization\n";
-    synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
-
     // The synchronization server.
     String changeLogStringDN = "cn=Changelog Server, " + synchroPluginStringDN;
     String changeLogLdif = "dn: " + changeLogStringDN + "\n"
@@ -93,7 +77,7 @@
     changeLogEntry = TestCaseUtils.entryFromLdifString(changeLogLdif);
 
     // The suffix to be synchronized.
-    String synchroServerStringDN = "o=test, " + synchroPluginStringDN;
+    String synchroServerStringDN = "o=test, cn=domains, " + synchroPluginStringDN;
     String synchroServerLdif = "dn: " + synchroServerStringDN + "\n"
          + "objectClass: top\n"
          + "objectClass: ds-cfg-synchronization-provider-config\n"
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/ModifyConflictTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/ModifyConflictTest.java
index 9b8f009..b7762e7 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/ModifyConflictTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/ModifyConflictTest.java
@@ -38,7 +38,6 @@
 
 import static org.opends.server.synchronization.protocol.OperationContext.*;
 
-import org.opends.server.TestAccessLogger;
 import org.opends.server.core.AddOperation;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.ModifyOperation;

--
Gitblit v1.10.0