From e13a57df8301091f093cf0b1a16527da8f9b3926 Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Wed, 27 Aug 2014 08:29:16 +0000
Subject: [PATCH] OPENDJ-1206 (CR-4368) Create a new ReplicationBackend/ChangelogBackend to support cn=changelog

---
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/TestChangeNotificationListener.java |  136 +-
 opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java                                        |  105 --
 opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java       |   21 
 opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java    |   23 
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/DeleteOperationTestCase.java        |  218 ++--
 opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyDNOperation.java  |   23 
 /dev/null                                                                                                       |  134 ---
 opendj-sdk/opends/src/server/org/opends/server/util/CollectionUtils.java                                        |  109 ++
 opendj-sdk/opends/src/server/org/opends/server/crypto/CryptoManagerSync.java                                    |  317 +++----
 opendj-sdk/opends/src/server/org/opends/server/types/DirectoryConfig.java                                       |   48 -
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/ModifyOperationTestCase.java        |  262 ++---
 opendj-sdk/opends/src/server/org/opends/server/core/AuthenticatedUsers.java                                     |  204 ++--
 opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendDeleteOperation.java    |   22 
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/AddOperationTestCase.java           |  887 ++++++--------------
 14 files changed, 922 insertions(+), 1,587 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/ChangeNotificationListener.java b/opendj-sdk/opends/src/server/org/opends/server/api/ChangeNotificationListener.java
deleted file mode 100644
index bd0e883..0000000
--- a/opendj-sdk/opends/src/server/org/opends/server/api/ChangeNotificationListener.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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 legal-notices/CDDLv1_0.txt
- * or http://forgerock.org/license/CDDLv1.0.html.
- * 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 legal-notices/CDDLv1_0.txt.
- * 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
- *
- *
- *      Copyright 2006-2008 Sun Microsystems, Inc.
- */
-package org.opends.server.api;
-
-
-
-import org.opends.server.types.Entry;
-import org.opends.server.types.operation.PostResponseAddOperation;
-import org.opends.server.types.operation.PostResponseDeleteOperation;
-import org.opends.server.types.operation.PostResponseModifyOperation;
-import org.opends.server.types.operation.
-            PostResponseModifyDNOperation;
-
-
-
-/**
- * This interface defines a mechanism that Directory Server components
- * may use if they need to be notified of changes that are made in the
- * Directory Server.  Similar functionality can be achieved using
- * post-response plugins, but this interface is better suited to core
- * functionality that should not be considered optional, since plugins
- * may be disabled.  Further, change notification listeners will only
- * be invoked for successful operations.
- * <BR><BR>
- * Each change notification listener will be notified whenever an
- * update is made in the server (just before the response is sent to
- * the client), so the listener should use a very efficient mechanism
- * for determining whether or not any action is required for the
- * associated operation and quickly return for cases in which the
- * update is not applicable.  Also note that even though the listener
- * will be invoked before the response is sent to the client, it may
- * not alter that response in any way and therefore the listener will
- * be given what is essentially a read-only view of the associated
- * operation.
- * <BR><BR>
- * Note that while this interface can be used by clients to be
- * notified of changes to the configuration data just as easily as it
- * can be used for any other entry anywhere in the server, components
- * that are only interested in being notified of changes to the server
- * configuration should use the {@code ConfigAddListener},
- * {@code ConfigDeleteListener}, and/or the
- * {@code ConfigChangeListener} interfaces instead.  They will be more
- * efficient overall because they will only be invoked for operations
- * in the server configuration, and then only for the specific entries
- * with which the component has registered.
- */
-@org.opends.server.types.PublicAPI(
-     stability=org.opends.server.types.StabilityLevel.VOLATILE,
-     mayInstantiate=false,
-     mayExtend=true,
-     mayInvoke=false)
-public interface ChangeNotificationListener
-{
-  /**
-   * Performs any processing that may be required after an add
-   * operation.
-   *
-   * @param  addOperation  The add operation that was performed in the
-   *                       server.
-   * @param  entry         The entry that was added to the server.
-   */
-  public void handleAddOperation(
-                   PostResponseAddOperation addOperation,
-                   Entry entry);
-
-
-
-  /**
-   * Performs any processing that may be required after a delete
-   * operation.
-   *
-   * @param  deleteOperation  The delete operation that was performed
-   *                          in the server.
-   * @param  entry            The entry that was removed from the
-   *                          server.
-   */
-  public void handleDeleteOperation(
-                   PostResponseDeleteOperation deleteOperation,
-                   Entry entry);
-
-
-
-  /**
-   * Performs any processing that may be required after a modify
-   * operation.
-   *
-   * @param  modifyOperation  The modify operation that was performed
-   *                          in the server.
-   * @param  oldEntry         The entry before it was updated.
-   * @param  newEntry         The entry after it was updated.
-   */
-  public void handleModifyOperation(
-                   PostResponseModifyOperation modifyOperation,
-                   Entry oldEntry, Entry newEntry);
-
-
-
-  /**
-   * Performs any processing that may be required after a modify DN
-   * operation.
-   *
-   * @param  modifyDNOperation  The modify DN operation that was
-   *                            performed in the server.
-   * @param  oldEntry           The entry before it was updated.
-   * @param  newEntry           The entry after it was updated.
-   */
-  public void handleModifyDNOperation(
-                   PostResponseModifyDNOperation modifyDNOperation,
-                   Entry oldEntry, Entry newEntry);
-}
-
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/AuthenticatedUsers.java b/opendj-sdk/opends/src/server/org/opends/server/core/AuthenticatedUsers.java
index 050d1b6..7127119 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/AuthenticatedUsers.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/AuthenticatedUsers.java
@@ -22,32 +22,29 @@
  *
  *
  *      Copyright 2008-2010 Sun Microsystems, Inc.
- *      Portions copyright 2011 ForgeRock AS
+ *      Portions copyright 2011-2014 ForgeRock AS
  */
 package org.opends.server.core;
+
+import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.Set;
-import org.opends.messages.Message;
-
-
-
 import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
-import org.opends.server.api.ChangeNotificationListener;
+import org.opends.messages.Message;
 import org.opends.server.api.ClientConnection;
 import org.opends.server.api.DITCacheMap;
+import org.opends.server.api.plugin.InternalDirectoryServerPlugin;
+import org.opends.server.api.plugin.PluginResult.PostResponse;
 import org.opends.server.loggers.debug.DebugTracer;
-import org.opends.server.types.DisconnectReason;
-import org.opends.server.types.DN;
-import org.opends.server.types.DebugLogLevel;
-import org.opends.server.types.Entry;
-import org.opends.server.types.operation.PostResponseAddOperation;
+import org.opends.server.types.*;
 import org.opends.server.types.operation.PostResponseDeleteOperation;
-import org.opends.server.types.operation.PostResponseModifyOperation;
 import org.opends.server.types.operation.PostResponseModifyDNOperation;
+import org.opends.server.types.operation.PostResponseModifyOperation;
 
 import static org.opends.messages.CoreMessages.*;
+import static org.opends.server.api.plugin.PluginType.*;
 import static org.opends.server.loggers.debug.DebugLogger.*;
 
 /**
@@ -60,34 +57,52 @@
  * user entries and notifying the corresponding client connections so that they
  * can update their cached versions.
  */
-public class AuthenticatedUsers
-       implements ChangeNotificationListener
+public class AuthenticatedUsers extends InternalDirectoryServerPlugin
 {
   /**
    * The tracer object for the debug logger.
    */
   private static final DebugTracer TRACER = getTracer();
 
-  // The mapping between authenticated user DNs and the associated client
-  // connection objects.
-  private DITCacheMap<CopyOnWriteArraySet<ClientConnection>> userMap;
+  /**
+   * The mapping between authenticated user DNs and the associated client
+   * connection objects.
+   */
+  private final DITCacheMap<CopyOnWriteArraySet<ClientConnection>> userMap;
 
-  // Lock to protect internal data structures.
+  /** Lock to protect internal data structures. */
   private final ReentrantReadWriteLock lock;
 
+  /** Dummy configuration DN. */
+  private static final String CONFIG_DN = "cn=Authenticated Users,cn=config";
 
   /**
    * Creates a new instance of this authenticated users object.
    */
   public AuthenticatedUsers()
   {
+    super(toDN(CONFIG_DN), EnumSet.of(
+        // No implementation is required for add operations, since a connection
+        // can not be authenticated as a user that does not exist yet.
+        POST_RESPONSE_MODIFY, POST_RESPONSE_MODIFY_DN, POST_RESPONSE_DELETE),
+        true);
     userMap = new DITCacheMap<CopyOnWriteArraySet<ClientConnection>>();
     lock = new ReentrantReadWriteLock();
 
-    DirectoryServer.registerChangeNotificationListener(this);
+    DirectoryServer.registerInternalPlugin(this);
   }
 
-
+  private static DN toDN(String dn)
+  {
+    try
+    {
+      return DN.decode(dn);
+    }
+    catch (DirectoryException e)
+    {
+      throw new RuntimeException(e);
+    }
+  }
 
   /**
    * Registers the provided user DN and client connection with this object.
@@ -102,8 +117,7 @@
     lock.writeLock().lock();
     try
     {
-      CopyOnWriteArraySet<ClientConnection> connectionSet =
-              userMap.get(userDN);
+      CopyOnWriteArraySet<ClientConnection> connectionSet = userMap.get(userDN);
       if (connectionSet == null)
       {
         connectionSet = new CopyOnWriteArraySet<ClientConnection>();
@@ -136,8 +150,7 @@
     lock.writeLock().lock();
     try
     {
-      CopyOnWriteArraySet<ClientConnection> connectionSet =
-              userMap.get(userDN);
+      CopyOnWriteArraySet<ClientConnection> connectionSet = userMap.get(userDN);
       if (connectionSet != null)
       {
         connectionSet.remove(clientConnection);
@@ -179,89 +192,59 @@
     }
   }
 
-
-
-  /**
-   * Performs any processing that may be required after an add
-   * operation.
-   *
-   * @param  addOperation  The add operation that was performed in the
-   *                       server.
-   * @param  entry         The entry that was added to the server.
-   */
-  public void handleAddOperation(
-                   PostResponseAddOperation addOperation,
-                   Entry entry)
+  /** {@inheritDoc} */
+  @Override
+  public PostResponse doPostResponse(PostResponseDeleteOperation op)
   {
-    // No implementation is required for add operations, since a connection
-    // can't be authenticated as a user that doesn't exist yet.
-  }
+    if (op.getResultCode() != ResultCode.SUCCESS) {
+      return PostResponse.continueOperationProcessing();
+    }
 
-
-
-  /**
-   * Performs any processing that may be required after a delete
-   * operation.
-   *
-   * @param  deleteOperation  The delete operation that was performed
-   *                          in the server.
-   * @param  entry            The entry that was removed from the
-   *                          server.
-   */
-  public void handleDeleteOperation(
-                   PostResponseDeleteOperation deleteOperation,
-                   Entry entry)
-  {
+    final DN entryDN = op.getEntryDN();
     // Identify any client connections that may be authenticated
-    // or authorized as the user whose entry has been deleted and
-    // terminate them.
+    // or authorized as the user whose entry has been deleted and terminate them
     Set<CopyOnWriteArraySet<ClientConnection>> arraySet =
             new HashSet<CopyOnWriteArraySet<ClientConnection>>();
     lock.writeLock().lock();
     try
     {
-      userMap.removeSubtree(entry.getDN(), arraySet);
+      userMap.removeSubtree(entryDN, arraySet);
     }
     finally
     {
       lock.writeLock().unlock();
     }
-    for (CopyOnWriteArraySet<ClientConnection>
-            connectionSet : arraySet)
+
+    for (CopyOnWriteArraySet<ClientConnection> connectionSet : arraySet)
     {
       for (ClientConnection conn : connectionSet)
       {
         Message message = WARN_CLIENTCONNECTION_DISCONNECT_DUE_TO_DELETE.get(
-                String.valueOf(entry.getDN()));
+                String.valueOf(entryDN));
 
         conn.disconnect(DisconnectReason.INVALID_CREDENTIALS, true, message);
       }
     }
+    return PostResponse.continueOperationProcessing();
   }
 
-
-
-  /**
-   * Performs any processing that may be required after a modify
-   * operation.
-   *
-   * @param  modifyOperation  The modify operation that was performed
-   *                          in the server.
-   * @param  oldEntry         The entry before it was updated.
-   * @param  newEntry         The entry after it was updated.
-   */
-  public void handleModifyOperation(
-                   PostResponseModifyOperation modifyOperation,
-                   Entry oldEntry, Entry newEntry)
+  /** {@inheritDoc} */
+  @Override
+  public PostResponse doPostResponse(PostResponseModifyOperation op)
   {
+    if (op.getResultCode() != ResultCode.SUCCESS) {
+      return PostResponse.continueOperationProcessing();
+    }
+
+    final Entry oldEntry = op.getCurrentEntry();
+    final Entry newEntry = op.getModifiedEntry();
     // Identify any client connections that may be authenticated
     // or authorized as the user whose entry has been modified
     // and update them with the latest version of the entry.
     lock.writeLock().lock();
     try
     {
-      CopyOnWriteArraySet<ClientConnection> connectionSet =
-           userMap.get(oldEntry.getDN());
+      CopyOnWriteArraySet<ClientConnection> connectionSet = userMap.get(oldEntry.getDN());
       if (connectionSet != null)
       {
         for (ClientConnection conn : connectionSet)
@@ -274,23 +257,19 @@
     {
       lock.writeLock().unlock();
     }
+    return PostResponse.continueOperationProcessing();
   }
 
-
-
-  /**
-   * Performs any processing that may be required after a modify DN
-   * operation.
-   *
-   * @param  modifyDNOperation  The modify DN operation that was
-   *                            performed in the server.
-   * @param  oldEntry           The entry before it was updated.
-   * @param  newEntry           The entry after it was updated.
-   */
-  public void handleModifyDNOperation(
-                   PostResponseModifyDNOperation modifyDNOperation,
-                   Entry oldEntry, Entry newEntry)
+  /** {@inheritDoc} */
+  @Override
+  public PostResponse doPostResponse(PostResponseModifyDNOperation op)
   {
+    if (op.getResultCode() != ResultCode.SUCCESS) {
+      return PostResponse.continueOperationProcessing();
+    }
+
+    Entry oldEntry = op.getOriginalEntry();
+    Entry newEntry = op.getUpdatedEntry();
     String oldDNString = oldEntry.getDN().toNormalizedString();
     String newDNString = newEntry.getDN().toNormalizedString();
 
@@ -303,8 +282,7 @@
       Set<CopyOnWriteArraySet<ClientConnection>> arraySet =
         new HashSet<CopyOnWriteArraySet<ClientConnection>>();
       userMap.removeSubtree(oldEntry.getDN(), arraySet);
-      for (CopyOnWriteArraySet<ClientConnection>
-              connectionSet : arraySet)
+      for (CopyOnWriteArraySet<ClientConnection> connectionSet : arraySet)
       {
         DN authNDN = null;
         DN authZDN = null;
@@ -319,17 +297,11 @@
             authNDN = conn.getAuthenticationInfo().getAuthenticationDN();
             try
             {
-              StringBuilder builder = new StringBuilder(
-                  authNDN.toNormalizedString());
-              int oldDNIndex = builder.lastIndexOf(oldDNString);
-              builder.replace(oldDNIndex, builder.length(),
-                      newDNString);
-              String newAuthNDNString = builder.toString();
-              newAuthNDN = DN.decode(newAuthNDNString);
+              newAuthNDN = getNewAuthDN(authNDN, oldDNString, newDNString);
             }
             catch (Exception e)
             {
-              // Shouldnt happen.
+              // Should not happen.
               if (debugEnabled())
               {
                 TRACER.debugCaught(DebugLogLevel.ERROR, e);
@@ -341,24 +313,18 @@
             authZDN = conn.getAuthenticationInfo().getAuthorizationDN();
             try
             {
-              StringBuilder builder = new StringBuilder(
-                  authZDN.toNormalizedString());
-              int oldDNIndex = builder.lastIndexOf(oldDNString);
-              builder.replace(oldDNIndex, builder.length(),
-                      newDNString);
-              String newAuthZDNString = builder.toString();
-              newAuthZDN = DN.decode(newAuthZDNString);
+              newAuthZDN = getNewAuthDN(authZDN, oldDNString, newDNString);
             }
             catch (Exception e)
             {
-              // Shouldnt happen.
+              // Should not happen.
               if (debugEnabled())
               {
                 TRACER.debugCaught(DebugLogLevel.ERROR, e);
               }
             }
           }
-          if ((newAuthNDN != null) && (authNDN != null) &&
+          if (newAuthNDN != null && authNDN != null &&
                authNDN.isDescendantOf(oldEntry.getDN()))
           {
             if (newAuthNSet == null)
@@ -368,7 +334,7 @@
             conn.getAuthenticationInfo().setAuthenticationDN(newAuthNDN);
             newAuthNSet.add(conn);
           }
-          if ((newAuthZDN != null) && (authZDN != null) &&
+          if (newAuthZDN != null && authZDN != null &&
                authZDN.isDescendantOf(oldEntry.getDN()))
           {
             if (newAuthZSet == null)
@@ -379,11 +345,11 @@
             newAuthZSet.add(conn);
           }
         }
-        if ((newAuthNDN != null) && (newAuthNSet != null))
+        if (newAuthNDN != null && newAuthNSet != null)
         {
           userMap.put(newAuthNDN, newAuthNSet);
         }
-        if ((newAuthZDN != null) && (newAuthZSet != null))
+        if (newAuthZDN != null && newAuthZSet != null)
         {
           userMap.put(newAuthZDN, newAuthZSet);
         }
@@ -393,6 +359,18 @@
     {
       lock.writeLock().unlock();
     }
+    return PostResponse.continueOperationProcessing();
+  }
+
+  private DN getNewAuthDN(DN authDN, String oldDNString, String newDNString) throws DirectoryException
+  {
+    // FIXME once we move to the SDK:
+    // Matt suggests we should be using the following code here:
+    // return authDN.rename(oldDNString, newDNString);
+    final StringBuilder builder = new StringBuilder(authDN.toNormalizedString());
+    final int oldDNIndex = builder.lastIndexOf(oldDNString);
+    builder.replace(oldDNIndex, builder.length(), newDNString);
+    return DN.decode(builder.toString());
   }
 }
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java b/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
index ae19c74..3d20d87 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -26,19 +26,6 @@
  */
 package org.opends.server.core;
 
-import static org.opends.messages.ConfigMessages.*;
-import static org.opends.messages.CoreMessages.*;
-import static org.opends.messages.ToolMessages.*;
-import static org.opends.server.config.ConfigConstants.*;
-import static org.opends.server.loggers.AccessLogger.*;
-import static org.opends.server.loggers.ErrorLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import static org.opends.server.schema.SchemaConstants.*;
-import static org.opends.server.util.DynamicConstants.*;
-import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
-import static org.opends.server.util.Validator.*;
-
 import java.io.*;
 import java.lang.management.ManagementFactory;
 import java.net.InetAddress;
@@ -94,6 +81,19 @@
 import org.opends.server.workflowelement.WorkflowElementConfigManager;
 import org.opends.server.workflowelement.localbackend.LocalBackendWorkflowElement;
 
+import static org.opends.messages.ConfigMessages.*;
+import static org.opends.messages.CoreMessages.*;
+import static org.opends.messages.ToolMessages.*;
+import static org.opends.server.config.ConfigConstants.*;
+import static org.opends.server.loggers.AccessLogger.*;
+import static org.opends.server.loggers.ErrorLogger.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.schema.SchemaConstants.*;
+import static org.opends.server.util.DynamicConstants.*;
+import static org.opends.server.util.ServerConstants.*;
+import static org.opends.server.util.StaticUtils.*;
+import static org.opends.server.util.Validator.*;
+
 /**
  * This class defines the core of the Directory Server.  It manages the startup
  * and shutdown processes and coordinates activities between all other
@@ -405,13 +405,6 @@
   /** The set of backup task listeners registered with the Directory Server. */
   private CopyOnWriteArrayList<BackupTaskListener> backupTaskListeners;
 
-  /**
-   * The set of change notification listeners registered with the Directory
-   * Server.
-   */
-  private List<ChangeNotificationListener>
-               changeNotificationListeners;
-
   /** The set of connection handlers registered with the Directory Server. */
   private List<ConnectionHandler> connectionHandlers;
 
@@ -922,8 +915,6 @@
       directoryServer.backendInitializationListeners =
            new CopyOnWriteArraySet<BackendInitializationListener>();
       directoryServer.baseDnRegistry = new BaseDnRegistry();
-      directoryServer.changeNotificationListeners =
-           new CopyOnWriteArrayList<ChangeNotificationListener>();
       directoryServer.initializationCompletedListeners =
            new CopyOnWriteArrayList<InitializationCompletedListener>();
       directoryServer.shutdownListeners =
@@ -941,7 +932,6 @@
            new ConcurrentHashMap<String,ExtendedOperationHandler>();
       directoryServer.saslMechanismHandlers =
            new ConcurrentHashMap<String,SASLMechanismHandler>();
-      directoryServer.authenticatedUsers = new AuthenticatedUsers();
       directoryServer.offlineSchemaChanges = new LinkedList<Modification>();
       directoryServer.backupTaskListeners =
            new CopyOnWriteArrayList<BackupTaskListener>();
@@ -1378,23 +1368,15 @@
       certificateMapperConfigManager.initializeCertificateMappers();
 
 
-      // Initialize the identity mappers.
       initializeIdentityMappers();
 
-
-      // Initialize the root DNs.
       rootDNConfigManager = new RootDNConfigManager();
       rootDNConfigManager.initializeRootDNs();
 
-
-      // Initialize the subentry manager.
+      directoryServer.authenticatedUsers = new AuthenticatedUsers();
+      // initialize both subentry manager and group manager for this backend.
       initializeSubentryManager();
-
-      // Initialize the group manager.
       initializeGroupManager();
-
-      // Now we can initialize both subentry manager and group manager
-      // for this backend.
       subentryManager.performBackendInitializationProcessing(configHandler);
       groupManager.performBackendInitializationProcessing(configHandler);
 
@@ -1424,14 +1406,9 @@
       // Reset the map as we can no longer guarantee offline state.
       directoryServer.offlineBackendsStateIDs.clear();
 
-      // Initialize all the extended operation handlers.
       initializeExtendedOperations();
-
-
-      // Initialize all the SASL mechanism handlers.
       initializeSASLMechanisms();
 
-
       // Initialize all the connection handlers
       // (including the administration connector).
       if (startConnectionHandlers)
@@ -1439,13 +1416,9 @@
         initializeConnectionHandlers();
       }
 
-
-      // Initialize all the monitor providers.
       monitorConfigManager = new MonitorConfigManager();
       monitorConfigManager.initializeMonitorProviders();
 
-
-      // Initialize all the authentication policy components.
       initializeAuthenticationPolicyComponents();
 
 
@@ -7155,54 +7128,6 @@
     return directoryServer.workQueue.trySubmitOperation(operation);
   }
 
-
-  /**
-   * Retrieves the set of change notification listeners registered with the
-   * Directory Server.
-   *
-   * @return  The set of change notification listeners registered with the
-   *          Directory Server.
-   */
-  public static List<ChangeNotificationListener>
-                     getChangeNotificationListeners()
-  {
-    return directoryServer.changeNotificationListeners;
-  }
-
-
-
-  /**
-   * Registers the provided change notification listener with the Directory
-   * Server so that it will be notified of any add, delete, modify, or modify DN
-   * operations that are performed.
-   *
-   * @param  changeListener  The change notification listener to register with
-   *                         the Directory Server.
-   */
-  public static void registerChangeNotificationListener(
-                          ChangeNotificationListener changeListener)
-  {
-    directoryServer.changeNotificationListeners.add(changeListener);
-  }
-
-
-
-  /**
-   * Deregisters the provided change notification listener with the Directory
-   * Server so that it will no longer be notified of any add, delete, modify, or
-   * modify DN operations that are performed.
-   *
-   * @param  changeListener  The change notification listener to deregister with
-   *                         the Directory Server.
-   */
-  public static void deregisterChangeNotificationListener(
-                          ChangeNotificationListener changeListener)
-  {
-    directoryServer.changeNotificationListeners.remove(changeListener);
-  }
-
-
-
   /**
    * Retrieves the set of synchronization providers that have been registered
    * with the Directory Server.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/crypto/CryptoManagerSync.java b/opendj-sdk/opends/src/server/org/opends/server/crypto/CryptoManagerSync.java
index 34ec46c..ff03eae 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/crypto/CryptoManagerSync.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/crypto/CryptoManagerSync.java
@@ -22,95 +22,93 @@
  *
  *
  *      Copyright 2008-2010 Sun Microsystems, Inc.
+ *      Portions Copyright 2014 ForgeRock AS
  */
-
 package org.opends.server.crypto;
 
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+
+import org.opends.admin.ads.ADSContext;
+import org.opends.messages.Message;
 import org.opends.server.api.Backend;
 import org.opends.server.api.BackendInitializationListener;
-import org.opends.server.api.ChangeNotificationListener;
-import org.opends.server.loggers.debug.DebugTracer;
-import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
-import static org.opends.server.loggers.debug.DebugLogger.getTracer;
+import org.opends.server.api.plugin.InternalDirectoryServerPlugin;
+import org.opends.server.api.plugin.PluginResult.PostResponse;
+import org.opends.server.config.ConfigConstants;
+import org.opends.server.controls.EntryChangeNotificationControl;
+import org.opends.server.controls.PersistentSearchChangeType;
+import org.opends.server.core.AddOperation;
+import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.DirectoryServer;
 import org.opends.server.loggers.ErrorLogger;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.protocols.internal.InternalClientConnection;
+import org.opends.server.protocols.internal.InternalSearchOperation;
+import org.opends.server.protocols.ldap.LDAPControl;
 import org.opends.server.types.*;
 import org.opends.server.types.operation.PostResponseAddOperation;
 import org.opends.server.types.operation.PostResponseDeleteOperation;
 import org.opends.server.types.operation.PostResponseModifyOperation;
-import org.opends.server.types.operation.PostResponseModifyDNOperation;
-import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
-import static org.opends.server.util.ServerConstants.OC_TOP;
-import static org.opends.server.util.ServerConstants.
-     OID_ENTRY_CHANGE_NOTIFICATION;
-import org.opends.server.config.ConfigConstants;
-import static org.opends.server.config.ConfigConstants.OC_CRYPTO_INSTANCE_KEY;
-import static org.opends.server.config.ConfigConstants.OC_CRYPTO_CIPHER_KEY;
-import static org.opends.server.config.ConfigConstants.OC_CRYPTO_MAC_KEY;
-import org.opends.server.protocols.internal.InternalClientConnection;
-import org.opends.server.protocols.internal.InternalSearchOperation;
-import org.opends.server.protocols.ldap.LDAPControl;
-import org.opends.server.controls.PersistentSearchChangeType;
-import org.opends.server.controls.EntryChangeNotificationControl;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.DeleteOperation;
-import org.opends.server.core.AddOperation;
-import static org.opends.messages.CoreMessages.*;
-import org.opends.messages.Message;
-import org.opends.admin.ads.ADSContext;
 
-import java.util.LinkedHashSet;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.HashMap;
+import static org.opends.messages.CoreMessages.*;
+import static org.opends.server.api.plugin.PluginType.*;
+import static org.opends.server.config.ConfigConstants.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.protocols.internal.InternalClientConnection.*;
+import static org.opends.server.util.ServerConstants.*;
+import static org.opends.server.util.StaticUtils.*;
 
 /**
  * This class defines an object that synchronizes certificates from the admin
  * data branch into the trust store backend, and synchronizes secret-key entries
  * from the admin data branch to the crypto manager secret-key cache.
  */
-public class CryptoManagerSync
-     implements BackendInitializationListener, ChangeNotificationListener
+public class CryptoManagerSync extends InternalDirectoryServerPlugin
+     implements BackendInitializationListener
 {
-  /**
-   * The debug log tracer for this object.
-   */
+  /** The debug log tracer for this object. */
   private static final DebugTracer TRACER = getTracer();
 
-
-
-  // The DN of the administration suffix.
+  /** The DN of the administration suffix. */
   private DN adminSuffixDN;
 
-  // The DN of the instance keys container within the admin suffix.
+  /** The DN of the instance keys container within the admin suffix. */
   private DN instanceKeysDN;
 
-  // The DN of the secret keys container within the admin suffix.
+  /** The DN of the secret keys container within the admin suffix. */
   private DN secretKeysDN;
 
-  // The DN of the trust store root.
+  /** The DN of the trust store root. */
   private DN trustStoreRootDN;
 
-  // The attribute type that is used to specify a server instance certificate.
-  AttributeType attrCert;
+  /** The attribute type that is used to specify a server instance certificate. */
+  private final AttributeType attrCert;
 
-  // The attribute type that holds a server certificate identifier.
-  AttributeType attrAlias;
+  /** The attribute type that holds a server certificate identifier. */
+  private final AttributeType attrAlias;
 
-  // The attribute type that holds the time a key was compromised.
-  AttributeType attrCompromisedTime;
+  /** The attribute type that holds the time a key was compromised. */
+  private final AttributeType attrCompromisedTime;
 
-  // A filter on object class to select key entries.
+  /** A filter on object class to select key entries. */
   private SearchFilter keySearchFilter;
 
-  // The instance key objectclass.
-  private ObjectClass ocInstanceKey;
+  /** The instance key objectclass. */
+  private final ObjectClass ocInstanceKey;
 
-  // The cipher key objectclass.
-  private ObjectClass ocCipherKey;
+  /** The cipher key objectclass. */
+  private final ObjectClass ocCipherKey;
 
-  // The mac key objectclass.
-  private ObjectClass ocMacKey;
+  /** The mac key objectclass. */
+  private final ObjectClass ocMacKey;
+
+  /** Dummy configuration DN. */
+  private static final String CONFIG_DN = "cn=Crypto Manager Sync,cn=config";
 
   /**
    * Creates a new instance of this trust store synchronization thread.
@@ -119,29 +117,17 @@
    * initialization, such as a failure to publish the instance-key-pair
    * public-key-certificate in ADS.
    */
-  public CryptoManagerSync()
-          throws InitializationException
+  public CryptoManagerSync() throws InitializationException
   {
-    this(true);
-  }
-
-  /**
-   * Creates a new instance of this trust store synchronization thread.
-   *
-   * @param publishInstanceKey whether the instance key must be published in
-   * the ADS or not.
-   * @throws InitializationException in case an exception occurs during
-   * initialization, such as a failure to publish the instance-key-pair
-   * public-key-certificate in ADS.
-   */
-  public CryptoManagerSync(boolean publishInstanceKey)
-  throws InitializationException
-  {
+    super(toDN(CONFIG_DN), EnumSet.of(
+        // No implementation required for modify_dn operations
+        // FIXME: Technically it is possible to perform a subtree modDN
+        // in this case however such subtree modDN would essentially be
+        // moving configuration branches which should not happen.
+        POST_RESPONSE_ADD, POST_RESPONSE_MODIFY, POST_RESPONSE_DELETE),
+        true);
     try {
-      if (publishInstanceKey)
-      {
-        CryptoManagerImpl.publishInstanceKeyEntryInADS();
-      }
+      CryptoManagerImpl.publishInstanceKeyEntryInADS();
     }
     catch (CryptoManagerException ex) {
       throw new InitializationException(ex.getMessageObject());
@@ -163,15 +149,11 @@
     }
     catch (DirectoryException e)
     {
-      //
     }
 
-    ocInstanceKey = DirectoryServer.getObjectClass(
-         OC_CRYPTO_INSTANCE_KEY, true);
-    ocCipherKey = DirectoryServer.getObjectClass(
-         OC_CRYPTO_CIPHER_KEY, true);
-    ocMacKey = DirectoryServer.getObjectClass(
-         OC_CRYPTO_MAC_KEY, true);
+    ocInstanceKey = DirectoryServer.getObjectClass(OC_CRYPTO_INSTANCE_KEY, true);
+    ocCipherKey = DirectoryServer.getObjectClass(OC_CRYPTO_CIPHER_KEY, true);
+    ocMacKey = DirectoryServer.getObjectClass(OC_CRYPTO_MAC_KEY, true);
 
     attrCert = DirectoryServer.getAttributeType(
          ConfigConstants.ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE, true);
@@ -185,22 +167,32 @@
       searchAdminSuffix();
     }
 
-    DirectoryServer.registerChangeNotificationListener(this);
+    DirectoryServer.registerInternalPlugin(this);
+  }
+
+  private static DN toDN(final String dn) throws InitializationException
+  {
+    try
+    {
+      return DN.decode(dn);
+    }
+    catch (DirectoryException e)
+    {
+      throw new RuntimeException(e);
+    }
   }
 
 
   private void searchAdminSuffix()
   {
-    InternalClientConnection conn =
-         InternalClientConnection.getRootConnection();
     LinkedHashSet<String> attributes = new LinkedHashSet<String>(0);
 
     ArrayList<Control> controls = new ArrayList<Control>(0);
 
     InternalSearchOperation searchOperation =
-         new InternalSearchOperation(conn,
-                                     InternalClientConnection.nextOperationID(),
-                                     InternalClientConnection.nextMessageID(),
+         new InternalSearchOperation(getRootConnection(),
+                                     nextOperationID(),
+                                     nextMessageID(),
                                      controls,
                                      adminSuffixDN, SearchScope.WHOLE_SUBTREE,
                                      DereferencePolicy.NEVER_DEREF_ALIASES,
@@ -242,9 +234,8 @@
   }
 
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
+  @Override
   public void performBackendInitializationProcessing(Backend backend)
   {
     DN[] baseDNs = backend.getBaseDNs();
@@ -260,9 +251,8 @@
     }
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
+  @Override
   public void performBackendFinalizationProcessing(Backend backend)
   {
     // No implementation required.
@@ -315,7 +305,7 @@
       {
         for (Control c : controls)
         {
-          if (c.getOID().equals(OID_ENTRY_CHANGE_NOTIFICATION))
+          if (OID_ENTRY_CHANGE_NOTIFICATION.equals(c.getOID()))
           {
             if (c instanceof LDAPControl)
             {
@@ -340,8 +330,7 @@
       if (ecn != null &&
            ecn.getChangeType() == PersistentSearchChangeType.DELETE)
       {
-        // The entry was deleted so we should remove it from the local trust
-        // store.
+        // entry was deleted so remove it from the local trust store
         if (dstEntry != null)
         {
           deleteEntry(dstDN);
@@ -349,24 +338,21 @@
       }
       else if (searchEntry.hasAttribute(attrCompromisedTime))
       {
-        // The key was compromised so we should remove it from the local
-        // trust store.
+        // key was compromised so remove it from the local trust store
         if (dstEntry != null)
         {
           deleteEntry(dstDN);
         }
       }
+      else if (dstEntry == null)
+      {
+        // The entry was added
+        addEntry(searchEntry, dstDN);
+      }
       else
       {
-        // The entry was added or modified.
-        if (dstEntry == null)
-        {
-          addEntry(searchEntry, dstDN);
-        }
-        else
-        {
-          modifyEntry(searchEntry, dstEntry);
-        }
+        // The entry was modified
+        modifyEntry(searchEntry, dstEntry);
       }
     }
   }
@@ -380,11 +366,8 @@
    */
   private void modifyEntry(Entry srcEntry, Entry dstEntry)
   {
-    List<Attribute> srcList;
-    srcList = srcEntry.getAttribute(attrCert);
-
-    List<Attribute> dstList;
-    dstList = dstEntry.getAttribute(attrCert);
+    List<Attribute> srcList = srcEntry.getAttribute(attrCert);
+    List<Attribute> dstList = dstEntry.getAttribute(attrCert);
 
     // Check for changes to the certificate value.
     boolean differ = false;
@@ -395,21 +378,12 @@
         differ = true;
       }
     }
-    else if (dstList == null)
+    else if (dstList == null
+        || srcList.size() != dstList.size()
+        || !srcList.equals(dstList))
     {
       differ = true;
     }
-    else if (srcList.size() != dstList.size())
-    {
-      differ = true;
-    }
-    else
-    {
-      if (!srcList.equals(dstList))
-      {
-        differ = true;
-      }
-    }
 
     if (differ)
     {
@@ -485,18 +459,22 @@
     }
   }
 
-
-  /**
-   * {@inheritDoc}
-   */
-  public void handleAddOperation(PostResponseAddOperation addOperation,
-                                 Entry entry)
+  /** {@inheritDoc} */
+  @Override
+  public PostResponse doPostResponse(PostResponseAddOperation op)
   {
-    if (addOperation.getEntryDN().isDescendantOf(instanceKeysDN))
+    if (op.getResultCode() != ResultCode.SUCCESS)
+    {
+      return PostResponse.continueOperationProcessing();
+    }
+
+    final Entry entry = op.getEntryToAdd();
+    final DN entryDN = op.getEntryDN();
+    if (entryDN.isDescendantOf(instanceKeysDN))
     {
       handleInstanceKeyAddOperation(entry);
     }
-    else if (addOperation.getEntryDN().isDescendantOf(secretKeysDN))
+    else if (entryDN.isDescendantOf(secretKeysDN))
     {
       try
       {
@@ -511,11 +489,11 @@
       }
       catch (CryptoManagerException e)
       {
-        Message message = Message.raw("Failed to import key entry: %s",
-                                      e.getMessage());
-        ErrorLogger.logError(message);
+        ErrorLogger.logError(
+            Message.raw("Failed to import key entry: %s", e.getMessage()));
       }
     }
+    return PostResponse.continueOperationProcessing();
   }
 
 
@@ -536,18 +514,17 @@
     }
   }
 
-  /**
-   * {@inheritDoc}
-   */
-  public void handleDeleteOperation(PostResponseDeleteOperation deleteOperation,
-                                    Entry entry)
+  /** {@inheritDoc} */
+  @Override
+  public PostResponse doPostResponse(PostResponseDeleteOperation op)
   {
-    if (!deleteOperation.getEntryDN().isDescendantOf(instanceKeysDN))
+    if (op.getResultCode() != ResultCode.SUCCESS
+        || !op.getEntryDN().isDescendantOf(instanceKeysDN))
     {
-      return;
+      return PostResponse.continueOperationProcessing();
     }
 
-    RDN srcRDN = entry.getDN().getRDN();
+    RDN srcRDN = op.getEntryToDelete().getDN().getRDN();
 
     // Only process the entry if it has the expected form of RDN.
     // FIXME: Technically it is possible to perform a subtree in
@@ -556,23 +533,28 @@
     if (!srcRDN.isMultiValued() &&
          srcRDN.getAttributeType(0).equals(attrAlias))
     {
-      DN dstDN = trustStoreRootDN.concat(srcRDN);
-
-      deleteEntry(dstDN);
+      DN destDN = trustStoreRootDN.concat(srcRDN);
+      deleteEntry(destDN);
     }
+    return PostResponse.continueOperationProcessing();
   }
 
-  /**
-   * {@inheritDoc}
-   */
-  public void handleModifyOperation(PostResponseModifyOperation modifyOperation,
-                                    Entry oldEntry, Entry newEntry)
+  /** {@inheritDoc} */
+  @Override
+  public PostResponse doPostResponse(PostResponseModifyOperation op)
   {
-    if (modifyOperation.getEntryDN().isDescendantOf(instanceKeysDN))
+    if (op.getResultCode() != ResultCode.SUCCESS)
+    {
+      return PostResponse.continueOperationProcessing();
+    }
+
+    final Entry newEntry = op.getModifiedEntry();
+    final DN entryDN = op.getEntryDN();
+    if (entryDN.isDescendantOf(instanceKeysDN))
     {
       handleInstanceKeyModifyOperation(newEntry);
     }
-    else if (modifyOperation.getEntryDN().isDescendantOf(secretKeysDN))
+    else if (entryDN.isDescendantOf(secretKeysDN))
     {
       try
       {
@@ -592,6 +574,7 @@
         ErrorLogger.logError(message);
       }
     }
+    return PostResponse.continueOperationProcessing();
   }
 
   private void handleInstanceKeyModifyOperation(Entry newEntry)
@@ -624,30 +607,14 @@
           deleteEntry(dstDN);
         }
       }
+      else if (dstEntry == null)
+      {
+        addEntry(newEntry, dstDN);
+      }
       else
       {
-        if (dstEntry == null)
-        {
-          addEntry(newEntry, dstDN);
-        }
-        else
-        {
-          modifyEntry(newEntry, dstEntry);
-        }
+        modifyEntry(newEntry, dstEntry);
       }
     }
   }
-
-  /**
-   * {@inheritDoc}
-   */
-  public void handleModifyDNOperation(
-       PostResponseModifyDNOperation modifyDNOperation, Entry oldEntry,
-       Entry newEntry)
-  {
-    // No implementation required.
-    // FIXME: Technically it is possible to perform a subtree modDN
-    // in this case however such subtree modDN would essentially be
-    // moving configuration branches which should not happen.
-  }
 }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/types/DirectoryConfig.java b/opendj-sdk/opends/src/server/org/opends/server/types/DirectoryConfig.java
index 3b86cba..ebecb1c 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/types/DirectoryConfig.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/types/DirectoryConfig.java
@@ -22,21 +22,17 @@
  *
  *
  *      Copyright 2006-2009 Sun Microsystems, Inc.
- *      Portions copyright 2013 ForgeRock AS.
+ *      Portions copyright 2013-2014 ForgeRock AS.
  */
 package org.opends.server.types;
 import java.util.List;
-import org.opends.messages.Message;
-
-
-
 import java.util.Map;
 import java.util.Set;
 
+import org.opends.messages.Message;
 import org.opends.server.api.AlertGenerator;
 import org.opends.server.api.ApproximateMatchingRule;
 import org.opends.server.api.AttributeSyntax;
-import org.opends.server.api.ChangeNotificationListener;
 import org.opends.server.api.ConfigHandler;
 import org.opends.server.api.EqualityMatchingRule;
 import org.opends.server.api.ExtendedOperationHandler;
@@ -50,10 +46,9 @@
 import org.opends.server.config.ConfigException;
 import org.opends.server.core.DirectoryServer;
 
-
 /**
  * This interface defines a set of methods that may be used by
- * third-party code to obtatin information about the core Directory
+ * third-party code to obtain information about the core Directory
  * Server configuration and the instances of various kinds of
  * components that have registered themselves with the server.
  * <BR><BR>
@@ -1089,43 +1084,6 @@
     DirectoryServer.deregisterSASLMechanismHandler(name);
   }
 
-
-
-  /**
-   * Registers the provided change notification listener with the
-   * Directory Server so that it will be notified of any add, delete,
-   * modify, or modify DN operations that are performed.
-   *
-   * @param  changeListener  The change notification listener to
-   *                         register with the Directory Server.
-   */
-  public static void
-       registerChangeNotificationListener(
-            ChangeNotificationListener changeListener)
-  {
-    DirectoryServer.registerChangeNotificationListener(
-                         changeListener);
-  }
-
-
-
-  /**
-   * Deregisters the provided change notification listener with the
-   * Directory Server so that it will no longer be notified of any
-   * add, delete, modify, or modify DN operations that are performed.
-   *
-   * @param  changeListener  The change notification listener to
-   *                         deregister with the Directory Server.
-   */
-  public static void deregisterChangeNotificationListener(
-                          ChangeNotificationListener changeListener)
-  {
-    DirectoryServer.deregisterChangeNotificationListener(
-                         changeListener);
-  }
-
-
-
   /**
    * Registers the provided shutdown listener with the Directory
    * Server so that it will be notified when the server shuts down.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/CollectionUtils.java b/opendj-sdk/opends/src/server/org/opends/server/util/CollectionUtils.java
new file mode 100644
index 0000000..175be36
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/CollectionUtils.java
@@ -0,0 +1,109 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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
+ *
+ *      Copyright 2014 ForgeRock AS
+ */
+package org.opends.server.util;
+
+import java.util.*;
+
+/**
+ * Utility class for {@link Collection}s.
+ */
+public final class CollectionUtils
+{
+
+  private CollectionUtils()
+  {
+    // private for utility classes
+  }
+
+  /**
+   * Creates a new {@link ArrayList} with the provided elements.
+   *
+   * @param <E>
+   *          the elements' type
+   * @param elements
+   *          the elements to add to the new ArrayList
+   * @return a new ArrayList with the provided elements
+   */
+  public static <E> ArrayList<E> newArrayList(E... elements)
+  {
+    return new ArrayList<E>(Arrays.asList(elements));
+  }
+
+  /**
+   * Creates a new {@link LinkedList} with the provided elements.
+   *
+   * @param <E>
+   *          the elements' type
+   * @param elements
+   *          the elements to add to the new LinkedList
+   * @return a new LinkedList with the provided elements
+   */
+  public static <E> LinkedList<E> newLinkedList(E... elements)
+  {
+    return new LinkedList<E>(Arrays.asList(elements));
+  }
+
+  /**
+   * Creates a new {@link HashSet} with the provided elements.
+   *
+   * @param <E>
+   *          the elements' type
+   * @param elements
+   *          the elements to add to the new HashSet
+   * @return a new HashSet with the provided elements
+   */
+  public static <E> HashSet<E> newHashSet(E... elements)
+  {
+    return new HashSet<E>(Arrays.asList(elements));
+  }
+
+  /**
+   * Creates a new {@link LinkedHashSet} with the provided elements.
+   *
+   * @param <E>
+   *          the elements' type
+   * @param elements
+   *          the elements to add to the new LinkedHashSet
+   * @return a new LinkedHashSet with the provided elements
+   */
+  public static <E> LinkedHashSet<E> newLinkedHashSet(E... elements)
+  {
+    return new LinkedHashSet<E>(Arrays.asList(elements));
+  }
+
+  /**
+   * Creates a new {@link TreeSet} with the provided elements.
+   *
+   * @param <E>
+   *          the elements' type
+   * @param elements
+   *          the elements to add to the new TreeSet
+   * @return a new TreeSet with the provided elements
+   */
+  public static <E> TreeSet<E> newTreeSet(E... elements)
+  {
+    return new TreeSet<E>(Arrays.asList(elements));
+  }
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java b/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java
index d260677..c8b7bf2 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java
@@ -184,31 +184,10 @@
         @Override
         public void run()
         {
-          // Notify persistent searches.
           for (PersistentSearch psearch : wfe.getPersistentSearches())
           {
             psearch.processAdd(entry);
           }
-
-          // Notify change listeners.
-          for (ChangeNotificationListener changeListener : DirectoryServer
-              .getChangeNotificationListeners())
-          {
-            try
-            {
-              changeListener.handleAddOperation(LocalBackendAddOperation.this, entry);
-            }
-            catch (Exception e)
-            {
-              if (debugEnabled())
-              {
-                TRACER.debugCaught(DebugLogLevel.ERROR, e);
-              }
-
-              logError(ERR_ADD_ERROR_NOTIFYING_CHANGE_LISTENER
-                  .get(getExceptionMessage(e)));
-            }
-          }
         }
       });
     }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendDeleteOperation.java b/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendDeleteOperation.java
index d8b715a..48900c1 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendDeleteOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendDeleteOperation.java
@@ -31,7 +31,6 @@
 
 import org.opends.messages.Message;
 import org.opends.server.api.Backend;
-import org.opends.server.api.ChangeNotificationListener;
 import org.opends.server.api.ClientConnection;
 import org.opends.server.api.SynchronizationProvider;
 import org.opends.server.api.plugin.PluginResult;
@@ -176,31 +175,10 @@
         @Override
         public void run()
         {
-          // Notify persistent searches.
           for (PersistentSearch psearch : wfe.getPersistentSearches())
           {
             psearch.processDelete(entry);
           }
-
-          // Notify change listeners.
-          for (ChangeNotificationListener changeListener : DirectoryServer
-              .getChangeNotificationListeners())
-          {
-            try
-            {
-              changeListener.handleDeleteOperation(LocalBackendDeleteOperation.this, entry);
-            }
-            catch (Exception e)
-            {
-              if (debugEnabled())
-              {
-                TRACER.debugCaught(DebugLogLevel.ERROR, e);
-              }
-
-              logError(ERR_DELETE_ERROR_NOTIFYING_CHANGE_LISTENER
-                  .get(getExceptionMessage(e)));
-            }
-          }
         }
       });
     }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyDNOperation.java b/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyDNOperation.java
index 78dccfb..a54ae5e 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyDNOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyDNOperation.java
@@ -34,7 +34,6 @@
 import org.opends.messages.Message;
 import org.opends.messages.MessageBuilder;
 import org.opends.server.api.Backend;
-import org.opends.server.api.ChangeNotificationListener;
 import org.opends.server.api.ClientConnection;
 import org.opends.server.api.SynchronizationProvider;
 import org.opends.server.api.plugin.PluginResult;
@@ -204,32 +203,10 @@
         @Override
         public void run()
         {
-          // Notify persistent searches.
           for (PersistentSearch psearch : wfe.getPersistentSearches())
           {
             psearch.processModifyDN(newEntry, currentEntry.getDN());
           }
-
-          // Notify change listeners.
-          for (ChangeNotificationListener changeListener : DirectoryServer
-              .getChangeNotificationListeners())
-          {
-            try
-            {
-              changeListener.handleModifyDNOperation(
-                  LocalBackendModifyDNOperation.this, currentEntry, newEntry);
-            }
-            catch (Exception e)
-            {
-              if (debugEnabled())
-              {
-                TRACER.debugCaught(DebugLogLevel.ERROR, e);
-              }
-
-              logError(ERR_MODDN_ERROR_NOTIFYING_CHANGE_LISTENER
-                  .get(getExceptionMessage(e)));
-            }
-          }
         }
       });
     }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java b/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
index 01466a5..a503933 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
@@ -317,33 +317,10 @@
         @Override
         public void run()
         {
-          // Notify persistent searches.
           for (PersistentSearch psearch : wfe.getPersistentSearches())
           {
             psearch.processModify(modifiedEntry, currentEntry);
           }
-
-          // Notify change listeners.
-          for (ChangeNotificationListener changeListener : DirectoryServer
-              .getChangeNotificationListeners())
-          {
-            try
-            {
-              changeListener
-                  .handleModifyOperation(LocalBackendModifyOperation.this,
-                      currentEntry, modifiedEntry);
-            }
-            catch (Exception e)
-            {
-              if (debugEnabled())
-              {
-                TRACER.debugCaught(DebugLogLevel.ERROR, e);
-              }
-
-              logError(ERR_MODIFY_ERROR_NOTIFYING_CHANGE_LISTENER
-                  .get(getExceptionMessage(e)));
-            }
-          }
         }
       });
     }
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/AddOperationTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/AddOperationTestCase.java
index 8efd9af..9513d78 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/AddOperationTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/AddOperationTestCase.java
@@ -26,8 +26,10 @@
  */
 package org.opends.server.core;
 
+import java.io.IOException;
 import java.net.Socket;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.locks.Lock;
@@ -51,6 +53,7 @@
 
 import static org.opends.server.protocols.internal.InternalClientConnection.*;
 import static org.opends.server.protocols.ldap.LDAPConstants.*;
+import static org.opends.server.util.CollectionUtils.*;
 import static org.testng.Assert.*;
 
 /**
@@ -76,21 +79,13 @@
    * @throws  Exception  If an unexpected problem occurs.
    */
   @DataProvider(name = "addOperations")
-  public Object[][] getAddOperations()
-         throws Exception
+  public Object[][] getAddOperations() throws Exception
   {
     ArrayList<Control> noControls = new ArrayList<Control>();
 
-    ArrayList<RawAttribute> ldapAttrList = new ArrayList<RawAttribute>();
-
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organizationalUnit"));
-    ldapAttrList.add(new LDAPAttribute("objectclass", values));
-
-    values.clear();
-    values.add(ByteString.valueOf("People"));
-    ldapAttrList.add(new LDAPAttribute("ou", values));
+    ArrayList<RawAttribute> ldapAttrList = newRawAttributes(
+        new LDAPAttribute("objectclass", byteStrings("top", "organizationalUnit")),
+        new LDAPAttribute("ou", byteStrings("People")));
 
     Entry entry = TestCaseUtils.makeEntry(
          "dn: ou=People,o=test",
@@ -129,9 +124,8 @@
 
 
   /** {@inheritDoc} */
-  @Override()
-  protected Operation[] createTestOperations()
-         throws Exception
+  @Override
+  protected Operation[] createTestOperations() throws Exception
   {
     Object[][]  objs = getAddOperations();
     Operation[] ops  = new Operation[objs.length];
@@ -173,19 +167,12 @@
    * Tests the <CODE>getEntryDN</CODE> method for the case in which we expect
    * the rawEntryDN to be decoded.
    */
-  @Test()
+  @Test
   public void testGetEntryDNInitiallyNull()
   {
-    ArrayList<RawAttribute> ldapAttrList = new ArrayList<RawAttribute>();
-
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organizationalUnit"));
-    ldapAttrList.add(new LDAPAttribute("objectclass", values));
-
-    values.clear();
-    values.add(ByteString.valueOf("People"));
-    ldapAttrList.add(new LDAPAttribute("ou", values));
+    ArrayList<RawAttribute> ldapAttrList = newRawAttributes(
+        new LDAPAttribute("objectclass", byteStrings("top", "organizationalUnit")),
+        new LDAPAttribute("ou", byteStrings("People")));
 
     AddOperationBasis addOperation =
          new AddOperationBasis(getRootConnection(), nextOperationID(), nextMessageID(),
@@ -194,7 +181,20 @@
     assertNotNull(addOperation.getEntryDN());
   }
 
+  private ArrayList<RawAttribute> newRawAttributes(RawAttribute... attributes)
+  {
+    return new ArrayList<RawAttribute>(Arrays.asList(attributes));
+  }
 
+  private ArrayList<ByteString> byteStrings(final String... v)
+  {
+    ArrayList<ByteString> values = new ArrayList<ByteString>();
+    for (String s : v)
+    {
+      values.add(ByteString.valueOf(s));
+    }
+    return values;
+  }
 
   /**
    * Tests the <CODE>getEntryDN</CODE> method for the case in which we expect
@@ -202,9 +202,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testGetEntryDNInitiallyNonNull()
-         throws Exception
+  @Test
+  public void testGetEntryDNInitiallyNonNull() throws Exception
   {
     Entry entry = TestCaseUtils.makeEntry(
          "dn: ou=People,o=test",
@@ -229,9 +228,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testGetEntryDNNonNullChangedToNull()
-         throws Exception
+  @Test
+  public void testGetEntryDNNonNullChangedToNull() throws Exception
   {
     Entry entry = TestCaseUtils.makeEntry(
          "dn: ou=People,o=test",
@@ -265,32 +263,27 @@
     assertNotNull(rawAttrs);
     assertFalse(rawAttrs.isEmpty());
 
-    ArrayList<RawAttribute> copiedAttrs =
-      new ArrayList<RawAttribute>(rawAttrs);
+    ArrayList<RawAttribute> copiedAttrs = new ArrayList<RawAttribute>(rawAttrs);
+    copiedAttrs.add(new LDAPAttribute("description", byteStrings("foo")));
     addOperation.setRawAttributes(copiedAttrs);
 
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("foo"));
-    addOperation.addRawAttribute(new LDAPAttribute("description", values));
-
-    assertTrue(find(addOperation));
+    assertTrue(find(addOperation, "description"));
 
     addOperation.setRawAttributes(rawAttrs);
 
-    assertFalse(find(addOperation));
+    assertFalse(find(addOperation, "description"));
   }
 
-  private boolean find(AddOperation addOperation)
+  private boolean find(AddOperation addOperation, final String attrName)
   {
-    boolean found = false;
     for (RawAttribute a : addOperation.getRawAttributes())
     {
-      if ("description".equalsIgnoreCase(a.getAttributeType()))
+      if (attrName.equalsIgnoreCase(a.getAttributeType()))
       {
         return true;
       }
     }
-    return found;
+    return false;
   }
 
 
@@ -300,9 +293,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testAddObjectClass()
-         throws Exception
+  @Test
+  public void testAddObjectClass() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -334,9 +326,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testRemoveObjectClass()
-         throws Exception
+  @Test
+  public void testRemoveObjectClass() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -370,9 +361,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testSetAttributeOverwrite()
-         throws Exception
+  @Test
+  public void testSetAttributeOverwrite() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -428,9 +418,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testSetAttributeAdd()
-         throws Exception
+  @Test
+  public void testSetAttributeAdd() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -464,9 +453,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testSetAttributeRemove()
-         throws Exception
+  @Test
+  public void testSetAttributeRemove() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -519,22 +507,14 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddSuccessRaw()
-         throws Exception
+  @Test
+  public void testInternalAddSuccessRaw() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organizationalUnit"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("People"));
-    attrs.add(new LDAPAttribute("ou", values));
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "organizationalUnit")),
+        new LDAPAttribute("ou", byteStrings("People")));
 
     AddOperation addOperation =
          getRootConnection().processAdd(ByteString.valueOf("ou=People,o=test"), attrs);
@@ -542,17 +522,14 @@
     retrieveCompletedOperationElements(addOperation);
   }
 
-
-
   /**
    * Tests an internal add operation that should be successful using processed
    * arguments.
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddSuccessProcessed()
-         throws Exception
+  @Test
+  public void testInternalAddSuccessProcessed() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -575,22 +552,14 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureMalformedDN()
-         throws Exception
+  @Test
+  public void testInternalAddFailureMalformedDN() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organizationalUnit"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("People"));
-    attrs.add(new LDAPAttribute("ou", values));
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "organizationalUnit")),
+        new LDAPAttribute("ou", byteStrings("People")));
 
     AddOperation addOperation =
          getRootConnection().processAdd(ByteString.valueOf("invalid"), attrs);
@@ -605,22 +574,14 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureAlreadyExists()
-         throws Exception
+  @Test
+  public void testInternalAddFailureAlreadyExists() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organization"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("test"));
-    attrs.add(new LDAPAttribute("o", values));
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "organization")),
+        new LDAPAttribute("o", byteStrings("test")));
 
     AddOperation addOperation =
          getRootConnection().processAdd(ByteString.valueOf("o=test"), attrs);
@@ -635,22 +596,14 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureNoSuchSuffix()
-         throws Exception
+  @Test
+  public void testInternalAddFailureNoSuchSuffix() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organization"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("undefined"));
-    attrs.add(new LDAPAttribute("o", values));
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "organization")),
+        new LDAPAttribute("o", byteStrings("undefined")));
 
     AddOperation addOperation =
          getRootConnection().processAdd(ByteString.valueOf("o=undefined"), attrs);
@@ -665,22 +618,14 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureNoSuchSuffixParent()
-         throws Exception
+  @Test
+  public void testInternalAddFailureNoSuchSuffixParent() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organizationalUnit"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("People"));
-    attrs.add(new LDAPAttribute("ou", values));
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "organizationalUnit")),
+        new LDAPAttribute("ou", byteStrings("People")));
 
     InternalClientConnection conn = getRootConnection();
 
@@ -697,22 +642,14 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureNoSuchParent()
-         throws Exception
+  @Test
+  public void testInternalAddFailureNoSuchParent() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organizationalUnit"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("People"));
-    attrs.add(new LDAPAttribute("ou", values));
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "organizationalUnit")),
+        new LDAPAttribute("ou", byteStrings("People")));
 
     InternalClientConnection conn = getRootConnection();
 
@@ -730,9 +667,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testExternalAddFailureNoUserModification()
-         throws Exception
+  @Test
+  public void testExternalAddFailureNoUserModification() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -741,49 +677,18 @@
     LDAPWriter w = new LDAPWriter(s);
     TestCaseUtils.configureSocket(s);
 
-    BindRequestProtocolOp bindRequest =
-         new BindRequestProtocolOp(ByteString.valueOf("cn=Directory Manager"),
-                                   3, ByteString.valueOf("password"));
-    LDAPMessage message = new LDAPMessage(1, bindRequest);
-    w.writeMessage(message);
+    bind(r, w);
 
-    message = r.readMessage();
-    BindResponseProtocolOp bindResponse =
-         message.getBindResponseProtocolOp();
-    assertEquals(bindResponse.getResultCode(), 0);
-
-
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organizationalUnit"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("People"));
-    attrs.add(new LDAPAttribute("ou", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("cn=Directory Manager"));
-    attrs.add(new LDAPAttribute("creatorsName", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("20060101000000Z"));
-    attrs.add(new LDAPAttribute("createTimestamp", values));
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "organizationalUnit")),
+        new LDAPAttribute("ou", byteStrings("People")),
+        new LDAPAttribute("creatorsName", byteStrings("cn=Directory Manager")),
+        new LDAPAttribute("createTimestamp", byteStrings("20060101000000Z")));
 
     long addRequests  = ldapStatistics.getAddRequests();
     long addResponses = ldapStatistics.getAddResponses();
 
-    AddRequestProtocolOp addRequest =
-         new AddRequestProtocolOp(ByteString.valueOf("ou=People,o=test"),
-                                  attrs);
-    message = new LDAPMessage(2, addRequest);
-    w.writeMessage(message);
-
-    message = r.readMessage();
-    AddResponseProtocolOp addResponse =
-         message.getAddResponseProtocolOp();
-    assertFalse(addResponse.getResultCode() == 0);
+    addSuccess(r, w, attrs);
 
     assertEquals(ldapStatistics.getAddRequests(), addRequests+1);
     waitForAddResponsesStat(addResponses+1);
@@ -791,30 +696,20 @@
     StaticUtils.close(s);
   }
 
-
-
   /**
    * Tests an internal add operation that fails because it has an undefined
    * objectclass.
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureUndefinedObjectClass()
-         throws Exception
+  @Test
+  public void testInternalAddFailureUndefinedObjectClass() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("undefined"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("People"));
-    attrs.add(new LDAPAttribute("ou", values));
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "undefined")),
+        new LDAPAttribute("ou", byteStrings("People")));
 
     InternalClientConnection conn = getRootConnection();
 
@@ -824,17 +719,14 @@
     assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
   }
 
-
-
   /**
    * Tests a successful internal add operation that contains a user-modifiable
    * operational attribute.
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddSuccessfulWithOperationalAttribute()
-         throws Exception
+  @Test
+  public void testInternalAddSuccessfulWithOperationalAttribute() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -865,30 +757,16 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddSuccessfulDisjointAttribute()
-         throws Exception
+  @Test
+  public void testInternalAddSuccessfulDisjointAttribute() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organizationalUnit"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("foo"));
-    attrs.add(new LDAPAttribute("description", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("People"));
-    attrs.add(new LDAPAttribute("ou", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("bar"));
-    attrs.add(new LDAPAttribute("description", values));
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "organizationalUnit")),
+        new LDAPAttribute("description", byteStrings("foo")),
+        new LDAPAttribute("ou", byteStrings("People")),
+        new LDAPAttribute("description", byteStrings("bar")));
 
     InternalClientConnection conn = getRootConnection();
 
@@ -898,38 +776,22 @@
     assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
   }
 
-
-
   /**
    * Tests a successful internal add operation that contains raw attributes with
    * options.
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddSuccessfulWithRawAttributeOptions()
-         throws Exception
+  @Test
+  public void testInternalAddSuccessfulWithRawAttributeOptions() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organizationalUnit"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("foo"));
-    attrs.add(new LDAPAttribute("description", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("People"));
-    attrs.add(new LDAPAttribute("ou", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("foo"));
-    attrs.add(new LDAPAttribute("description;lang-en-us", values));
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "organizationalUnit")),
+        new LDAPAttribute("description", byteStrings("foo")),
+        new LDAPAttribute("ou", byteStrings("People")),
+        new LDAPAttribute("description;lang-en-us", byteStrings("foo")));
 
     InternalClientConnection conn = getRootConnection();
 
@@ -947,26 +809,15 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddSuccessfulWithRawAttributeOptionsOnlyOptions()
-         throws Exception
+  @Test
+  public void testInternalAddSuccessfulWithRawAttributeOptionsOnlyOptions() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organizationalUnit"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("People"));
-    attrs.add(new LDAPAttribute("ou", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("foo"));
-    attrs.add(new LDAPAttribute("description;lang-en-us", values));
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "organizationalUnit")),
+        new LDAPAttribute("ou", byteStrings("People")),
+        new LDAPAttribute("description;lang-en-us", byteStrings("foo")));
 
     InternalClientConnection conn = getRootConnection();
 
@@ -976,17 +827,14 @@
     assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
   }
 
-
-
   /**
    * Tests a successful internal add operation that contains attributes with
    * options.
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddSuccessfulWithAttributeOptions()
-         throws Exception
+  @Test
+  public void testInternalAddSuccessfulWithAttributeOptions() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1019,23 +867,14 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureRootDSE()
-         throws Exception
+  @Test
+  public void testInternalAddFailureRootDSE() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("ds-root-dse"));
-    values.add(ByteString.valueOf("extensibleObject"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("Root DSE"));
-    attrs.add(new LDAPAttribute("cn", values));
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "ds-root-dse", "extensibleObject")),
+        new LDAPAttribute("cn", byteStrings("Root DSE")));
 
     InternalClientConnection conn = getRootConnection();
 
@@ -1044,16 +883,13 @@
     assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
   }
 
-
-
   /**
    * Tests a successful internal add operation that is missing RDN attributes.
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddSuccessfulWithMissingRDNAttributes()
-         throws Exception
+  @Test
+  public void testInternalAddSuccessfulWithMissingRDNAttributes() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1078,9 +914,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureWithMissingRDNAttributes()
-         throws Exception
+  @Test
+  public void testInternalAddFailureWithMissingRDNAttributes() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1105,9 +940,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddSuccessfulWithMissingParentObjectClass()
-         throws Exception
+  @Test
+  public void testInternalAddSuccessfulWithMissingParentObjectClass() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1151,9 +985,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureNoObjectClasses()
-         throws Exception
+  @Test
+  public void testInternalAddFailureNoObjectClasses() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1173,9 +1006,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureOnlyAbstractObjectClass()
-         throws Exception
+  @Test
+  public void testInternalAddFailureOnlyAbstractObjectClass() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1196,9 +1028,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureNoStructuralObjectClass()
-         throws Exception
+  @Test
+  public void testInternalAddFailureNoStructuralObjectClass() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1220,9 +1051,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureMultipleStructuralObjectClasses()
-         throws Exception
+  @Test
+  public void testInternalAddFailureMultipleStructuralObjectClasses() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1246,9 +1076,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureMissingRequiredAttribute()
-         throws Exception
+  @Test
+  public void testInternalAddFailureMissingRequiredAttribute() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1275,9 +1104,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureMissingRequiredAttributeExtensibleObject()
-         throws Exception
+  @Test
+  public void testInternalAddFailureMissingRequiredAttributeExtensibleObject() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1305,9 +1133,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureDisallowedAttribute()
-         throws Exception
+  @Test
+  public void testInternalAddFailureDisallowedAttribute() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1337,9 +1164,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddSuccessfulDisallowedAttributeExtensibleObject()
-         throws Exception
+  @Test
+  public void testInternalAddSuccessfulDisallowedAttributeExtensibleObject() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1370,9 +1196,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureEmptyAttribute()
-         throws Exception
+  @Test
+  public void testInternalAddFailureEmptyAttribute() throws Exception
   {
     TestCaseUtils.initializeTestBackend(false);
 
@@ -1382,13 +1207,9 @@
          "objectClass: organization",
          "o: test");
 
-    Map<AttributeType,List<Attribute>> userAttrs = entry.getUserAttributes();
-
     AttributeType attrType = DirectoryServer.getAttributeType("description");
-    ArrayList<Attribute> attrList = new ArrayList<Attribute>();
-    attrList.add(Attributes.empty(attrType));
-    userAttrs.put(attrType, attrList);
-
+    Map<AttributeType,List<Attribute>> userAttrs = entry.getUserAttributes();
+    userAttrs.put(attrType, newArrayList(Attributes.empty(attrType)));
 
     InternalClientConnection conn = getRootConnection();
 
@@ -1406,9 +1227,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureServerCompletelyReadOnly()
-         throws Exception
+  @Test
+  public void testInternalAddFailureServerCompletelyReadOnly() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1440,9 +1260,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddSuccessServerExternallyReadOnly()
-         throws Exception
+  @Test
+  public void testInternalAddSuccessServerExternallyReadOnly() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1475,9 +1294,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testExternalAddFailureServerExternallyReadOnly()
-         throws Exception
+  @Test
+  public void testExternalAddFailureServerExternallyReadOnly() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1486,43 +1304,18 @@
     LDAPWriter w = new LDAPWriter(s);
     TestCaseUtils.configureSocket(s);
 
-    BindRequestProtocolOp bindRequest =
-         new BindRequestProtocolOp(ByteString.valueOf("cn=Directory Manager"),
-                                   3, ByteString.valueOf("password"));
-    LDAPMessage message = new LDAPMessage(1, bindRequest);
-    w.writeMessage(message);
+    bind(r, w);
 
-    message = r.readMessage();
-    BindResponseProtocolOp bindResponse =
-         message.getBindResponseProtocolOp();
-    assertEquals(bindResponse.getResultCode(), 0);
-
-
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organizationalUnit"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("People"));
-    attrs.add(new LDAPAttribute("ou", values));
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "organizationalUnit")),
+        new LDAPAttribute("ou", byteStrings("People")));
 
     DirectoryServer.setWritabilityMode(WritabilityMode.INTERNAL_ONLY);
 
     long addRequests  = ldapStatistics.getAddRequests();
     long addResponses = ldapStatistics.getAddResponses();
 
-    AddRequestProtocolOp addRequest =
-         new AddRequestProtocolOp(ByteString.valueOf("ou=People,o=test"),
-                                  attrs);
-    message = new LDAPMessage(2, addRequest);
-    w.writeMessage(message);
-
-    message = r.readMessage();
-    AddResponseProtocolOp addResponse =
-         message.getAddResponseProtocolOp();
-    assertFalse(addResponse.getResultCode() == 0);
+    addSuccess(r, w, attrs);
 
     assertEquals(ldapStatistics.getAddRequests(), addRequests+1);
     waitForAddResponsesStat(addResponses+1);
@@ -1532,7 +1325,26 @@
     DirectoryServer.setWritabilityMode(WritabilityMode.ENABLED);
   }
 
+  private void bind(LDAPReader r, LDAPWriter w) throws Exception
+  {
+    final BindRequestProtocolOp bindRequest = new BindRequestProtocolOp(
+        ByteString.valueOf("cn=Directory Manager"), 3, ByteString.valueOf("password"));
+    w.writeMessage(new LDAPMessage(1, bindRequest));
 
+    final LDAPMessage message = r.readMessage();
+    final BindResponseProtocolOp bindResponse = message.getBindResponseProtocolOp();
+    assertEquals(bindResponse.getResultCode(), 0);
+  }
+
+  private void addSuccess(LDAPReader r, LDAPWriter w,
+      ArrayList<RawAttribute> attrs) throws Exception
+  {
+    writeAddRequest(w, attrs, null);
+
+    LDAPMessage message = r.readMessage();
+    AddResponseProtocolOp addResponse = message.getAddResponseProtocolOp();
+    assertFalse(addResponse.getResultCode() == 0);
+  }
 
   /**
    * Tests a failed internal add operation with the backend in complete
@@ -1540,9 +1352,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddFailureBackendCompletelyReadOnly()
-         throws Exception
+  @Test
+  public void testInternalAddFailureBackendCompletelyReadOnly() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1575,9 +1386,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalAddSuccessBackendExternallyReadOnly()
-         throws Exception
+  @Test
+  public void testInternalAddSuccessBackendExternallyReadOnly() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1611,9 +1421,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testExternalAddFailureBackendExternallyReadOnly()
-         throws Exception
+  @Test
+  public void testExternalAddFailureBackendExternallyReadOnly() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1622,27 +1431,11 @@
     LDAPWriter w = new LDAPWriter(s);
     TestCaseUtils.configureSocket(s);
 
-    BindRequestProtocolOp bindRequest =
-         new BindRequestProtocolOp(ByteString.valueOf("cn=Directory Manager"),
-                                   3, ByteString.valueOf("password"));
-    LDAPMessage message = new LDAPMessage(1, bindRequest);
-    w.writeMessage(message);
+    bind(r, w);
 
-    message = r.readMessage();
-    BindResponseProtocolOp bindResponse =
-         message.getBindResponseProtocolOp();
-    assertEquals(bindResponse.getResultCode(), 0);
-
-
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organizationalUnit"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("People"));
-    attrs.add(new LDAPAttribute("ou", values));
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "organizationalUnit")),
+        new LDAPAttribute("ou", byteStrings("People")));
 
     Backend<?> b = DirectoryServer.getBackend(DN.decode("o=test"));
     b.setWritabilityMode(WritabilityMode.INTERNAL_ONLY);
@@ -1650,16 +1443,7 @@
     long addRequests  = ldapStatistics.getAddRequests();
     long addResponses = ldapStatistics.getAddResponses();
 
-    AddRequestProtocolOp addRequest =
-         new AddRequestProtocolOp(ByteString.valueOf("ou=People,o=test"),
-                                  attrs);
-    message = new LDAPMessage(2, addRequest);
-    w.writeMessage(message);
-
-    message = r.readMessage();
-    AddResponseProtocolOp addResponse =
-         message.getAddResponseProtocolOp();
-    assertFalse(addResponse.getResultCode() == 0);
+    addSuccess(r, w, attrs);
 
     assertEquals(ldapStatistics.getAddRequests(), addRequests+1);
     waitForAddResponsesStat(addResponses+1);
@@ -1677,29 +1461,31 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testSuccessWithNotificationListener()
-         throws Exception
+  @Test
+  public void testSuccessWithNotificationListener() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
     TestChangeNotificationListener changeListener =
          new TestChangeNotificationListener();
-    DirectoryServer.registerChangeNotificationListener(changeListener);
-    assertEquals(changeListener.getAddCount(), 0);
+    DirectoryServer.registerInternalPlugin(changeListener);
+    try{
+      assertEquals(changeListener.getAddCount(), 0);
 
-    Entry entry = TestCaseUtils.makeEntry(
-         "dn: ou=People,o=test",
-         "objectClass: top",
-         "objectClass: organizationalUnit",
-         "ou: People");
+      Entry entry = TestCaseUtils.makeEntry(
+          "dn: ou=People,o=test",
+          "objectClass: top",
+          "objectClass: organizationalUnit",
+          "ou: People");
 
-    AddOperation addOperation = getRootConnection().processAdd(entry);
-    assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
-    retrieveCompletedOperationElements(addOperation);
+      AddOperation addOperation = getRootConnection().processAdd(entry);
+      assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
+      retrieveCompletedOperationElements(addOperation);
 
-    assertEquals(changeListener.getAddCount(), 1);
-    DirectoryServer.deregisterChangeNotificationListener(changeListener);
+      assertEquals(changeListener.getAddCount(), 1);
+    }finally {
+      DirectoryServer.deregisterInternalPlugin(changeListener);
+    }
   }
 
 
@@ -1710,28 +1496,30 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testFailureWithNotificationListener()
-         throws Exception
+  @Test
+  public void testFailureWithNotificationListener() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
     TestChangeNotificationListener changeListener =
          new TestChangeNotificationListener();
-    DirectoryServer.registerChangeNotificationListener(changeListener);
-    assertEquals(changeListener.getAddCount(), 0);
+    DirectoryServer.registerInternalPlugin(changeListener);
+    try{
+      assertEquals(changeListener.getAddCount(), 0);
 
-    Entry entry = TestCaseUtils.makeEntry(
-         "dn: ou=People,ou=nonexistent,o=test",
-         "objectClass: top",
-         "objectClass: organizationalUnit",
-         "ou: People");
+      Entry entry = TestCaseUtils.makeEntry(
+          "dn: ou=People,ou=nonexistent,o=test",
+          "objectClass: top",
+          "objectClass: organizationalUnit",
+          "ou: People");
 
-    AddOperation addOperation = getRootConnection().processAdd(entry);
-    assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
+      AddOperation addOperation = getRootConnection().processAdd(entry);
+      assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
 
-    assertEquals(changeListener.getAddCount(), 0);
-    DirectoryServer.deregisterChangeNotificationListener(changeListener);
+      assertEquals(changeListener.getAddCount(), 0);
+    }finally {
+      DirectoryServer.deregisterInternalPlugin(changeListener);
+    }
   }
 
 
@@ -1741,9 +1529,8 @@
    *
    * @throws  Exception  If an unexpected probem occurs.
    */
-  @Test()
-  public void testCancelBeforeStartup()
-         throws Exception
+  @Test
+  public void testCancelBeforeStartup() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1771,9 +1558,8 @@
    *
    * @throws  Exception  If an unexpected probem occurs.
    */
-  @Test()
-  public void testCancelAfterOperation()
-         throws Exception
+  @Test
+  public void testCancelAfterOperation() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1808,8 +1594,7 @@
    * @throws  Exception  If an unexpected problem occurs.
    */
   @Test(groups = { "slow" })
-  public void testCannotLockEntry()
-         throws Exception
+  public void testCannotLockEntry() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1839,9 +1624,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDisconnectInPreParseAdd()
-         throws Exception
+  @Test
+  public void testDisconnectInPreParseAdd() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1850,44 +1634,39 @@
     LDAPWriter w = new LDAPWriter(s);
     TestCaseUtils.configureSocket(s);
 
-    BindRequestProtocolOp bindRequest =
-         new BindRequestProtocolOp(ByteString.valueOf("cn=Directory Manager"),
-                                   3, ByteString.valueOf("password"));
-    LDAPMessage message = new LDAPMessage(1, bindRequest);
-    w.writeMessage(message);
+    bind(r, w);
 
-    message = r.readMessage();
-    BindResponseProtocolOp bindResponse =
-         message.getBindResponseProtocolOp();
-    assertEquals(bindResponse.getResultCode(), 0);
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "organizationalUnit")),
+        new LDAPAttribute("ou", byteStrings("People")));
 
+    addDisconnect(r, w, attrs, "PreParse");
 
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organizationalUnit"));
-    attrs.add(new LDAPAttribute("objectClass", values));
+    StaticUtils.close(s);
+  }
 
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("People"));
-    attrs.add(new LDAPAttribute("ou", values));
+  private void addDisconnect(LDAPReader r, LDAPWriter w,
+      ArrayList<RawAttribute> attrs, String section) throws Exception
+  {
+    writeAddRequest(w, attrs, section);
 
-    AddRequestProtocolOp addRequest =
-         new AddRequestProtocolOp(ByteString.valueOf("ou=People,o=test"),
-                                  attrs);
-    message = new LDAPMessage(2, addRequest,
-         DisconnectClientPlugin.createDisconnectControlList("PreParse"));
-    w.writeMessage(message);
-
-    message = r.readMessage();
+    LDAPMessage message = r.readMessage();
     if (message != null)
     {
       // If we got an element back, then it must be a notice of disconnect
       // unsolicited notification.
       assertEquals(message.getProtocolOpType(), OP_TYPE_EXTENDED_RESPONSE);
     }
+  }
 
-    StaticUtils.close(s);
+  private void writeAddRequest(LDAPWriter w, ArrayList<RawAttribute> attrs,
+      String section) throws IOException
+  {
+    AddRequestProtocolOp addRequest = new AddRequestProtocolOp(ByteString.valueOf("ou=People,o=test"), attrs);
+    List<Control> controls = section != null
+        ? DisconnectClientPlugin.createDisconnectControlList(section)
+        : null;
+    w.writeMessage(new LDAPMessage(2, addRequest, controls));
   }
 
 
@@ -1898,9 +1677,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDisconnectInPreOperationAdd()
-         throws Exception
+  @Test
+  public void testDisconnectInPreOperationAdd() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1909,58 +1687,25 @@
     LDAPWriter w = new LDAPWriter(s);
     TestCaseUtils.configureSocket(s);
 
-    BindRequestProtocolOp bindRequest =
-         new BindRequestProtocolOp(ByteString.valueOf("cn=Directory Manager"),
-                                   3, ByteString.valueOf("password"));
-    LDAPMessage message = new LDAPMessage(1, bindRequest);
-    w.writeMessage(message);
+    bind(r, w);
 
-    message = r.readMessage();
-    BindResponseProtocolOp bindResponse =
-         message.getBindResponseProtocolOp();
-    assertEquals(bindResponse.getResultCode(), 0);
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "organizationalUnit")),
+        new LDAPAttribute("ou", byteStrings("People")));
 
-
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organizationalUnit"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("People"));
-    attrs.add(new LDAPAttribute("ou", values));
-
-    AddRequestProtocolOp addRequest =
-         new AddRequestProtocolOp(ByteString.valueOf("ou=People,o=test"),
-                                  attrs);
-    message = new LDAPMessage(2, addRequest,
-         DisconnectClientPlugin.createDisconnectControlList(
-              "PreOperation"));
-    w.writeMessage(message);
-
-    message = r.readMessage();
-    if (message != null)
-    {
-      // If we got an element back, then it must be a notice of disconnect
-      // unsolicited notification.
-      assertEquals(message.getProtocolOpType(), OP_TYPE_EXTENDED_RESPONSE);
-    }
+    addDisconnect(r, w, attrs, "PreOperation");
 
     StaticUtils.close(s);
   }
 
-
-
   /**
    * Tests an add operation that should be disconnected in a post-operation
    * plugin.
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDisconnectInPostOperationAdd()
-         throws Exception
+  @Test
+  public void testDisconnectInPostOperationAdd() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1969,58 +1714,25 @@
     LDAPWriter w = new LDAPWriter(s);
     TestCaseUtils.configureSocket(s);
 
-    BindRequestProtocolOp bindRequest =
-         new BindRequestProtocolOp(ByteString.valueOf("cn=Directory Manager"),
-                                   3, ByteString.valueOf("password"));
-    LDAPMessage message = new LDAPMessage(1, bindRequest);
-    w.writeMessage(message);
+    bind(r, w);
 
-    message = r.readMessage();
-    BindResponseProtocolOp bindResponse =
-         message.getBindResponseProtocolOp();
-    assertEquals(bindResponse.getResultCode(), 0);
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "organizationalUnit")),
+        new LDAPAttribute("ou", byteStrings("People")));
 
-
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organizationalUnit"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("People"));
-    attrs.add(new LDAPAttribute("ou", values));
-
-    AddRequestProtocolOp addRequest =
-         new AddRequestProtocolOp(ByteString.valueOf("ou=People,o=test"),
-                                  attrs);
-    message = new LDAPMessage(2, addRequest,
-         DisconnectClientPlugin.createDisconnectControlList(
-              "PostOperation"));
-    w.writeMessage(message);
-
-    message = r.readMessage();
-    if (message != null)
-    {
-      // If we got an element back, then it must be a notice of disconnect
-      // unsolicited notification.
-      assertEquals(message.getProtocolOpType(), OP_TYPE_EXTENDED_RESPONSE);
-    }
+    addDisconnect(r, w, attrs, "PostOperation");
 
     StaticUtils.close(s);
   }
 
-
-
   /**
    * Tests an add operation that should be disconnected in a post-response
    * plugin.
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDisconnectInPostResponseAdd()
-         throws Exception
+  @Test
+  public void testDisconnectInPostResponseAdd() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -2029,40 +1741,18 @@
     LDAPWriter w = new LDAPWriter(s);
     //TestCaseUtils.configureSocket(s);
 
-    BindRequestProtocolOp bindRequest =
-         new BindRequestProtocolOp(ByteString.valueOf("cn=Directory Manager"),
-                                   3, ByteString.valueOf("password"));
-    LDAPMessage message = new LDAPMessage(1, bindRequest);
-    w.writeMessage(message);
+    bind(r, w);
 
-    message = r.readMessage();
-    BindResponseProtocolOp bindResponse =
-         message.getBindResponseProtocolOp();
-    assertEquals(bindResponse.getResultCode(), 0);
+    ArrayList<RawAttribute> attrs = newRawAttributes(
+        new LDAPAttribute("objectClass", byteStrings("top", "organizationalUnit")),
+        new LDAPAttribute("ou", byteStrings("People")));
 
-
-    ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
-    ArrayList<ByteString> values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("top"));
-    values.add(ByteString.valueOf("organizationalUnit"));
-    attrs.add(new LDAPAttribute("objectClass", values));
-
-    values = new ArrayList<ByteString>();
-    values.add(ByteString.valueOf("People"));
-    attrs.add(new LDAPAttribute("ou", values));
-
-    AddRequestProtocolOp addRequest =
-         new AddRequestProtocolOp(ByteString.valueOf("ou=People,o=test"),
-                                  attrs);
-    message = new LDAPMessage(2, addRequest,
-         DisconnectClientPlugin.createDisconnectControlList(
-              "PostResponse"));
-    w.writeMessage(message);
+    writeAddRequest(w, attrs, "PostResponse");
 
 responseLoop:
     while (true)
     {
-      message = r.readMessage();
+      LDAPMessage message = r.readMessage();
       if (message == null)
       {
         // The connection has been closed.
@@ -2092,17 +1782,14 @@
     StaticUtils.close(s);
   }
 
-
-
   /**
    * Tests an add operation that attempts to add an entry with a user attribute
    * marked OBSOLETE in the server schema.
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testAddObsoleteUserAttribute()
-         throws Exception
+  @Test
+  public void testAddObsoleteUserAttribute() throws Exception
   {
     TestCaseUtils.initializeTestBackend(false);
 
@@ -2159,9 +1846,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testAddObsoleteOperationalAttribute()
-         throws Exception
+  @Test
+  public void testAddObsoleteOperationalAttribute() throws Exception
   {
     TestCaseUtils.initializeTestBackend(false);
 
@@ -2218,9 +1904,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testAddObsoleteObjectClass()
-         throws Exception
+  @Test
+  public void testAddObsoleteObjectClass() throws Exception
   {
     TestCaseUtils.initializeTestBackend(false);
 
@@ -2275,22 +1960,17 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testShortCircuitInPreParse()
-         throws Exception
+  @Test
+  public void testShortCircuitInPreParse() throws Exception
   {
     TestCaseUtils.initializeTestBackend(false);
 
     List<Control> controls =
          ShortCircuitPlugin.createShortCircuitControlList(0, "PreParse");
 
-    ArrayList<ByteString> ocValues = new ArrayList<ByteString>();
-    ocValues.add(ByteString.valueOf("top"));
-    ocValues.add(ByteString.valueOf("organization"));
-
-    ArrayList<RawAttribute> rawAttrs = new ArrayList<RawAttribute>();
-    rawAttrs.add(RawAttribute.create("objectClass", ocValues));
-    rawAttrs.add(RawAttribute.create("o", "test"));
+    ArrayList<RawAttribute> rawAttrs = newRawAttributes(
+        RawAttribute.create("objectClass", byteStrings("top", "organization")),
+        RawAttribute.create("o", "test"));
 
     AddOperationBasis addOperation =
          new AddOperationBasis(getRootConnection(), nextOperationID(), nextMessageID(),
@@ -2300,4 +1980,3 @@
     assertFalse(DirectoryServer.entryExists(DN.decode("o=test")));
   }
 }
-
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/DeleteOperationTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/DeleteOperationTestCase.java
index dbe200a..ebcafeb 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/DeleteOperationTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/DeleteOperationTestCase.java
@@ -68,9 +68,8 @@
   }
 
   /** {@inheritDoc} */
-  @Override()
-  protected Operation[] createTestOperations()
-         throws Exception
+  @Override
+  protected Operation[] createTestOperations() throws Exception
   {
     List<Control> noControls = new ArrayList<Control>();
     return new Operation[]
@@ -130,7 +129,7 @@
    * Tests the <CODE>getEntryDN</CODE> method that should decode the rawEntryDN
    * to compute the entryDN.
    */
-  @Test()
+  @Test
   public void testGetEntryDNNull()
   {
     DeleteOperation deleteOperation =
@@ -145,9 +144,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testGetEntryDNNotNull()
-         throws Exception
+  @Test
+  public void testGetEntryDNNotNull() throws Exception
   {
     DeleteOperation deleteOperation =
         newDeleteOperation(null, DN.decode("o=test"));
@@ -165,9 +163,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testGetEntryDNChangedToNull()
-         throws Exception
+  @Test
+  public void testGetEntryDNChangedToNull() throws Exception
   {
     DeleteOperation deleteOperation =
         newDeleteOperation(null, DN.decode("o=test"));
@@ -201,9 +198,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testGetEntryToDeleteExists()
-         throws Exception
+  @Test
+  public void testGetEntryToDeleteExists() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -221,13 +217,13 @@
 
   private DeleteOperation processDeleteRaw(String entryDN)
   {
-    InternalClientConnection conn =getRootConnection();
+    InternalClientConnection conn = getRootConnection();
     return conn.processDelete(ByteString.valueOf(entryDN));
   }
 
   private DeleteOperation processDelete(String entryDN) throws DirectoryException
   {
-    InternalClientConnection conn =getRootConnection();
+    InternalClientConnection conn = getRootConnection();
     return conn.processDelete(DN.decode(entryDN));
   }
 
@@ -244,9 +240,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testGetEntryToDeleteNonExistent()
-         throws Exception
+  @Test
+  public void testGetEntryToDeleteNonExistent() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -268,9 +263,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testExternalDelete()
-         throws Exception
+  @Test
+  public void testExternalDelete() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -285,9 +279,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDeleteWithValidRawDNSuffix()
-         throws Exception
+  @Test
+  public void testDeleteWithValidRawDNSuffix() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -303,9 +296,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDeleteWithValidProcessedDNSuffix()
-         throws Exception
+  @Test
+  public void testDeleteWithValidProcessedDNSuffix() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -321,9 +313,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDeleteWithValidRawDNLeaf()
-         throws Exception
+  @Test
+  public void testDeleteWithValidRawDNLeaf() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -344,9 +335,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDeleteWithValidProcessedDNLeaf()
-         throws Exception
+  @Test
+  public void testDeleteWithValidProcessedDNLeaf() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -367,9 +357,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDeleteWithMalformedRawDN()
-         throws Exception
+  @Test
+  public void testDeleteWithMalformedRawDN() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -385,9 +374,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDeleteWithNonExistentSuffixRawDN()
-         throws Exception
+  @Test
+  public void testDeleteWithNonExistentSuffixRawDN() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -403,9 +391,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDeleteWithNonExistentSuffixProcessedDN()
-         throws Exception
+  @Test
+  public void testDeleteWithNonExistentSuffixProcessedDN() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -420,9 +407,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDeleteWithRawDNBelowNonExistentSuffix()
-         throws Exception
+  @Test
+  public void testDeleteWithRawDNBelowNonExistentSuffix() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -438,9 +424,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDeleteWithProcessedDNBelowNonExistentSuffix()
-         throws Exception
+  @Test
+  public void testDeleteWithProcessedDNBelowNonExistentSuffix() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -456,9 +441,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDeleteWithNonExistentRawDNBelowExistingSuffix()
-         throws Exception
+  @Test
+  public void testDeleteWithNonExistentRawDNBelowExistingSuffix() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -474,9 +458,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDeleteWithNonExistentProcessedDNBelowExistingSuffix()
-         throws Exception
+  @Test
+  public void testDeleteWithNonExistentProcessedDNBelowExistingSuffix() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -491,9 +474,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDeleteWithNonLeafRawDN()
-         throws Exception
+  @Test
+  public void testDeleteWithNonLeafRawDN() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -513,9 +495,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDeleteWithNonLeafProcessedDN()
-         throws Exception
+  @Test
+  public void testDeleteWithNonLeafProcessedDN() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -536,9 +517,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDeleteWithServerWritabilityDisabled()
-         throws Exception
+  @Test
+  public void testDeleteWithServerWritabilityDisabled() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -558,9 +538,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalDeleteWithServerWritabilityInternalOnly()
-         throws Exception
+  @Test
+  public void testInternalDeleteWithServerWritabilityInternalOnly() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -580,9 +559,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testExternalDeleteWithServerWritabilityInternalOnly()
-         throws Exception
+  @Test
+  public void testExternalDeleteWithServerWritabilityInternalOnly() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -602,9 +580,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDeleteWithBackendWritabilityDisabled()
-         throws Exception
+  @Test
+  public void testDeleteWithBackendWritabilityDisabled() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -625,9 +602,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testInternalDeleteWithBackendWritabilityInternalOnly()
-         throws Exception
+  @Test
+  public void testInternalDeleteWithBackendWritabilityInternalOnly() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -648,9 +624,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testExternalDeleteWithBackendWritabilityInternalOnly()
-         throws Exception
+  @Test
+  public void testExternalDeleteWithBackendWritabilityInternalOnly() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -681,9 +656,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testCancelBeforeStartup()
-         throws Exception
+  @Test
+  public void testCancelBeforeStartup() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -702,9 +676,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testCancelAfterOperation()
-         throws Exception
+  @Test
+  public void testCancelAfterOperation() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -729,8 +702,7 @@
    * @throws  Exception  If an unexpected problem occurs.
    */
   @Test(groups = { "slow" })
-  public void testCannotLockEntry()
-         throws Exception
+  public void testCannotLockEntry() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -754,9 +726,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDisconnectInPreParseDelete()
-         throws Exception
+  @Test
+  public void testDisconnectInPreParseDelete() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -802,9 +773,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDisconnectInPreOperationDelete()
-         throws Exception
+  @Test
+  public void testDisconnectInPreOperationDelete() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -851,9 +821,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDisconnectInPostOperationDelete()
-         throws Exception
+  @Test
+  public void testDisconnectInPostOperationDelete() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -900,9 +869,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDisconnectInPostResponseDelete()
-         throws Exception
+  @Test
+  public void testDisconnectInPostResponseDelete() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -970,23 +938,28 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testSuccessWithNotificationListener()
-         throws Exception
+  @Test
+  public void testSuccessWithNotificationListener() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
     TestChangeNotificationListener changeListener =
          new TestChangeNotificationListener();
-    DirectoryServer.registerChangeNotificationListener(changeListener);
-    assertEquals(changeListener.getAddCount(), 0);
+    DirectoryServer.registerInternalPlugin(changeListener);
+    try
+    {
+      assertEquals(changeListener.getAddCount(), 0);
 
-    DeleteOperation deleteOperation = processDeleteRaw("o=test");
-    assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
-    retrieveCompletedOperationElements(deleteOperation);
+      DeleteOperation deleteOperation = processDeleteRaw("o=test");
+      assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+      retrieveCompletedOperationElements(deleteOperation);
 
-    assertEquals(changeListener.getDeleteCount(), 1);
-    DirectoryServer.deregisterChangeNotificationListener(changeListener);
+      assertEquals(changeListener.getDeleteCount(), 1);
+    }
+    finally
+    {
+      DirectoryServer.deregisterInternalPlugin(changeListener);
+    }
   }
 
 
@@ -997,22 +970,27 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testFailureWithNotificationListener()
-         throws Exception
+  @Test
+  public void testFailureWithNotificationListener() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
     TestChangeNotificationListener changeListener =
          new TestChangeNotificationListener();
-    DirectoryServer.registerChangeNotificationListener(changeListener);
-    assertEquals(changeListener.getAddCount(), 0);
+    DirectoryServer.registerInternalPlugin(changeListener);
+    try
+    {
+      assertEquals(changeListener.getAddCount(), 0);
 
-    DeleteOperation deleteOperation = processDeleteRaw("cn=nonexistent,o=test");
-    assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
+      DeleteOperation deleteOperation = processDeleteRaw("cn=nonexistent,o=test");
+      assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
 
-    assertEquals(changeListener.getDeleteCount(), 0);
-    DirectoryServer.deregisterChangeNotificationListener(changeListener);
+      assertEquals(changeListener.getDeleteCount(), 0);
+    }
+    finally
+    {
+      DirectoryServer.deregisterInternalPlugin(changeListener);
+    }
   }
 
 
@@ -1023,9 +1001,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testShortCircuitInPreParse()
-         throws Exception
+  @Test
+  public void testShortCircuitInPreParse() throws Exception
   {
     TestCaseUtils.initializeTestBackend(true);
 
@@ -1039,4 +1016,3 @@
     assertTrue(DirectoryServer.entryExists(DN.decode("o=test")));
   }
 }
-
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/ModifyOperationTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/ModifyOperationTestCase.java
index 107de9e..eb9fc1f 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/ModifyOperationTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/ModifyOperationTestCase.java
@@ -53,6 +53,7 @@
 import static org.opends.server.TestCaseUtils.*;
 import static org.opends.server.protocols.internal.InternalClientConnection.*;
 import static org.opends.server.protocols.ldap.LDAPConstants.*;
+import static org.opends.server.util.CollectionUtils.*;
 import static org.testng.Assert.*;
 
 /**
@@ -87,55 +88,45 @@
    * @throws  Exception  If an unexpected problem occurs.
    */
   @DataProvider(name = "modifyOperations")
-  public Object[][] getModifyOperations()
-         throws Exception
+  public Object[][] getModifyOperations() throws Exception
   {
     List<ModifyOperation> opList = new ArrayList<ModifyOperation>();
 
     List<Control> noControls = new ArrayList<Control>();
 
-
-    List<RawModification> ldapMods = new ArrayList<RawModification>();
     LDAPAttribute ldapAttr = new LDAPAttribute("description", "foo");
-    ldapMods.add(add(ldapAttr));
+    List<RawModification> ldapMods = newRawModifications(add(ldapAttr));
 
     opList.add(newModifyOperation(null, ByteString.empty(), ldapMods));
     opList.add(newModifyOperation(noControls, ByteString.empty(), ldapMods));
     opList.add(newModifyOperation(null, ByteString.valueOf("o=test"), ldapMods));
     opList.add(newModifyOperation(noControls, ByteString.valueOf("o=test"), ldapMods));
 
-    ldapMods = new ArrayList<RawModification>();
-    ldapMods.add(delete(ldapAttr));
+    ldapMods = newRawModifications(delete(ldapAttr));
 
     opList.add(newModifyOperation(null, ByteString.empty(), ldapMods));
     opList.add(newModifyOperation(noControls, ByteString.empty(), ldapMods));
     opList.add(newModifyOperation(null, ByteString.valueOf("o=test"), ldapMods));
     opList.add(newModifyOperation(noControls, ByteString.valueOf("o=test"), ldapMods));
 
-    ldapMods = new ArrayList<RawModification>();
-    ldapMods.add(replace(ldapAttr));
+    ldapMods = newRawModifications(replace(ldapAttr));
 
     opList.add(newModifyOperation(null, ByteString.empty(), ldapMods));
     opList.add(newModifyOperation(noControls, ByteString.empty(), ldapMods));
     opList.add(newModifyOperation(null, ByteString.valueOf("o=test"), ldapMods));
     opList.add(newModifyOperation(noControls, ByteString.valueOf("o=test"), ldapMods));
 
-    ldapMods = new ArrayList<RawModification>();
-    ArrayList<ByteString> values2 = new ArrayList<ByteString>();
-    values2.add(ByteString.valueOf("bar"));
+    ArrayList<ByteString> values2 = newArrayList(ByteString.valueOf("bar"));
     LDAPAttribute ldapAttr2 = new LDAPAttribute("description", values2);
-    ldapMods.add(delete(ldapAttr));
-    ldapMods.add(add(ldapAttr2));
+    ldapMods = newRawModifications(delete(ldapAttr), add(ldapAttr2));
 
     opList.add(newModifyOperation(null, ByteString.empty(), ldapMods));
     opList.add(newModifyOperation(noControls, ByteString.empty(), ldapMods));
     opList.add(newModifyOperation(null, ByteString.valueOf("o=test"), ldapMods));
     opList.add(newModifyOperation(noControls, ByteString.valueOf("o=test"), ldapMods));
 
-    ldapMods = new ArrayList<RawModification>();
     ldapAttr2 = new LDAPAttribute("cn", values2);
-    ldapMods.add(replace(ldapAttr));
-    ldapMods.add(replace(ldapAttr2));
+    ldapMods = newRawModifications(replace(ldapAttr), replace(ldapAttr2));
 
     opList.add(newModifyOperation(null, ByteString.empty(), ldapMods));
     opList.add(newModifyOperation(noControls, ByteString.empty(), ldapMods));
@@ -144,8 +135,7 @@
 
 
 
-    List<Modification> mods = new ArrayList<Modification>();
-    mods.add(new Modification(ModificationType.ADD,
+    List<Modification> mods = newModifications(new Modification(ModificationType.ADD,
         Attributes.create("description", "foo")));
 
     opList.add(newModifyOperation(null, DN.nullDN(), mods));
@@ -153,8 +143,7 @@
     opList.add(newModifyOperation(null, DN.decode("o=test"), mods));
     opList.add(newModifyOperation(noControls, DN.decode("o=test"), mods));
 
-    mods = new ArrayList<Modification>();
-    mods.add(new Modification(ModificationType.DELETE,
+    mods = newModifications(new Modification(ModificationType.DELETE,
         Attributes.create("description", "foo")));
 
     opList.add(newModifyOperation(null, DN.nullDN(), mods));
@@ -162,8 +151,7 @@
     opList.add(newModifyOperation(null, DN.decode("o=test"), mods));
     opList.add(newModifyOperation(noControls, DN.decode("o=test"), mods));
 
-    mods = new ArrayList<Modification>();
-    mods.add(new Modification(ModificationType.REPLACE,
+    mods = newModifications(new Modification(ModificationType.REPLACE,
         Attributes.create("description", "foo")));
 
     opList.add(newModifyOperation(null, DN.nullDN(), mods));
@@ -171,22 +159,22 @@
     opList.add(newModifyOperation(null, DN.decode("o=test"), mods));
     opList.add(newModifyOperation(noControls, DN.decode("o=test"), mods));
 
-    mods = new ArrayList<Modification>();
-    mods.add(new Modification(ModificationType.DELETE,
-        Attributes.create("description", "foo")));
-    mods.add(new Modification(ModificationType.ADD,
-        Attributes.create("description", "bar")));
+    mods = newModifications(
+        new Modification(ModificationType.DELETE,
+            Attributes.create("description", "foo")),
+        new Modification(ModificationType.ADD,
+            Attributes.create("description", "bar")));
 
     opList.add(newModifyOperation(null, DN.nullDN(), mods));
     opList.add(newModifyOperation(noControls, DN.nullDN(), mods));
     opList.add(newModifyOperation(null, DN.decode("o=test"), mods));
     opList.add(newModifyOperation(noControls, DN.decode("o=test"), mods));
 
-    mods = new ArrayList<Modification>();
-    mods.add(new Modification(ModificationType.REPLACE,
-        Attributes.create("description", "foo")));
-    mods.add(new Modification(ModificationType.REPLACE,
-        Attributes.create("cn", "bar")));
+    mods = newModifications(
+        new Modification(ModificationType.REPLACE,
+            Attributes.create("description", "foo")),
+        new Modification(ModificationType.REPLACE,
+            Attributes.create("cn", "bar")));
 
     opList.add(newModifyOperation(null, DN.nullDN(), mods));
     opList.add(newModifyOperation(noControls, DN.nullDN(), mods));
@@ -236,9 +224,8 @@
 
 
   /** {@inheritDoc} */
-  @Override()
-  protected Operation[] createTestOperations()
-         throws Exception
+  @Override
+  protected Operation[] createTestOperations() throws Exception
   {
     Object[][]  objs = getModifyOperations();
     Operation[] ops  = new Operation[objs.length];
@@ -280,27 +267,25 @@
    * Tests the <CODE>getEntryDN</CODE> method that should decode
    * the raw entry dn and return a non-null DN.
    */
-  @Test()
+  @Test
   public void testGetEntryDNInitiallyNull()
   {
     LDAPAttribute attr = newLDAPAttribute("description", "foo");
-
-    List<RawModification> mods = new ArrayList<RawModification>();
-    mods.add(replace(attr));
+    List<RawModification> mods = newRawModifications(replace(attr));
 
     ModifyOperation modifyOperation = newModifyOperation(null, ByteString.empty(), mods);
     assertNotNull(modifyOperation.getEntryDN());
   }
 
 
-  private LDAPAttribute newLDAPAttribute(String sttributeType, String... valueStrings)
+  private LDAPAttribute newLDAPAttribute(String attributeType, String... valueStrings)
   {
     ArrayList<ByteString> values = new ArrayList<ByteString>();
     for (String valueStr : valueStrings)
     {
       values.add(ByteString.valueOf(valueStr));
     }
-    return new LDAPAttribute(sttributeType, values);
+    return new LDAPAttribute(attributeType, values);
   }
 
   /**
@@ -309,13 +294,12 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testGetEntryDNInitiallyNonNull()
-         throws Exception
+  @Test
+  public void testGetEntryDNInitiallyNonNull() throws Exception
   {
-    List<Modification> mods = new ArrayList<Modification>();
-    mods.add(new Modification(ModificationType.REPLACE,
-        Attributes.create("description", "foo")));
+    List<Modification> mods = newModifications(
+        new Modification(ModificationType.REPLACE,
+            Attributes.create("description", "foo")));
     ModifyOperation modifyOperation = newModifyOperation(null, DN.nullDN(), mods);
     assertNotNull(modifyOperation.getEntryDN());
   }
@@ -329,15 +313,13 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testGetEntryDNNonNullChangedToNull()
-         throws Exception
+  @Test
+  public void testGetEntryDNNonNullChangedToNull() throws Exception
   {
-    List<Modification> mods = new ArrayList<Modification>();
-    mods.add(new Modification(ModificationType.REPLACE,
-        Attributes.create("description", "foo")));
-    ModifyOperation modifyOperation =
-        newModifyOperation(null, DN.nullDN(), mods);
+    List<Modification> mods = newModifications(
+        new Modification(ModificationType.REPLACE,
+            Attributes.create("description", "foo")));
+    ModifyOperation modifyOperation = newModifyOperation(null, DN.nullDN(), mods);
     assertNotNull(modifyOperation.getEntryDN());
 
     modifyOperation.setRawEntryDN(ByteString.valueOf("ou=Users,o=test"));
@@ -358,9 +340,7 @@
          throws Exception
   {
     List<RawModification> rawMods = modifyOperation.getRawModifications();
-
-    List<RawModification> clonedMods =
-         new ArrayList<RawModification>(rawMods);
+    List<RawModification> clonedMods = new ArrayList<RawModification>(rawMods);
     modifyOperation.setRawModifications(clonedMods);
 
     LDAPAttribute attr = newLDAPAttribute("test", "test");
@@ -428,9 +408,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testGetAndAddModifications()
-         throws Exception
+  @Test
+  public void testGetAndAddModifications() throws Exception
   {
     Entry e = DirectoryServer.getEntry(DN.decode("o=test"));
     assertNull(e.getAttribute(DirectoryServer.getAttributeType("description", true)));
@@ -441,9 +420,9 @@
              Attributes.create("description", "foo")));
 
 
-    List<Modification> mods = new ArrayList<Modification>();
-    mods.add(new Modification(ModificationType.REPLACE,
-        Attributes.create("l", "Austin")));
+    List<Modification> mods = newModifications(
+        new Modification(ModificationType.REPLACE,
+            Attributes.create("l", "Austin")));
 
     ModifyOperation modifyOperation =
         getRootConnection().processModify(DN.decode("o=test"), mods);
@@ -461,7 +440,7 @@
   /**
    * Tests to ensure that a modify attempt fails if an invalid DN is provided.
    */
-  @Test()
+  @Test
   public void testFailInvalidDN()
   {
     LDAPAttribute attr = newLDAPAttribute("description", "foo");
@@ -476,7 +455,7 @@
    * Tests to ensure that a modify attempt fails if the target DN is a suffix
    * that doesn't exist.
    */
-  @Test()
+  @Test
   public void testFailNoSuchSuffix()
   {
     LDAPAttribute attr = newLDAPAttribute("description", "foo");
@@ -546,9 +525,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testSuccessAddAttribute()
-         throws Exception
+  @Test
+  public void testSuccessAddAttribute() throws Exception
   {
     Entry e = DirectoryServer.getEntry(DN.decode("o=test"));
     assertNull(e.getAttribute(DirectoryServer.getAttributeType("description", true)));
@@ -570,9 +548,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testSuccessAddAttributeValue()
-         throws Exception
+  @Test
+  public void testSuccessAddAttributeValue() throws Exception
   {
     Entry e = DirectoryServer.getEntry(DN.decode("o=test"));
 
@@ -2397,8 +2374,7 @@
     assertEquals(bindResponse.getResultCode(), 0);
 
     LDAPAttribute attr = newLDAPAttribute("entryUUID", "12345678-1234-1234-1234-1234567890ab");
-    List<RawModification> mods = new ArrayList<RawModification>();
-    mods.add(replace(attr));
+    List<RawModification> mods = newRawModifications(replace(attr));
 
     long modifyRequests  = ldapStatistics.getModifyRequests();
     long modifyResponses = ldapStatistics.getModifyResponses();
@@ -2538,8 +2514,7 @@
     assertEquals(bindResponse.getResultCode(), 0);
 
     LDAPAttribute attr = newLDAPAttribute("objectClass", "extensibleObject");
-    List<RawModification> mods = new ArrayList<RawModification>();
-    mods.add(add(attr));
+    List<RawModification> mods = newRawModifications(add(attr));
 
     long modifyRequests  = ldapStatistics.getModifyRequests();
     long modifyResponses = ldapStatistics.getModifyResponses();
@@ -2685,8 +2660,7 @@
     assertEquals(bindResponse.getResultCode(), 0);
 
     LDAPAttribute attr = newLDAPAttribute("objectClass", "extensibleObject");
-    List<RawModification> mods = new ArrayList<RawModification>();
-    mods.add(add(attr));
+    List<RawModification> mods = newRawModifications(add(attr));
 
     long modifyRequests  = ldapStatistics.getModifyRequests();
     long modifyResponses = ldapStatistics.getModifyResponses();
@@ -2716,22 +2690,27 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testSuccessNotifyChangeListeners()
-         throws Exception
+  @Test
+  public void testSuccessNotifyChangeListeners() throws Exception
   {
     TestChangeNotificationListener changeListener =
          new TestChangeNotificationListener();
-    DirectoryServer.registerChangeNotificationListener(changeListener);
-    assertEquals(changeListener.getModifyCount(), 0);
+    DirectoryServer.registerInternalPlugin(changeListener);
+    try
+    {
+      assertEquals(changeListener.getModifyCount(), 0);
 
-    LDAPAttribute attr = newLDAPAttribute("description", "foo");
-    ModifyOperation modifyOperation = processModify("o=test", replace(attr));
-    assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
-    retrieveSuccessfulOperationElements(modifyOperation);
+      LDAPAttribute attr = newLDAPAttribute("description", "foo");
+      ModifyOperation modifyOperation = processModify("o=test", replace(attr));
+      assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
+      retrieveSuccessfulOperationElements(modifyOperation);
 
-    assertEquals(changeListener.getModifyCount(), 1);
-    DirectoryServer.deregisterChangeNotificationListener(changeListener);
+      assertEquals(changeListener.getModifyCount(), 1);
+    }
+    finally
+    {
+      DirectoryServer.deregisterInternalPlugin(changeListener);
+    }
   }
 
 
@@ -2743,21 +2722,26 @@
    * @throws  Exception  If an unexpected problem occurs.
    */
   @Test(dataProvider = "baseDNs")
-  public void testFailDoNotNotifyChangeListeners(String baseDN)
-         throws Exception
+  public void testFailDoNotNotifyChangeListeners(String baseDN) throws Exception
   {
     TestChangeNotificationListener changeListener =
          new TestChangeNotificationListener();
-    DirectoryServer.registerChangeNotificationListener(changeListener);
-    assertEquals(changeListener.getModifyCount(), 0);
+    DirectoryServer.registerInternalPlugin(changeListener);
+    try
+    {
+      assertEquals(changeListener.getModifyCount(), 0);
 
-    LDAPAttribute attr = newLDAPAttribute("dc", "foo");
-    ModifyOperation modifyOperation = processModify(baseDN, replace(attr));
-    assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS);
-    retrieveFailedOperationElements(modifyOperation);
+      LDAPAttribute attr = newLDAPAttribute("dc", "foo");
+      ModifyOperation modifyOperation = processModify(baseDN, replace(attr));
+      assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS);
+      retrieveFailedOperationElements(modifyOperation);
 
-    assertEquals(changeListener.getModifyCount(), 0);
-    DirectoryServer.deregisterChangeNotificationListener(changeListener);
+      assertEquals(changeListener.getModifyCount(), 0);
+    }
+    finally
+    {
+      DirectoryServer.deregisterInternalPlugin(changeListener);
+    }
   }
 
 
@@ -2772,9 +2756,7 @@
          throws Exception
   {
     LDAPAttribute attr = newLDAPAttribute("description", "foo");
-
-    List<RawModification> mods = new ArrayList<RawModification>();
-    mods.add(replace(attr));
+    List<RawModification> mods = newRawModifications(replace(attr));
 
     ModifyOperation modifyOperation =
         newModifyOperation(null, ByteString.valueOf(baseDN), mods);
@@ -2798,9 +2780,7 @@
          throws Exception
   {
     LDAPAttribute attr = newLDAPAttribute("description", "foo");
-
-    List<RawModification> mods = new ArrayList<RawModification>();
-    mods.add(replace(attr));
+    List<RawModification> mods = newRawModifications(replace(attr));
 
     ModifyOperation modifyOperation =
         newModifyOperation(null, ByteString.valueOf(baseDN), mods);
@@ -2869,8 +2849,7 @@
 
     LDAPAttribute attr = newLDAPAttribute("description", "foo");
 
-    List<RawModification> mods = new ArrayList<RawModification>();
-    mods.add(replace(attr));
+    List<RawModification> mods = newRawModifications(replace(attr));
 
     ModifyRequestProtocolOp modifyRequest =
          new ModifyRequestProtocolOp(ByteString.valueOf(baseDN), mods);
@@ -2897,9 +2876,8 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testDisconnectInPreOperationModify()
-         throws Exception
+  @Test
+  public void testDisconnectInPreOperationModify() throws Exception
   {
 
     Socket s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort());
@@ -2921,8 +2899,7 @@
 
     LDAPAttribute attr = newLDAPAttribute("description", "foo");
 
-    List<RawModification> mods = new ArrayList<RawModification>();
-    mods.add(replace(attr));
+    List<RawModification> mods = newRawModifications(replace(attr));
 
     ModifyRequestProtocolOp modifyRequest =
          new ModifyRequestProtocolOp(ByteString.valueOf("o=test"), mods);
@@ -2973,8 +2950,7 @@
 
     LDAPAttribute attr = newLDAPAttribute("description", "foo");
 
-    List<RawModification> mods = new ArrayList<RawModification>();
-    mods.add(replace(attr));
+    List<RawModification> mods = newRawModifications(replace(attr));
 
     ModifyRequestProtocolOp modifyRequest =
          new ModifyRequestProtocolOp(ByteString.valueOf(baseDN), mods);
@@ -3049,9 +3025,7 @@
 
 
     LDAPAttribute attr = newLDAPAttribute("description", "foo");
-
-    List<RawModification> mods = new ArrayList<RawModification>();
-    mods.add(replace(attr));
+    List<RawModification> mods = newRawModifications(replace(attr));
 
     ModifyRequestProtocolOp modifyRequest =
          new ModifyRequestProtocolOp(ByteString.valueOf(baseDN), mods);
@@ -3092,10 +3066,18 @@
     StaticUtils.close(s);
   }
 
+  private List<Modification> newModifications(Modification... mods)
+  {
+    return newArrayList(mods);
+  }
 
+  private List<RawModification> newRawModifications(RawModification... mods)
+  {
+    return newArrayList(mods);
+  }
 
   /**
-   * Tests a modify operation that attemtps to set a value for an attribute type
+   * Tests a modify operation that attempts to set a value for an attribute type
    * that is marked OBSOLETE in the server schema.
    *
    * @param  baseDN  The base DN for the test backend.
@@ -3214,16 +3196,14 @@
    *
    * @throws  Exception  If an unexpected problem occurs.
    */
-  @Test()
-  public void testShortCircuitInPreParse()
-         throws Exception
+  @Test
+  public void testShortCircuitInPreParse() throws Exception
   {
     List<Control> controls =
          ShortCircuitPlugin.createShortCircuitControlList(0, "PreParse");
 
-    List<RawModification> mods = new ArrayList<RawModification>();
-    mods.add(RawModification.create(ModificationType.REPLACE, "description",
-                                    "foo"));
+    List<RawModification> mods = newRawModifications(
+        RawModification.create(ModificationType.REPLACE, "description", "foo"));
 
     ModifyOperation modifyOperation =
         newModifyOperation(controls, ByteString.valueOf("o=test"), mods);
@@ -3264,9 +3244,7 @@
          "userPassword: password");
 
     LDAPAttribute attr = newLDAPAttribute("givenName", "Test");
-
-    List<RawModification> mods = new ArrayList<RawModification>();
-    mods.add(add(attr));
+    List<RawModification> mods = newRawModifications(add(attr));
 
     List<Control> requestControls = new ArrayList<Control>();
     requestControls.add(
@@ -3303,9 +3281,7 @@
          "userPassword: password");
 
     LDAPAttribute attr = newLDAPAttribute("givenName", "Foo");
-
-    List<RawModification> mods = new ArrayList<RawModification>();
-    mods.add(delete(attr));
+    List<RawModification> mods = newRawModifications(delete(attr));
 
     List<Control> requestControls = new ArrayList<Control>();
     requestControls.add(
@@ -3342,8 +3318,7 @@
          "userPassword: password");
 
     LDAPAttribute attr = new LDAPAttribute("description");
-    List<RawModification> mods = new ArrayList<RawModification>();
-    mods.add(delete(attr));
+    List<RawModification> mods = newRawModifications(delete(attr));
 
     List<Control> requestControls = new ArrayList<Control>();
     requestControls.add(
@@ -3518,11 +3493,10 @@
    *           If an unexpected problem occurs.
    */
   @Test
-  public void testModifyDelPasswordAttributeWithOption()
-      throws Exception
+  public void testModifyDelPasswordAttributeWithOption() throws Exception
   {
     // @formatter:off
-        Entry e = TestCaseUtils.makeEntry(
+    Entry e = TestCaseUtils.makeEntry(
         "dn: cn=Test User,o=test",
         "objectClass: top",
         "objectClass: person",
@@ -3560,8 +3534,7 @@
    *           If an unexpected problem occurs.
    */
   @Test
-  public void testModifyReplaceEmptyPasswordAttributeWithOption()
-      throws Exception
+  public void testModifyReplaceEmptyPasswordAttributeWithOption() throws Exception
   {
     // @formatter:off
         Entry e = TestCaseUtils.makeEntry(
@@ -3600,8 +3573,7 @@
    *           If an unexpected problem occurs.
    */
   @Test
-  public void testModifyAddPasswordAttributeWithOption()
-      throws Exception
+  public void testModifyAddPasswordAttributeWithOption() throws Exception
   {
     // @formatter:off
         TestCaseUtils.addEntry(
@@ -3638,8 +3610,7 @@
    *           If an unexpected problem occurs.
    */
   @Test
-  public void testModifyReplaceWithValuesPasswordAttributeWithOption()
-      throws Exception
+  public void testModifyReplaceWithValuesPasswordAttributeWithOption() throws Exception
   {
     // @formatter:off
         TestCaseUtils.addEntry(
@@ -3676,8 +3647,7 @@
    *           If an unexpected problem occurs.
    */
   @Test(dataProvider = "baseDNs")
-  public void testAddCertificateWithoutBinaryOption(String baseDN)
-         throws Exception
+  public void testAddCertificateWithoutBinaryOption(String baseDN) throws Exception
   {
     TestCaseUtils.addEntry(
          "dn: uid=test.user," + baseDN,
@@ -3750,8 +3720,8 @@
     // First check that adding "dc" fails because it is not allowed by
     // inetOrgPerson.
     LDAPAttribute attr = newLDAPAttribute("dc", "foo");
-    List<RawModification> mods = new ArrayList<RawModification>();
-    mods.add(add(attr));
+    List<RawModification> mods = newRawModifications(add(attr));
+
     ModifyOperation modifyOperation = processModify("cn=Test User," + baseDN, mods);
     assertEquals(modifyOperation.getResultCode(), ResultCode.OBJECTCLASS_VIOLATION);
 
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/TestChangeNotificationListener.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/TestChangeNotificationListener.java
index 3d0a33b..2d3dcb4 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/TestChangeNotificationListener.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/TestChangeNotificationListener.java
@@ -22,105 +22,109 @@
  *
  *
  *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Portions Copyright 2014 ForgeRock AS
  */
 package org.opends.server.core;
 
-
-
+import java.util.EnumSet;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import org.opends.server.api.ChangeNotificationListener;
-import org.opends.server.types.Entry;
+import org.opends.server.api.plugin.InternalDirectoryServerPlugin;
+import org.opends.server.api.plugin.PluginResult.PostResponse;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.ResultCode;
 import org.opends.server.types.operation.PostResponseAddOperation;
 import org.opends.server.types.operation.PostResponseDeleteOperation;
-import org.opends.server.types.operation.PostResponseModifyOperation;
 import org.opends.server.types.operation.PostResponseModifyDNOperation;
+import org.opends.server.types.operation.PostResponseModifyOperation;
 
-
+import static org.opends.server.api.plugin.PluginType.*;
 
 /**
  * This class provides a simple change notification listener that simply counts
  * the number of times that it is invoked during processing.
  */
-public class TestChangeNotificationListener
-       implements ChangeNotificationListener
+class TestChangeNotificationListener extends InternalDirectoryServerPlugin
 {
-  // The number of times that the listener has been invoked for add operations.
-  private AtomicInteger addCount;
+  /** The number of times that the listener has been invoked for add operations. */
+  private final AtomicInteger addCount = new AtomicInteger(0);
 
-  // The number of times that the listener has been invoked for delete
-  // operations.
-  private AtomicInteger deleteCount;
+  /**
+   * The number of times that the listener has been invoked for delete
+   * operations.
+   */
+  private final AtomicInteger deleteCount = new AtomicInteger(0);
 
-  // The number of times that the listener has been invoked for modify
-  // operations.
-  private AtomicInteger modifyCount;
+  /**
+   * The number of times that the listener has been invoked for modify
+   * operations.
+   */
+  private final AtomicInteger modifyCount = new AtomicInteger(0);
 
-  // The number of times that the listener has been invoked for modify DN
-  // operations.
-  private AtomicInteger modifyDNCount;
-
-
+  /**
+   * The number of times that the listener has been invoked for modify DN
+   * operations.
+   */
+  private final AtomicInteger modifyDNCount = new AtomicInteger(0);
 
   /**
    * Creates a new instance of this change notification listener.
+   *
+   * @throws DirectoryException
+   *           If a problem occurs while creating an instance of this class
    */
-  public TestChangeNotificationListener()
+  public TestChangeNotificationListener() throws DirectoryException
   {
-    addCount      = new AtomicInteger(0);
-    deleteCount   = new AtomicInteger(0);
-    modifyCount   = new AtomicInteger(0);
-    modifyDNCount = new AtomicInteger(0);
+    super(DN.decode("cn=TestChangeNotificationListener"),
+        EnumSet.of(POST_RESPONSE_ADD, POST_RESPONSE_MODIFY, POST_RESPONSE_MODIFY_DN, POST_RESPONSE_DELETE),
+        true);
   }
 
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public void handleAddOperation(PostResponseAddOperation addOperation,
-                                 Entry entry)
+  /** {@inheritDoc} */
+  @Override
+  public PostResponse doPostResponse(PostResponseAddOperation op)
   {
-    addCount.incrementAndGet();
+    if (op.getResultCode() == ResultCode.SUCCESS)
+    {
+      addCount.incrementAndGet();
+    }
+    return PostResponse.continueOperationProcessing();
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public void handleDeleteOperation(PostResponseDeleteOperation deleteOperation,
-                                    Entry entry)
+  /** {@inheritDoc} */
+  @Override
+  public PostResponse doPostResponse(PostResponseDeleteOperation op)
   {
-    deleteCount.incrementAndGet();
+    if (op.getResultCode() == ResultCode.SUCCESS)
+    {
+      deleteCount.incrementAndGet();
+    }
+    return PostResponse.continueOperationProcessing();
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public void handleModifyOperation(PostResponseModifyOperation modifyOperation,
-                                    Entry oldEntry, Entry newEntry)
+  /** {@inheritDoc} */
+  @Override
+  public PostResponse doPostResponse(PostResponseModifyOperation op)
   {
-    modifyCount.incrementAndGet();
+    if (op.getResultCode() == ResultCode.SUCCESS)
+    {
+      modifyCount.incrementAndGet();
+    }
+    return PostResponse.continueOperationProcessing();
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public void handleModifyDNOperation(
-                   PostResponseModifyDNOperation modifyDNOperation,
-                   Entry oldEntry, Entry newEntry)
+  /** {@inheritDoc} */
+  @Override
+  public PostResponse doPostResponse(PostResponseModifyDNOperation op)
   {
-    modifyDNCount.incrementAndGet();
+    if (op.getResultCode() == ResultCode.SUCCESS)
+    {
+      modifyDNCount.incrementAndGet();
+    }
+    return PostResponse.continueOperationProcessing();
   }
 
-
-
   /**
    * Resets all of the counts to zero.
    */
@@ -132,8 +136,6 @@
     modifyDNCount.set(0);
   }
 
-
-
   /**
    * Retrieves the current invocation count for add operations.
    *
@@ -144,8 +146,6 @@
     return addCount.get();
   }
 
-
-
   /**
    * Retrieves the current invocation count for delete operations.
    *
@@ -156,8 +156,6 @@
     return deleteCount.get();
   }
 
-
-
   /**
    * Retrieves the current invocation count for modify operations.
    *
@@ -168,8 +166,6 @@
     return modifyCount.get();
   }
 
-
-
   /**
    * Retrieves the current invocation count for modify DN operations.
    *

--
Gitblit v1.10.0