From df1323b2cab4997aff8f3ca12817715e30c92cb2 Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Wed, 19 Nov 2014 11:01:37 +0000
Subject: [PATCH] OPENDJ-1545 Remove Workflow, NetworkGroups and related attempts at building a proxy

---
 opendj3-server-dev/src/server/org/opends/server/core/DirectoryServer.java                                        |   59 ---
 /dev/null                                                                                                        |  321 ---------------------
 opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/WorkflowTopologyTest.java           |  139 ++------
 opendj3-server-dev/src/server/org/opends/server/core/BindOperationBasis.java                                     |   52 ---
 opendj3-server-dev/src/server/org/opends/server/core/RootDseWorkflowTopology.java                                |   30 +
 opendj3-server-dev/src/server/org/opends/server/core/WorkflowTopologyNode.java                                   |  120 +++----
 opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/NetworkGroupTest.java |   35 -
 opendj3-server-dev/src/server/org/opends/server/core/networkgroups/NetworkGroup.java                             |   50 +--
 opendj3-server-dev/src/server/org/opends/server/core/WorkflowTopology.java                                       |   91 ++++-
 9 files changed, 223 insertions(+), 674 deletions(-)

diff --git a/opendj3-server-dev/src/server/org/opends/server/core/BindOperationBasis.java b/opendj3-server-dev/src/server/org/opends/server/core/BindOperationBasis.java
index acabb16..4ec7e5a 100644
--- a/opendj3-server-dev/src/server/org/opends/server/core/BindOperationBasis.java
+++ b/opendj3-server-dev/src/server/org/opends/server/core/BindOperationBasis.java
@@ -42,7 +42,7 @@
 
 import static org.forgerock.opendj.ldap.ResultCode.*;
 import static org.opends.messages.CoreMessages.*;
-import static org.opends.server.config.ConfigConstants.*;
+import static org.opends.server.core.DirectoryServer.*;
 import static org.opends.server.loggers.AccessLogger.*;
 
 /**
@@ -501,19 +501,16 @@
   @Override
   public final void run()
   {
-    setResultCode(ResultCode.UNDEFINED);
-
     // Start the processing timer and initially set the result to indicate that
     // the result is unknown.
+    setResultCode(ResultCode.UNDEFINED);
     setProcessingStartTime();
 
-    // Log the bind request message.
     logBindRequest(this);
 
-    ClientConnection clientConnection = getClientConnection();
-
     // Wipe out any existing authentication for the client connection and create
     // a placeholder that will be used if the bind is successful.
+    ClientConnection clientConnection = getClientConnection();
     clientConnection.setUnauthenticated();
 
     // Abandon any operations that may be in progress for the client.
@@ -522,20 +519,13 @@
     clientConnection.cancelAllOperationsExcept(cancelRequest, getMessageID());
 
 
-    // Get the plugin config manager that will be used for invoking plugins.
-    PluginConfigManager pluginConfigManager =
-        DirectoryServer.getPluginConfigManager();
-
-
     // This flag is set to true as soon as a workflow has been executed.
     boolean workflowExecuted = false;
-
-
     try
     {
       // Invoke the pre-parse bind plugins.
       PluginResult.PreParse preParseResult =
-          pluginConfigManager.invokePreParseBindPlugins(this);
+          getPluginConfigManager().invokePreParseBindPlugins(this);
       if (!preParseResult.continueProcessing())
       {
         setResultCode(preParseResult.getResultCode());
@@ -567,30 +557,7 @@
           }
       }
 
-
-      // Special case to manage RootDNs
-      // RootDNs are stored in cn=config but this workflow is not
-      // available through non-admin network groups.
-      // So if the bind DN is in cn=config, we directly retrieve
-      // the workflow handling cn=config
-      // FIXME: it would be better to store RootDNs in a separate backend.
-      // Issue #3502 has been logged to track this request.
-      boolean isInConfig;
-      try {
-        isInConfig = bindDN.isDescendantOf(DN.valueOf(DN_CONFIG_ROOT));
-      } catch (DirectoryException ex) {
-        // can not happen
-        isInConfig = false;
-      }
-
-      Workflow workflow;
-      if (isInConfig) {
-        workflow = WorkflowImpl.getWorkflow("__config.ldif__#cn=config");
-      } else {
-        // Retrieve the network group attached to the client connection
-        // and get a workflow to process the operation.
-        workflow = NetworkGroup.getWorkflowCandidate(bindDN);
-      }
+      Workflow workflow = NetworkGroup.getWorkflowCandidate(bindDN);
       if (workflow == null)
       {
         // We have found no workflow for the requested base DN, just return
@@ -612,10 +579,7 @@
     }
     finally
     {
-      // Stop the processing timer.
       setProcessingStopTime();
-
-      // Log the bind response.
       logBindResponse(this);
 
       // Send the bind response to the client.
@@ -627,23 +591,19 @@
       {
         clientConnection.finishSaslBind();
       }
-
       clientConnection.finishBindOrStartTLS();
 
-      // Invoke the post-response bind plugins.
       invokePostResponsePlugins(workflowExecuted);
     }
   }
 
-
   /**
    * Invokes the post response plugins. If a workflow has been executed
    * then invoke the post response plugins provided by the workflow
    * elements of the workflow, otherwise invoke the post response plugins
    * that have been registered with the current operation.
    *
-   * @param workflowExecuted <code>true</code> if a workflow has been
-   *                         executed
+   * @param workflowExecuted <code>true</code> if a workflow has been executed
    */
   private void invokePostResponsePlugins(boolean workflowExecuted)
   {
diff --git a/opendj3-server-dev/src/server/org/opends/server/core/DirectoryServer.java b/opendj3-server-dev/src/server/org/opends/server/core/DirectoryServer.java
index 575cdde..2b9cbe7 100644
--- a/opendj3-server-dev/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opendj3-server-dev/src/server/org/opends/server/core/DirectoryServer.java
@@ -229,6 +229,7 @@
 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.workflowelement.localbackend.LocalBackendWorkflowElement.*;
 
 /**
  * This class defines the core of the Directory Server.  It manages the startup
@@ -2146,53 +2147,29 @@
     // with the default/internal/admin network group.
     for (DN curBaseDN: backend.getBaseDNs())
     {
-      createAndRegisterWorkflow(curBaseDN, backend);
+      createWorkflow(curBaseDN, backend);
     }
   }
 
-  private static void createAndRegisterWorkflow(DN baseDN, Backend<?> backend) throws DirectoryException
-  {
-    WorkflowImpl workflowImpl = createWorkflow(baseDN, backend);
-    NetworkGroup.getDefaultNetworkGroup().registerWorkflow(workflowImpl);
-  }
-
-
   /**
    * Creates one workflow for a given base DN in a backend.
    *
    * @param baseDN   the base DN of the workflow to create
    * @param backend  the backend handled by the workflow
-   *
-   * @return the newly created workflow
-   *
    * @throws  DirectoryException  If the workflow ID for the provided
    *                              workflow conflicts with the workflow
    *                              ID of an existing workflow.
    */
-  private static WorkflowImpl createWorkflow(DN baseDN, Backend<?> backend) throws DirectoryException
+  private static void createWorkflow(DN baseDN, Backend<?> backend) throws DirectoryException
   {
-    String backendID = backend.getBackendID();
-
     // Create a root workflow element to encapsulate the backend
-    LocalBackendWorkflowElement rootWE =
-        LocalBackendWorkflowElement.createAndRegister(backendID, backend);
+    final String backendID = backend.getBackendID();
+    LocalBackendWorkflowElement rootWE = createAndRegister(backendID, backend);
 
-    // The workflow ID is "backendID + baseDN".
-    // We cannot use backendID as workflow identifier because a backend
-    // may handle several base DNs. We cannot use baseDN either because
-    // we might want to configure several workflows handling the same
-    // baseDN through different network groups. So a mix of both
-    // backendID and baseDN should be ok.
-    String workflowID = backend.getBackendID() + "#" + baseDN;
-
-    // Create the workflow for the base DN and register the workflow with
-    // the server.
-    WorkflowImpl workflowImpl = new WorkflowImpl(workflowID, baseDN, rootWE);
-    workflowImpl.register();
-    return workflowImpl;
+    // Create the workflow for the base DN and register the workflow with the server
+    NetworkGroup.getDefaultNetworkGroup().registerWorkflow(backendID, baseDN, rootWE);
   }
 
-
   /**
    * Creates the missing workflows, one for the config backend and one for
    * the rootDSE backend.
@@ -5367,10 +5344,8 @@
 
       // Since we've committed the changes we need to log any issues
       // that this registration has caused
-      if (warnings != null) {
-        for (LocalizableMessage warning : warnings) {
-          logger.error(warning);
-        }
+      for (LocalizableMessage warning : warnings) {
+        logger.error(warning);
       }
 
       // When a new baseDN is registered with the server we have to create
@@ -5381,7 +5356,7 @@
         // the workflow with the default network group, but don't register
         // the workflow if the backend happens to be the configuration
         // backend because it's too soon for the config backend.
-        createAndRegisterWorkflow(baseDN, backend);
+        createWorkflow(baseDN, backend);
       }
     }
   }
@@ -5409,17 +5384,14 @@
 
       // Since we've committed the changes we need to log any issues
       // that this registration has caused
-      if (warnings != null) {
-        for (LocalizableMessage error : warnings) {
-          logger.error(error);
-        }
+      for (LocalizableMessage error : warnings) {
+        logger.error(error);
       }
 
       // Now we need to deregister the workflow that was associated with the base DN
       if (!baseDN.equals(DN.valueOf("cn=config")))
       {
-        WorkflowImpl workflow = (WorkflowImpl) NetworkGroup.getDefaultNetworkGroup().deregisterWorkflow(baseDN);
-        workflow.deregister();
+        NetworkGroup.getDefaultNetworkGroup().deregisterWorkflow(baseDN);
       }
     }
   }
@@ -7175,10 +7147,7 @@
         logger.traceException(e);
     }
 
-    // Deregister all workflows.
-    WorkflowImpl.deregisterAllOnShutdown();
-
-    // Deregister all network group configuration.
+    // Deregister all workflows and network group configuration.
     NetworkGroup.deregisterAllOnShutdown();
 
     // Force a new InternalClientConnection to be created on restart.
diff --git a/opendj3-server-dev/src/server/org/opends/server/core/RootDseWorkflowTopology.java b/opendj3-server-dev/src/server/org/opends/server/core/RootDseWorkflowTopology.java
index d89c49a..9a791c9 100644
--- a/opendj3-server-dev/src/server/org/opends/server/core/RootDseWorkflowTopology.java
+++ b/opendj3-server-dev/src/server/org/opends/server/core/RootDseWorkflowTopology.java
@@ -35,6 +35,7 @@
 import org.opends.server.types.DN;
 import org.opends.server.types.Operation;
 import org.opends.server.types.OperationType;
+import org.opends.server.workflowelement.localbackend.LocalBackendWorkflowElement;
 
 /**
  * This class implements the workflow node that handles the root DSE entry.
@@ -52,21 +53,23 @@
    */
   private NetworkGroupNamingContexts namingContexts;
 
-
   /**
    * Creates a workflow node to handle the root DSE entry.
    *
-   * @param workflowImpl    the workflow which contains the processing for
-   *                        the root DSE backend
-   * @param namingContexts  the list of naming contexts being registered
-   *                        with the network group the root DSE belongs to
+   * @param backendId
+   *          the backendId
+   * @param baseDN
+   *          identifies the data handled by the workflow
+   * @param rootWorkflowElement
+   *          the root node of the task tree
+   * @param namingContexts
+   *          the list of naming contexts being registered with the network
+   *          group the root DSE belongs to
    */
-  public RootDseWorkflowTopology(
-      WorkflowImpl               workflowImpl,
-      NetworkGroupNamingContexts namingContexts
-      )
+  public RootDseWorkflowTopology(String backendId, DN baseDN, LocalBackendWorkflowElement rootWorkflowElement,
+      NetworkGroupNamingContexts namingContexts)
   {
-    super(workflowImpl);
+    super(backendId, baseDN, rootWorkflowElement);
     this.namingContexts = namingContexts;
   }
 
@@ -89,7 +92,7 @@
     }
     else
     {
-      getWorkflowImpl().execute(operation);
+      super.execute(operation);
     }
   }
 
@@ -113,7 +116,7 @@
     // is a search base on the null suffix.
     if (originalScope == SearchScope.BASE_OBJECT)
     {
-      getWorkflowImpl().execute(searchOp);
+      super.execute(searchOp);
       return;
     }
 
@@ -177,9 +180,8 @@
    */
   public StringBuilder toString(String leftMargin)
   {
-    String workflowID = getWorkflowImpl().getWorkflowId();
     StringBuilder sb = new StringBuilder();
-    sb.append(leftMargin).append("Workflow ID = ").append(workflowID).append("\n");
+    sb.append(leftMargin).append("Workflow ID = ").append(getWorkflowId()).append("\n");
     sb.append(leftMargin).append("         baseDN:[ \"\" ]\n");
     return sb;
   }
diff --git a/opendj3-server-dev/src/server/org/opends/server/core/WorkflowImpl.java b/opendj3-server-dev/src/server/org/opends/server/core/WorkflowImpl.java
deleted file mode 100644
index f99cb70..0000000
--- a/opendj3-server-dev/src/server/org/opends/server/core/WorkflowImpl.java
+++ /dev/null
@@ -1,321 +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 2008 Sun Microsystems, Inc.
- *      Portions Copyright 2014 ForgeRock AS
- */
-package org.opends.server.core;
-
-import java.util.TreeMap;
-
-import org.forgerock.i18n.LocalizableMessageBuilder;
-import org.forgerock.opendj.ldap.ResultCode;
-import org.opends.server.types.CanceledOperationException;
-import org.opends.server.types.DN;
-import org.opends.server.types.DirectoryException;
-import org.opends.server.types.Operation;
-import org.opends.server.workflowelement.localbackend.LocalBackendWorkflowElement;
-
-import static org.forgerock.util.Reject.*;
-import static org.opends.messages.CoreMessages.*;
-
-/**
- * This class implements the workflow interface. Each task in the workflow
- * is implemented by a WorkflowElement. All the tasks in the workflow are
- * structured in a tree of tasks and the root node of the task tree is
- * stored in the Workflow class itself. To execute a workflow, one just need
- * to call the execute method on the root node of the task tree. Then each
- * task in turn will execute its subordinate nodes and synchronizes them
- * as needed.
- */
-public class WorkflowImpl implements Workflow
-{
-  /** The workflow identifier used by the configuration. */
-  private final String workflowID;
-
-  /** The root of the workflow task tree. */
-  private LocalBackendWorkflowElement rootWorkflowElement;
-
-  /** The base DN of the data handled by the workflow. */
-  private final DN baseDN;
-
-  /**
-   * Flag indicating whether the workflow root node of the task tree is
-   * handling a private local backend.
-   * A private local backend is used by the server to store "private data"
-   * such as schemas, tasks, monitoring data, configuration data... Such
-   * private data are not returned upon a subtree search on the root DSE.
-   * Also it is not planned to have anything but a single node task tree
-   * to handle private local backend. So workflows used for proxy and
-   * virtual will always be made public (ie. not private). So, unless the
-   * rootWorkflowElement is handling a private local backend, the isPrivate
-   * flag will always return false.
-   */
-  private final boolean isPrivate;
-
-  /** The set of workflows registered with the server. */
-  private static TreeMap<String, Workflow> registeredWorkflows =
-    new TreeMap<String, Workflow>();
-
-  /** A lock to protect concurrent access to the registeredWorkflows. */
-  private final static Object registeredWorkflowsLock = new Object();
-
-  /**
-   * A reference counter used to count the number of workflow nodes that
-   * were registered with a network group. A workflow can be disabled or
-   * deleted only when its reference counter value is 0.
-   */
-  private int referenceCounter;
-  private final Object referenceCounterLock = new Object();
-
-
-  /**
-   * Creates a new instance of a workflow implementation. To define a workflow
-   * one needs to provide a task tree root node (the rootWorkflowElement) and
-   * a base DN to identify the data set upon which the tasks can be applied.
-   *
-   * The rootWorkflowElement must not be null.
-   *
-   * @param workflowId          workflow internal identifier
-   * @param baseDN              identifies the data handled by the workflow
-   * @param rootWorkflowElement the root node of the workflow task tree
-   */
-  public WorkflowImpl(String workflowId, DN baseDN, LocalBackendWorkflowElement rootWorkflowElement
-      )
-  {
-    this.workflowID = workflowId;
-    this.baseDN = baseDN;
-    this.rootWorkflowElement = rootWorkflowElement;
-    if (this.rootWorkflowElement != null)
-    {
-      this.isPrivate = rootWorkflowElement.isPrivate();
-    }
-    else
-    {
-      this.isPrivate = false;
-    }
-  }
-
-  /**
-   * Gets the base DN of the data set being handled by the workflow.
-   *
-   * @return the workflow base DN
-   */
-  @Override
-  public DN getBaseDN()
-  {
-    return baseDN;
-  }
-
-
-  /**
-   * Gets the workflow internal identifier.
-   *
-   * @return the workflow internal identifier
-   */
-  public String getWorkflowId()
-  {
-    return workflowID;
-  }
-
-
-  /**
-   * Indicates whether the root node of the workflow task tree is
-   * handling a private local backend.
-   *
-   * @return <code>true</code> if the workflow encapsulates a private local
-   *         backend
-   */
-  public boolean isPrivate()
-  {
-    return isPrivate;
-  }
-
-
-  /**
-   * Executes all the tasks defined by the workflow task tree for a given
-   * operation.
-   *
-   * @param operation  the operation to execute
-   *
-   * @throws CanceledOperationException if this operation should
-   * be canceled.
-   */
-  @Override
-  public void execute(Operation operation)
-    throws CanceledOperationException
-  {
-    if (rootWorkflowElement != null)
-    {
-      rootWorkflowElement.execute(operation);
-    }
-    else
-    {
-      // No root workflow element? It's a configuration error.
-      operation.setResultCode(ResultCode.OPERATIONS_ERROR);
-      LocalizableMessageBuilder message = new LocalizableMessageBuilder(
-        ERR_ROOT_WORKFLOW_ELEMENT_NOT_DEFINED.get(workflowID));
-      operation.setErrorMessage(message);
-    }
-  }
-
-
-  /**
-   * Registers the current workflow (this) with the server.
-   *
-   * @throws  DirectoryException  If the workflow ID for the provided workflow
-   *                              conflicts with the workflow ID of an existing
-   *                              workflow.
-   */
-  void register() throws DirectoryException
-  {
-    ifNull(workflowID);
-
-    synchronized (registeredWorkflowsLock)
-    {
-      // The workflow must not be already registered
-      if (registeredWorkflows.containsKey(workflowID))
-      {
-        throw new DirectoryException(
-            ResultCode.UNWILLING_TO_PERFORM,
-            ERR_REGISTER_WORKFLOW_ALREADY_EXISTS.get(workflowID));
-      }
-
-      TreeMap<String, Workflow> newRegisteredWorkflows =
-        new TreeMap<String, Workflow>(registeredWorkflows);
-      newRegisteredWorkflows.put(workflowID, this);
-      registeredWorkflows = newRegisteredWorkflows;
-    }
-  }
-
-
-  /**
-   * Deregisters the current workflow (this) with the server.
-   */
-  void deregister()
-  {
-    ifNull(workflowID);
-
-    // Deregister the workflow with the list of registered workflows.
-    synchronized (registeredWorkflowsLock)
-    {
-      TreeMap<String, Workflow> newWorkflows =
-        new TreeMap<String, Workflow>(registeredWorkflows);
-      newWorkflows.remove(workflowID);
-      registeredWorkflows = newWorkflows;
-    }
-  }
-
-
-  /**
-   * Deregisters all Workflows that have been registered.  This should be
-   * called when the server is shutting down.
-   */
-  static void deregisterAllOnShutdown()
-  {
-    synchronized (registeredWorkflowsLock)
-    {
-      registeredWorkflows = new TreeMap<String, Workflow>();
-    }
-  }
-
-
-  /**
-   * Gets a workflow that was registered with the server.
-   *
-   * @param workflowID  the ID of the workflow to get
-   * @return the requested workflow
-   */
-  static Workflow getWorkflow(String workflowID)
-  {
-    return registeredWorkflows.get(workflowID);
-  }
-
-  /**
-   * Gets the root workflow element for test purpose only.
-   *
-   * @return the root workflow element.
-   */
-  LocalBackendWorkflowElement getRootWorkflowElement()
-  {
-    return rootWorkflowElement;
-  }
-
-  /**
-   * Display the workflow object.
-   * @return a string identifying the workflow.
-   */
-  @Override
-  public String toString()
-  {
-    return "Workflow " + workflowID;
-  }
-
-  /**
-   * Increments the workflow reference counter.
-   * <p>
-   * As long as the counter value is not 0 the workflow cannot be
-   * disabled nor deleted.
-   */
-  public void incrementReferenceCounter()
-  {
-    synchronized (referenceCounterLock)
-    {
-      referenceCounter++;
-    }
-  }
-
-
-  /**
-   * Decrements the workflow reference counter.
-   * <p>
-   * As long as the counter value is not 0 the workflow cannot be
-   * disabled nor deleted.
-   */
-  public void decrementReferenceCounter()
-  {
-    synchronized (referenceCounterLock)
-    {
-      if (referenceCounter == 0)
-      {
-        // the counter value is 0, we should not need to decrement anymore
-        throw new AssertionError(
-          "Reference counter of the workflow " + workflowID
-          + " is already set to 0, cannot decrement it anymore"
-          );
-      }
-      referenceCounter--;
-    }
-  }
-
-
-  /**
-   * Gets the value of the reference counter of the workflow.
-   *
-   * @return the reference counter of the workflow
-   */
-  public int getReferenceCounter()
-  {
-    return referenceCounter;
-  }
-}
diff --git a/opendj3-server-dev/src/server/org/opends/server/core/WorkflowTopology.java b/opendj3-server-dev/src/server/org/opends/server/core/WorkflowTopology.java
index d985c77..62c06a2 100644
--- a/opendj3-server-dev/src/server/org/opends/server/core/WorkflowTopology.java
+++ b/opendj3-server-dev/src/server/org/opends/server/core/WorkflowTopology.java
@@ -26,8 +26,12 @@
  */
 package org.opends.server.core;
 
-import org.opends.server.types.DN;
 import org.forgerock.opendj.ldap.SearchScope;
+import org.forgerock.util.Reject;
+import org.opends.server.types.CanceledOperationException;
+import org.opends.server.types.DN;
+import org.opends.server.types.Operation;
+import org.opends.server.workflowelement.localbackend.LocalBackendWorkflowElement;
 
 /**
  * This class is the base class used to build the workflow topology.
@@ -39,36 +43,41 @@
  * nodes in the workflow topology (WorkflowTopologyNode) and the second
  * one is used to implement the root DSE node (RootDseWorkflowTopology).
  */
-public abstract class WorkflowTopology implements Workflow
+abstract class WorkflowTopology implements Workflow
 {
-  /** The workflow implementation containing the task tree (ie. the processing). */
-  private WorkflowImpl workflowImpl;
+  /** The workflow identifier used by the configuration. */
+  private final String workflowId;
+
+  /** The root of the workflow task tree. */
+  private final LocalBackendWorkflowElement rootWorkflowElement;
+
+  /** The base DN of the data handled by the workflow. */
+  private final DN baseDN;
 
   /**
    * Create a new instance of the workflow topology base class.
-   * The instance is initialized with the workflow implementation which
-   * contains the task tree (ie. the processing).
    *
-   * @param workflowImpl the workflow which contains the processing
+   * @param backendId
+   *          the backendId
+   * @param baseDN
+   *          identifies the data handled by the workflow
+   * @param rootWorkflowElement
+   *          the root node of the task tree
    */
-  protected WorkflowTopology(WorkflowImpl workflowImpl)
+  protected WorkflowTopology(String backendId, DN baseDN, LocalBackendWorkflowElement rootWorkflowElement)
   {
-    this.workflowImpl = workflowImpl;
+    Reject.ifNull(rootWorkflowElement);
+    // The workflow ID is "backendID + baseDN".
+    // We cannot use backendID as workflow identifier because a backend
+    // may handle several base DNs. We cannot use baseDN either because
+    // we might want to configure several workflows handling the same
+    // baseDN through different network groups.
+    // So a mix of both backendID and baseDN should be ok.
+    this.workflowId = backendId + "#" + baseDN;
+    this.baseDN = baseDN;
+    this.rootWorkflowElement = rootWorkflowElement;
   }
 
-
-  /**
-   * Returns the workflow implementation which contains the task tree
-   * (ie. the processing).
-   *
-   * @return the workflow implementation which contains the processing
-   */
-  public WorkflowImpl getWorkflowImpl()
-  {
-    return workflowImpl;
-  }
-
-
   /**
    * Gets the base DN of the workflow node. The base DN of the workflow
    * node is the base DN of the attached workflow implementation containing
@@ -79,9 +88,43 @@
   @Override
   public DN getBaseDN()
   {
-    return getWorkflowImpl().getBaseDN();
+    return this.baseDN;
   }
 
+  /**
+   * Gets the root workflow element for test purpose only.
+   *
+   * @return the root workflow element.
+   */
+  LocalBackendWorkflowElement getRootWorkflowElement()
+  {
+    return rootWorkflowElement;
+  }
+
+  /**
+   * Gets the workflow internal identifier.
+   *
+   * @return the workflow internal identifier
+   */
+  public String getWorkflowId()
+  {
+    return workflowId;
+  }
+
+  /**
+   * Executes all the tasks defined by the workflow task tree for a given
+   * operation.
+   *
+   * @param operation
+   *          the operation to execute
+   * @throws CanceledOperationException
+   *           if this operation should be canceled.
+   */
+  @Override
+  public void execute(Operation operation) throws CanceledOperationException
+  {
+    rootWorkflowElement.execute(operation);
+  }
 
   /**
    * Elaborates a new search scope according to the current search scope.
@@ -112,7 +155,7 @@
   @Override
   public String toString()
   {
-    return getClass().getSimpleName() + " " + workflowImpl;
+    return getClass().getSimpleName() + " workflow=" + workflowId;
   }
 
 }
diff --git a/opendj3-server-dev/src/server/org/opends/server/core/WorkflowTopologyNode.java b/opendj3-server-dev/src/server/org/opends/server/core/WorkflowTopologyNode.java
index a9dd913..886167b 100644
--- a/opendj3-server-dev/src/server/org/opends/server/core/WorkflowTopologyNode.java
+++ b/opendj3-server-dev/src/server/org/opends/server/core/WorkflowTopologyNode.java
@@ -33,6 +33,7 @@
 import org.opends.server.types.DN;
 import org.opends.server.types.Operation;
 import org.opends.server.types.OperationType;
+import org.opends.server.workflowelement.localbackend.LocalBackendWorkflowElement;
 
 /**
  * This class implements a workflow node. A workflow node is used
@@ -54,29 +55,31 @@
  */
 public class WorkflowTopologyNode extends WorkflowTopology
 {
-  // Parent node of the current workflow node.
-  private WorkflowTopologyNode parent = null;
+  /** Parent node of the current workflow node. */
+  private WorkflowTopologyNode parent;
 
-
-  // The list of subordinate nodes of the current workflow node.
+  /** The list of subordinate nodes of the current workflow node. */
   private final ArrayList<WorkflowTopologyNode> subordinates = new ArrayList<WorkflowTopologyNode>();
 
-
   /**
    * Creates a new node for a workflow topology. The new node is initialized
-   * with a WorkflowImpl which contains the real processing. Optionally,
-   * the node may have tasks to be executed before and/or after the real
-   * processing. In the current implementation, such pre and post workflow
-   * elements are not used.
+   * with a WorkflowImpl which contains the real processing. Optionally, the
+   * node may have tasks to be executed before and/or after the real processing.
+   * In the current implementation, such pre and post workflow elements are not
+   * used.
    *
-   * @param workflowImpl          the real processing attached to the node
+   * @param backendId
+   *          the backendId
+   * @param baseDN
+   *          identifies the data handled by the workflow
+   * @param rootWorkflowElement
+   *          the root node of the task tree
    */
-  public WorkflowTopologyNode(WorkflowImpl workflowImpl)
+  public WorkflowTopologyNode(String backendId, DN baseDN, LocalBackendWorkflowElement rootWorkflowElement)
   {
-    super(workflowImpl);
+    super(backendId, baseDN, rootWorkflowElement);
   }
 
-
   /**
    * Executes an operation on a set of data being identified by the
    * workflow node base DN.
@@ -87,13 +90,11 @@
    * be canceled.
    */
   @Override
-  public void execute(Operation operation)
-      throws CanceledOperationException {
-    // Execute the operation
-    getWorkflowImpl().execute(operation);
+  public void execute(Operation operation) throws CanceledOperationException
+  {
+    super.execute(operation);
 
-    // For subtree search operation we need to go through the subordinate
-    // nodes.
+    // For subtree search operation we need to go through the subordinate nodes.
     if (operation.getOperationType() == OperationType.SEARCH)
     {
       executeSearchOnSubordinates((SearchOperation) operation);
@@ -138,7 +139,7 @@
 
       // If the new search scope is 'base' and the search base DN does not
       // map the subordinate workflow then skip the subordinate workflow.
-      if ((newScope == SearchScope.BASE_OBJECT)
+      if (newScope == SearchScope.BASE_OBJECT
           && !subordinateDN.parent().equals(originalBaseDN))
       {
         continue;
@@ -207,7 +208,8 @@
    */
   public boolean isPrivate()
   {
-    return getWorkflowImpl().isPrivate();
+    LocalBackendWorkflowElement rwe = getRootWorkflowElement();
+    return rwe != null && rwe.isPrivate();
   }
 
 
@@ -231,29 +233,26 @@
 
     // Is the dn a subordinate of the current base DN?
     DN curBaseDN = getBaseDN();
-    if (curBaseDN != null)
+    if (curBaseDN != null && dn.isDescendantOf(curBaseDN))
     {
-      if (dn.isDescendantOf(curBaseDN))
+      // The dn may be handled by the current workflow.
+      // Now we have to check whether the dn is handled by
+      // a subordinate.
+      for (WorkflowTopologyNode subordinate: getSubordinates())
       {
-        // The dn may be handled by the current workflow.
-        // Now we have to check whether the dn is handled by
-        // a subordinate.
-        for (WorkflowTopologyNode subordinate: getSubordinates())
+        parentBaseDN = subordinate.getParentBaseDN(dn);
+        if (parentBaseDN != null)
         {
-          parentBaseDN = subordinate.getParentBaseDN(dn);
-          if (parentBaseDN != null)
-          {
-            // the dn is handled by a subordinate
-            break;
-          }
+          // the dn is handled by a subordinate
+          break;
         }
+      }
 
-        // If the dn is not handled by any subordinate, then it is
-        // handled by the current workflow.
-        if (parentBaseDN == null)
-        {
-          parentBaseDN = curBaseDN;
-        }
+      // If the dn is not handled by any subordinate, then it is
+      // handled by the current workflow.
+      if (parentBaseDN == null)
+      {
+        parentBaseDN = curBaseDN;
       }
     }
 
@@ -499,46 +498,25 @@
    */
   public StringBuilder toString(String leftMargin)
   {
-    StringBuilder sb = new StringBuilder();
+    final StringBuilder sb = new StringBuilder();
+    sb.append(leftMargin).append("Workflow ID = ").append(getWorkflowId()).append("\n");
+    sb.append(leftMargin).append("         baseDN:[").append(" \"").append(getBaseDN()).append("\" ]\n");
+    sb.append(leftMargin).append("         Root Workflow Element: ").append(getRootWorkflowElement()).append("\n");
+    sb.append(leftMargin).append("         Parent: ").append(getParent()).append("\n");
 
-    // display the baseDN
-    DN baseDN = getBaseDN();
-    String workflowID = this.getWorkflowImpl().getWorkflowId();
-    sb.append(leftMargin + "Workflow ID = " + workflowID + "\n");
-    sb.append(leftMargin + "         baseDN:[");
-    if (baseDN.isRootDN())
-    {
-      sb.append(" \"\"");
-    }
-    else
-    {
-      sb.append(" \"" + baseDN.toString() + "\"");
-    }
-    sb.append(" ]\n");
-
-    // display the root workflow element
-    sb.append(leftMargin
-        + "         Root Workflow Element: "
-        + getWorkflowImpl().getRootWorkflowElement() + "\n");
-
-    // display parent workflow
-    sb.append(leftMargin + "         Parent: " + getParent() + "\n");
-
-    // dump each subordinate
-    sb.append(leftMargin + "         List of subordinates:\n");
+    sb.append(leftMargin).append("         List of subordinates:\n");
     ArrayList<WorkflowTopologyNode> subordinates = getSubordinates();
-    if (subordinates.isEmpty())
-    {
-      sb.append(leftMargin + "            NONE\n");
-    }
-    else
+    if (!subordinates.isEmpty())
     {
       for (WorkflowTopologyNode subordinate: getSubordinates())
       {
         sb.append(subordinate.toString(leftMargin + "            "));
       }
     }
-
+    else
+    {
+      sb.append(leftMargin).append("            NONE\n");
+    }
     return sb;
   }
 
diff --git a/opendj3-server-dev/src/server/org/opends/server/core/networkgroups/NetworkGroup.java b/opendj3-server-dev/src/server/org/opends/server/core/networkgroups/NetworkGroup.java
index 41080d5..76f0aa4 100644
--- a/opendj3-server-dev/src/server/org/opends/server/core/networkgroups/NetworkGroup.java
+++ b/opendj3-server-dev/src/server/org/opends/server/core/networkgroups/NetworkGroup.java
@@ -32,10 +32,10 @@
 import org.forgerock.opendj.ldap.ResultCode;
 import org.opends.server.core.RootDseWorkflowTopology;
 import org.opends.server.core.Workflow;
-import org.opends.server.core.WorkflowImpl;
 import org.opends.server.core.WorkflowTopologyNode;
 import org.opends.server.types.DN;
 import org.opends.server.types.DirectoryException;
+import org.opends.server.workflowelement.localbackend.LocalBackendWorkflowElement;
 
 import static org.forgerock.util.Reject.*;
 import static org.opends.messages.CoreMessages.*;
@@ -127,21 +127,18 @@
    *
    * @param baseDN
    *          the baseDN of the workflow to deregister, may be null
-   * @return the deregistered workflow
    */
-  public Workflow deregisterWorkflow(DN baseDN)
+  public void deregisterWorkflow(DN baseDN)
   {
     if (baseDN == null)
     {
-      return null;
+      return;
     }
 
-    Workflow workflow = null;
     if (baseDN.isRootDN())
     {
       // deregister the rootDSE
       deregisterWorkflow(rootDSEWorkflowNode);
-      workflow = rootDSEWorkflowNode.getWorkflowImpl();
     }
     else
     {
@@ -157,7 +154,6 @@
             // deregisterWorkflowNode() because we want the naming
             // context list to be updated as well.
             deregisterWorkflow(node);
-            workflow = node.getWorkflowImpl();
 
             // Only one workflow can match the baseDN, so we can break
             // the loop here.
@@ -166,14 +162,6 @@
         }
       }
     }
-
-    // Now that the workflow node has been deregistered with the network
-    // group, update the reference counter of the workflow.
-    if (workflow != null)
-    {
-      ((WorkflowImpl) workflow).decrementReferenceCounter();
-    }
-    return workflow;
   }
 
   /**
@@ -186,8 +174,6 @@
     return namingContexts;
   }
 
-
-
   /**
    * Gets the highest workflow in the topology that can handle the
    * baseDN.
@@ -246,7 +232,7 @@
   private void checkNotRegistered(WorkflowTopologyNode workflowNode)
       throws DirectoryException
   {
-    String workflowID = workflowNode.getWorkflowImpl().getWorkflowId();
+    String workflowID = workflowNode.getWorkflowId();
     ifNull(workflowID);
 
     // The workflow base DN should not be already present in the
@@ -257,8 +243,7 @@
       if (nodeBaseDN.equals(workflowNode.getBaseDN()))
       {
         LocalizableMessage message = ERR_REGISTER_WORKFLOW_BASE_DN_ALREADY_EXISTS.get(
-            workflowID, networkGroupID, node.getWorkflowImpl().getWorkflowId(),
-            workflowNode.getWorkflowImpl().getBaseDN());
+            workflowID, networkGroupID, workflowID, workflowNode.getBaseDN());
         throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
       }
     }
@@ -300,7 +285,7 @@
     {
       TreeMap<String, WorkflowTopologyNode> newWorkflowNodes =
           new TreeMap<String, WorkflowTopologyNode>(registeredWorkflowNodes);
-      newWorkflowNodes.remove(workflowNode.getWorkflowImpl().getWorkflowId());
+      newWorkflowNodes.remove(workflowNode.getWorkflowId());
       registeredWorkflowNodes = newWorkflowNodes;
     }
   }
@@ -346,26 +331,30 @@
   /**
    * Registers a workflow with the network group.
    *
-   * @param workflow
-   *          the workflow to register
+   * @param backendId
+   *          the workflow backendId
+   * @param baseDN
+   *          identifies the data handled by the workflow
+   * @param rootWorkflowElement
+   *          the root node of the task tree
    * @throws DirectoryException
    *           If the workflow ID for the provided workflow conflicts
    *           with the workflow ID of an existing workflow or if the
    *           base DN of the workflow is the same than the base DN of
    *           another workflow already registered
    */
-  public void registerWorkflow(WorkflowImpl workflow) throws DirectoryException
+  public void registerWorkflow(String backendId, DN baseDN, LocalBackendWorkflowElement rootWorkflowElement)
+      throws DirectoryException
   {
-    DN baseDN = workflow.getBaseDN();
     if (baseDN.isRootDN())
     {
       // NOTE - The rootDSE workflow is stored with the registeredWorkflows.
-      rootDSEWorkflowNode = new RootDseWorkflowTopology(workflow, namingContexts);
+      rootDSEWorkflowNode = new RootDseWorkflowTopology(backendId, baseDN, rootWorkflowElement, namingContexts);
       return;
     }
 
     // Try to insert it in the workflow topology.
-    WorkflowTopologyNode workflowNode = new WorkflowTopologyNode(workflow);
+    WorkflowTopologyNode workflowNode = new WorkflowTopologyNode(backendId, baseDN, rootWorkflowElement);
     registerWorkflowNode(workflowNode);
 
     // Now add the workflow in the workflow topology...
@@ -383,12 +372,8 @@
     }
 
     rebuildNamingContextList();
-
-    workflow.incrementReferenceCounter();
   }
 
-
-
   /**
    * Registers a workflow node with the network group.
    *
@@ -402,7 +387,7 @@
   private void registerWorkflowNode(WorkflowTopologyNode workflowNode)
       throws DirectoryException
   {
-    String workflowID = workflowNode.getWorkflowImpl().getWorkflowId();
+    String workflowID = workflowNode.getWorkflowId();
     ifNull(workflowID);
 
     synchronized (registeredWorkflowNodesLock)
@@ -423,5 +408,4 @@
       registeredWorkflowNodes = newRegisteredWorkflowNodes;
     }
   }
-
 }
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/WorkflowTopologyTest.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/WorkflowTopologyTest.java
index 09f0b02..1d0511f 100644
--- a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/WorkflowTopologyTest.java
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/WorkflowTopologyTest.java
@@ -32,14 +32,12 @@
 import org.forgerock.opendj.ldap.ResultCode;
 import org.opends.server.TestCaseUtils;
 import org.opends.server.types.DN;
-import org.opends.server.types.DirectoryException;
-import org.opends.server.util.StaticUtils;
 import org.opends.server.util.UtilTestCase;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
-import static org.opends.messages.CoreMessages.*;
+import static org.opends.server.workflowelement.localbackend.LocalBackendWorkflowElement.*;
 import static org.testng.Assert.*;
 
 /**
@@ -411,10 +409,7 @@
       DN dummyDN
       )
   {
-    WorkflowImpl workflow = new WorkflowImpl(baseDN.toString(), baseDN, null);
-
-    // Create a worflow with the dit, no pre/post-workflow element.
-    WorkflowTopologyNode workflowNode = new WorkflowTopologyNode(workflow);
+    WorkflowTopologyNode workflowNode = newWorkflowTopologyNode(baseDN);
 
     // The base DN in the workflow should match baseDN parameter
     DN workflowBaseDN = workflowNode.getBaseDN();
@@ -443,13 +438,14 @@
    * Create a topology with 2 workflows. The test case contains creation
    * of clean topologies as well as bad topologies (same baseDN for the parent
    * and subordinate, subordinate above parent...).
-   *
+   * <pre>
    *                 W1 (baseDN)
    *                 |
    *                 |
    *                 W2 (subordinateDN)
+   * </pre>
    *
-   * There is no worklfow element attached to the DITs.
+   * There is no workflow element attached to the DITs.
    *
    * @param baseDN         base DN for the parent workflow (W1)
    * @param subordinateDN  base DN for the subordinate workflow (W2)
@@ -463,30 +459,10 @@
       DN unrelatedDN
       )
   {
-    // Create one DIT set for baseDN and one DIT set for subordinateDN
-    // (no workflow element in any DIT). Create a dummy DIT as well using
-    // the unrelatedDN.
-    WorkflowImpl workflow = new WorkflowImpl(baseDN.toString(), baseDN, null);
-    WorkflowImpl subWorkflow = new WorkflowImpl(subordinateDN.toString(), subordinateDN, null);
-    WorkflowImpl unrelatedWorkflow = null;
-    if (unrelatedDN != null)
-    {
-      unrelatedWorkflow = new WorkflowImpl(unrelatedDN.toString(), unrelatedDN, null);
-    }
-
-    // Create a worflow for each dit, no pre/post-workflow element
-    WorkflowTopologyNode w1    = new WorkflowTopologyNode(workflow);
-    WorkflowTopologyNode w1bis = new WorkflowTopologyNode(workflow);
-    WorkflowTopologyNode w2    = new WorkflowTopologyNode(subWorkflow);
-
-    WorkflowTopologyNode w3 = null;
-    if (unrelatedWorkflow != null)
-    {
-      w3 = new WorkflowTopologyNode(unrelatedWorkflow);
-    }
-
-    // insert status
-    boolean insert;
+    WorkflowTopologyNode w1 = newWorkflowTopologyNode(baseDN);
+    WorkflowTopologyNode w1bis = newWorkflowTopologyNode(baseDN);
+    WorkflowTopologyNode w2 = newWorkflowTopologyNode(subordinateDN);
+    WorkflowTopologyNode w3 = newWorkflowTopologyNode(unrelatedDN);
 
     // Try to create a topology with unrelated workflows:
     //
@@ -497,8 +473,7 @@
     // Insert should be rejected
     if (w3 != null)
     {
-      insert = w1.insertSubordinate (w3);
-      assertEquals (insert, false);
+      assertFalse(w1.insertSubordinate(w3));
     }
 
     // Try to create a topology with the very same workflow:
@@ -508,8 +483,7 @@
     //         w1 (baseDN)
     //
     // Insert should be rejected
-    insert = w1.insertSubordinate (w1);
-    assertEquals (insert, false);
+    assertFalse(w1.insertSubordinate(w1));
 
     // Try to create a topology with a workflow whose baseDN is the same than
     // parent baseDN:
@@ -519,8 +493,7 @@
     //         w1bis (baseDN)
     //
     // Insert should be rejected
-    insert = w1.insertSubordinate (w1bis);
-    assertEquals (insert, false);
+    assertFalse(w1.insertSubordinate(w1bis));
 
     // Try to create a topology where subordinate is above the parent:
     //
@@ -529,8 +502,7 @@
     //         w1 (baseDN)
     //
     // Insert should be rejected
-    insert = w2.insertSubordinate (w1);
-    assertEquals (insert, false);
+    assertFalse(w2.insertSubordinate(w1));
 
     // Try to create a clean topology:
     //
@@ -541,8 +513,7 @@
     // Expected results:
     //
     // - insert should be working
-    insert = w1.insertSubordinate (w2);
-    assertEquals (insert, true);
+    assertTrue(w1.insertSubordinate(w2));
 
     // - w1 should be the parent of w2
     WorkflowTopologyNode parent1 = w2.getParent();
@@ -556,8 +527,17 @@
     // - w2 should have no subordinate
     ArrayList<WorkflowTopologyNode> subordinates2 = w2.getSubordinates();
     assertEquals (subordinates2.size(), 0);
+  }
 
-  } // createWorkflow_simpleTopology1
+  private WorkflowTopologyNode newWorkflowTopologyNode(DN baseDN)
+  {
+    if (baseDN != null)
+    {
+      final String workflowId = baseDN.toString();
+      return new WorkflowTopologyNode(workflowId, baseDN, createAndRegister(workflowId, null));
+    }
+    return null;
+  }
 
 
   /**
@@ -565,7 +545,7 @@
    * right workflow for a given DN. Then remove a workflow in the chain and
    * check that topology is properly updated in term of parent/subordinate
    * links.
-   *
+   * <pre>
    *                 W1 (baseDN1)
    *                 |
    *                 +----> subordinateDN1
@@ -578,8 +558,9 @@
    *                 |
    *                 +----> subordinateDN3
    *                 |
+   * </pre>
    *
-   * There is no worklfow element attached to the DITs.
+   * There is no workflow element attached to the DITs.
    *
    * @param baseDN1         base DN for the top workflow (W1)
    * @param baseDN2         base DN for the first subordinate workflow (W2)
@@ -600,10 +581,9 @@
       DN unrelatedDN
       )
   {
-    // Create a worflow for each baseDN, no pre/post-workflow element
-    WorkflowTopologyNode w1 = new WorkflowTopologyNode(new WorkflowImpl(baseDN1.toString(), baseDN1, null));
-    WorkflowTopologyNode w2 = new WorkflowTopologyNode(new WorkflowImpl(baseDN2.toString(), baseDN2, null));
-    WorkflowTopologyNode w3 = new WorkflowTopologyNode(new WorkflowImpl(baseDN3.toString(), baseDN3, null));
+    WorkflowTopologyNode w1 = newWorkflowTopologyNode(baseDN1);
+    WorkflowTopologyNode w2 = newWorkflowTopologyNode(baseDN2);
+    WorkflowTopologyNode w3 = newWorkflowTopologyNode(baseDN3);
 
     // insert status
     boolean insert;
@@ -735,7 +715,7 @@
 
   /**
    * Create a topology of workflows.
-   *
+   * <pre>
    *                 W1
    *               baseDN1
    *                 /\
@@ -743,8 +723,9 @@
    *               /    \
    *              W2    W3
    *         baseDN2    baseDN3
+   * </pre>
    *
-   * There is no worklfow element attached to the DITs.
+   * There is no workflow element attached to the DITs.
    *
    * @param baseDN1         base DN for the top workflow (W1)
    * @param baseDN2         base DN for the first subordinate workflow (W2)
@@ -765,10 +746,9 @@
       DN unrelatedDN
       )
   {
-    // Create a worflow for each baseDN, no pre/post-workflow element
-    WorkflowTopologyNode w1 = new WorkflowTopologyNode(new WorkflowImpl(baseDN1.toString(), baseDN1, null));
-    WorkflowTopologyNode w2 = new WorkflowTopologyNode(new WorkflowImpl(baseDN2.toString(), baseDN2, null));
-    WorkflowTopologyNode w3 = new WorkflowTopologyNode(new WorkflowImpl(baseDN3.toString(), baseDN3, null));
+    WorkflowTopologyNode w1 = newWorkflowTopologyNode(baseDN1);
+    WorkflowTopologyNode w2 = newWorkflowTopologyNode(baseDN2);
+    WorkflowTopologyNode w3 = newWorkflowTopologyNode(baseDN3);
 
     // Put all the workflows in a pool
     WorkflowTopologyNode[] workflowPool = {w1, w2, w3};
@@ -784,15 +764,11 @@
         {
           // makes no sense to try to insert a workflow in itself!
           // let's do it anyway... but it should fail ;-)
-          boolean insertDone = parent.insertSubordinate (parent);
-          assertEquals (insertDone, false);
+          assertFalse(parent.insertSubordinate(parent));
         }
         else
         {
-          if (parent.insertSubordinate (subordinate))
-          {
-            // insert done
-          }
+          parent.insertSubordinate(subordinate); // we do not check the output?
         }
       }
     }
@@ -861,44 +837,9 @@
   {
     // Check the function that elaborates the global result code
     WorkflowResultCode globalResultCode = new WorkflowResultCode (
-        initialResultCode, new LocalizableMessageBuilder("")
-        );
+        initialResultCode, new LocalizableMessageBuilder(""));
     globalResultCode.elaborateGlobalResultCode (
-        receivedResultCode, new LocalizableMessageBuilder("")
-        );
+        receivedResultCode, new LocalizableMessageBuilder(""));
     assertEquals (globalResultCode.resultCode(), expectedGlobalResultCode);
   }
-
-
-  /**
-   * Tests the workflow registration.
-   */
-  @Test (dataProvider = "DNSet_1", groups = "virtual")
-  public void testWorkflowRegistration(
-      DN baseDN,
-      DN subordinateDN,
-      DN dummyDN
-      )
-      throws DirectoryException
-  {
-    // Create a workflow to handle the baseDN with no workflow element
-    WorkflowImpl workflow = new WorkflowImpl(baseDN.toString(), baseDN, null);
-
-    // Register the workflow with the server. Don't catch the
-    // DirectoryException that could be thrown by the register() method.
-    workflow.register();
-
-    // Register the same workflow twice and catch the expected
-    // DirectoryException.
-    try
-    {
-      workflow.register();
-      fail("Expected DirectoryException to br thrown");
-    }
-    catch (DirectoryException e)
-    {
-      assertTrue(StaticUtils.hasDescriptor(e.getMessageObject(),
-          ERR_REGISTER_WORKFLOW_ALREADY_EXISTS));
-    }
-  }
 }
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/NetworkGroupTest.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/NetworkGroupTest.java
index 72f3f0f..a8a46b7 100644
--- a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/NetworkGroupTest.java
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/NetworkGroupTest.java
@@ -36,7 +36,6 @@
 import org.opends.server.core.ModifyOperation;
 import org.opends.server.core.SearchOperation;
 import org.opends.server.core.Workflow;
-import org.opends.server.core.WorkflowImpl;
 import org.opends.server.protocols.internal.InternalClientConnection;
 import org.opends.server.protocols.internal.SearchRequest;
 import org.opends.server.types.Attribute;
@@ -53,6 +52,7 @@
 import static org.opends.server.config.ConfigConstants.*;
 import static org.opends.server.protocols.internal.InternalClientConnection.*;
 import static org.opends.server.protocols.internal.Requests.*;
+import static org.opends.server.workflowelement.localbackend.LocalBackendWorkflowElement.*;
 import static org.testng.Assert.*;
 
 /**
@@ -160,20 +160,13 @@
   @Test (dataProvider = "DNSet_0", groups = "virtual")
   public void testNetworkGroupRegistration(String networkGroupID, DN workflowBaseDN) throws Exception
   {
-    // Create and register the network group with the server.
     NetworkGroup networkGroup = new NetworkGroup(networkGroupID);
+    registerWorkflow(networkGroup, workflowBaseDN);
 
-    // Create a workflow -- the workflow ID is the string representation
-    // of the workflow base DN.
-    WorkflowImpl workflow = new WorkflowImpl(workflowBaseDN.toString(), workflowBaseDN, null);
-    networkGroup.registerWorkflow(workflow);
-
-    // Register again the workflow with the network group and catch the
-    // expected DirectoryServer exception.
     try
     {
-      networkGroup.registerWorkflow(workflow);
-      fail("DirectoryException should have been thrown");
+      registerWorkflow(networkGroup, workflowBaseDN);
+      fail("DirectoryException should have been thrown on double registration");
     }
     catch (DirectoryException de)
     {
@@ -259,14 +252,15 @@
     NetworkGroup networkGroup1 = new NetworkGroup(ng1);
     NetworkGroup networkGroup2 = new NetworkGroup(ng2);
 
-    // Create a workflow -- the workflow ID is the string representation
-    // of the workflow base DN.
-    WorkflowImpl workflow1 = new WorkflowImpl(dn1.toString(), dn1, null);
-    WorkflowImpl workflow2 = new WorkflowImpl(dn2.toString(), dn2, null);
-
     // Register the workflow with the network group.
-    networkGroup1.registerWorkflow(workflow1);
-    networkGroup2.registerWorkflow(workflow2);
+    registerWorkflow(networkGroup1, dn1);
+    registerWorkflow(networkGroup2, dn2);
+  }
+
+  private void registerWorkflow(NetworkGroup networkGroup, DN dn) throws DirectoryException
+  {
+    String workflowId = dn.toString();
+    networkGroup.registerWorkflow(workflowId, dn, createAndRegister(workflowId, null));
   }
 
   /**
@@ -294,9 +288,8 @@
     TestCaseUtils.initializeMemoryBackend(backendID2, backend2, true);
     searchPublicNamingContexts(ResultCode.SUCCESS, 2);
 
-    // Now put in the list of subordinate naming context the backend1
-    // naming context. This white list will prevent the backend2 to be
-    // visible.
+    // Now put in the list of subordinate naming context the backend1 naming context.
+    // This white list will prevent the backend2 to be visible.
     TestCaseUtils.dsconfig(
         "set-root-dse-backend-prop",
         "--set", "subordinate-base-dn:" + backend1);

--
Gitblit v1.10.0