[jboss-cvs] JBossAS SVN: r64326 - in projects/microcontainer/trunk: deployers-impl/src/tests/org/jboss/test/deployers/deployer and 6 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Fri Jul 27 10:19:13 EDT 2007


Author: adrian at jboss.org
Date: 2007-07-27 10:19:13 -0400 (Fri, 27 Jul 2007)
New Revision: 64326

Added:
   projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/deployer/support/TestSimpleDeployer2.java
   projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/deployer/test/HeuristicRussionDollUnitTestCase.java
Modified:
   projects/microcontainer/trunk/deployers-impl/src/main/org/jboss/deployers/plugins/deployers/DeployerWrapper.java
   projects/microcontainer/trunk/deployers-impl/src/main/org/jboss/deployers/plugins/deployers/DeployersImpl.java
   projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/deployer/DeployersDeployerTestSuite.java
   projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/deployer/test/HeuristicAllOrNothingUnitTestCase.java
   projects/microcontainer/trunk/deployers-spi/src/main/org/jboss/deployers/spi/deployer/Deployer.java
   projects/microcontainer/trunk/deployers-spi/src/main/org/jboss/deployers/spi/deployer/helpers/AbstractDeployer.java
   projects/microcontainer/trunk/deployers-structure-spi/src/main/org/jboss/deployers/structure/spi/DeploymentUnit.java
   projects/microcontainer/trunk/deployers-structure-spi/src/main/org/jboss/deployers/structure/spi/helpers/AbstractDeploymentUnit.java
Log:
[JBMICROCONT-168] - Add support for parent first or last to the deployer (default first) - a simple mechanism for Russian Doll behaviour

Modified: projects/microcontainer/trunk/deployers-impl/src/main/org/jboss/deployers/plugins/deployers/DeployerWrapper.java
===================================================================
--- projects/microcontainer/trunk/deployers-impl/src/main/org/jboss/deployers/plugins/deployers/DeployerWrapper.java	2007-07-27 14:17:21 UTC (rev 64325)
+++ projects/microcontainer/trunk/deployers-impl/src/main/org/jboss/deployers/plugins/deployers/DeployerWrapper.java	2007-07-27 14:19:13 UTC (rev 64326)
@@ -153,6 +153,11 @@
       return deployer.getStage();
    }
 
+   public boolean isParentFirst()
+   {
+      return deployer.isParentFirst();
+   }
+
    public void deploy(DeploymentUnit unit) throws DeploymentException
    {
       if (unit == null)

Modified: projects/microcontainer/trunk/deployers-impl/src/main/org/jboss/deployers/plugins/deployers/DeployersImpl.java
===================================================================
--- projects/microcontainer/trunk/deployers-impl/src/main/org/jboss/deployers/plugins/deployers/DeployersImpl.java	2007-07-27 14:17:21 UTC (rev 64325)
+++ projects/microcontainer/trunk/deployers-impl/src/main/org/jboss/deployers/plugins/deployers/DeployersImpl.java	2007-07-27 14:19:13 UTC (rev 64326)
@@ -587,7 +587,47 @@
       DeploymentContext deploymentContext = deploymentControllerContext.getDeploymentContext();
       try
       {
-         doInstall(deploymentContext, stageName, true, true);
+         List<Deployer> theDeployers = getDeployersList(stageName);
+         
+         if (log.isTraceEnabled())
+            log.trace("Deployers for " + stageName + " " + theDeployers);
+         
+         if (theDeployers.isEmpty() == false)
+         {
+            int i = 0;
+            try
+            {
+               while (i < theDeployers.size())
+               {
+                  Deployer deployer = theDeployers.get(i);
+                  if (deployer.isParentFirst())
+                     doInstallParentFirst(deployer, deploymentContext);
+                  else
+                     doInstallParentLast(deployer, deploymentContext);
+                  ++i;
+               }
+            }
+            catch (Throwable t)
+            {
+               deploymentContext.setState(DeploymentState.ERROR);
+               deploymentContext.setProblem(t);
+               
+               // Unwind the previous deployments
+               for (int j = i-1; j >= 0; --j)
+               {
+                  Deployer deployer = theDeployers.get(j);
+                  if (deployer.isParentFirst())
+                     doUninstallParentLast(deployer, deploymentContext, true, true);
+                  else
+                     doUninstallParentFirst(deployer, deploymentContext, true, true);
+               }
+               
+               // It can happen that subdeployments are not processed if the parent fails immediately
+               // so there is no callback to undeploy when nothing was done
+               setState(deploymentContext, DeploymentState.UNDEPLOYED, DeploymentState.DEPLOYING);
+               throw t;
+            }
+         }
       }
       finally
       {
@@ -598,65 +638,15 @@
          }
       }
    }
-
+   
    /**
-    * Do the install
+    * Do the install parent first
     * 
-    * @param context the context
-    * @param stageName the stage
-    * @param doChildren whether to do children
-    * @param doComponents whether to do components
-    * @throws Throwable for any problem
-    */
-   protected void doInstall(DeploymentContext context, String stageName, boolean doChildren, boolean doComponents) throws Throwable
-   {
-      List<Deployer> theDeployers = getDeployersList(stageName);
-      
-      if (log.isTraceEnabled())
-         log.trace("Deployers for " + stageName + " " + theDeployers);
-      
-      if (theDeployers.isEmpty() == false)
-      {
-         int i = 0;
-         try
-         {
-            while (i < theDeployers.size())
-            {
-               Deployer deployer = theDeployers.get(i);
-               doInstall(deployer, context, doChildren, doComponents);
-               ++i;
-            }
-         }
-         catch (Throwable t)
-         {
-            context.setState(DeploymentState.ERROR);
-            context.setProblem(t);
-            
-            // Unwind the previous deployments
-            for (int j = i-1; j >= 0; --j)
-            {
-               Deployer deployer = theDeployers.get(j);
-               doUninstall(deployer, context, true, true);
-            }
-            
-            // It can happen that subdeployments are not processed if the parent fails immediately
-            // so there is no callback to undeploy when nothing was done
-            setState(context, DeploymentState.UNDEPLOYED, DeploymentState.DEPLOYING);
-            throw t;
-         }
-      }
-   }
-
-   /**
-    * Do the install
-    * 
     * @param deployer the deployer
     * @param context the context
-    * @param doChildren whether to do children
-    * @param doComponents whether to do components
     * @throws Throwable for any problem
     */
-   protected void doInstall(Deployer deployer, DeploymentContext context, boolean doChildren, boolean doComponents) throws Throwable
+   protected void doInstallParentFirst(Deployer deployer, DeploymentContext context) throws Throwable
    {
       List<DeploymentContext> currentComponents = context.getComponents();
       // Take a copy of the components so we don't start looping on newly added components
@@ -682,7 +672,7 @@
       else if (log.isTraceEnabled())
          log.trace("Deployer " + deployer + " not relevant for " + context.getName());
       
-      if (doComponents && components != null)
+      if (components != null)
       {
          try
          {
@@ -691,7 +681,7 @@
                DeploymentContext component = components.get(i);
                try
                {
-                  doInstall(deployer, component, false, true);
+                  doInstallParentFirst(deployer, component);
                }
                catch (DeploymentException e)
                {
@@ -699,7 +689,7 @@
                   for (int j = i - 1; j >= 0; --j)
                   {
                      component = components.get(j);
-                     doUninstall(deployer, component, false, true);
+                     doUninstallParentLast(deployer, component, false, true);
                   }
                   throw e;
                }
@@ -708,13 +698,13 @@
          catch (DeploymentException e)
          {
             // Just undeploy this context
-            doUninstall(deployer, context, false, false);
+            doUninstallParentLast(deployer, context, false, false);
             throw e;
          }
       }
 
       List<DeploymentContext> children = context.getChildren();
-      if (doChildren && children != null)
+      if (children != null)
       {
          try
          {
@@ -723,7 +713,7 @@
                DeploymentContext child = children.get(i);
                try
                {
-                  doInstall(deployer, child, true, true);
+                  doInstallParentFirst(deployer, child);
                }
                catch (DeploymentException e)
                {
@@ -731,7 +721,7 @@
                   for (int j = i - 1; j >= 0; --j)
                   {
                      child = children.get(j);
-                     doUninstall(deployer, child, true, true);
+                     doUninstallParentLast(deployer, child, true, true);
                   }
                   throw e;
                }
@@ -740,31 +730,99 @@
          catch (DeploymentException e)
          {
             // Undeploy the context but the children are already unwound
-            doUninstall(deployer, context, false, true);
+            doUninstallParentLast(deployer, context, false, true);
             throw e;
          }
       }         
    }
    
+   /**
+    * Do the install parent last
+    * 
+    * @param deployer the deployer
+    * @param context the context
+    * @throws Throwable for any problem
+    */
+   protected void doInstallParentLast(Deployer deployer, DeploymentContext context) throws Throwable
+   {
+      List<DeploymentContext> children = context.getChildren();
+      for (int i = 0; i < children.size(); ++i)
+      {
+         DeploymentContext child = children.get(i);
+         try
+         {
+            doInstallParentLast(deployer, child);
+         }
+         catch (DeploymentException e)
+         {
+            // Unwind the previous children
+            for (int j = i - 1; j >= 0; --j)
+            {
+               child = children.get(j);
+               doUninstallParentFirst(deployer, child, true, true);
+            }
+            throw e;
+         }
+      }
+      
+      List<DeploymentContext> components = context.getComponents();
+      if (components != null)
+      {
+         try
+         {
+            for (int i = 0; i < components.size(); ++i)
+            {
+               DeploymentContext component = components.get(i);
+               try
+               {
+                  doInstallParentLast(deployer, component);
+               }
+               catch (DeploymentException e)
+               {
+                  // Unwind the previous components
+                  for (int j = i - 1; j >= 0; --j)
+                  {
+                     component = components.get(j);
+                     doUninstallParentFirst(deployer, component, true, true);
+                  }
+                  throw e;
+               }
+            }
+         }
+         catch (DeploymentException e)
+         {
+            // Just undeploy the children, the components are already unwound
+            doUninstallParentFirst(deployer, context, false, false);
+            throw e;
+         }
+      }
+
+      DeploymentUnit unit = context.getDeploymentUnit();
+      if (isRelevant(deployer, unit, context.isTopLevel(), context.isComponent()))
+      {
+         try
+         {
+            deployer.deploy(unit);
+         }
+         catch (DeploymentException e)
+         {
+            // Undeploy the children and components
+            doUninstallParentFirst(deployer, context, false, true);
+            context.setState(DeploymentState.ERROR);
+            context.setProblem(e);
+            throw e;
+         }
+      }
+      else if (log.isTraceEnabled())
+         log.trace("Deployer " + deployer + " not relevant for " + context.getName());
+   }
+   
    public void uninstall(ControllerContext context, ControllerState fromState, ControllerState toState)
    {
       DeploymentControllerContext deploymentControllerContext = (DeploymentControllerContext) context;
       String stageName = fromState.getStateString();
       
       DeploymentContext deploymentContext = deploymentControllerContext.getDeploymentContext();
-      doUninstall(deploymentContext, stageName, true, true);
-   }
-
-   /**
-    * Do the uninstall
-    * 
-    * @param context the context
-    * @param stageName the stage
-    * @param doChildren whether to do children
-    * @param doComponents whether to do components
-    */
-   protected void doUninstall(DeploymentContext context, String stageName, boolean doChildren, boolean doComponents)
-   {
       List<Deployer> theDeployers = getDeployersList(stageName);
       
       if (log.isTraceEnabled())
@@ -775,20 +833,23 @@
          for (int i = theDeployers.size()-1; i >= 0; --i)
          {
             Deployer deployer = theDeployers.get(i);
-            doUninstall(deployer, context, doChildren, doComponents);
+            if (deployer.isParentFirst())
+               doUninstallParentLast(deployer, deploymentContext, true, true);
+            else
+               doUninstallParentFirst(deployer, deploymentContext, true, true);
          }
       }
    }
 
    /**
-    * Do the uninstall
+    * Do the uninstall parent last
     *
     * @param deployer the deployer
     * @param context the context
     * @param doChildren whether to do children
     * @param doComponents whether to do components
     */
-   protected void doUninstall(Deployer deployer, DeploymentContext context, boolean doChildren, boolean doComponents)
+   protected void doUninstallParentLast(Deployer deployer, DeploymentContext context, boolean doChildren, boolean doComponents)
    {
       if (doChildren)
       {
@@ -798,7 +859,7 @@
             for (int i = children.size()-1; i >=  0; --i)
             {
                DeploymentContext child = children.get(i);
-               doUninstall(deployer, child, true, true);
+               doUninstallParentLast(deployer, child, true, true);
             }
          }
       }
@@ -811,7 +872,7 @@
             for (int i = components.size()-1; i >=  0; --i)
             {
                DeploymentContext component = components.get(i);
-               doUninstall(deployer, component, false, true);
+               doUninstallParentLast(deployer, component, false, true);
             }
          }
       }
@@ -822,6 +883,49 @@
       else if (log.isTraceEnabled())
          log.trace("Deployer " + deployer + " not relevant for " + context.getName());
    }
+
+   /**
+    * Do the uninstall parent first
+    *
+    * @param deployer the deployer
+    * @param context the context
+    * @param doContext whether to do context
+    * @param doComponents whether to do components
+    */
+   protected void doUninstallParentFirst(Deployer deployer, DeploymentContext context, boolean doContext, boolean doComponents)
+   {
+      if (doContext)
+      {
+         DeploymentUnit unit = context.getDeploymentUnit();
+         if (isRelevant(deployer, unit, context.isTopLevel(), context.isComponent()))
+            deployer.undeploy(unit);
+         else if (log.isTraceEnabled())
+            log.trace("Deployer " + deployer + " not relevant for " + context.getName());
+      }
+
+      if (doComponents)
+      {
+         List<DeploymentContext> components = context.getComponents();
+         if (components != null && components.isEmpty() == false)
+         {
+            for (int i = components.size()-1; i >=  0; --i)
+            {
+               DeploymentContext component = components.get(i);
+               doUninstallParentFirst(deployer, component, true, true);
+            }
+         }
+      }
+
+      List<DeploymentContext> children = context.getChildren();
+      if (children != null && children.isEmpty() == false)
+      {
+         for (int i = children.size()-1; i >=  0; --i)
+         {
+            DeploymentContext child = children.get(i);
+            doUninstallParentFirst(deployer, child, true, true);
+         }
+      }
+   }
    
    /**
     * Build a list of  deployers for this stage

Modified: projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/deployer/DeployersDeployerTestSuite.java
===================================================================
--- projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/deployer/DeployersDeployerTestSuite.java	2007-07-27 14:17:21 UTC (rev 64325)
+++ projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/deployer/DeployersDeployerTestSuite.java	2007-07-27 14:19:13 UTC (rev 64326)
@@ -32,6 +32,8 @@
 import org.jboss.test.deployers.deployer.test.DeployerProtocolUnitTestCase;
 import org.jboss.test.deployers.deployer.test.DeployerWidthFirstUnitTestCase;
 import org.jboss.test.deployers.deployer.test.DeployersImplUnitTestCase;
+import org.jboss.test.deployers.deployer.test.HeuristicAllOrNothingUnitTestCase;
+import org.jboss.test.deployers.deployer.test.HeuristicRussionDollUnitTestCase;
 import org.jboss.test.deployers.deployer.test.MultipleComponentTypeUnitTestCase;
 
 /**
@@ -59,6 +61,8 @@
       suite.addTest(DeployersImplUnitTestCase.suite());
       suite.addTest(ComponentUnitTestCase.suite());
       suite.addTest(MultipleComponentTypeUnitTestCase.suite());
+      suite.addTest(HeuristicAllOrNothingUnitTestCase.suite());
+      suite.addTest(HeuristicRussionDollUnitTestCase.suite());
 
       return suite;
    }

Added: projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/deployer/support/TestSimpleDeployer2.java
===================================================================
--- projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/deployer/support/TestSimpleDeployer2.java	                        (rev 0)
+++ projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/deployer/support/TestSimpleDeployer2.java	2007-07-27 14:19:13 UTC (rev 64326)
@@ -0,0 +1,92 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.deployers.deployer.support;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jboss.deployers.spi.DeploymentException;
+import org.jboss.deployers.spi.deployer.helpers.AbstractRealDeployer;
+import org.jboss.deployers.structure.spi.DeploymentUnit;
+
+/**
+ * TestSimpleDeployer.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public class TestSimpleDeployer2 extends AbstractRealDeployer
+{
+   public List<String> deployed = new ArrayList<String>();
+   public List<String> undeployed = new ArrayList<String>();
+   
+   public TestSimpleDeployer2(boolean parentFirst, int order)
+   {
+      setRelativeOrder(order);
+      setParentFirst(parentFirst);
+      setWantComponents(true);
+   }
+   
+   public List<String> getDeployedUnits()
+   {
+      return deployed;
+   }
+   
+   public List<String> getUndeployedUnits()
+   {
+      return undeployed;
+   }
+   
+   public String toString()
+   {
+      return "TestSimpleDeployer(" + isParentFirst() + ")";
+   }
+   
+   public void clear()
+   {
+      deployed.clear();
+      undeployed.clear();
+   }
+
+   public void deploy(DeploymentUnit unit) throws DeploymentException
+   {
+      log.debug(this + " deploy  : " + unit.getName());
+      deployed.add(unit.getName());
+      if (unit.isComponent() == false)
+      {
+         if (this.equals(unit.getAttachment("fail")))
+            throw new DeploymentException("Asked to fail");
+      }
+      else
+      {
+        TestComponentMetaData md = unit.getAttachment(TestComponentMetaData.class);
+        if (md != null && md.fail)
+           throw new DeploymentException("Asked to fail");
+      }
+   }
+
+   public void undeploy(DeploymentUnit unit)
+   {
+      log.debug(this + " undeploy: " + unit.getName());
+      undeployed.add(unit.getName());
+   }
+}

Modified: projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/deployer/test/HeuristicAllOrNothingUnitTestCase.java
===================================================================
--- projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/deployer/test/HeuristicAllOrNothingUnitTestCase.java	2007-07-27 14:17:21 UTC (rev 64325)
+++ projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/deployer/test/HeuristicAllOrNothingUnitTestCase.java	2007-07-27 14:19:13 UTC (rev 64326)
@@ -43,7 +43,7 @@
 import org.jboss.test.deployers.deployer.support.TestSimpleDeployer;
 
 /**
- * DeployerProtocolUnitTestCase.
+ * HeuristicAllOrNothingUnitTestCase.
  * 
  * @author <a href="adrian at jboss.com">Adrian Brock</a>
  * @version $Revision: 1.1 $

Added: projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/deployer/test/HeuristicRussionDollUnitTestCase.java
===================================================================
--- projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/deployer/test/HeuristicRussionDollUnitTestCase.java	                        (rev 0)
+++ projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/deployer/test/HeuristicRussionDollUnitTestCase.java	2007-07-27 14:19:13 UTC (rev 64326)
@@ -0,0 +1,744 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.deployers.deployer.test;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.jboss.deployers.client.spi.DeployerClient;
+import org.jboss.deployers.client.spi.Deployment;
+import org.jboss.deployers.spi.DeploymentState;
+import org.jboss.deployers.spi.attachments.MutableAttachments;
+import org.jboss.deployers.spi.attachments.PredeterminedManagedObjectAttachments;
+import org.jboss.deployers.spi.deployer.Deployer;
+import org.jboss.deployers.spi.structure.ContextInfo;
+import org.jboss.test.deployers.AbstractDeployerTest;
+import org.jboss.test.deployers.deployer.support.TestComponentDeployer;
+import org.jboss.test.deployers.deployer.support.TestComponentMetaData;
+import org.jboss.test.deployers.deployer.support.TestComponentMetaDataContainer;
+import org.jboss.test.deployers.deployer.support.TestSimpleDeployer2;
+
+/**
+ * HeuristicRussionDollUnitTestCase.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public class HeuristicRussionDollUnitTestCase extends AbstractDeployerTest
+{
+   private TestComponentDeployer deployer0 = new TestComponentDeployer(1);
+   private TestSimpleDeployer2 deployer1 = new TestSimpleDeployer2(true, 2);
+   private TestSimpleDeployer2 deployer2 = new TestSimpleDeployer2(false, 3);
+   
+   private static String parentName = "parent";
+   private static String childPath = "child";
+   private static String childName = parentName + "/" + childPath;
+   private static String child1Path = "child1";
+   private static String child1Name = parentName + "/" + child1Path;
+   private static String child2Path = "child2";
+   private static String child2Name = parentName + "/" + child2Path;
+
+   private static TestComponentMetaData parentmd1 = new TestComponentMetaData(parentName + ".1", false);
+   private static TestComponentMetaData parentmd2 = new TestComponentMetaData(parentName + ".2", false);
+   private static TestComponentMetaData childmd1 = new TestComponentMetaData(childName + ".1", false);
+   private static TestComponentMetaData childmd2 = new TestComponentMetaData(childName + ".2", false);
+   private static TestComponentMetaData child1md1 = new TestComponentMetaData(child1Name + ".1", false);
+   private static TestComponentMetaData child1md2 = new TestComponentMetaData(child1Name + ".2", false);
+   private static TestComponentMetaData child2md1 = new TestComponentMetaData(child2Name + ".1", false);
+   private static TestComponentMetaData child2md2 = new TestComponentMetaData(child2Name + ".2", false);
+
+   private static List<String> expectedNothing = Collections.emptyList();
+   private static List<String> expectedParent = makeList(parentName);
+   private static List<String> expectedParentMD12 = makeList(parentName, parentmd1.name, parentmd2.name);
+   private static List<String> expectedPMD21 = makeList(parentmd2.name, parentmd1.name);
+   private static List<String> expectedMD12Parent = makeList(parentmd1.name, parentmd2.name, parentName);
+   private static List<String> expectedMD21Parent = makeList(parentmd2.name, parentmd1.name, parentName);
+   private static List<String> expectedChild = makeList(childName);
+   private static List<String> expectedMD12Child = makeList(childmd1.name, childmd2.name, childName);
+   private static List<String> expectedMD21C = makeList(childmd2.name, childmd1.name);
+   private static List<String> expectedPMD21ChildMD21 = makeList(parentmd2.name, parentmd1.name, childName, childmd2.name, childmd1.name);
+   private static List<String> expectedChild1 = makeList(child1Name);
+   private static List<String> expectedMD12Child1 = makeList(child1md1.name, child1md2.name, child1Name);
+   private static List<String> expectedMD21C1 = makeList(child1md2.name, child1md1.name);
+   private static List<String> expectedParentChild = makeList(parentName, childName);
+   private static List<String> expectedParentMD12Child = makeList(parentName, parentmd1.name, parentmd2.name, childName);
+   private static List<String> expectedParentMD12ChildMD12 = makeList(parentName, parentmd1.name, parentmd2.name, childName, childmd1.name, childmd2.name);
+   private static List<String> expectedChildParent = makeList(childName, parentName);
+   private static List<String> expectedMD12ChildMD12Parent = makeList(childmd1.name, childmd2.name, childName, parentmd1.name, parentmd2.name, parentName);
+   private static List<String> expectedMD21ChildMD21Parent = makeList(childmd2.name, childmd1.name, childName, parentmd2.name, parentmd1.name, parentName);
+   private static List<String> expectedChild1Parent = makeList(child1Name, parentName);
+   private static List<String> expectedMD21Child1MD21Parent = makeList(child1md2.name, child1md1.name, child1Name, parentmd2.name, parentmd1.name, parentName);
+   private static List<String> expectedParentChild1 = makeList(parentName, child1Name);
+   private static List<String> expectedParentMD12Child1 = makeList(parentName, parentmd1.name, parentmd2.name, child1Name);
+   private static List<String> expectedParentChild1Child2 = makeList(parentName, child1Name, child2Name);
+   private static List<String> expectedParentMD12Child1MD12Child2 = makeList(parentName, parentmd1.name, parentmd2.name, child1Name, child1md1.name, child1md2.name, child2Name);
+   private static List<String> expectedParentMD12Child1MD12Child2MD12 = makeList(parentName, parentmd1.name, parentmd2.name, child1Name, child1md1.name, child1md2.name, child2Name, child2md1.name, child2md2.name);
+   private static List<String> expectedChild1Child2Parent = makeList(child1Name, child2Name, parentName);
+   private static List<String> expectedMD12Child1MD12Child2MD12Parent = makeList(child1md1.name, child1md2.name, child1Name, child2md1.name, child2md2.name, child2Name, parentmd1.name, parentmd2.name, parentName);
+   private static List<String> expectedChild2Child1Parent = makeList(child2Name, child1Name, parentName);
+   private static List<String> expectedMD21Child2MD21Child1MD21Parent = makeList(child2md2.name, child2md1.name, child2Name, child1md2.name, child1md1.name, child1Name, parentmd2.name, parentmd1.name, parentName);
+   private static List<String> expectedChild1Child2 = makeList(child1Name, child2Name);
+   private static List<String> expectedMD12Child1MD12Child2 = makeList(child1md1.name, child1md2.name, child1Name, child2md1.name, child2md2.name, child2Name);
+   private static List<String> expectedChild2Child1 = makeList(child2Name, child1Name);
+   private static List<String> expectedPMD21Child2MD21Child1MD21 = makeList(parentmd2.name, parentmd1.name, child2Name, child2md2.name, child2md1.name, child1Name, child1md2.name, child1md1.name);
+   private static List<String> expectedMD21C2Child1MD21 = makeList(child2md2.name, child2md1.name, child1Name, child1md2.name, child1md1.name);
+   
+   private static TestComponentMetaDataContainer parentmd = new TestComponentMetaDataContainer(parentmd1, parentmd2);
+   private static TestComponentMetaDataContainer childmd = new TestComponentMetaDataContainer(childmd1, childmd2);
+   private static TestComponentMetaDataContainer child1md = new TestComponentMetaDataContainer(child1md1, child1md2);
+   private static TestComponentMetaDataContainer child2md = new TestComponentMetaDataContainer(child2md1, child2md2);
+   
+   @SuppressWarnings("unchecked")
+   private static <T> List<T> makeList(T... objects)
+   {
+      List<T> result = new ArrayList<T>();
+      for (T object : objects)
+         result.add(object);
+      return result;
+   }
+   
+   public static Test suite()
+   {
+      return new TestSuite(HeuristicRussionDollUnitTestCase.class);
+   }
+   
+   public HeuristicRussionDollUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public void testDeployParentNoErrors() throws Exception
+   {
+      DeployerClient main = getMainDeployer();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParent, deployer1.getDeployedUnits());
+      assertEquals(expectedNothing, deployer1.getUndeployedUnits());
+      assertEquals(expectedParent, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.DEPLOYED, main.getDeploymentState(deployment.getName()));
+   }
+
+   public void testDeployParentFailInParentDeployer1() throws Exception
+   {
+      DeployerClient main = getMainDeployer();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      makeFail(deployment, deployer1);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParent, deployer1.getDeployedUnits());
+      assertEquals(expectedNothing, deployer1.getUndeployedUnits());
+      assertEquals(expectedNothing, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+   }
+
+   public void testDeployParentFailInParentDeployer2() throws Exception
+   {
+      DeployerClient main = getMainDeployer();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      makeFail(deployment, deployer2);
+      main.addDeployment(deployment);
+      main.process();
+
+      Set<String> expected = new HashSet<String>();
+      expected.add(deployment.getName());
+      assertEquals(expectedParent, deployer1.getDeployedUnits());
+      assertEquals(expectedParent, deployer1.getUndeployedUnits());
+      assertEquals(expectedParent, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+   }
+
+   public void testDeployParentOneChildNoErrors() throws Exception
+   {
+      DeployerClient main = getMainDeployer();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addChild(deployment, childPath); 
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentChild, deployer1.getDeployedUnits());
+      assertEquals(expectedNothing, deployer1.getUndeployedUnits());
+      assertEquals(expectedChildParent, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.DEPLOYED, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.DEPLOYED, main.getDeploymentState(childName));
+   }
+   
+   public void testDeployParentOneChildFailInParentDeployer1() throws Exception
+   {
+      DeployerClient main = getMainDeployer();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      makeFail(deployment, deployer1);
+      addChild(deployment, childPath); 
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParent, deployer1.getDeployedUnits());
+      assertEquals(expectedNothing, deployer1.getUndeployedUnits());
+      assertEquals(expectedNothing, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(childName));
+   }
+   
+   public void testDeployParentOneChildFailInParentDeployer2() throws Exception
+   {
+      DeployerClient main = getMainDeployer();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      makeFail(deployment, deployer2);
+      addChild(deployment, "child"); 
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentChild, deployer1.getDeployedUnits());
+      assertEquals(expectedChildParent, deployer1.getUndeployedUnits());
+      assertEquals(expectedChildParent, deployer2.getDeployedUnits());
+      assertEquals(expectedChild, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(childName));
+   }
+   
+   public void testDeployParentOneChildFailInChildDeployer1() throws Exception
+   {
+      DeployerClient main = getMainDeployer();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      ContextInfo child = addChild(deployment, childPath); 
+      makeFail(child, deployer1);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentChild, deployer1.getDeployedUnits());
+      assertEquals(expectedParent, deployer1.getUndeployedUnits());
+      assertEquals(expectedNothing, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(childName));
+   }
+   
+   public void testDeployParentOneChildFailInChildDeployer2() throws Exception
+   {
+      DeployerClient main = getMainDeployer();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      ContextInfo child = addChild(deployment, childPath); 
+      makeFail(child, deployer2);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentChild, deployer1.getDeployedUnits());
+      assertEquals(expectedChildParent, deployer1.getUndeployedUnits());
+      assertEquals(expectedChild, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(childName));
+   }
+
+   public void testDeployParentMultipleChildrenNoErrors() throws Exception
+   {
+      DeployerClient main = getMainDeployer();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addChild(deployment, child1Path); 
+      addChild(deployment, child2Path); 
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentChild1Child2, deployer1.getDeployedUnits());
+      assertEquals(expectedNothing, deployer1.getUndeployedUnits());
+      assertEquals(expectedChild1Child2Parent, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.DEPLOYED, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.DEPLOYED, main.getDeploymentState(child1Name));
+      assertEquals(DeploymentState.DEPLOYED, main.getDeploymentState(child2Name));
+   }
+
+   public void testDeployParentMultipleChildrenFailInParentDeployer1() throws Exception
+   {
+      DeployerClient main = getMainDeployer();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      makeFail(deployment, deployer1);
+      addChild(deployment, child1Path); 
+      addChild(deployment, child2Path); 
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParent, deployer1.getDeployedUnits());
+      assertEquals(expectedNothing, deployer1.getUndeployedUnits());
+      assertEquals(expectedNothing, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(child1Name));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(child2Name));
+   }
+
+   public void testDeployParentMultipleChildrenFailInParentDeployer2() throws Exception
+   {
+      DeployerClient main = getMainDeployer();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      makeFail(deployment, deployer2);
+      addChild(deployment, child1Path); 
+      addChild(deployment, child2Path); 
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentChild1Child2, deployer1.getDeployedUnits());
+      assertEquals(expectedChild2Child1Parent, deployer1.getUndeployedUnits());
+      assertEquals(expectedChild1Child2Parent, deployer2.getDeployedUnits());
+      assertEquals(expectedChild2Child1, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(child1Name));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(child2Name));
+   }
+
+   public void testDeployParentMultipleChildrenFailInChild1Deployer1() throws Exception
+   {
+      DeployerClient main = getMainDeployer();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      ContextInfo child1 = addChild(deployment, child1Path); 
+      makeFail(child1, deployer1);
+      addChild(deployment, child2Path); 
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentChild1, deployer1.getDeployedUnits());
+      assertEquals(expectedParent, deployer1.getUndeployedUnits());
+      assertEquals(expectedNothing, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(child1Name));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(child2Name));
+   }
+
+   public void testDeployParentMultipleChildrenFailInChild1Deployer2() throws Exception
+   {
+      DeployerClient main = getMainDeployer();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      ContextInfo child1 = addChild(deployment, child1Path); 
+      makeFail(child1, deployer2);
+      addChild(deployment, child2Path); 
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentChild1Child2, deployer1.getDeployedUnits());
+      assertEquals(expectedChild2Child1Parent, deployer1.getUndeployedUnits());
+      assertEquals(expectedChild1, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(child1Name));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(child2Name));
+   }
+
+   public void testDeployParentMultipleChildrenFailInChild2Deployer1() throws Exception
+   {
+      DeployerClient main = getMainDeployer();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addChild(deployment, child1Path); 
+      ContextInfo child2 = addChild(deployment, child2Path); 
+      makeFail(child2, deployer1);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentChild1Child2, deployer1.getDeployedUnits());
+      assertEquals(expectedChild1Parent, deployer1.getUndeployedUnits());
+      assertEquals(expectedNothing, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(child1Name));
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(child2Name));
+   }
+
+   public void testDeployParentMultipleChildrenFailInChild2Deployer2() throws Exception
+   {
+      DeployerClient main = getMainDeployer();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addChild(deployment, child1Path); 
+      ContextInfo child2 = addChild(deployment, child2Path); 
+      makeFail(child2, deployer2);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentChild1Child2, deployer1.getDeployedUnits());
+      assertEquals(expectedChild2Child1Parent, deployer1.getUndeployedUnits());
+      assertEquals(expectedChild1Child2, deployer2.getDeployedUnits());
+      assertEquals(expectedChild1, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(child1Name));
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(child2Name));
+   }
+
+   public void testDeployParentWithComponentsNoErrors() throws Exception
+   {
+      DeployerClient main = getMainDeployerWithComponentDeployers();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addMetaData(deployment, parentmd);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentMD12, deployer1.getDeployedUnits());
+      assertEquals(expectedNothing, deployer1.getUndeployedUnits());
+      assertEquals(expectedMD12Parent, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.DEPLOYED, main.getDeploymentState(deployment.getName()));
+   }
+
+   public void testDeployParentWithComponentsFailInParentDeployer1() throws Exception
+   {
+      DeployerClient main = getMainDeployerWithComponentDeployers();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addMetaData(deployment, parentmd);
+      makeFail(deployment, deployer1);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParent, deployer1.getDeployedUnits());
+      assertEquals(expectedNothing, deployer1.getUndeployedUnits());
+      assertEquals(expectedNothing, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+   }
+
+   public void testDeployParentWithComponentsFailInParentDeployer2() throws Exception
+   {
+      DeployerClient main = getMainDeployerWithComponentDeployers();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addMetaData(deployment, parentmd);
+      makeFail(deployment, deployer2);
+      main.addDeployment(deployment);
+      main.process();
+
+      Set<String> expected = new HashSet<String>();
+      expected.add(deployment.getName());
+      assertEquals(expectedParentMD12, deployer1.getDeployedUnits());
+      assertEquals(expectedMD21Parent, deployer1.getUndeployedUnits());
+      assertEquals(expectedMD12Parent, deployer2.getDeployedUnits());
+      assertEquals(expectedPMD21, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+   }
+
+   public void testDeployParentWithComponentsOneChildNoErrors() throws Exception
+   {
+      DeployerClient main = getMainDeployerWithComponentDeployers();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addMetaData(deployment, parentmd);
+      ContextInfo child = addChild(deployment, childPath);
+      addMetaData(child, childmd);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentMD12ChildMD12, deployer1.getDeployedUnits());
+      assertEquals(expectedNothing, deployer1.getUndeployedUnits());
+      assertEquals(expectedMD12ChildMD12Parent, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.DEPLOYED, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.DEPLOYED, main.getDeploymentState(childName));
+   }
+   
+   public void testDeployParentWithComponentsOneChildFailInParentDeployer1() throws Exception
+   {
+      DeployerClient main = getMainDeployerWithComponentDeployers();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addMetaData(deployment, parentmd);
+      makeFail(deployment, deployer1);
+      ContextInfo child = addChild(deployment, childPath);
+      addMetaData(child, childmd);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParent, deployer1.getDeployedUnits());
+      assertEquals(expectedNothing, deployer1.getUndeployedUnits());
+      assertEquals(expectedNothing, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(childName));
+   }
+   
+   public void testDeployParentWithComponentsOneChildFailInParentDeployer2() throws Exception
+   {
+      DeployerClient main = getMainDeployerWithComponentDeployers();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addMetaData(deployment, parentmd);
+      makeFail(deployment, deployer2);
+      ContextInfo child = addChild(deployment, childPath);
+      addMetaData(child, childmd);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentMD12ChildMD12, deployer1.getDeployedUnits());
+      assertEquals(expectedMD21ChildMD21Parent, deployer1.getUndeployedUnits());
+      assertEquals(expectedMD12ChildMD12Parent, deployer2.getDeployedUnits());
+      assertEquals(expectedPMD21ChildMD21, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(childName));
+   }
+   
+   public void testDeployParentWithComponentsOneChildFailInChildDeployer1() throws Exception
+   {
+      DeployerClient main = getMainDeployerWithComponentDeployers();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addMetaData(deployment, parentmd);
+      ContextInfo child = addChild(deployment, childPath);
+      addMetaData(child, childmd);
+      makeFail(child, deployer1);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentMD12Child, deployer1.getDeployedUnits());
+      assertEquals(expectedMD21Parent, deployer1.getUndeployedUnits());
+      assertEquals(expectedNothing, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(childName));
+   }
+   
+   public void testDeployParentWithComponentsOneChildFailInChildDeployer2() throws Exception
+   {
+      DeployerClient main = getMainDeployerWithComponentDeployers();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addMetaData(deployment, parentmd);
+      ContextInfo child = addChild(deployment, childPath);
+      addMetaData(child, childmd);
+      makeFail(child, deployer2);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentMD12ChildMD12, deployer1.getDeployedUnits());
+      assertEquals(expectedMD21ChildMD21Parent, deployer1.getUndeployedUnits());
+      assertEquals(expectedMD12Child, deployer2.getDeployedUnits());
+      assertEquals(expectedMD21C, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(childName));
+   }
+
+   public void testDeployParentWithComponentsMultipleChildrenNoErrors() throws Exception
+   {
+      DeployerClient main = getMainDeployerWithComponentDeployers();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addMetaData(deployment, parentmd);
+      ContextInfo child1 = addChild(deployment, child1Path);
+      addMetaData(child1, child1md);
+      ContextInfo child2 = addChild(deployment, child2Path);
+      addMetaData(child2, child2md);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentMD12Child1MD12Child2MD12, deployer1.getDeployedUnits());
+      assertEquals(expectedNothing, deployer1.getUndeployedUnits());
+      assertEquals(expectedMD12Child1MD12Child2MD12Parent, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.DEPLOYED, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.DEPLOYED, main.getDeploymentState(child1Name));
+      assertEquals(DeploymentState.DEPLOYED, main.getDeploymentState(child2Name));
+   }
+
+   public void testDeployParentWithComponentsMultipleChildrenFailInParentDeployer1() throws Exception
+   {
+      DeployerClient main = getMainDeployerWithComponentDeployers();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addMetaData(deployment, parentmd);
+      makeFail(deployment, deployer1);
+      ContextInfo child1 = addChild(deployment, child1Path);
+      addMetaData(child1, child1md);
+      ContextInfo child2 = addChild(deployment, child2Path);
+      addMetaData(child2, child2md);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParent, deployer1.getDeployedUnits());
+      assertEquals(expectedNothing, deployer1.getUndeployedUnits());
+      assertEquals(expectedNothing, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(child1Name));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(child2Name));
+   }
+
+   public void testDeployParentWithComponentsMultipleChildrenFailInParentDeployer2() throws Exception
+   {
+      DeployerClient main = getMainDeployerWithComponentDeployers();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addMetaData(deployment, parentmd);
+      makeFail(deployment, deployer2);
+      ContextInfo child1 = addChild(deployment, child1Path);
+      addMetaData(child1, child1md);
+      ContextInfo child2 = addChild(deployment, child2Path);
+      addMetaData(child2, child2md);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentMD12Child1MD12Child2MD12, deployer1.getDeployedUnits());
+      assertEquals(expectedMD21Child2MD21Child1MD21Parent, deployer1.getUndeployedUnits());
+      assertEquals(expectedMD12Child1MD12Child2MD12Parent, deployer2.getDeployedUnits());
+      assertEquals(expectedPMD21Child2MD21Child1MD21, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(child1Name));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(child2Name));
+   }
+
+   public void testDeployParentWithComponentsMultipleChildrenFailInChild1Deployer1() throws Exception
+   {
+      DeployerClient main = getMainDeployerWithComponentDeployers();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addMetaData(deployment, parentmd);
+      ContextInfo child1 = addChild(deployment, child1Path);
+      addMetaData(child1, child1md);
+      makeFail(child1, deployer1);
+      ContextInfo child2 = addChild(deployment, child2Path);
+      addMetaData(child2, child2md);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentMD12Child1, deployer1.getDeployedUnits());
+      assertEquals(expectedMD21Parent, deployer1.getUndeployedUnits());
+      assertEquals(expectedNothing, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(child1Name));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(child2Name));
+   }
+
+   public void testDeployParentWithComponentsMultipleChildrenFailInChild1Deployer2() throws Exception
+   {
+      DeployerClient main = getMainDeployerWithComponentDeployers();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addMetaData(deployment, parentmd);
+      ContextInfo child1 = addChild(deployment, child1Path);
+      addMetaData(child1, child1md);
+      makeFail(child1, deployer2);
+      ContextInfo child2 = addChild(deployment, child2Path);
+      addMetaData(child2, child2md);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentMD12Child1MD12Child2MD12, deployer1.getDeployedUnits());
+      assertEquals(expectedMD21Child2MD21Child1MD21Parent, deployer1.getUndeployedUnits());
+      assertEquals(expectedMD12Child1, deployer2.getDeployedUnits());
+      assertEquals(expectedMD21C1, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(child1Name));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(child2Name));
+   }
+
+   public void testDeployParentWithComponentsMultipleChildrenFailInChild2Deployer1() throws Exception
+   {
+      DeployerClient main = getMainDeployerWithComponentDeployers();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addMetaData(deployment, parentmd);
+      ContextInfo child1 = addChild(deployment, child1Path);
+      addMetaData(child1, child1md);
+      ContextInfo child2 = addChild(deployment, child2Path);
+      addMetaData(child2, child2md);
+      makeFail(child2, deployer1);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentMD12Child1MD12Child2, deployer1.getDeployedUnits());
+      assertEquals(expectedMD21Child1MD21Parent, deployer1.getUndeployedUnits());
+      assertEquals(expectedNothing, deployer2.getDeployedUnits());
+      assertEquals(expectedNothing, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(child1Name));
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(child2Name));
+   }
+
+   public void testDeployParentWithComponentsMultipleChildrenFailInChild2Deployer2() throws Exception
+   {
+      DeployerClient main = getMainDeployerWithComponentDeployers();
+      
+      Deployment deployment = createSimpleDeployment(parentName);
+      addMetaData(deployment, parentmd);
+      ContextInfo child1 = addChild(deployment, child1Path);
+      addMetaData(child1, child1md);
+      ContextInfo child2 = addChild(deployment, child2Path);
+      addMetaData(child2, child2md);
+      makeFail(child2, deployer2);
+      main.addDeployment(deployment);
+      main.process();
+
+      assertEquals(expectedParentMD12Child1MD12Child2MD12, deployer1.getDeployedUnits());
+      assertEquals(expectedMD21Child2MD21Child1MD21Parent, deployer1.getUndeployedUnits());
+      assertEquals(expectedMD12Child1MD12Child2, deployer2.getDeployedUnits());
+      assertEquals(expectedMD21C2Child1MD21, deployer2.getUndeployedUnits());
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(deployment.getName()));
+      assertEquals(DeploymentState.UNDEPLOYED, main.getDeploymentState(child1Name));
+      assertEquals(DeploymentState.ERROR, main.getDeploymentState(child2Name));
+   }
+
+   protected static void addMetaData(PredeterminedManagedObjectAttachments attachments, TestComponentMetaDataContainer md)
+   {
+      MutableAttachments mutable = (MutableAttachments) attachments.getPredeterminedManagedObjects();
+      mutable.addAttachment(TestComponentMetaDataContainer.class, md);
+   }
+   
+   protected static void makeFail(PredeterminedManagedObjectAttachments attachments, Deployer deployer)
+   {
+      MutableAttachments mutable = (MutableAttachments) attachments.getPredeterminedManagedObjects();
+      mutable.addAttachment("fail", deployer);
+   }
+   
+   protected DeployerClient getMainDeployer()
+   {
+      return createMainDeployer(deployer1, deployer2);
+   }
+   
+   protected DeployerClient getMainDeployerWithComponentDeployers()
+   {
+      return createMainDeployer(deployer0, deployer1, deployer2);
+   }
+}

Modified: projects/microcontainer/trunk/deployers-spi/src/main/org/jboss/deployers/spi/deployer/Deployer.java
===================================================================
--- projects/microcontainer/trunk/deployers-spi/src/main/org/jboss/deployers/spi/deployer/Deployer.java	2007-07-27 14:17:21 UTC (rev 64325)
+++ projects/microcontainer/trunk/deployers-spi/src/main/org/jboss/deployers/spi/deployer/Deployer.java	2007-07-27 14:19:13 UTC (rev 64326)
@@ -108,6 +108,13 @@
    Set<String> getOutputs();
    
    /**
+    * Whether to process parents before children (default true)
+    * 
+    * @return true to process parents first
+    */
+   boolean isParentFirst();
+   
+   /**
     * Deploy a deployment
     * 
     * @param unit the unit

Modified: projects/microcontainer/trunk/deployers-spi/src/main/org/jboss/deployers/spi/deployer/helpers/AbstractDeployer.java
===================================================================
--- projects/microcontainer/trunk/deployers-spi/src/main/org/jboss/deployers/spi/deployer/helpers/AbstractDeployer.java	2007-07-27 14:17:21 UTC (rev 64325)
+++ projects/microcontainer/trunk/deployers-spi/src/main/org/jboss/deployers/spi/deployer/helpers/AbstractDeployer.java	2007-07-27 14:19:13 UTC (rev 64326)
@@ -74,6 +74,9 @@
    /** The type */
    private String type;
    
+   /** Whether to process parents first */
+   private boolean parentFirst = true;
+   
    public int getRelativeOrder()
    {
       return relativeOrder;
@@ -392,6 +395,21 @@
       this.type = type;
    }
 
+   public boolean isParentFirst()
+   {
+      return parentFirst;
+   }
+
+   /**
+    * Set the parentFirst.
+    * 
+    * @param parentFirst the parentFirst.
+    */
+   public void setParentFirst(boolean parentFirst)
+   {
+      this.parentFirst = parentFirst;
+   }
+
    public void undeploy(DeploymentUnit unit)
    {
       // Nothing

Modified: projects/microcontainer/trunk/deployers-structure-spi/src/main/org/jboss/deployers/structure/spi/DeploymentUnit.java
===================================================================
--- projects/microcontainer/trunk/deployers-structure-spi/src/main/org/jboss/deployers/structure/spi/DeploymentUnit.java	2007-07-27 14:17:21 UTC (rev 64325)
+++ projects/microcontainer/trunk/deployers-structure-spi/src/main/org/jboss/deployers/structure/spi/DeploymentUnit.java	2007-07-27 14:19:13 UTC (rev 64326)
@@ -137,6 +137,13 @@
    List<DeploymentUnit> getChildren();
    
    /**
+    * Whether this unit is a component
+    * 
+    * @return true for a component
+    */
+   boolean isComponent();
+   
+   /**
     * Add a component
     * 
     * @param name the name

Modified: projects/microcontainer/trunk/deployers-structure-spi/src/main/org/jboss/deployers/structure/spi/helpers/AbstractDeploymentUnit.java
===================================================================
--- projects/microcontainer/trunk/deployers-structure-spi/src/main/org/jboss/deployers/structure/spi/helpers/AbstractDeploymentUnit.java	2007-07-27 14:17:21 UTC (rev 64325)
+++ projects/microcontainer/trunk/deployers-structure-spi/src/main/org/jboss/deployers/structure/spi/helpers/AbstractDeploymentUnit.java	2007-07-27 14:19:13 UTC (rev 64326)
@@ -166,6 +166,11 @@
       return new AbstractDeploymentUnit(component);
    }
    
+   public boolean isComponent()
+   {
+      return deploymentContext.isComponent();
+   }
+
    public DeploymentUnit addComponent(String name)
    {
       DeploymentContext component = createComponentDeploymentContext(name, deploymentContext);




More information about the jboss-cvs-commits mailing list