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

Jean-Noel Rouvignac
19.01.2014 df1323b2cab4997aff8f3ca12817715e30c92cb2
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,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.
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,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;
  }
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);