mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Jean-Noel Rouvignac
04.37.2014 dfd0f76471fe45e631f7f456652355afc97fe917
OPENDJ-1545 Remove Workflow, NetworkGroups and related attempts at building a proxy


Reduced dependency towards NetworkGroup class.

NetworkGroup.java:
Removed all network groups but the default network group.

WorkflowConfigurationTest.java: REMOVED
1 files deleted
6 files modified
1162 ■■■■■ changed files
opendj3-server-dev/src/server/org/opends/server/core/DirectoryServer.java 62 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/core/networkgroups/NetworkGroup.java 349 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/protocols/internal/InternalClientConnection.java 8 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java 8 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java 12 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/WorkflowConfigurationTest.java 517 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/NetworkGroupTest.java 206 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/core/DirectoryServer.java
@@ -2130,61 +2130,6 @@
  /**
   * Deregisters a workflow with the default network group. This method is
   * intended to be called when workflow configuration mode is
   * auto.
   *
   * @param baseDN  the DN of the workflow to deregister
   */
  private static void deregisterWorkflowWithDefaultNetworkGroup(
      DN baseDN
      )
  {
    // Get the default network group and deregister all the workflows
    // being configured for the backend (there is one worklfow per
    // backend base DN).
    NetworkGroup defaultNetworkGroup = NetworkGroup.getDefaultNetworkGroup();
    defaultNetworkGroup.deregisterWorkflow(baseDN);
  }
  /**
   * Deregisters a workflow with the admin network group. This method is
   * intended to be called when workflow configuration mode is
   * auto.
   *
   * @param baseDN  the DN of the workflow to deregister
   */
  private static void deregisterWorkflowWithAdminNetworkGroup(
      DN baseDN
      )
  {
    // Get the admin network group and deregister all the workflows
    // being configured for the backend (there is one worklfow per
    // backend base DN).
    NetworkGroup adminNetworkGroup = NetworkGroup.getAdminNetworkGroup();
    adminNetworkGroup.deregisterWorkflow(baseDN);
  }
  /**
   * Deregisters a workflow with the internal network group and
   * deregisters the workflow with the server. This method is
   * intended to be called when workflow configuration mode is
   * auto.
   *
   * @param baseDN  the DN of the workflow to deregister
   */
  private static void deregisterWorkflowWithInternalNetworkGroup(DN baseDN)
  {
    // Get the internal network group and deregister all the workflows
    // being configured for the backend (there is one workflow per
    // backend base DN).
    NetworkGroup internalNetworkGroup = NetworkGroup.getInternalNetworkGroup();
    WorkflowImpl workflowImpl = (WorkflowImpl) internalNetworkGroup.deregisterWorkflow(baseDN);
    workflowImpl.deregister();
  }
  /**
   * Creates a set of workflows for a given backend and registers the
   * workflows with the default network group, the internal network group
   * and he admin network group. There are as many workflows
@@ -2210,8 +2155,6 @@
      throws DirectoryException
  {
    WorkflowImpl workflowImpl = createWorkflow(baseDN, backend);
    NetworkGroup.getAdminNetworkGroup().registerWorkflow(workflowImpl);
    NetworkGroup.getInternalNetworkGroup().registerWorkflow(workflowImpl);
    NetworkGroup.getDefaultNetworkGroup().registerWorkflow(workflowImpl);
  }
@@ -5653,9 +5596,8 @@
      // Now we need to deregister the workflow that was associated with the base DN
      if (!baseDN.equals(DN.valueOf("cn=config")))
      {
        deregisterWorkflowWithAdminNetworkGroup(baseDN);
        deregisterWorkflowWithDefaultNetworkGroup(baseDN);
        deregisterWorkflowWithInternalNetworkGroup(baseDN);
        WorkflowImpl workflow = (WorkflowImpl) NetworkGroup.getDefaultNetworkGroup().deregisterWorkflow(baseDN);
        workflow.deregister();
      }
    }
  }
opendj3-server-dev/src/server/org/opends/server/core/networkgroups/NetworkGroup.java
@@ -26,9 +26,6 @@
 */
package org.opends.server.core.networkgroups;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.TreeMap;
import org.forgerock.i18n.LocalizableMessage;
@@ -40,7 +37,6 @@
import org.opends.server.core.WorkflowTopologyNode;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.InitializationException;
import static org.forgerock.util.Reject.*;
import static org.opends.messages.CoreMessages.*;
@@ -58,84 +54,29 @@
public class NetworkGroup
{
  // The admin network group has no criterion, no policy,
  // and gives access to all the workflows.
  private static final String ADMIN_NETWORK_GROUP_NAME = "admin";
  private static NetworkGroup adminNetworkGroup =
      new NetworkGroup(ADMIN_NETWORK_GROUP_NAME);
  // The default network group has no criterion, no policy, and gives
  // access to all the workflows. The purpose of the default network
  // group is to allow new clients to perform a first operation before
  // they can be attached to a specific network group.
  /**
   * The default network group has no criterion, no policy, and gives
   * access to all the workflows. The purpose of the default network
   * group is to allow new clients to perform a first operation before
   * they can be attached to a specific network group.
   */
  private static final String DEFAULT_NETWORK_GROUP_NAME = "default";
  private static NetworkGroup defaultNetworkGroup =
      new NetworkGroup(DEFAULT_NETWORK_GROUP_NAME);
  // The internal network group has no criterion, no policy, and gives
  // access to all the workflows. The purpose of the internal network
  // group is to allow internal connections to perform operations.
  private static final String INTERNAL_NETWORK_GROUP_NAME = "internal";
  private static NetworkGroup internalNetworkGroup =
      new NetworkGroup(INTERNAL_NETWORK_GROUP_NAME);
  // The ordered list of network groups.
  private static List<NetworkGroup> orderedNetworkGroups =
      new ArrayList<NetworkGroup>();
  // The list of all network groups that are registered with the server.
  // The defaultNetworkGroup is not in the list of registered network
  // groups.
  private static TreeMap<String, NetworkGroup> registeredNetworkGroups =
      new TreeMap<String, NetworkGroup>();
  // A lock to protect concurrent access to the registeredNetworkGroups.
  private static final Object registeredNetworkGroupsLock = new Object();
  /**
   * Deregisters all network groups that have been registered. This
   * should be called when the server is shutting down.
   */
  public static void deregisterAllOnShutdown()
  {
    synchronized (registeredNetworkGroupsLock)
    {
      // Invalidate all NetworkGroups so they cannot accidentally be
      // used after a restart.
      Collection<NetworkGroup> networkGroups =
          registeredNetworkGroups.values();
      for (NetworkGroup networkGroup : networkGroups)
      {
        networkGroup.invalidate();
      }
      defaultNetworkGroup.invalidate();
      adminNetworkGroup.invalidate();
      internalNetworkGroup.invalidate();
      registeredNetworkGroups = new TreeMap<String, NetworkGroup>();
      orderedNetworkGroups = new ArrayList<NetworkGroup>();
      defaultNetworkGroup = new NetworkGroup("default");
      adminNetworkGroup = new NetworkGroup("admin");
      internalNetworkGroup = new NetworkGroup("internal");
    }
    // Invalidate all NetworkGroups so they cannot accidentally be
    // used after a restart.
    defaultNetworkGroup.invalidate();
    defaultNetworkGroup = new NetworkGroup("default");
  }
  /**
   * Returns the admin network group.
   *
   * @return the admin network group
   */
  public static NetworkGroup getAdminNetworkGroup()
  {
    return adminNetworkGroup;
  }
  /**
   * Returns the default network group. The default network group is
   * always defined and has no criterion, no policy and provide full
   * access to all the registered workflows.
@@ -147,60 +88,31 @@
    return defaultNetworkGroup;
  }
  /**
   * Returns the internal network group.
   *
   * @return the internal network group
   */
  public static NetworkGroup getInternalNetworkGroup()
  {
    return internalNetworkGroup;
  }
  /**
   * Gets the network group having the specified ID.
   * <p>
   * This method is for testing only.
   *
   * @param networkGroupID
   *          The network group ID.
   * @return The network group, of <code>null</code> if no match was found.
   */
  static NetworkGroup getNetworkGroup(String networkGroupID)
  {
    return registeredNetworkGroups.get(networkGroupID);
  }
  private final boolean isAdminNetworkGroup;
  private final boolean isDefaultNetworkGroup;
  private final boolean isInternalNetworkGroup;
  // List of naming contexts handled by the network group.
  /** List of naming contexts handled by the network group. */
  private NetworkGroupNamingContexts namingContexts =
      new NetworkGroupNamingContexts();
  // The network group internal identifier.
  /** The network group internal identifier. */
  private final String networkGroupID;
  // The network group priority.
  private int priority = 100;
  // Workflow nodes registered with the current network group.
  // Keys are workflowIDs.
  /**
   * Workflow nodes registered with the current network group.
   * Keys are workflowIDs.
   */
  private TreeMap<String, WorkflowTopologyNode> registeredWorkflowNodes =
      new TreeMap<String, WorkflowTopologyNode>();
  // A lock to protect concurrent access to the registered Workflow
  // nodes.
  /**
   * A lock to protect concurrent access to the registered Workflow
   * nodes.
   */
  private final Object registeredWorkflowNodesLock = new Object();
  // The workflow node for the rootDSE entry. The RootDSE workflow node
  // is not stored in the list of registered workflow nodes.
  private RootDseWorkflowTopology rootDSEWorkflowNode = null;
  /**
   * The workflow node for the rootDSE entry. The RootDSE workflow node
   * is not stored in the list of registered workflow nodes.
   */
  private RootDseWorkflowTopology rootDSEWorkflowNode;
  /**
   * Creates a new system network group using the provided ID.
@@ -208,15 +120,9 @@
   * @param networkGroupID
   *          The network group internal identifier.
   */
  public NetworkGroup(String networkGroupID)
  NetworkGroup(String networkGroupID)
  {
    this.networkGroupID = networkGroupID;
    this.isInternalNetworkGroup =
        INTERNAL_NETWORK_GROUP_NAME.equals(networkGroupID);
    this.isAdminNetworkGroup =
        ADMIN_NETWORK_GROUP_NAME.equals(networkGroupID);
    this.isDefaultNetworkGroup =
        DEFAULT_NETWORK_GROUP_NAME.equals(networkGroupID);
  }
  /**
@@ -268,70 +174,7 @@
    // Now that the workflow node has been deregistered with the network
    // group, update the reference counter of the workflow.
    if (workflow != null && !isAdminNetworkGroup && !isInternalNetworkGroup && !isDefaultNetworkGroup)
    {
      WorkflowImpl workflowImpl = (WorkflowImpl) workflow;
      workflowImpl.decrementReferenceCounter();
    }
    return workflow;
  }
  /**
   * Deregisters a workflow with the network group. The workflow to
   * deregister is identified by its workflow ID.
   *
   * @param workflowID
   *          the workflow identifier of the workflow to deregister
   * @return the deregistered workflow
   */
  public Workflow deregisterWorkflow(String workflowID)
  {
    Workflow workflow = null;
    String rootDSEWorkflowID = null;
    if (rootDSEWorkflowNode != null)
    {
      rootDSEWorkflowID =
          rootDSEWorkflowNode.getWorkflowImpl().getWorkflowId();
    }
    if (workflowID.equalsIgnoreCase(rootDSEWorkflowID))
    {
      // deregister the rootDSE
      deregisterWorkflow(rootDSEWorkflowNode);
      workflow = rootDSEWorkflowNode.getWorkflowImpl();
    }
    else
    {
      // deregister a workflow node
      synchronized (registeredWorkflowNodesLock)
      {
        for (WorkflowTopologyNode node : registeredWorkflowNodes.values())
        {
          String curID = node.getWorkflowImpl().getWorkflowId();
          if (curID.equals(workflowID))
          {
            // Call deregisterWorkflow() instead of
            // 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.
            break;
          }
        }
      }
    }
    // Now that the workflow node has been deregistered with the network
    // group, update the reference counter of the workflow.
    if ((workflow != null) && !isAdminNetworkGroup
        && !isInternalNetworkGroup && !isDefaultNetworkGroup)
    if (workflow != null)
    {
      WorkflowImpl workflowImpl = (WorkflowImpl) workflow;
      workflowImpl.decrementReferenceCounter();
@@ -458,130 +301,6 @@
  }
  /**
   * Deregisters the current network group (this) with the server. The
   * method also decrements the reference counter of the workflows so
   * that workflows can be disabled or deleted if needed.
   * <p>
   * This methods is package private for testing purposes.
   */
  void deregister()
  {
    // Finalization specific to user network groups.
    synchronized (registeredNetworkGroupsLock)
    {
      // Deregister this network group.
      TreeMap<String, NetworkGroup> networkGroups =
          new TreeMap<String, NetworkGroup>(registeredNetworkGroups);
      networkGroups.remove(networkGroupID);
      registeredNetworkGroups = networkGroups;
      orderedNetworkGroups.remove(this);
      // Decrement the reference counter of the workflows registered
      // with this network group.
      synchronized (registeredWorkflowNodesLock)
      {
        for (WorkflowTopologyNode workflowNode : registeredWorkflowNodes
            .values())
        {
          WorkflowImpl workflowImpl = workflowNode.getWorkflowImpl();
          workflowImpl.decrementReferenceCounter();
        }
      }
    }
  }
  /**
   * Registers the current network group (this) with the server.
   * <p>
   * This methods is package private for testing purposes.
   *
   * @throws InitializationException
   *           If the network group ID for the provided network group
   *           conflicts with the network group ID of an existing
   *           network group.
   */
  void register() throws InitializationException
  {
    ifNull(networkGroupID);
    synchronized (registeredNetworkGroupsLock)
    {
      // The network group must not be already registered
      if (registeredNetworkGroups.containsKey(networkGroupID))
      {
        LocalizableMessage message =
            ERR_REGISTER_NETWORK_GROUP_ALREADY_EXISTS
                .get(networkGroupID);
        throw new InitializationException(message);
      }
      TreeMap<String, NetworkGroup> newRegisteredNetworkGroups =
          new TreeMap<String, NetworkGroup>(registeredNetworkGroups);
      newRegisteredNetworkGroups.put(networkGroupID, this);
      registeredNetworkGroups = newRegisteredNetworkGroups;
      // Insert the network group at the right position in the ordered
      // list.
      int index = 0;
      for (NetworkGroup ng : registeredNetworkGroups.values())
      {
        if (ng.equals(this))
        {
          continue;
        }
        if (this.priority > ng.priority)
        {
          index++;
        }
      }
      orderedNetworkGroups.add(index, this);
    }
  }
  /**
   * Sets the network group priority.
   * <p>
   * This methods is package private for testing purposes.
   *
   * @param prio
   *          the network group priority
   */
  void setNetworkGroupPriority(int prio)
  {
    // Check whether the priority has changed
    if (priority != prio)
    {
      synchronized (registeredNetworkGroupsLock)
      {
        priority = prio;
        // Nothing to do if the network group is not registered
        if (registeredNetworkGroups.containsKey(networkGroupID))
        {
          // If the network group was already registered, remove it from
          // the ordered list
          orderedNetworkGroups.remove(this);
          // Then insert it at the right position in the ordered list
          int index = 0;
          for (NetworkGroup ng : registeredNetworkGroups.values())
          {
            if (ng.equals(this))
            {
              continue;
            }
            if (this.priority > ng.priority)
            {
              index++;
            }
          }
          orderedNetworkGroups.add(index, this);
        }
      }
    }
  }
  /**
   * Checks whether the base DN of a new workflow to register is present
   * in a workflow already registered with the network group.
   *
@@ -597,14 +316,6 @@
    String workflowID = workflowNode.getWorkflowImpl().getWorkflowId();
    ifNull(workflowID);
    // If the network group is the "internal" or the "admin" network group
    // then bypass the check because the internal network group may contain
    // duplicates of base DNs.
    if (isInternalNetworkGroup || isAdminNetworkGroup)
    {
      return;
    }
    // The workflow base DN should not be already present in the
    // network group. Bypass the check for the private workflows...
    for (WorkflowTopologyNode node : registeredWorkflowNodes.values())
@@ -771,11 +482,7 @@
      // group, update the reference counter of the workflow, unless
      // the network group is either default, or administration, or
      // internal network group.
      if (!isAdminNetworkGroup && !isInternalNetworkGroup
          && !isDefaultNetworkGroup)
      {
        workflow.incrementReferenceCounter();
      }
      workflow.incrementReferenceCounter();
    }
  }
opendj3-server-dev/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
@@ -38,7 +38,6 @@
import org.opends.server.api.ClientConnection;
import org.opends.server.api.ConnectionHandler;
import org.opends.server.core.*;
import org.opends.server.core.networkgroups.NetworkGroup;
import org.opends.server.types.*;
import org.opends.server.util.AddChangeRecordEntry;
import org.opends.server.util.DeleteChangeRecordEntry;
@@ -250,13 +249,6 @@
    this(getAuthInfoForDN(userDN));
  }
  /** {@inheritDoc} */
  @Override
  public NetworkGroup getNetworkGroup()
  {
    return NetworkGroup.getInternalNetworkGroup();
  }
  /**
   * Creates an authentication information object for the user with
   * the specified DN.
opendj3-server-dev/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
@@ -43,7 +43,6 @@
import org.opends.server.api.ClientConnection;
import org.opends.server.api.ConnectionHandler;
import org.opends.server.core.*;
import org.opends.server.core.networkgroups.NetworkGroup;
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.protocols.internal.SearchRequest;
import org.opends.server.types.*;
@@ -111,13 +110,6 @@
  /** {@inheritDoc} */
  @Override
  public NetworkGroup getNetworkGroup()
  {
    return NetworkGroup.getAdminNetworkGroup();
  }
  /** {@inheritDoc} */
  @Override
  public void handleNotification(Notification notif, Object handback)
  {
    // We don't have the expected notification
opendj3-server-dev/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -55,7 +55,6 @@
import org.opends.server.api.ClientConnection;
import org.opends.server.api.ConnectionHandler;
import org.opends.server.core.*;
import org.opends.server.core.networkgroups.NetworkGroup;
import org.opends.server.extensions.ConnectionSecurityProvider;
import org.opends.server.extensions.RedirectingByteChannel;
import org.opends.server.extensions.TLSByteChannel;
@@ -514,17 +513,6 @@
    connectionID = DirectoryServer.newConnectionAccepted(this);
  }
  /** {@inheritDoc} */
  @Override
  public NetworkGroup getNetworkGroup()
  {
    if (connectionHandler.isAdminConnectionHandler())
    {
      return NetworkGroup.getAdminNetworkGroup();
    }
    return NetworkGroup.getDefaultNetworkGroup();
  }
  /**
   * Retrieves the connection ID assigned to this connection.
   *
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/WorkflowConfigurationTest.java
File was deleted
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/NetworkGroupTest.java
@@ -43,7 +43,6 @@
import org.opends.server.types.Attributes;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.InitializationException;
import org.opends.server.types.Modification;
import org.opends.server.util.StaticUtils;
import org.testng.annotations.BeforeClass;
@@ -163,58 +162,6 @@
    };
  }
  /**
   * Provides information to create a network group to test the routing
   * process.
   *
   * Each set of DNs contains:
   * - one base DN for the 1st workflow
   * - one base DN for the 2nd workflow
   * - one base DN for the 3rd workflow
   * - one subordinate DN for the 1st workflow
   * - one subordinate DN for the 2nd workflow
   * - one subordinate DN for the 3rd workflow
   * - one unrelated DN which has no hierarchical relationship with
   *   any of the above DNs
   */
  @DataProvider (name = "DNSet_2")
  public Object[][] initDNSet_2() throws Exception
  {
    // Network group definition
    DN     dn1          = DN.valueOf("o=test1");
    DN     dn2          = DN.valueOf("o=test2");
    DN     dn3          = DN.valueOf("o=test3");
    DN     subordinate1 = DN.valueOf("ou=subtest1,o=test1");
    DN     subordinate2 = DN.valueOf("ou=subtest2,o=test2");
    DN     subordinate3 = DN.valueOf("ou=subtest3,o=test3");
    DN     unrelatedDN  = DN.valueOf("o=dummy");
    // Network group info
    return new Object[][] {
        // Test1: one DN for one workflow
        {
          dn1, null, null,
          subordinate1, null, null,
          unrelatedDN
        },
        // Test2: two DNs for two workflows
        {
          dn1, dn2, null,
          subordinate1, subordinate2, null,
          unrelatedDN
        },
        // Test3: three DNs for three workflows
        {
          dn1, dn2, dn3,
          subordinate1, subordinate2, subordinate3,
          unrelatedDN
        }
    };
  }
  /**
   * Provides information to create a network group with resource limits.
   */
@@ -298,20 +245,6 @@
  {
    // Create and register the network group with the server.
    NetworkGroup networkGroup = new NetworkGroup(networkGroupID);
    networkGroup.register();
    // Register again the network group with the server and catch the
    // expected DirectoryServer exception.
    try
    {
      networkGroup.register();
      fail("InitializationException sjhould have been thrown");
    }
    catch (InitializationException e)
    {
      assertTrue(StaticUtils.hasDescriptor(e.getMessageObject(),
          ERR_REGISTER_NETWORK_GROUP_ALREADY_EXISTS));
    }
    // Create a workflow -- the workflow ID is the string representation
    // of the workflow base DN.
@@ -332,10 +265,6 @@
      assertTrue(StaticUtils.hasDescriptor(de.getMessageObject(),
          ERR_REGISTER_WORKFLOW_NODE_ALREADY_EXISTS));
    }
    // Clean the network group
    networkGroup.deregisterWorkflow(workflow.getWorkflowId());
    networkGroup.deregister();
  }
@@ -365,124 +294,20 @@
    doCheckNetworkGroup(defaultNG, dnToSearch, dnSubordinate, null, existsInDefault);
    // let's get the admin network group -- it should always exist
    NetworkGroup adminNG = NetworkGroup.getAdminNetworkGroup();
    NetworkGroup adminNG = NetworkGroup.getDefaultNetworkGroup();
    assertNotNull(adminNG);
    // let's check the routing through the network group
    doCheckNetworkGroup(adminNG, dnToSearch, dnSubordinate, null, existsInAdmin);
    // let's get the internal network group -- it should always exist
    NetworkGroup internalNG = NetworkGroup.getInternalNetworkGroup();
    NetworkGroup internalNG = NetworkGroup.getDefaultNetworkGroup();
    assertNotNull(internalNG);
    // let's check the routing through the network group
    doCheckNetworkGroup(internalNG, dnToSearch, dnSubordinate, null, existsInInternal);
  }
  /**
   * Creates a network group with several workflows inside and do some check
   * on the route processing.
   *
   * @param dn1           the DN for the 1st workflow
   * @param dn2           the DN for the 2nd workflow
   * @param dn3           the DN for the 3rd workflow
   * @param subordinate1  the subordinate DN for the 1st workflow
   * @param subordinate2  the subordinate DN for the 2nd workflow
   * @param subordinate3  the subordinate DN for the 3rd workflow
   * @param unrelatedDN   a DN with no hierarchical relationship with
   *                      any of the DNs above
   *
   * @throws  DirectoryException  If the network group ID for a provided
   *                              network group conflicts with the network
   *                              group ID of an existing network group.
   */
  @Test (dataProvider = "DNSet_2", groups = "virtual")
  public void createNetworkGroup(
      DN dn1,
      DN dn2,
      DN dn3,
      DN subordinate1,
      DN subordinate2,
      DN subordinate3,
      DN unrelatedDN
      ) throws Exception
  {
    // The network group identifier is always the same for this test.
    String networkGroupID = "Network Group for test2";
    // Create the network group
    NetworkGroup networkGroup = new NetworkGroup(networkGroupID);
    assertNotNull(networkGroup);
    // Register the network group with the server
    networkGroup.register();
    // Create and register workflow 1, 2 and 3
    createAndRegisterWorkflow(networkGroup, dn1);
    createAndRegisterWorkflow(networkGroup, dn2);
    createAndRegisterWorkflow(networkGroup, dn3);
    // Check the route through the network group
    doCheckNetworkGroup(networkGroup, dn1, subordinate1, unrelatedDN, true);
    doCheckNetworkGroup(networkGroup, dn2, subordinate2, unrelatedDN, true);
    doCheckNetworkGroup(networkGroup, dn3, subordinate3, unrelatedDN, true);
    // Deregister the workflow1 and check the route again.
    // Workflow to deregister is identified by its baseDN.
    networkGroup.deregisterWorkflow(dn1);
    doCheckNetworkGroup(networkGroup, dn1, subordinate1, unrelatedDN, false);
    doCheckNetworkGroup(networkGroup, dn2, subordinate2, unrelatedDN, true);
    doCheckNetworkGroup(networkGroup, dn3, subordinate3, unrelatedDN, true);
    // Deregister the workflow2 and check the route again
    networkGroup.deregisterWorkflow(dn2);
    doCheckNetworkGroup(networkGroup, dn1, subordinate1, unrelatedDN, false);
    doCheckNetworkGroup(networkGroup, dn2, subordinate2, unrelatedDN, false);
    doCheckNetworkGroup(networkGroup, dn3, subordinate3, unrelatedDN, true);
    // Deregister the workflow3 and check the route again
    networkGroup.deregisterWorkflow(dn3);
    doCheckNetworkGroup(networkGroup, dn1, subordinate1, unrelatedDN, false);
    doCheckNetworkGroup(networkGroup, dn2, subordinate2, unrelatedDN, false);
    doCheckNetworkGroup(networkGroup, dn3, subordinate3, unrelatedDN, false);
    // Now create again the workflow 1, 2 and 3...
    WorkflowImpl w1 = createAndRegisterWorkflow(networkGroup, dn1);
    WorkflowImpl w2 = createAndRegisterWorkflow(networkGroup, dn2);
    WorkflowImpl w3 = createAndRegisterWorkflow(networkGroup, dn3);
    // ... and deregister the workflows using their workflowID
    // instead of their baseDN
    if (w1 != null)
    {
      networkGroup.deregisterWorkflow(w1.getWorkflowId());
      doCheckNetworkGroup(networkGroup, dn1, subordinate1, unrelatedDN, false);
      doCheckNetworkGroup(networkGroup, dn2, subordinate2, unrelatedDN, true);
      doCheckNetworkGroup(networkGroup, dn3, subordinate3, unrelatedDN, true);
    }
    if (w2 != null)
    {
      networkGroup.deregisterWorkflow(w2.getWorkflowId());
      doCheckNetworkGroup(networkGroup, dn1, subordinate1, unrelatedDN, false);
      doCheckNetworkGroup(networkGroup, dn2, subordinate2, unrelatedDN, false);
      doCheckNetworkGroup(networkGroup, dn3, subordinate3, unrelatedDN, true);
    }
    if (w3 != null)
    {
      networkGroup.deregisterWorkflow(w3.getWorkflowId());
      doCheckNetworkGroup(networkGroup, dn1, subordinate1, unrelatedDN, false);
      doCheckNetworkGroup(networkGroup, dn2, subordinate2, unrelatedDN, false);
      doCheckNetworkGroup(networkGroup, dn3, subordinate3, unrelatedDN, false);
    }
    // Deregister the network group
    networkGroup.deregister();
  }
  /**
   * This test checks that network groups are updated as appropriate when
   * backend base DNs are added or removed. When a new backend base DN is
@@ -594,19 +419,8 @@
          "--set", "enabled:true",
          "--set", "priority:" + 123);
      try
      {
        // Ensure that the network group was created ok.
        NetworkGroup networkGroup = NetworkGroup.getNetworkGroup(networkGroupID);
        assertNotNull(networkGroup, "The network group does not seem to be registered.");
      }
      finally
      {
        // Remove the network group.
        TestCaseUtils.dsconfig(
            "delete-network-group",
            "--group-name", networkGroupID);
      }
      // Remove the network group.
      TestCaseUtils.dsconfig("delete-network-group", "--group-name", networkGroupID);
    }
    finally
    {
@@ -658,7 +472,7 @@
      try
      {
        // Ensure that the network group was created ok.
        NetworkGroup networkGroup = NetworkGroup.getNetworkGroup(networkGroupID);
        NetworkGroup networkGroup = NetworkGroup.getDefaultNetworkGroup();
        assertNotNull(networkGroup, "The network group does not seem to be registered.");
        TestCaseUtils.dsconfig(
@@ -717,11 +531,7 @@
  {
    // Create and register the network group with the server.
    NetworkGroup networkGroup1 = new NetworkGroup(ng1);
    networkGroup1.register();
    networkGroup1.setNetworkGroupPriority(prio1);
    NetworkGroup networkGroup2 = new NetworkGroup(ng2);
    networkGroup2.register();
    networkGroup2.setNetworkGroupPriority(prio2);
    // Create a workflow -- the workflow ID is the string representation
    // of the workflow base DN.
@@ -731,12 +541,6 @@
    // Register the workflow with the network group.
    networkGroup1.registerWorkflow(workflow1);
    networkGroup2.registerWorkflow(workflow2);
    // Clean the network group
    networkGroup1.deregisterWorkflow(workflow1.getWorkflowId());
    networkGroup1.deregister();
    networkGroup2.deregisterWorkflow(workflow2.getWorkflowId());
    networkGroup2.deregister();
  }
  /**