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

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


WorkflowImpl.java: REMOVED
Moved all instance fields and methods to WorkflowTopology.
Removed the referenceCounter and related methods.
Removed all the workflow registration methods which where redundant with the workflow topology registration methods.

WorkflowTopology.java:
Moved all needed instance fields and methods here from WorkflowImpl + changed ctor.

RootDseWorkflowTopology.java, WorkflowTopologyNode.java, NetworkGroup.java, NetworkGroupTest.java:
Consequence of the changes to WorkflowImpl and WorkflowTopology.

WorkflowTopologyTest.java:
Removed testWorkflowRegistration(), consequence of removing WorkflowImpl registration methods.
Code cleanup.
Javadoc cleanup.


BindOperationBasis.java:
Since there is only one type of network group, it can now directly use NetworkGroup.getWorkflowCandidate().

DirectoryServer.java:
Moved NetworkGroup registration inside createWorkflow().
Inlined createAndRegisterWorkflow().
In registerBaseDN() and deregisterBaseDN() removed null checks because the lists are never null.
1 files deleted
8 files modified
861 ■■■■ changed files
opendj3-server-dev/src/server/org/opends/server/core/BindOperationBasis.java 52 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/core/DirectoryServer.java 51 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/core/RootDseWorkflowTopology.java 30 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/core/WorkflowImpl.java 321 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/core/WorkflowTopology.java 91 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/core/WorkflowTopologyNode.java 92 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/core/networkgroups/NetworkGroup.java 50 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/WorkflowTopologyTest.java 139 ●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/networkgroups/NetworkGroupTest.java 35 ●●●●● patch | view | raw | blame | history
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)
  {
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,11 +5344,9 @@
      // 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);
        }
      }
      // When a new baseDN is registered with the server we have to create
      // a new workflow to handle the base DN.
@@ -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);
        }
      }
      // 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.
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;
  }
opendj3-server-dev/src/server/org/opends/server/core/WorkflowImpl.java
File was deleted
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;
  }
}
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,9 +233,7 @@
    // Is the dn a subordinate of the current base DN?
    DN curBaseDN = getBaseDN();
    if (curBaseDN != null)
    {
      if (dn.isDescendantOf(curBaseDN))
    if (curBaseDN != null && dn.isDescendantOf(curBaseDN))
      {
        // The dn may be handled by the current workflow.
        // Now we have to check whether the dn is handled by
@@ -255,7 +255,6 @@
          parentBaseDN = curBaseDN;
        }
      }
    }
    return parentBaseDN;
  }
@@ -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;
  }
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;
    }
  }
}
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));
    }
  }
}
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);