opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -2427,21 +2427,26 @@ * TODO implement the registration with the appropriate network group. * * @param backend the backend handled by the workflow * * @throws DirectoryException If the workflow ID for the provided * workflow conflicts with the workflow * ID of an existing workflow. */ private static void createAndRegisterWorkflows( Backend backend ) ) throws DirectoryException { // Create a root workflow element to encapsulate the backend LocalBackendWorkflowElement rootWE = new LocalBackendWorkflowElement(backend); new LocalBackendWorkflowElement(backend.getBackendID(), backend); // Create a worklfow for each baseDN being configured // in the backend and register the workflow with the network groups // in the backend and register the workflow with the network groups. // The workflow identifier is the same as the backend ID. for (DN curBaseDN: backend.getBaseDNs()) { WorkflowImpl workflowImpl = new WorkflowImpl( curBaseDN, (WorkflowElement) rootWE); curBaseDN.toString(), curBaseDN, (WorkflowElement) rootWE); registerWorkflowInNetworkGroups(workflowImpl); } } @@ -2456,10 +2461,15 @@ * TODO implement the registration with the appropriate network group. * * @param workflowImpl the workflow to register * * @throws DirectoryException If the workflow ID for the provided * workflow conflicts with the workflow * ID of an existing workflow in a * network group. */ private static void registerWorkflowInNetworkGroups( WorkflowImpl workflowImpl ) ) throws DirectoryException { // Register first the workflow with the default network group NetworkGroup defaultNetworkGroup = NetworkGroup.getDefaultNetworkGroup(); @@ -2482,14 +2492,25 @@ * For the prototype: there is no configuration for the workflows. * So we create one workflow per local backend, and we register it * to the pool. * * @throws ConfigException If there is a configuration problem with any of * the workflows. */ private void createAndRegisterRemainingWorkflows() throws ConfigException { // Create a workflow for the cn=config backend createAndRegisterWorkflows (configHandler); try { // Create a workflow for the cn=config backend createAndRegisterWorkflows (configHandler); // Create a workflows for the rootDSE backend createAndRegisterWorkflows (rootDSEBackend); // Create a workflows for the rootDSE backend createAndRegisterWorkflows (rootDSEBackend); } catch (DirectoryException de) { throw new ConfigException(de.getMessageID(), de.getErrorMessage()); } } opends/src/server/org/opends/server/core/NetworkGroup.java
@@ -27,31 +27,42 @@ package org.opends.server.core; import java.util.ArrayList; import static org.opends.server.messages.CoreMessages.*; import static org.opends.server.messages.MessageHandler.getMessage; import static org.opends.server.util.Validator.ensureNotNull; import java.util.TreeMap; import org.opends.server.types.DN; import org.opends.server.types.DirectoryException; import org.opends.server.types.ResultCode; import org.opends.server.workflowelement.WorkflowElement; /** * This class defines the network group. A network group is used to categorize * client connections. A network group is defined by a set of criteria, a * set of policies and a set of workflows. A client connection belongs to a * network group whenever it satisfies all the network group criteria. As soon * as a client connection belongs to a network group, it has to comply with * all the network group policies and all the client operation can be routed * to one the network group workflows. * set of policies and a set of workflow nodes. A client connection belongs to * a network group whenever it satisfies all the network group criteria. As * soon as a client connection belongs to a network group, it has to comply * with all the network group policies. Any cleared client operation can be * routed to one the network group workflow nodes. */ public class NetworkGroup { // Workflows registered with the current network group. private ArrayList<WorkflowTopologyNode> registeredWorkflows = new ArrayList<WorkflowTopologyNode>(); // Workflow nodes registered with the current network group. // Keys are workflowIDs. private TreeMap<String, WorkflowTopologyNode> registeredWorkflowNodes = new TreeMap<String, WorkflowTopologyNode>(); // The workflow for the rootDSE entry. The RootDSE workflow // is not stored in the list of registered workflows. private RootDseWorkflowTopology rootDSEWorkflow = null; // A lock to protect concurrent access to the registered Workflow nodes. private static 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; // List of naming contexts handled by the network group. @@ -68,39 +79,77 @@ new NetworkGroup ("default"); // The list of all network groups that have been created. // The default network group is not stored in that pool. private static ArrayList<NetworkGroup> networkGroupPool = 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>(); // Human readable network group name. private String networkGroupName = null; // A lock to protect concurrent access to the registeredNetworkGroups. private static Object registeredNetworkGroupsLock = new Object(); // The network group internal identifier. private String networkGroupID = null; /** * Creates a new instance of the network group. * * @param networkGroupName the name of the network group for debug purpose * @param networkGroupID the network group internal identifier */ public NetworkGroup ( String networkGroupName public NetworkGroup( String networkGroupID ) { this.networkGroupName = networkGroupName; this.networkGroupID = networkGroupID; } /** * Registers a network group with the pool of network groups. * Registers the current network group (this) with the server. * * @param networkGroup the network group to register * @throws DirectoryException If the network group ID for the provided * network group conflicts with the network * group ID of an existing network group. */ public static void registerNetworkGroup( NetworkGroup networkGroup ) public void register() throws DirectoryException { networkGroupPool.add(networkGroup); ensureNotNull(networkGroupID); synchronized (registeredNetworkGroupsLock) { // The network group must not be already registered if (registeredNetworkGroups.containsKey(networkGroupID)) { int msgID = MSGID_REGISTER_NETWORK_GROUP_ALREADY_EXISTS; String message = getMessage(msgID, networkGroupID); throw new DirectoryException( ResultCode.UNWILLING_TO_PERFORM, message, msgID); } TreeMap<String, NetworkGroup> newRegisteredNetworkGroups = new TreeMap<String, NetworkGroup>(registeredNetworkGroups); newRegisteredNetworkGroups.put(networkGroupID, this); registeredNetworkGroups = newRegisteredNetworkGroups; } } /** * Deregisters the current network group (this) with the server. */ public void deregister() { synchronized (registeredNetworkGroupsLock) { TreeMap<String, NetworkGroup> networkGroups = new TreeMap<String, NetworkGroup>(registeredNetworkGroups); networkGroups.remove(networkGroupID); registeredNetworkGroups = networkGroups; } } @@ -108,10 +157,14 @@ * Registers a workflow with the network group. * * @param workflow the workflow to register * * @throws DirectoryException If the workflow ID for the provided * workflow conflicts with the workflow * ID of an existing workflow. */ public void registerWorkflow( WorkflowImpl workflow ) ) throws DirectoryException { // The workflow is rgistered with no pre/post workflow element. registerWorkflow(workflow, null, null); @@ -125,12 +178,16 @@ * @param workflow the workflow to register * @param preWorkflowElements the tasks to execute before the workflow * @param postWorkflowElements the tasks to execute after the workflow * * @throws DirectoryException If the workflow ID for the provided * workflow conflicts with the workflow * ID of an existing workflow. */ private void registerWorkflow( WorkflowImpl workflow, WorkflowElement[] preWorkflowElements, WorkflowElement[] postWorkflowElements ) ) throws DirectoryException { // true as soon as the workflow has been registered boolean registered = false; @@ -139,45 +196,44 @@ DN baseDN = workflow.getBaseDN(); if (baseDN.isNullDN()) { // NOTE - The rootDSE workflow is not stored in the pool. rootDSEWorkflow = new RootDseWorkflowTopology(workflow, namingContexts); // NOTE - The rootDSE workflow is stored with the registeredWorkflows. rootDSEWorkflowNode = new RootDseWorkflowTopology(workflow, namingContexts); registered = true; } else { // This workflow is not the rootDSE workflow. Try to insert it in the // workflow topology. if (! baseDNAlreadyRegistered(baseDN)) WorkflowTopologyNode workflowNode = new WorkflowTopologyNode( workflow, preWorkflowElements, postWorkflowElements); // Register the workflow node with the network group. If the workflow // ID is already existing then an exception is raised. registerWorkflowNode(workflowNode); registered = true; // Now add the workflow in the workflow topology... for (WorkflowTopologyNode curNode: registeredWorkflowNodes.values()) { WorkflowTopologyNode workflowTopology = new WorkflowTopologyNode( workflow, preWorkflowElements, postWorkflowElements); // Add the workflow in the workflow topology... for (WorkflowTopologyNode curWorkflow: registeredWorkflows) // Try to insert the new workflow under an existing workflow... if (curNode.insertSubordinate(workflowNode)) { // Try to insert the new workflow under an existing workflow... if (curWorkflow.insertSubordinate(workflowTopology)) { // new workflow has been inserted in the topology break; } // ... or try to insert the existing workflow below the new // workflow if (workflowTopology.insertSubordinate(curWorkflow)) { // new workflow has been inserted in the topology break; } // new workflow has been inserted in the topology break; } // ... then register the workflow with the pool. registeredWorkflows.add(workflowTopology); registered = true; // Rebuild the list of naming context handled by the network group rebuildNamingContextList(); // ... or try to insert the existing workflow below the new // workflow if (workflowNode.insertSubordinate(curNode)) { // new workflow has been inserted in the topology break; } } // Rebuild the list of naming context handled by the network group rebuildNamingContextList(); } // If the workflow has been registered successfully then register it @@ -194,26 +250,98 @@ /** * Deregisters a workflow with the network group. * Deregisters a workflow with the network group. The workflow to * deregister is identified by its baseDN. * * @param baseDN the baseDN of the workflow to deregister * @param baseDN the baseDN of the workflow to deregister, may be null */ public void deregisterWorkflow ( public void deregisterWorkflow( DN baseDN ) { Workflow workflow = getWorkflowCandidate(baseDN); if (workflow != null) if (baseDN == null) { deregisterWorkflow(workflow); return; } if (baseDN.isNullDN()) { // deregister the rootDSE deregisterWorkflow(rootDSEWorkflowNode); } else { // deregister a workflow node synchronized (registeredWorkflowNodesLock) { for (WorkflowTopologyNode node: registeredWorkflowNodes.values()) { DN curDN = node.getBaseDN(); if (curDN.equals(baseDN)) { // Call deregisterWorkflow() instead of deregisterWorkflowNode() // because we want the naming context list to be updated as well. deregisterWorkflow(node); // Only one workflow can match the baseDN, so we can break // the loop here. break; } } } } } /** * Deregisters a workflow with the network group. * Deregisters a workflow with the network group. The workflow to * deregister is identified by its workflow ID. * * @param workflow the workflow to deregister * @param workflowID the workflow identifier of the workflow to deregister */ public void deregisterWorkflow( String workflowID ) { String rootDSEWorkflowID = null; if (rootDSEWorkflowNode != null) { rootDSEWorkflowID = rootDSEWorkflowNode.getWorkflowImpl().getWorkflowId(); } if (workflowID.equalsIgnoreCase(rootDSEWorkflowID)) { // deregister the rootDSE deregisterWorkflow(rootDSEWorkflowNode); } 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); // Only one workflow can match the baseDN, so we can break // the loop here. break; } } } } } /** * Deregisters a workflow node with the network group. * * @param workflowNode the workflow node to deregister */ private void deregisterWorkflow( Workflow workflow @@ -223,21 +351,21 @@ boolean deregistered = false; // Is it the rootDSE workflow? if (workflow == rootDSEWorkflow) if (workflow == rootDSEWorkflowNode) { rootDSEWorkflow = null; rootDSEWorkflowNode = null; deregistered = true; } else { // Deregister the workflow with the network group. WorkflowTopologyNode workflowNode = (WorkflowTopologyNode) workflow; deregisterWorkflowNode(workflowNode); deregistered = true; // The workflow to deregister is not the root DSE workflow. // Remove it from the workflow topology. WorkflowTopologyNode workflowTopology = (WorkflowTopologyNode) workflow; workflowTopology.remove(); // Then deregister the workflow with the network group. registeredWorkflows.remove(workflow); deregistered = true; workflowNode.remove(); // Rebuild the list of naming context handled by the network group rebuildNamingContextList(); @@ -245,12 +373,63 @@ // If the workflow has been deregistered then deregister it with // the default network group as well if (deregistered) if (deregistered && (this != defaultNetworkGroup)) { if (this != defaultNetworkGroup) defaultNetworkGroup.deregisterWorkflow(workflow); } } /** * Registers a workflow node with the network group. * * @param workflowNode the workflow node to register * * @throws DirectoryException If the workflow node ID for the provided * workflow node conflicts with the workflow * node ID of an existing workflow node. */ private void registerWorkflowNode( WorkflowTopologyNode workflowNode ) throws DirectoryException { String workflowID = workflowNode.getWorkflowImpl().getWorkflowId(); ensureNotNull(workflowID); synchronized (registeredWorkflowNodesLock) { // The workflow must not be already registered if (registeredWorkflowNodes.containsKey(workflowID)) { defaultNetworkGroup.deregisterWorkflow(workflow); int msgID = MSGID_REGISTER_WORKFLOW_NODE_ALREADY_EXISTS; String message = getMessage(msgID, workflowID, networkGroupID); throw new DirectoryException( ResultCode.UNWILLING_TO_PERFORM, message, msgID); } TreeMap<String, WorkflowTopologyNode> newRegisteredWorkflowNodes = new TreeMap<String, WorkflowTopologyNode>(registeredWorkflowNodes); newRegisteredWorkflowNodes.put(workflowID, workflowNode); registeredWorkflowNodes = newRegisteredWorkflowNodes; } } /** * Deregisters the current worklow (this) with the server. * * @param workflowNode the workflow node to deregister */ private void deregisterWorkflowNode( WorkflowTopologyNode workflowNode ) { synchronized (registeredWorkflowNodesLock) { TreeMap<String, WorkflowTopologyNode> newWorkflowNodes = new TreeMap<String, WorkflowTopologyNode>(registeredWorkflowNodes); newWorkflowNodes.remove(workflowNode.getWorkflowImpl().getWorkflowId()); registeredWorkflowNodes = newWorkflowNodes; } } @@ -262,7 +441,7 @@ * @return the highest workflow in the topology that can handle the base DN, * <code>null</code> if none was found */ public Workflow getWorkflowCandidate ( public Workflow getWorkflowCandidate( DN baseDN ) { @@ -273,7 +452,7 @@ if (baseDN.isNullDN()) { // The rootDSE workflow is the candidate. workflowCandidate = rootDSEWorkflow; workflowCandidate = rootDSEWorkflowNode; } else { @@ -317,12 +496,12 @@ namingContexts.resetLists(); // a registered workflow with no parent is a naming context for (WorkflowTopologyNode curWorkflow: registeredWorkflows) for (WorkflowTopologyNode workflowNode: registeredWorkflowNodes.values()) { WorkflowTopologyNode parent = curWorkflow.getParent(); WorkflowTopologyNode parent = workflowNode.getParent(); if (parent == null) { namingContexts.addNamingContext (curWorkflow); namingContexts.addNamingContext (workflowNode); } } } @@ -336,7 +515,7 @@ * @return <code>false</code> if the base DN is registered with the * network group, <code>false</code> otherwise */ private boolean baseDNAlreadyRegistered ( private boolean baseDNAlreadyRegistered( DN baseDN ) { @@ -345,9 +524,9 @@ // go through the list of registered workflow and check whether a base DN // has already been used in a registered workflow for (WorkflowTopologyNode curWorkflow: registeredWorkflows) for (WorkflowTopologyNode workflowNode: registeredWorkflowNodes.values()) { DN curDN = curWorkflow.getBaseDN(); DN curDN = workflowNode.getBaseDN(); if (baseDN.equals (curDN)) { alreadyRegistered = true; @@ -377,28 +556,28 @@ * @param leftMargin white spaces used to indent traces * @return a string buffer that contains trace information */ public StringBuffer toString (String leftMargin) public StringBuffer toString(String leftMargin) { StringBuffer sb = new StringBuffer(); String newMargin = leftMargin + " "; sb.append (leftMargin + "Networkgroup (" + networkGroupName+ "\n"); sb.append (leftMargin + "Networkgroup (" + networkGroupID+ "\n"); sb.append (leftMargin + "List of registered workflows:\n"); for (WorkflowTopologyNode w: registeredWorkflows) for (WorkflowTopologyNode node: registeredWorkflowNodes.values()) { sb.append (w.toString (newMargin)); sb.append (node.toString (newMargin)); } namingContexts.toString (leftMargin); sb.append (leftMargin + "rootDSEWorkflow:\n"); if (rootDSEWorkflow == null) if (rootDSEWorkflowNode == null) { sb.append (newMargin + "null\n"); } else { sb.append (rootDSEWorkflow.toString (newMargin)); sb.append (rootDSEWorkflowNode.toString (newMargin)); } return sb; opends/src/server/org/opends/server/core/WorkflowImpl.java
@@ -27,8 +27,16 @@ package org.opends.server.core; import static org.opends.server.messages.CoreMessages.*; import static org.opends.server.messages.MessageHandler.getMessage; import static org.opends.server.util.Validator.ensureNotNull; import java.util.TreeMap; import org.opends.server.types.DN; import org.opends.server.types.DirectoryException; import org.opends.server.types.Operation; import org.opends.server.types.ResultCode; import org.opends.server.workflowelement.WorkflowElement; @@ -43,6 +51,8 @@ */ public class WorkflowImpl implements Workflow { // The workflow identifier used by the configuration. private String workflowID = null; // The root of the workflow task tree. private WorkflowElement rootWorkflowElement = null; @@ -63,6 +73,13 @@ // flag will always return false. private boolean isPrivate = false; // The set of workflows registered with the server. private static TreeMap<String, Workflow> registeredWorkflows = new TreeMap<String, Workflow>(); // A lock to protect concurrent access to the registeredWorkflows. private static Object registeredWorkflowsLock = new Object(); /** * Creates a new instance of a workflow implementation. To define a worfklow @@ -71,14 +88,17 @@ * * The rootWorkflowElement must not be null. * * @param workflowId workflow internal identifier * @param baseDN identifies the data handled by the workflow * @param rootWorkflowElement the root node of the workflow task tree */ public WorkflowImpl( String workflowId, DN baseDN, WorkflowElement rootWorkflowElement ) { this.workflowID = workflowId; this.baseDN = baseDN; this.rootWorkflowElement = rootWorkflowElement; if (this.rootWorkflowElement != null) @@ -100,6 +120,17 @@ /** * Gets the workflow internal identifier. * * @return the workflow internal indentifier */ public String getWorkflowId() { return workflowID; } /** * Indicates whether the root node of the workflow task tree is * handling a private local backend. * @@ -124,4 +155,79 @@ { rootWorkflowElement.execute(operation); } /** * Registers the current worklow (this) with the server. * * @throws DirectoryException If the workflow ID for the provided workflow * conflicts with the workflow ID of an existing * workflow. */ public void register() throws DirectoryException { ensureNotNull(workflowID); synchronized (registeredWorkflowsLock) { // The workflow must not be already registered if (registeredWorkflows.containsKey(workflowID)) { int msgID = MSGID_REGISTER_WORKFLOW_ALREADY_EXISTS; String message = getMessage(msgID, workflowID); throw new DirectoryException( ResultCode.UNWILLING_TO_PERFORM, message, msgID); } TreeMap<String, Workflow> newRegisteredWorkflows = new TreeMap<String, Workflow>(registeredWorkflows); newRegisteredWorkflows.put(workflowID, this); registeredWorkflows = newRegisteredWorkflows; } } /** * Deregisters the current worklow (this) with the server. */ public void deregister() { ensureNotNull(workflowID); synchronized (registeredWorkflowsLock) { TreeMap<String, Workflow> newWorkflows = new TreeMap<String, Workflow>(registeredWorkflows); newWorkflows.remove(workflowID); registeredWorkflows = newWorkflows; } } /** * Deregisters a worklow with the server. The workflow to deregister * is identified with its identifier. * * @param workflowID the identifier of the workflow to deregister * * @return the workflow that has been deregistered, * <code>null</code> if no workflow has been found. */ public WorkflowImpl deregister(String workflowID) { WorkflowImpl workflowToDeregister = null; synchronized (registeredWorkflowsLock) { if (registeredWorkflows.containsKey(workflowID)) { workflowToDeregister = (WorkflowImpl) registeredWorkflows.get(workflowID); workflowToDeregister.deregister(); } } return workflowToDeregister; } } opends/src/server/org/opends/server/messages/CoreMessages.java
@@ -6352,6 +6352,37 @@ /** * The message ID for the message that will be used if an attempt is made to * register a workflow with an ID that is already registered with the server. * This takes a single argument, which is the conflicting workflow ID. */ public static final int MSGID_REGISTER_WORKFLOW_ALREADY_EXISTS = CATEGORY_MASK_CORE | SEVERITY_MASK_SEVERE_ERROR | 635; /** * The message ID for the message that will be used if an attempt is made to * register a workflow node with an ID that is already registered with a * network group. This takes two arguments, which are the conflicting * workflow ID and the network group ID. */ public static final int MSGID_REGISTER_WORKFLOW_NODE_ALREADY_EXISTS = CATEGORY_MASK_CORE | SEVERITY_MASK_SEVERE_ERROR | 636; /** * The message ID for the message that will be used if an attempt is made to * register a network group with an ID that is already registered. This * takes a single argument, which is the conflicting network group ID. */ public static final int MSGID_REGISTER_NETWORK_GROUP_ALREADY_EXISTS = CATEGORY_MASK_CORE | SEVERITY_MASK_SEVERE_ERROR | 637; /** * Associates a set of generic messages with the message IDs defined * in this class. */ @@ -8655,6 +8686,18 @@ registerMessage(MSGID_IDLETIME_UNEXPECTED_ERROR, "An unexpected error occurred in the idle time limit " + "thread: %s"); registerMessage(MSGID_REGISTER_WORKFLOW_ALREADY_EXISTS, "Unable to register workflow %s with the Directory " + "Server because another workflow with the same " + "workflow ID is already registered"); registerMessage(MSGID_REGISTER_WORKFLOW_NODE_ALREADY_EXISTS, "Unable to register workflow node %s with the network " + "group %s because another workflow node with the same " + "workflow node ID is already registered"); registerMessage(MSGID_REGISTER_NETWORK_GROUP_ALREADY_EXISTS, "Unable to register network group %s with the Directory " + "Server because another network group with the same " + "network group ID is already registered"); } } opends/src/server/org/opends/server/workflowelement/LeafWorkflowElement.java
@@ -36,5 +36,14 @@ public abstract class LeafWorkflowElement extends WorkflowElement { // Empty at the moment. /** * Creates a new instance of the leaf workflow element. * * @param workflowElementID the workflow element identifier as defined * in the configuration. */ protected LeafWorkflowElement(String workflowElementID) { super(workflowElementID); } } opends/src/server/org/opends/server/workflowelement/WorkflowElement.java
@@ -41,6 +41,10 @@ public abstract class WorkflowElement { // The workflow element identifier. private String workflowElementID = null; /** * Indicates whether the workflow element encapsulates a private * local backend. @@ -50,10 +54,13 @@ /** * Creates a new instance of the workflow element. * * @param workflowElementID the workflow element identifier as defined * in the configuration. */ public WorkflowElement() public WorkflowElement(String workflowElementID) { // No implementation is required. this.workflowElementID = workflowElementID; } @@ -78,4 +85,15 @@ { return isPrivate; } /** * Provides the workflow element identifier. * * @return the worflow element identifier */ public String getWorkflowElementID() { return workflowElementID; } } opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
@@ -142,12 +142,16 @@ /** * Creates a new instance of the local backend workflow element. * * @param workflowElementID the workflow element identifier * @param backend the backend associated to that workflow element */ public LocalBackendWorkflowElement( String workflowElementID, Backend backend ) { super(workflowElementID); this.backend = backend; if (this.backend != null) opends/tests/unit-tests-testng/src/server/org/opends/server/core/NetworkGroupTest.java
@@ -27,6 +27,7 @@ package org.opends.server.core; import static org.opends.server.messages.CoreMessages.*; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; @@ -41,10 +42,10 @@ /** * This set of tests checks that network groups are properly created. * This set of tests test the network groups. */ public class NetworkGroupTest { { //=========================================================================== // // B E F O R E C L A S S @@ -72,6 +73,53 @@ //=========================================================================== /** * Provides information to create a network group with one workflow inside. * * Each set of DNs contains: * - one network group identifier * - one base DN for the workflow to register with the network group */ @DataProvider (name = "DNSet_0") public Object[][] initDNSet_0() throws Exception { // Network group ID String networkGroupID1 = "networkGroup1"; String networkGroupID2 = "networkGroup2"; // Workflow base DNs DN dn1 = null; DN dn2 = null; try { dn1 = DN.decode("o=test1"); dn2 = DN.decode("o=test2"); } catch (DirectoryException de) { throw de; } // Network group info Object[][] myData = { // Test1: create a network group with the identifier networkGroupID1 { networkGroupID1, dn1 }, // Test2: create the same network group to check that previous // network group was properly cleaned. { networkGroupID1, dn1 }, // Test3: create another network group { networkGroupID2, dn2 }, }; return myData; } /** * Provides a single DN to search a workflow in a network group. * * Each set of DNs is composed of: @@ -137,8 +185,10 @@ return myData; } /** * Provides information to create a network group. * Provides information to create a network group to test the routing * process. * * Each set of DNs contains: * - one base DN for the 1st workflow @@ -223,11 +273,76 @@ // //=========================================================================== /** * Gets a workflow candidate in the default network group. * Tests the network group registration. * * @param networkGroupID the ID of the network group to register * @param workflowBaseDN1 the base DN of the first workflow node to register * in the network group */ @Test (dataProvider = "DNSet_0", groups = "virtual") public void testNetworkGroupRegistration( String networkGroupID, DN workflowBaseDN ) throws DirectoryException { // 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. boolean exceptionRaised = false; try { networkGroup.register(); } catch (DirectoryException de) { exceptionRaised = true; assertEquals( de.getMessageID(), MSGID_REGISTER_NETWORK_GROUP_ALREADY_EXISTS); } assertEquals(exceptionRaised, true); // Create a workflow -- the workflow ID is the string representation // of the workflow base DN. WorkflowElement nullWE = null; WorkflowImpl workflow = new WorkflowImpl( workflowBaseDN.toString(), workflowBaseDN, nullWE); // Register the workflow with the network group. networkGroup.registerWorkflow(workflow); // Register again the workflow with the network group and catch the // expected DirectoryServer exception. exceptionRaised = false; try { networkGroup.registerWorkflow(workflow); } catch (DirectoryException de) { exceptionRaised = true; assertEquals( de.getMessageID(), MSGID_REGISTER_WORKFLOW_NODE_ALREADY_EXISTS); } assertEquals(exceptionRaised, true); // Clean the network group networkGroup.deregisterWorkflow(workflow.getWorkflowId()); networkGroup.deregister(); } /** * Check the route process in the default network group. * * @param dnToSearch the DN of a workflow in the default network group * @param dnSubordinate a subordinate of dnToSearch * @param dnToSearch the DN of a workflow to search in the default * network group * @param dnSubordinate a subordinate DN of dnToSearch * @param exists true if we are supposed to find a workflow for * dnToSearch */ @@ -238,16 +353,121 @@ boolean exists ) { // let's get the default network group (it should always exist) // let's get the default network group -- it should always exist NetworkGroup defaultNG = NetworkGroup.getDefaultNetworkGroup(); assertNotNull(defaultNG); // let's check the routing through the network group doCheckNetworkGroup(defaultNG, dnToSearch, dnSubordinate, exists); doCheckNetworkGroup(defaultNG, dnToSearch, dnSubordinate, null, exists); // Dump info StringBuffer sb = defaultNG.toString("defaultNetworkGroup> "); writeln(sb.toString()); // Dump the default network group dump(defaultNG, "defaultNetworkGroup> "); } /** * 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 DirectoryException { // 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 thorugh 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; WorkflowImpl w2; WorkflowImpl w3; w1 = createAndRegisterWorkflow(networkGroup, dn1); w2 = createAndRegisterWorkflow(networkGroup, dn2); 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(); } @@ -255,8 +475,11 @@ * Checks the DN routing through a network group. * * @param networkGroup the network group to use for the check * @param dnToSearch the DN of a workflow in the network group * @param dnToSearch the DN of a workflow in the network group; may * be null * @param dnSubordinate a subordinate of dnToSearch * @param unrelatedDN a DN with no hierarchical relationship with * any of the DNs above, may be null * @param shouldExist true if we are supposed to find a workflow for * dnToSearch */ @@ -264,9 +487,15 @@ NetworkGroup networkGroup, DN dnToSearch, DN dnSubordinate, DN unrelatedDN, boolean shouldExist ) { if (dnToSearch == null) { return; } // Let's retrieve the workflow that maps best the dnToSearch Workflow workflow = networkGroup.getWorkflowCandidate(dnToSearch); if (shouldExist) @@ -285,82 +514,14 @@ Workflow workflow2 = networkGroup.getWorkflowCandidate(dnSubordinate); assertEquals(workflow2, workflow); } } /** * Creates a network group with several workflows inside. Routing operation * is done through the default root DSE workflow (which is automatically * created by the network group class). * * @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 */ @Test (dataProvider = "DNSet_2", groups = "virtual") public void createNetworkGroup2( DN dn1, DN dn2, DN dn3, DN subordinate1, DN subordinate2, DN subordinate3, DN unrelatedDN ) { String networkGroupName = "Network Group for test2"; // Create the network group NetworkGroup ng = new NetworkGroup(networkGroupName); assertNotNull(ng); // Register the network group NetworkGroup.registerNetworkGroup(ng); // Create and register workflow 1 if (dn1 != null) { createAndRegisterWorkflow(ng, dn1, subordinate1, unrelatedDN); } // Create and register workflow 2 if (dn2 != null) { createAndRegisterWorkflow(ng, dn2, subordinate2, unrelatedDN); } // Create and register workflow 3 if (dn3 != null) { createAndRegisterWorkflow(ng, dn3, subordinate3, unrelatedDN); } // Dump info StringBuffer sb = ng.toString("createNetworkGroup2(" + dn1 + ")> "); writeln(sb.toString()); // Dump info of defaultNetworkGroup StringBuffer sb2 = NetworkGroup.getDefaultNetworkGroup().toString("defaultNetworkGroup> "); writeln(sb2.toString()); // Deregister the workflow1... deregisterWorkflow(ng, dn1, subordinate1, unrelatedDN); // ... and dump info again sb = ng.toString("DEREGISTER Workflow> "); writeln(sb.toString()); // dump info of defaultNetworkGroup sb2 = NetworkGroup.getDefaultNetworkGroup().toString( "DEREGISTER defaultNetworkGroup> " ); writeln(sb2.toString()); // Check that the unrelatedDN is not handled by any workflow if (unrelatedDN != null) { Workflow unrelatedWorkflow = networkGroup.getWorkflowCandidate(unrelatedDN); assertNull(unrelatedWorkflow); } } @@ -368,81 +529,36 @@ * Creates a workflow and register it with a network group. * * @param networkGroup a network group to register the workflow with * @param workflowBaseDN the base DN of the workflow to register * @param subordinateDN subordinate DN of the workflowBaseDN * @param unrelatedDN a DN with no hierarchical relationship with * any of the base DN above * @param workflowBaseDN the base DN of the workflow to register; may be * null * @throws DirectoryException If the workflow ID for the provided * workflow conflicts with the workflow * ID of an existing workflow. */ private void createAndRegisterWorkflow( private WorkflowImpl createAndRegisterWorkflow( NetworkGroup networkGroup, DN workflowBaseDN, DN subordinateDN, DN unrelatedDN ) DN workflowBaseDN ) throws DirectoryException { assertNotNull(networkGroup); // Create and register a workflow (no task in the workflow) WorkflowElement rootWE = null; WorkflowImpl realWorkflow = new WorkflowImpl(workflowBaseDN, rootWE); assertNotNull(realWorkflow); // Register the workflow with the network group. networkGroup.registerWorkflow(realWorkflow); // Now check that workflow is accessible through the network group Workflow electedWorkflow; electedWorkflow = networkGroup.getWorkflowCandidate(workflowBaseDN); assertEquals(electedWorkflow.getBaseDN(), workflowBaseDN); electedWorkflow = networkGroup.getWorkflowCandidate(subordinateDN); assertEquals(electedWorkflow.getBaseDN(), workflowBaseDN); // Check that the unrelatedDN is not handled by the workflow Workflow unrelatedWorkflow = networkGroup.getWorkflowCandidate(unrelatedDN); assertNull(unrelatedWorkflow); } /** * Deregisters a workflow with a network group. The workflow to * deregister is identified by its baseDN. * * @param networkGroup a network group that contains the workflow * to deregister * @param workflowBaseDN the base DN of the workflow to deregister * @param subordinateDN subordinate DN of the workflowBaseDN * @param unrelatedDN a DN with no hierarchical relationship with * any of the base DN above */ private void deregisterWorkflow( NetworkGroup networkGroup, DN workflowBaseDN, DN subordinateDN, DN unrelatedDN ) { assertNotNull(networkGroup); // get the workflow in the network group Workflow workflow = networkGroup.getWorkflowCandidate(workflowBaseDN); if (workflow == null) if (workflowBaseDN == null) { // found no workflow return; return null; } // Deregister the workflow with the network group networkGroup.deregisterWorkflow(workflow.getBaseDN()); // Create a workflow with no task inside. The workflow identifier // is the a string representation of the workflow base DN. WorkflowElement rootWE = null; String workflowId = workflowBaseDN.toString(); WorkflowImpl workflow = new WorkflowImpl( workflowId, workflowBaseDN, rootWE); assertNotNull(workflow); // Check that the workflow is no more accessible through the network // group Workflow electedWorkflow; electedWorkflow = networkGroup.getWorkflowCandidate(workflowBaseDN); assertNull(electedWorkflow); electedWorkflow = networkGroup.getWorkflowCandidate(subordinateDN); assertNull(electedWorkflow); // Register the workflow with the network group. networkGroup.registerWorkflow(workflow); return workflow; } @@ -451,12 +567,7 @@ */ private void write(String msg) { boolean dumpInfo = true; if (dumpInfo) { System.out.print(msg); } System.out.print(msg); } @@ -467,4 +578,21 @@ { write(msg + "\n"); } /** * Dump the network group info to the console. */ private void dump(NetworkGroup networkGroup, String prompt) { final boolean doDump = false; if (doDump) { StringBuffer sb = networkGroup.toString(prompt); writeln(sb.toString()); } } } opends/tests/unit-tests-testng/src/server/org/opends/server/core/WorkflowTopologyTest.java
@@ -27,8 +27,10 @@ package org.opends.server.core; import static org.opends.server.messages.CoreMessages.*; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertNotNull; import java.util.ArrayList; @@ -428,7 +430,7 @@ * @param dummyDN a DN not registered in any workflow */ @Test (dataProvider = "DNSet_1", groups = "virtual") public void createWorkflow_basic ( public void createWorkflow_basic( DN baseDN, DN subordinateDN, DN dummyDN @@ -436,30 +438,32 @@ { // create a DIT set with the baseDN (no workflow element in the DIT). WorkflowElement nullWE = null; WorkflowImpl realWorkflow = new WorkflowImpl (baseDN, nullWE); WorkflowImpl workflow = new WorkflowImpl (baseDN.toString(), baseDN, nullWE); // Create a worflow with the dit, no pre/post-workflow element. WorkflowTopologyNode workflow = new WorkflowTopologyNode (realWorkflow, null, null); WorkflowTopologyNode workflowNode = new WorkflowTopologyNode (workflow, null, null); // The base DN in the workflow should match baseDN parameter DN workflowBaseDN = workflow.getBaseDN(); DN workflowBaseDN = workflowNode.getBaseDN(); assertEquals (workflowBaseDN, baseDN); // There should be no parent workflow. WorkflowTopologyNode parent = workflow.getParent(); WorkflowTopologyNode parent = workflowNode.getParent(); assertEquals (parent, null); // The workflow should handle the baseDN and subordinateDN. DN readBaseDN = null; readBaseDN = workflow.getParentBaseDN (baseDN); readBaseDN = workflowNode.getParentBaseDN (baseDN); assertEquals (readBaseDN, baseDN); readBaseDN = workflow.getParentBaseDN (subordinateDN); readBaseDN = workflowNode.getParentBaseDN (subordinateDN); assertEquals (readBaseDN, baseDN); // The workflow should not handle the dummyDN. if (dummyDN != null) { readBaseDN = workflow.getParentBaseDN (dummyDN); readBaseDN = workflowNode.getParentBaseDN (dummyDN); assertNull (readBaseDN); } @@ -498,11 +502,11 @@ WorkflowImpl unrelatedWorkflow = null; { WorkflowElement nullWE = null; workflow = new WorkflowImpl (baseDN, nullWE); subWorkflow = new WorkflowImpl (subordinateDN, nullWE); workflow = new WorkflowImpl (baseDN.toString(), baseDN, nullWE); subWorkflow = new WorkflowImpl (subordinateDN.toString(), subordinateDN, nullWE); if (unrelatedDN != null) { unrelatedWorkflow = new WorkflowImpl (unrelatedDN, nullWE); unrelatedWorkflow = new WorkflowImpl (unrelatedDN.toString(), unrelatedDN, nullWE); } } @@ -643,9 +647,9 @@ WorkflowImpl workflow3; { WorkflowElement nullWE = null; workflow1 = new WorkflowImpl (baseDN1, nullWE); workflow2 = new WorkflowImpl (baseDN2, nullWE); workflow3 = new WorkflowImpl(baseDN3, nullWE); workflow1 = new WorkflowImpl (baseDN1.toString(), baseDN1, nullWE); workflow2 = new WorkflowImpl (baseDN2.toString(), baseDN2, nullWE); workflow3 = new WorkflowImpl (baseDN3.toString(), baseDN3, nullWE); } w1 = new WorkflowTopologyNode (workflow1, null, null); @@ -803,7 +807,7 @@ * @param unrelatedDN a DN not registered in any workflow */ @Test (dataProvider = "DNSet_3", groups = "virtual") public void createWorkflow_complexTopology1 ( public void createWorkflow_complexTopology1( DN baseDN1, DN baseDN2, DN baseDN3, @@ -825,9 +829,9 @@ { WorkflowElement nullWE = null; workflow1 = new WorkflowImpl (baseDN1, nullWE); workflow2 = new WorkflowImpl (baseDN2, nullWE); workflow3 = new WorkflowImpl (baseDN3, nullWE); workflow1 = new WorkflowImpl (baseDN1.toString(), baseDN1, nullWE); workflow2 = new WorkflowImpl (baseDN2.toString(), baseDN2, nullWE); workflow3 = new WorkflowImpl (baseDN3.toString(), baseDN3, nullWE); } w1 = new WorkflowTopologyNode (workflow1, null, null); @@ -935,4 +939,41 @@ ); 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 { WorkflowElement nullWE = null; // Create a workflow to handle the baseDN with no workflow element WorkflowImpl workflow = new WorkflowImpl( baseDN.toString(), baseDN, nullWE); // 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. boolean exceptionRaised = false; try { workflow.register(); } catch (DirectoryException e) { exceptionRaised = true; assertEquals(e.getMessageID(), MSGID_REGISTER_WORKFLOW_ALREADY_EXISTS); } assertEquals(exceptionRaised, true); } }