[jboss-cvs] JBossAS SVN: r88268 - in projects/aop/trunk: asintegration-mc/src/main/java/org/jboss/aop/asintegration/jboss5 and 4 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Wed May 6 11:04:29 EDT 2009


Author: kabir.khan at jboss.com
Date: 2009-05-06 11:04:29 -0400 (Wed, 06 May 2009)
New Revision: 88268

Added:
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/Aspect2A.java
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/Aspect2B.java
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/Aspect3A.java
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/Aspect3B.java
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/AspectA1.java
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/AspectA2.java
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/AspectA3.java
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow1.java
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow2A.java
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow2B.java
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow3A.java
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow3B.java
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/ScopedVFSClassLoaderDomainTestCase.java
Modified:
   projects/aop/trunk/asintegration-core/src/main/java/org/jboss/aop/domain/ScopedClassLoaderDomain.java
   projects/aop/trunk/asintegration-mc/src/main/java/org/jboss/aop/asintegration/jboss5/DomainRegistry.java
   projects/aop/trunk/asintegration-mc/src/main/java/org/jboss/aop/asintegration/jboss5/ScopedVFSClassLoaderDomain.java
   projects/aop/trunk/asintegration-mc/src/main/java/org/jboss/aop/asintegration/jboss5/VFSClassLoaderDomainRegistry.java
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/classpool/jbosscl/test/JBossClClassPoolTest.java
   projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/classpool/jbosscl/test/JBossClClassPoolTestSuite.java
Log:
[JBAOP-707] Scoped aop domains need to look at all the scoped aop domains within the classloader domain

Modified: projects/aop/trunk/asintegration-core/src/main/java/org/jboss/aop/domain/ScopedClassLoaderDomain.java
===================================================================
--- projects/aop/trunk/asintegration-core/src/main/java/org/jboss/aop/domain/ScopedClassLoaderDomain.java	2009-05-06 15:03:54 UTC (rev 88267)
+++ projects/aop/trunk/asintegration-core/src/main/java/org/jboss/aop/domain/ScopedClassLoaderDomain.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -84,13 +84,6 @@
       }
    }
 
-// These are indexed by classloader now, so no need to manage them explicitly here
-//   @Override
-//   public InterceptionMarkers getInterceptionMarkers(ClassLoader loader)
-//   {
-//      return interceptionMarkers;
-//   }
-
    @Override
    public Object getPerVMAspect(String def)
    {

Modified: projects/aop/trunk/asintegration-mc/src/main/java/org/jboss/aop/asintegration/jboss5/DomainRegistry.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/main/java/org/jboss/aop/asintegration/jboss5/DomainRegistry.java	2009-05-06 15:03:54 UTC (rev 88267)
+++ projects/aop/trunk/asintegration-mc/src/main/java/org/jboss/aop/asintegration/jboss5/DomainRegistry.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -21,6 +21,9 @@
 */
 package org.jboss.aop.asintegration.jboss5;
 
+import java.util.List;
+import java.util.concurrent.locks.ReadWriteLock;
+
 import org.jboss.aop.Domain;
 import org.jboss.classloader.spi.ClassLoaderDomain;
 import org.jboss.classloader.spi.ClassLoaderSystem;
@@ -50,4 +53,8 @@
    Module getModule(ClassLoader loader);
 
    ClassLoader getClassLoader(Module module);
+   
+   List<ScopedVFSClassLoaderDomain> getAOPDomainsForClassLoaderDomain(ClassLoaderDomain domain);
+   
+   ReadWriteLock getAOPDomainsLockForClassLoaderDomain(ClassLoaderDomain domain);
 }
\ No newline at end of file

Modified: projects/aop/trunk/asintegration-mc/src/main/java/org/jboss/aop/asintegration/jboss5/ScopedVFSClassLoaderDomain.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/main/java/org/jboss/aop/asintegration/jboss5/ScopedVFSClassLoaderDomain.java	2009-05-06 15:03:54 UTC (rev 88267)
+++ projects/aop/trunk/asintegration-mc/src/main/java/org/jboss/aop/asintegration/jboss5/ScopedVFSClassLoaderDomain.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -23,10 +23,40 @@
 
 
 import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.ReadWriteLock;
 
+import org.jboss.aop.Advisor;
 import org.jboss.aop.AspectManager;
+import org.jboss.aop.Domain;
+import org.jboss.aop.DomainDefinition;
+import org.jboss.aop.advice.AdviceBinding;
+import org.jboss.aop.advice.AdviceStack;
 import org.jboss.aop.advice.AspectDefinition;
+import org.jboss.aop.advice.ClassifiedBindingAndPointcutCollection;
+import org.jboss.aop.advice.DynamicCFlowDefinition;
+import org.jboss.aop.advice.InterceptorFactory;
+import org.jboss.aop.advice.PrecedenceDef;
+import org.jboss.aop.array.ArrayReplacement;
 import org.jboss.aop.domain.ScopedClassLoaderDomain;
+import org.jboss.aop.introduction.AnnotationIntroduction;
+import org.jboss.aop.introduction.InterfaceIntroduction;
+import org.jboss.aop.metadata.ClassMetaDataBinding;
+import org.jboss.aop.metadata.ClassMetaDataLoader;
+import org.jboss.aop.metadata.SimpleClassMetaDataLoader;
+import org.jboss.aop.microcontainer.lifecycle.LifecycleCallbackBinding;
+import org.jboss.aop.pointcut.CFlowStack;
+import org.jboss.aop.pointcut.DynamicCFlow;
+import org.jboss.aop.pointcut.Pointcut;
+import org.jboss.aop.pointcut.PointcutInfo;
+import org.jboss.aop.pointcut.Typedef;
+import org.jboss.aop.util.UnmodifiableEmptyCollections;
 import org.jboss.classloader.spi.ClassLoaderDomain;
 
 
@@ -48,6 +78,7 @@
       super(loader, name, parentDelegation, manager, parentFirst);
       classLoaderDomainRef = new WeakReference<ClassLoaderDomain>(classLoaderDomain);
       this.registry = registry;
+      super.domainSearchStrategy = new AccumulativeDomainSearchStrategy();
    }
 
    private ClassLoaderDomain getClassLoaderDomain()
@@ -76,15 +107,28 @@
       }
       
       return false;
-//      return cl.getLoaderRepository() != null;
    }
 
+   /**
+    * Creates the binding collection to be used as the collection by this domain
+    * @return a {@link DomainClassifiedBindingAndPointcutCollection}
+    */
+   @Override
+   protected ClassifiedBindingAndPointcutCollection createBindingCollection()
+   {
+      return new ScopedClassifiedBindingAndPointcutCollection();
+   }
+
    protected Object getPerVmAspectWithNoParentDelegation(String def)
    {
       Object aspect = myPerVMAspects.get(def);
       if (aspect != null)
       {
-         return aspect;
+         if (searchParentsForPerVmDefinition(def, this))
+         {
+            return aspect;
+         }
+         return null;
       }
 
       aspect = super.getSuperPerVmAspect(def);
@@ -114,8 +158,11 @@
                //We have a different version of the class deployed
                AspectDefinition aspectDefinition = getAspectDefinition(def);
                //Override the classloader to create the aspect instance
-               aspect = createPerVmAspect(def, aspectDefinition, getClassLoader());
-               myPerVMAspects.put(def, aspect);
+               if (aspectDefinition != null)
+               {
+                  aspect = createPerVmAspect(def, aspectDefinition, getClassLoader());
+                  myPerVMAspects.put(def, aspect);
+               }
             }
          }
       }
@@ -123,12 +170,1395 @@
       return aspect;
    }
    
+   protected boolean searchParentsForPerVmDefinition(String def, AspectManager manager)
+   {
+      if (perVMAspects.containsKey(def))
+      {
+         return true;
+      }
+      if (manager instanceof Domain == false)
+      {
+         return false;
+      }
+      return searchParentsForPerVmDefinition(def, ((Domain)manager).getParent());
+   }
    
-   
    private ClassLoaderDomain getAspectRepository(Class<?> clazz)
    {
       ClassLoader cl = clazz.getClassLoader();
       ClassLoaderDomain domain = registry.getClassLoaderDomainForLoader(cl);
       return domain;
    }
+
+
+   class AccumulativeDomainSearchStrategy implements DomainSearchStrategy
+   {
+      public Object synchronizeAnnotationIntroductions()
+      {
+         return getSiblingScopedDomains();
+      }
+      
+      public Map<String, AnnotationIntroduction> getAnnotationIntroductions()
+      {
+         final Map<String, AnnotationIntroduction> empty = Collections.emptyMap();
+         Map<String, AnnotationIntroduction> result = empty;
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               synchronized (aopDomain.annotationIntroductions)
+               {
+                  if (aopDomain.annotationIntroductions.size() > 0)
+                  {
+                     if (result == empty)
+                     {
+                        result = new LinkedHashMap<String, AnnotationIntroduction>();
+                     }
+                     
+                     result.putAll(aopDomain.annotationIntroductions);
+                  }
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      public Object synchronizeAnnotationOverrides()
+      {
+         return getSiblingScopedDomains();
+      }
+
+      public Map<String, AnnotationIntroduction> getAnnotationOverrides()
+      {
+         final Map<String, AnnotationIntroduction> empty = Collections.emptyMap();
+         Map<String, AnnotationIntroduction> result = empty;
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               synchronized (aopDomain.annotationOverrides)
+               {
+                  if (aopDomain.annotationOverrides.size() > 0)
+                  {
+                     if (result == empty)
+                     {
+                        result = new LinkedHashMap<String, AnnotationIntroduction>();
+                     }
+                     
+                     result.putAll(aopDomain.annotationOverrides);
+                  }
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      public Object synchronizeArrayReplacements()
+      {
+         return getSiblingScopedDomains();
+      }
+
+      public Map<String, ArrayReplacement> getArrayReplacements()
+      {
+         final Map<String, ArrayReplacement> empty = Collections.emptyMap();
+         Map<String, ArrayReplacement> result = empty;
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               synchronized (aopDomain.arrayReplacements)
+               {
+                  if (aopDomain.arrayReplacements.size() > 0)
+                  {
+                     if (result == empty)
+                     {
+                        result = new LinkedHashMap<String, ArrayReplacement>();
+                     }
+                     
+                     result.putAll(aopDomain.arrayReplacements);
+                  }
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+      
+      
+      public Object synchronizeInterfaceIntroductions()
+      {
+         return getSiblingScopedDomains();
+      }
+      
+      public Map<String, InterfaceIntroduction> getInterfaceIntroductions()
+      {
+         final Map<String, InterfaceIntroduction> empty = Collections.emptyMap();
+         Map<String, InterfaceIntroduction> result = empty;
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               synchronized (aopDomain.interfaceIntroductions)
+               {
+                  if (aopDomain.interfaceIntroductions.size() > 0)
+                  {
+                     if (result == empty)
+                     {
+                        result = new LinkedHashMap<String, InterfaceIntroduction>();
+                     }
+                     
+                     result.putAll(aopDomain.interfaceIntroductions);
+                  }
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+      
+      public Object synchronizeTypedefs()
+      {
+         return getSiblingScopedDomains();
+      }
+      
+      public Map<String, Typedef> getTypedefs()
+      {
+         final Map<String, Typedef> empty = Collections.emptyMap();
+         Map<String, Typedef> result = empty;
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               synchronized (aopDomain.typedefs)
+               {
+                  if (aopDomain.typedefs.size() > 0)
+                  {
+                     if (result == empty)
+                     {
+                        result = new LinkedHashMap<String, Typedef>();
+                     }
+                     
+                     result.putAll(aopDomain.typedefs);
+                  }
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+      
+      public Typedef getTypedef(String name)
+      {
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               synchronized (aopDomain.typedefs)
+               {
+                  Typedef def = aopDomain.typedefs.get(name);
+                  if (def != null)
+                  {
+                     return def;
+                  }
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return null;
+      }
+      
+
+      public Object synchronizeAdviceStacks()
+      {
+         return getSiblingScopedDomains();
+      }
+ 
+      public Map<String, AdviceStack> getInterceptorStacks()
+      {
+         final Map<String, AdviceStack> empty = Collections.emptyMap();
+         Map<String, AdviceStack> result = empty;
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               synchronized (aopDomain.interceptorStacks)
+               {
+                  if (aopDomain.interceptorStacks.size() > 0)
+                  {
+                     if (result == empty)
+                     {
+                        result = new HashMap<String, AdviceStack>();
+                     }
+                     
+                     result.putAll(aopDomain.interceptorStacks);
+                  }
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+      
+      public AdviceStack getAdviceStack(String name)
+      {
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               synchronized (aopDomain.interceptorStacks)
+               {
+                  AdviceStack stack = aopDomain.interceptorStacks.get(name);
+                  if (stack != null)
+                  {
+                     return stack;
+                  }
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return null;
+      }
+      
+      public Object synchronizeClassMetaDataLoaders()
+      {
+         return getSiblingScopedDomains();
+      }
+      
+      public Map<String, ClassMetaDataLoader> getClassMetaDataLoaders()
+      {
+         final Map<String, ClassMetaDataLoader> empty = Collections.emptyMap();
+         Map<String, ClassMetaDataLoader> result = empty;
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               synchronized (aopDomain.classMetaDataLoaders)
+               {
+                  if (aopDomain.classMetaDataLoaders.size() > 0)
+                  {
+                     if (result == empty)
+                     {
+                        result = new HashMap<String, ClassMetaDataLoader>();
+                     }
+                     
+                     result.putAll(aopDomain.classMetaDataLoaders);
+                  }
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+      
+      public ClassMetaDataLoader findClassMetaDataLoader(String group)
+      {
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               synchronized (aopDomain.classMetaDataLoaders)
+               {
+                  ClassMetaDataLoader loader = aopDomain.classMetaDataLoaders.get(group);
+                  if (loader != null && loader != SimpleClassMetaDataLoader.singleton)
+                  {
+                     return loader;
+                  }
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return null;
+      }
+
+      public Object synchronizeCFlowStacks()
+      {
+         return getSiblingScopedDomains();
+      }
+      
+      public Map<String, CFlowStack> getCflowStacks()
+      {
+         final Map<String, CFlowStack> empty = Collections.emptyMap();
+         Map<String, CFlowStack> result = empty;
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               //ConcurrentMap no need to synchronize
+               if (aopDomain.cflowStacks.size() > 0)
+               {
+                  if (result == empty)
+                  {
+                     result = new HashMap<String, CFlowStack>();
+                  }
+                  
+                  result.putAll(aopDomain.cflowStacks);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+      
+      public CFlowStack getCFlowStack(String name)
+      {
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               //ConcurrentMap no need to synchronize
+               CFlowStack stack = aopDomain.cflowStacks.get(name);
+               if (stack != null)
+               {
+                  return stack;
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return null;
+      }
+
+      
+      public Object synchronizeDynamicCflows()
+      {
+         return getSiblingScopedDomains();
+      }
+      
+      public Map<String, DynamicCFlowDefinition> getDynamicCFlows()
+      {
+         final Map<String, DynamicCFlowDefinition> empty = Collections.emptyMap();
+         Map<String, DynamicCFlowDefinition> result = empty;
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               //ConcurrentMap no need to synchronize
+               if (aopDomain.dynamicCFlows.size() > 0)
+               {
+                  if (result == empty)
+                  {
+                     result = new HashMap<String, DynamicCFlowDefinition>();
+                  }
+                  
+                  result.putAll(aopDomain.dynamicCFlows);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+      
+      public DynamicCFlow getDynamicCFlow(String name, ClassLoader cl)
+      {
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               //ConcurrentMap no need to synchronize
+               DynamicCFlowDefinition def = aopDomain.dynamicCFlows.get(name);
+               if (def != null)
+               {
+                  return def.create(cl);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return null;
+      }
+ 
+      
+      public Object synchronizePrecedenceDefs()
+      {
+         return getSiblingScopedDomains();
+      }
+      
+      public LinkedHashMap<String, PrecedenceDef> getPrecedenceDefs()
+      {
+         final Map<String, PrecedenceDef> empty = Collections.emptyMap();
+         Map<String, PrecedenceDef> result = empty;
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               synchronized (aopDomain.precedenceDefs)
+               {
+                  if (aopDomain.precedenceDefs.size() > 0)
+                  {
+                     if (result == empty)
+                     {
+                        result = new LinkedHashMap<String, PrecedenceDef>();
+                     }
+                     
+                     result.putAll(aopDomain.precedenceDefs);
+                  }
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return (LinkedHashMap<String, PrecedenceDef>)result;
+      }
+
+      public Object synchronizeClassMetaData()
+      {
+         return getSiblingScopedDomains();
+      }
+      
+      public Map<String, ClassMetaDataBinding> getClassMetaData()
+      {
+         final Map<String, ClassMetaDataBinding> empty = Collections.emptyMap();
+         Map<String, ClassMetaDataBinding> result = empty;
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               synchronized (aopDomain.classMetaData)
+               {
+                  if (aopDomain.classMetaData.size() > 0)
+                  {
+                     if (result == empty)
+                     {
+                        result = new LinkedHashMap<String, ClassMetaDataBinding>();
+                     }
+                     
+                     result.putAll(aopDomain.classMetaData);
+                  }
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      public InterceptorFactory getInterceptorFactory(String name)
+      {
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               synchronized (aopDomain.interceptorFactories)
+               {
+                  InterceptorFactory factory = aopDomain.interceptorFactories.get(name);
+                  if (factory != null)
+                  {
+                     return factory;
+                  }
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return null;
+      }
+
+      public AspectDefinition getAspectDefinition(String name)
+      {
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               //ConcurrentMap no need to synchronize
+               AspectDefinition def = aopDomain.aspectDefinitions.get(name);
+               if (def != null)
+               {
+                  return def;
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return null;
+      }
+
+      public DomainDefinition getContainer(String name)
+      {
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               //ConcurrentMap no need to synchronize
+               DomainDefinition def = aopDomain.containers.get(name);
+               if (def != null)
+               {
+                  return def;
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return null;
+      }
+
+      public Map<String, LifecycleCallbackBinding> getLifecycleBindings()
+      {
+         final Map<String, LifecycleCallbackBinding> empty = Collections.emptyMap();
+         Map<String, LifecycleCallbackBinding> result = empty;
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               synchronized (aopDomain.lifecycleManager.getLifecycleBindings())
+               {
+                  if (aopDomain.lifecycleManager.getLifecycleBindings().size() > 0)
+                  {
+                     if (result == empty)
+                     {
+                        result = new LinkedHashMap<String, LifecycleCallbackBinding>();
+                     }
+                     
+                     result.putAll(aopDomain.lifecycleManager.getLifecycleBindings());
+                  }
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      public Object synchronizePerVmAspects()
+      {
+         return getSiblingScopedDomains();
+      }
+      
+      public Map<String, Object> getPerVMAspects()
+      {
+         final Map<String, Object> empty = Collections.emptyMap();
+         Map<String, Object> result = empty;
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               //ConcurrentMap no need to synchronize
+               if (aopDomain.perVMAspects.size() > 0)
+               {
+                  if (result == empty)
+                  {
+                     result = new HashMap<String, Object>();
+                  }
+                  
+                  result.putAll(aopDomain.perVMAspects);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+      
+      public Object getPerVMAspect(String def, Advisor advisor)
+      {
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               Object o = aopDomain.getPerVMAspectInternal(def, advisor);
+               if (o != null)
+               {
+                  return o;
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return null;
+      }
+
+   }
+   
+   class ScopedClassifiedBindingAndPointcutCollection extends DomainClassifiedBindingAndPointcutCollection
+   {
+      @Override
+      protected LinkedHashMap<String, AdviceBinding> getBindingsForDomain()
+      {
+         LinkedHashMap<String, AdviceBinding> result = UnmodifiableEmptyCollections.EMPTY_LINKED_HASHMAP;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               LinkedHashMap<String, AdviceBinding> entries = aopDomain.getBindingCollection().getBindingsInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_LINKED_HASHMAP)
+                  {
+                     result = new LinkedHashMap<String, AdviceBinding>();
+                  }
+                  result.putAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected LinkedHashMap<String, PointcutInfo> getPointcutInfosForDomain()
+      {
+         LinkedHashMap<String, PointcutInfo> result = UnmodifiableEmptyCollections.EMPTY_LINKED_HASHMAP;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               LinkedHashMap<String, PointcutInfo> entries = aopDomain.getBindingCollection().getPointcutInfosInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_LINKED_HASHMAP)
+                  {
+                     result = new LinkedHashMap<String, PointcutInfo>();
+                  }
+                  result.putAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected LinkedHashMap<String, Pointcut> getPointcutsForDomain()
+      {
+         LinkedHashMap<String, Pointcut> result = UnmodifiableEmptyCollections.EMPTY_LINKED_HASHMAP;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               LinkedHashMap<String, Pointcut> entries = aopDomain.getBindingCollection().getPointcutsInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_LINKED_HASHMAP)
+                  {
+                     result = new LinkedHashMap<String, Pointcut>();
+                  }
+                  result.putAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<AdviceBinding> getConstructionBindingsForDomain()
+      {
+         ArrayList<AdviceBinding> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<AdviceBinding> entries = aopDomain.getBindingCollection().getConstructionBindingsInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<AdviceBinding>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<PointcutInfo> getConstructionPointcutInfosForDomain()
+      {
+         ArrayList<PointcutInfo> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<PointcutInfo> entries = aopDomain.getBindingCollection().getConstructionPointcutInfosInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<PointcutInfo>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<Pointcut> getConstructionPointcutsForDomain()
+      {
+         ArrayList<Pointcut> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<Pointcut> entries = aopDomain.getBindingCollection().getConstructionPointcutsInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<Pointcut>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<AdviceBinding> getConstructorCallBindingsForDomain()
+      {
+         ArrayList<AdviceBinding> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<AdviceBinding> entries = aopDomain.getBindingCollection().getConstructorCallBindingsInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<AdviceBinding>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<PointcutInfo> getConstructorCallPointcutInfosForDomain()
+      {
+         ArrayList<PointcutInfo> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<PointcutInfo> entries = aopDomain.getBindingCollection().getConstructorCallPointcutInfosInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<PointcutInfo>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<Pointcut> getConstructorCallPointcutsForDomain()
+      {
+         ArrayList<Pointcut> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<Pointcut> entries = aopDomain.getBindingCollection().getConstructorCallPointcutsInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<Pointcut>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<AdviceBinding> getConstructorExecutionBindingsForDomain()
+      {
+         ArrayList<AdviceBinding> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<AdviceBinding> entries = aopDomain.getBindingCollection().getConstructorExecutionBindingsInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<AdviceBinding>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<PointcutInfo> getConstructorExecutionPointcutInfosForDomain()
+      {
+         ArrayList<PointcutInfo> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<PointcutInfo> entries = aopDomain.getBindingCollection().getConstructorExecutionPointcutInfosInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<PointcutInfo>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<Pointcut> getConstructorExecutionPointcutsForDomain()
+      {
+         ArrayList<Pointcut> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<Pointcut> entries = aopDomain.getBindingCollection().getConstructorExecutionPointcutsInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<Pointcut>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<AdviceBinding> getFieldReadBindingsForDomain()
+      {
+         ArrayList<AdviceBinding> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<AdviceBinding> entries = aopDomain.getBindingCollection().getFieldReadBindingsInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<AdviceBinding>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<PointcutInfo> getFieldReadPointcutInfosForDomain()
+      {
+         ArrayList<PointcutInfo> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<PointcutInfo> entries = aopDomain.getBindingCollection().getFieldReadPointcutInfosInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<PointcutInfo>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<Pointcut> getFieldReadPointcutsForDomain()
+      {
+         ArrayList<Pointcut> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<Pointcut> entries = aopDomain.getBindingCollection().getFieldReadPointcutsInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<Pointcut>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<AdviceBinding> getFieldWriteBindingsForDomain()
+      {
+         ArrayList<AdviceBinding> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<AdviceBinding> entries = aopDomain.getBindingCollection().getFieldWriteBindingsInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<AdviceBinding>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<PointcutInfo> getFieldWritePointcutInfosForDomain()
+      {
+         ArrayList<PointcutInfo> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<PointcutInfo> entries = aopDomain.getBindingCollection().getFieldWritePointcutInfosInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<PointcutInfo>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<Pointcut> getFieldWritePointcutsForDomain()
+      {
+         ArrayList<Pointcut> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<Pointcut> entries = aopDomain.getBindingCollection().getFieldWritePointcutsInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<Pointcut>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<AdviceBinding> getMethodCallBindingsForDomain()
+      {
+         ArrayList<AdviceBinding> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<AdviceBinding> entries = aopDomain.getBindingCollection().getMethodCallBindingsInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<AdviceBinding>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<PointcutInfo> getMethodCallPointcutInfosForDomain()
+      {
+         ArrayList<PointcutInfo> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<PointcutInfo> entries = aopDomain.getBindingCollection().getMethodCallPointcutInfosInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<PointcutInfo>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<Pointcut> getMethodCallPointcutsForDomain()
+      {
+         ArrayList<Pointcut> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<Pointcut> entries = aopDomain.getBindingCollection().getMethodCallPointcutsInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<Pointcut>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<AdviceBinding> getMethodExecutionBindingsForDomain()
+      {
+         ArrayList<AdviceBinding> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<AdviceBinding> entries = aopDomain.getBindingCollection().getMethodExecutionBindingsInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<AdviceBinding>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<PointcutInfo> getMethodExecutionPointcutInfosForDomain()
+      {
+         ArrayList<PointcutInfo> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<PointcutInfo> entries = aopDomain.getBindingCollection().getMethodExecutionPointcutInfosInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<PointcutInfo>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+
+      @Override
+      protected Collection<Pointcut> getMethodExecutionPointcutsForDomain()
+      {
+         ArrayList<Pointcut> result = UnmodifiableEmptyCollections.EMPTY_ARRAYLIST;
+         
+         ReadWriteLock lock = lockReadSiblingDomains();
+         try
+         {
+            for (ScopedVFSClassLoaderDomain aopDomain : getSiblingScopedDomains())
+            {
+               @SuppressWarnings("deprecation")
+               Collection<Pointcut> entries = aopDomain.getBindingCollection().getMethodExecutionPointcutsInternal();
+               if (entries != null && entries.size() > 0)
+               {
+                  if (result == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+                  {
+                     result = new ArrayList<Pointcut>();
+                  }
+                  result.addAll(entries);
+               }
+            }
+         }
+         finally
+         {
+            unlockReadSiblingDomains(lock);
+         }
+         return result;
+      }
+   }
+   
+   private ReadWriteLock lockReadSiblingDomains()
+   {
+      ReadWriteLock domainsLock = registry.getAOPDomainsLockForClassLoaderDomain(getClassLoaderDomain());
+      domainsLock.readLock().lock();
+      return domainsLock;
+   }
+   
+   private void unlockReadSiblingDomains(ReadWriteLock domainsLock)
+   {
+      domainsLock.readLock().lock();
+   }
+   
+   private List<ScopedVFSClassLoaderDomain> getSiblingScopedDomains()
+   {
+      return registry.getAOPDomainsForClassLoaderDomain(getClassLoaderDomain());
+   }
+
 }

Modified: projects/aop/trunk/asintegration-mc/src/main/java/org/jboss/aop/asintegration/jboss5/VFSClassLoaderDomainRegistry.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/main/java/org/jboss/aop/asintegration/jboss5/VFSClassLoaderDomainRegistry.java	2009-05-06 15:03:54 UTC (rev 88267)
+++ projects/aop/trunk/asintegration-mc/src/main/java/org/jboss/aop/asintegration/jboss5/VFSClassLoaderDomainRegistry.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -22,8 +22,13 @@
 package org.jboss.aop.asintegration.jboss5;
 
 import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 import java.util.WeakHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.jboss.aop.Domain;
 import org.jboss.classloader.spi.ClassLoaderDomain;
@@ -46,9 +51,15 @@
    /** classloader domains by their classloaders */
    private Map<ClassLoader, WeakReference<ClassLoaderDomain>> classLoaderDomainsByLoader = new WeakHashMap<ClassLoader, WeakReference<ClassLoaderDomain>>();
 
+   /** aopDomains by classloader */
+   private Map<ClassLoader, ScopedVFSClassLoaderDomain> aopDomainsByClassLoader = new WeakHashMap<ClassLoader, ScopedVFSClassLoaderDomain>();
+   
    /** aopDomains by classloader domain */
-   private Map<ClassLoaderDomain, ScopedVFSClassLoaderDomain> aopDomainsByClassLoaderDomain = new WeakHashMap<ClassLoaderDomain, ScopedVFSClassLoaderDomain>();
-   
+   private Map<ClassLoaderDomain, List<ScopedVFSClassLoaderDomain>> aopDomainsByClassLoaderDomain = new WeakHashMap<ClassLoaderDomain, List<ScopedVFSClassLoaderDomain>>();
+
+   private Map<ClassLoaderDomain, ReadWriteLock> aopDomainsLocksByClassLoaderDomain = new WeakHashMap<ClassLoaderDomain, ReadWriteLock>();
+
+
    /** parent deployment unit classloaders indexed by children */
    private Map<ClassLoader, WeakReference<ClassLoader>> classLoaderUnitParents = new WeakHashMap<ClassLoader, WeakReference<ClassLoader>>(); 
    
@@ -104,6 +115,11 @@
       
       String domainName = module.getDeterminedDomainName();
       ClassLoaderDomain clDomain = system.getDomain(domainName);
+      if (clDomain == null && domain != null)
+      {
+         throw new IllegalStateException("Have " + domain + " but no classloader domain");
+      }
+
       boolean ret = false;
       if (!classLoaderDomainsByLoader.containsKey(loader))
       {
@@ -118,7 +134,36 @@
          ret = true;
          if (domain != null)
          {
-            aopDomainsByClassLoaderDomain.put(clDomain, domain);
+            aopDomainsByClassLoader.put(loader, domain);
+
+            ReadWriteLock lock = aopDomainsLocksByClassLoaderDomain.get(clDomain);
+            if (lock == null)
+            {
+               lock = new ReentrantReadWriteLock();
+               aopDomainsLocksByClassLoaderDomain.put(clDomain, lock);
+            }
+            
+            lock.writeLock().lock();
+            try
+            {
+               List<ScopedVFSClassLoaderDomain> aopDomains = aopDomainsByClassLoaderDomain.get(clDomain);
+               if (aopDomains == null)
+               {
+                  synchronized (aopDomainsByClassLoaderDomain)
+                  {
+                     aopDomains = new CopyOnWriteArrayList<ScopedVFSClassLoaderDomain>();
+                     if (!aopDomains.contains(clDomain))
+                     {
+                        aopDomainsByClassLoaderDomain.put(clDomain, aopDomains);
+                     }
+                  }
+               }
+               aopDomains.add(domain);
+            }
+            finally
+            {
+               lock.writeLock().unlock();
+            }
          }
       }
       
@@ -140,13 +185,14 @@
          }
          if (cnt == 0)
          {
-            aopDomainsByClassLoaderDomain.remove(clDomain);
+            //aopDomainsByClassLoaderDomain.remove(clDomain);
             classLoaderDomainReferenceCounts.remove(clDomain);
          }
          else
          {
             classLoaderDomainReferenceCounts.put(clDomain, ++cnt);
          }
+         ScopedVFSClassLoaderDomain aopDomain = aopDomainsByClassLoader.remove(loader);
          classLoaderUnitParents.remove(loader);
          WeakReference<Module> moduleRef = classLoaderModules.remove(loader);
          if (moduleRef != null)
@@ -157,17 +203,23 @@
                moduleClassLoaders.remove(module);
             }
          }
+
+         List<ScopedVFSClassLoaderDomain> aopDomains = aopDomainsByClassLoaderDomain.get(clDomain);
+         if (aopDomains != null)
+         {
+            aopDomains.remove(aopDomain);
+         }
+         if (aopDomain != null)
+         {
+            aopDomain.getParent().unsubscribeSubDomain(aopDomain);
+         }
       }
+      aopDomainsByClassLoader.remove(loader);
    }
 
    public synchronized Domain getRegisteredDomain(ClassLoader cl)
    {
-      ClassLoaderDomain clDomain = getClassLoaderDomainForLoader(cl);
-      if (clDomain != null)
-      {
-         return aopDomainsByClassLoaderDomain.get(clDomain);
-      }
-      return null;
+      return aopDomainsByClassLoader.get(cl);
    }
    
    public synchronized ClassLoaderDomain getClassLoaderDomainForLoader(ClassLoader cl)
@@ -220,4 +272,19 @@
       }
       return null;
    }
+
+   public List<ScopedVFSClassLoaderDomain> getAOPDomainsForClassLoaderDomain(ClassLoaderDomain domain)
+   {
+      List<ScopedVFSClassLoaderDomain> domains = aopDomainsByClassLoaderDomain.get(domain);
+      if (domains != null)
+      {
+         return domains;
+      }
+      return Collections.emptyList();
+   }
+
+   public ReadWriteLock getAOPDomainsLockForClassLoaderDomain(ClassLoaderDomain domain)
+   {
+      return aopDomainsLocksByClassLoaderDomain.get(domain);
+   }
 }

Modified: projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/classpool/jbosscl/test/JBossClClassPoolTest.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/classpool/jbosscl/test/JBossClClassPoolTest.java	2009-05-06 15:03:54 UTC (rev 88267)
+++ projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/classpool/jbosscl/test/JBossClClassPoolTest.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -36,7 +36,9 @@
 import junit.framework.Test;
 
 import org.jboss.aop.AspectManager;
+import org.jboss.aop.asintegration.jboss5.DomainRegistry;
 import org.jboss.aop.asintegration.jboss5.RegisterModuleCallback;
+import org.jboss.aop.asintegration.jboss5.ScopedVFSClassLoaderDomain;
 import org.jboss.aop.asintegration.jboss5.VFSClassLoaderDomainRegistry;
 import org.jboss.aop.classpool.jbosscl.JBossClDelegatingClassPoolFactory;
 import org.jboss.beans.metadata.spi.BeanMetaDataFactory;
@@ -654,10 +656,19 @@
       {
          domainRegistry.setSystem(getSystem());
       }
+      
       //TODO I have just hacked the domain here so this might cause problems
       //with the tests if we try to do weaving. However, it should be fine while just testing pools
       //and loaders
-      domainRegistry.initMapsForLoader(loader, module, null, parent);
+      ScopedVFSClassLoaderDomainSetup setup = peekClassLoaderDomainSetup();
+      ScopedVFSClassLoaderDomain domain = null;
+      if (setup != null)
+      {
+         ClassLoaderDomain clDomain = getSystem().getDomain(module.getDomainName());
+         setup.setClassLoaderAndDomain(loader, clDomain);
+         domain = setup.getDomain();
+      }
+      domainRegistry.initMapsForLoader(loader, module, domain, parent);
    }
    
    protected void unregisterModule(ClassLoader loader)
@@ -948,4 +959,55 @@
       }
    }
 
+   private static ScopedVFSClassLoaderDomainSetup classLoaderDomainSetup;
+   
+   protected static void pushClassLoaderDomainSetup(ScopedVFSClassLoaderDomainSetup setup)
+   {
+      classLoaderDomainSetup = setup;
+   }
+   
+   protected static ScopedVFSClassLoaderDomainSetup popClassLoaderDomainSetup()
+   {
+      ScopedVFSClassLoaderDomainSetup setup = classLoaderDomainSetup;
+      classLoaderDomainSetup = null;
+      return setup;
+   }
+   
+   protected static ScopedVFSClassLoaderDomainSetup peekClassLoaderDomainSetup()
+   {
+      return classLoaderDomainSetup;
+   }
+   
+   public class ScopedVFSClassLoaderDomainSetup
+   {
+      ScopedVFSClassLoaderDomain domain;
+      
+      String name;
+      boolean parentDelegation;
+      AspectManager manager;
+      boolean parentFirst; 
+      DomainRegistry registry;
+      
+      public ScopedVFSClassLoaderDomainSetup(String name, boolean parentDelegation, AspectManager manager, boolean parentFirst, DomainRegistry registry)
+      {
+         this.name = name;
+         this.parentDelegation = parentDelegation;
+         this.manager = manager;
+         this.parentFirst = parentFirst;
+         this.registry = registry;
+      }
+      
+      public ScopedVFSClassLoaderDomain getDomain()
+      {
+         return domain;
+      }
+
+      public void setClassLoaderAndDomain(ClassLoader loader, ClassLoaderDomain clDomain)
+      {
+         if (domain == null)
+         {
+            domain = new ScopedVFSClassLoaderDomain(loader, name, parentDelegation, manager, parentFirst, clDomain, registry);
+         }
+      }
+   }
 }

Modified: projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/classpool/jbosscl/test/JBossClClassPoolTestSuite.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/classpool/jbosscl/test/JBossClClassPoolTestSuite.java	2009-05-06 15:03:54 UTC (rev 88267)
+++ projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/classpool/jbosscl/test/JBossClClassPoolTestSuite.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -21,6 +21,8 @@
 */ 
 package org.jboss.test.aop.classpool.jbosscl.test;
 
+import org.jboss.test.aop.scopeddomain.test.ScopedVFSClassLoaderDomainTestCase;
+
 import junit.framework.Test;
 import junit.framework.TestSuite;
 import junit.textui.TestRunner;
@@ -43,7 +45,7 @@
       
       suite.addTest(JBossClClassPoolSanityTestSuite.suite());
       suite.addTest(JBossClClassPoolDelegatingTestSuite.suite());
-
+      suite.addTest(ScopedVFSClassLoaderDomainTestCase.suite());
       return suite;
    }
 

Added: projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/Aspect2A.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/Aspect2A.java	                        (rev 0)
+++ projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/Aspect2A.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -0,0 +1,32 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file 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.aop.scopeddomain.test;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class Aspect2A
+{
+
+}

Added: projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/Aspect2B.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/Aspect2B.java	                        (rev 0)
+++ projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/Aspect2B.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -0,0 +1,32 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file 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.aop.scopeddomain.test;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class Aspect2B
+{
+
+}

Added: projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/Aspect3A.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/Aspect3A.java	                        (rev 0)
+++ projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/Aspect3A.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -0,0 +1,32 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file 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.aop.scopeddomain.test;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class Aspect3A
+{
+
+}

Added: projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/Aspect3B.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/Aspect3B.java	                        (rev 0)
+++ projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/Aspect3B.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -0,0 +1,32 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file 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.aop.scopeddomain.test;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class Aspect3B
+{
+
+}

Added: projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/AspectA1.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/AspectA1.java	                        (rev 0)
+++ projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/AspectA1.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -0,0 +1,32 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file 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.aop.scopeddomain.test;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class AspectA1
+{
+
+}

Added: projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/AspectA2.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/AspectA2.java	                        (rev 0)
+++ projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/AspectA2.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -0,0 +1,32 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file 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.aop.scopeddomain.test;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class AspectA2
+{
+
+}

Added: projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/AspectA3.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/AspectA3.java	                        (rev 0)
+++ projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/AspectA3.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -0,0 +1,32 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file 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.aop.scopeddomain.test;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class AspectA3
+{
+
+}

Added: projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow1.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow1.java	                        (rev 0)
+++ projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow1.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -0,0 +1,40 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file 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.aop.scopeddomain.test;
+
+import org.jboss.aop.joinpoint.Invocation;
+import org.jboss.aop.pointcut.DynamicCFlow;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class MockDynamicCFlow1 implements DynamicCFlow
+{
+
+   public boolean shouldExecute(Invocation invocation)
+   {
+      return false;
+   }
+
+}

Added: projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow2A.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow2A.java	                        (rev 0)
+++ projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow2A.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -0,0 +1,40 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file 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.aop.scopeddomain.test;
+
+import org.jboss.aop.joinpoint.Invocation;
+import org.jboss.aop.pointcut.DynamicCFlow;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class MockDynamicCFlow2A implements DynamicCFlow
+{
+
+   public boolean shouldExecute(Invocation invocation)
+   {
+      return false;
+   }
+
+}

Added: projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow2B.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow2B.java	                        (rev 0)
+++ projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow2B.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -0,0 +1,40 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file 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.aop.scopeddomain.test;
+
+import org.jboss.aop.joinpoint.Invocation;
+import org.jboss.aop.pointcut.DynamicCFlow;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class MockDynamicCFlow2B implements DynamicCFlow
+{
+
+   public boolean shouldExecute(Invocation invocation)
+   {
+      return false;
+   }
+
+}

Added: projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow3A.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow3A.java	                        (rev 0)
+++ projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow3A.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -0,0 +1,40 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file 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.aop.scopeddomain.test;
+
+import org.jboss.aop.joinpoint.Invocation;
+import org.jboss.aop.pointcut.DynamicCFlow;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class MockDynamicCFlow3A implements DynamicCFlow
+{
+
+   public boolean shouldExecute(Invocation invocation)
+   {
+      return false;
+   }
+
+}

Added: projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow3B.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow3B.java	                        (rev 0)
+++ projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/MockDynamicCFlow3B.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -0,0 +1,40 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file 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.aop.scopeddomain.test;
+
+import org.jboss.aop.joinpoint.Invocation;
+import org.jboss.aop.pointcut.DynamicCFlow;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class MockDynamicCFlow3B implements DynamicCFlow
+{
+
+   public boolean shouldExecute(Invocation invocation)
+   {
+      return false;
+   }
+
+}

Added: projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/ScopedVFSClassLoaderDomainTestCase.java
===================================================================
--- projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/ScopedVFSClassLoaderDomainTestCase.java	                        (rev 0)
+++ projects/aop/trunk/asintegration-mc/src/test/java/org/jboss/test/aop/scopeddomain/test/ScopedVFSClassLoaderDomainTestCase.java	2009-05-06 15:04:29 UTC (rev 88268)
@@ -0,0 +1,1733 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file 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.aop.scopeddomain.test;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import javassist.ClassPool;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.jboss.aop.AspectManager;
+import org.jboss.aop.Domain;
+import org.jboss.aop.DomainDefinition;
+import org.jboss.aop.advice.AdviceBinding;
+import org.jboss.aop.advice.AdviceStack;
+import org.jboss.aop.advice.AspectDefinition;
+import org.jboss.aop.advice.ClassifiedBindingAndPointcutCollection;
+import org.jboss.aop.advice.DynamicCFlowDefinition;
+import org.jboss.aop.advice.GenericAspectFactory;
+import org.jboss.aop.advice.InterceptorFactory;
+import org.jboss.aop.advice.PrecedenceDef;
+import org.jboss.aop.advice.Scope;
+import org.jboss.aop.advice.ScopedInterceptorFactory;
+import org.jboss.aop.array.ArrayReplacement;
+import org.jboss.aop.asintegration.jboss5.ScopedVFSClassLoaderDomain;
+import org.jboss.aop.introduction.AnnotationIntroduction;
+import org.jboss.aop.introduction.InterfaceIntroduction;
+import org.jboss.aop.metadata.ClassMetaDataBinding;
+import org.jboss.aop.metadata.SimpleClassMetaDataBinding;
+import org.jboss.aop.metadata.SimpleClassMetaDataLoader;
+import org.jboss.aop.microcontainer.lifecycle.LifecycleCallbackBinding;
+import org.jboss.aop.pointcut.CFlowStack;
+import org.jboss.aop.pointcut.Pointcut;
+import org.jboss.aop.pointcut.PointcutInfo;
+import org.jboss.aop.pointcut.Typedef;
+import org.jboss.aop.pointcut.TypedefExpression;
+import org.jboss.classloader.spi.ClassLoaderDomain;
+import org.jboss.test.aop.classpool.jbosscl.test.JBossClClassPoolTest;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class ScopedVFSClassLoaderDomainTestCase extends JBossClClassPoolTest
+{
+   public static Test suite()
+   {
+      return new TestSuite(ScopedVFSClassLoaderDomainTestCase.class);
+   }
+
+   public ScopedVFSClassLoaderDomainTestCase(String name)
+   {
+      // FIXME ScopedVFSClassLoaderDomainTestCase constructor
+      super(name);
+   }
+   
+   public void testBindingCollectionExecution() throws Exception
+   {
+      Domains domains = new Domains();
+      try
+      {
+         AdviceBinding ex1 = new AdviceBinding("1", "all(Pojo1)", null);
+         AdviceBinding ex2A = new AdviceBinding("2A", "all(Pojo2A)", null);
+         AdviceBinding ex2B = new AdviceBinding("2B", "all(Pojo2B)", null);
+         AdviceBinding ex3A = new AdviceBinding("3A", "all(Pojo3A)", null);
+         AdviceBinding ex3B = new AdviceBinding("3B", "all(Pojo3B)", null);
+         domains.getMain().addBinding(ex1);
+         domains.getMiddleA().addBinding(ex2A);
+         domains.getMiddleB().addBinding(ex2B);
+         domains.getBottomA().addBinding(ex3A);
+         domains.getBottomB().addBinding(ex3B);
+         AdviceBinding[] expectedExectutionBindings = new AdviceBinding[] {ex2A, ex2B, ex1, ex3A, ex3B};
+   
+         checkAllBindingsAndPointcuts(domains, expectedExectutionBindings);
+         checkFieldReadBindingsAndPointcuts(domains, expectedExectutionBindings);
+         checkFieldWriteBindingsAndPointcuts(domains, expectedExectutionBindings);
+         checkConstructorExecutionBindingsAndPointcuts(domains, expectedExectutionBindings);
+         checkMethodExecutionBindingsAndPointcuts(domains, expectedExectutionBindings);
+   
+         AdviceBinding mc1 = new AdviceBinding("MC1", "call(* Pojo1->*(..))", null); 
+         AdviceBinding mc2A = new AdviceBinding("MC2A", "call(* Pojo2A->*(..))", null); 
+         AdviceBinding mc2B = new AdviceBinding("MC2B", "call(* Pojo2B->*(..))", null); 
+         AdviceBinding mc3A = new AdviceBinding("MC3A", "call(* Pojo3A->*(..))", null); 
+         AdviceBinding mc3B = new AdviceBinding("MC3B", "call(* Pojo3B->*(..))", null); 
+   
+         AdviceBinding cc1 = new AdviceBinding("CC1", "call(Pojo1->new(..))", null); 
+         AdviceBinding cc2A = new AdviceBinding("CC2A", "call(Pojo2A->new(..))", null); 
+         AdviceBinding cc2B = new AdviceBinding("CC2B", "call(Pojo2B->new(..))", null); 
+         AdviceBinding cc3A = new AdviceBinding("CC3A", "call(Pojo3A->new(..))", null); 
+         AdviceBinding cc3B = new AdviceBinding("CC3C", "call(Pojo3B->new(..))", null); 
+   
+         domains.getMain().addBinding(mc1);
+         domains.getMiddleA().addBinding(mc2A);
+         domains.getMiddleB().addBinding(mc2B);
+         domains.getBottomA().addBinding(mc3A);
+         domains.getBottomB().addBinding(mc3B);
+   
+         domains.getMain().addBinding(cc1);
+         domains.getMiddleA().addBinding(cc2A);
+         domains.getMiddleB().addBinding(cc2B);
+         domains.getBottomA().addBinding(cc3A);
+         domains.getBottomB().addBinding(cc3B);
+         
+         checkMethodCallBindingsAndPointcuts(domains, new AdviceBinding[] {mc2A, mc2B, mc1, mc3A, mc3B});
+         checkConstructorCallBindingsAndPointcuts(domains, new AdviceBinding[] {cc2A, cc2B, cc1, cc3A, cc3B});
+         
+         domains.removePoolAndDomain(domains.getMiddlePoolB());
+         
+         expectedExectutionBindings = new AdviceBinding[] {ex2A, ex1, ex3A, ex3B};
+
+         checkFieldReadBindingsAndPointcuts(domains, expectedExectutionBindings);
+         checkFieldWriteBindingsAndPointcuts(domains, expectedExectutionBindings);
+         checkConstructorExecutionBindingsAndPointcuts(domains, expectedExectutionBindings);
+         checkMethodExecutionBindingsAndPointcuts(domains, expectedExectutionBindings);
+         checkMethodCallBindingsAndPointcuts(domains, new AdviceBinding[] {mc2A, mc1, mc3A, mc3B});
+         checkConstructorCallBindingsAndPointcuts(domains, new AdviceBinding[] {cc2A, cc1, cc3A, cc3B});
+      }
+      finally
+      {
+         domains.cleanup();
+      }
+   }
+   
+   private void checkAllBindingsAndPointcuts(Domains domains, AdviceBinding[] expectedBindings)
+   {
+      ClassifiedBindingAndPointcutCollection coll = domains.getBottomA().getBindingCollection();
+      Map<String, AdviceBinding> allBindings = coll.getBindings();
+      assertEquals(expectedBindings.length, allBindings.size());
+      int i = 0;
+      for (String key : allBindings.keySet())
+      {
+         assertEquals(expectedBindings[i].getName(), key);
+         assertEquals(expectedBindings[i], allBindings.get(key));
+         i++;
+      }
+
+      i = 0;
+      Map<String, Pointcut> allPointcuts = coll.getPointcuts();
+      assertEquals(expectedBindings.length, allPointcuts.size());
+      for (String key : allPointcuts.keySet())
+      {
+         assertEquals(expectedBindings[i].getPointcut(), allPointcuts.get(key));
+         i++;
+      }
+   
+      i = 0;
+      Map<String, PointcutInfo> allPointcutInfos = coll.getPointcutInfos();
+      assertEquals(expectedBindings.length, allPointcutInfos.size());
+      for (String key : allPointcutInfos.keySet())
+      {
+         assertEquals(expectedBindings[i].getPointcut(), allPointcutInfos.get(key).getPointcut());
+         i++;
+      }
+   }
+   
+   private void checkFieldReadBindingsAndPointcuts(Domains domains, AdviceBinding[] expectedBindings)
+   {
+      checkExpectedBindingsAndPointcuts(domains, expectedBindings, new BindingsAndPointcutSetup()
+      {
+         public Collection<AdviceBinding> bindings(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getFieldReadBindings();
+         }
+
+         public Collection<Pointcut> pointcuts(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getFieldReadPointcuts();
+         }
+      
+         public Collection<PointcutInfo> pointcutInfos(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getFieldReadPointcutInfos();
+         }
+      });
+   }
+   
+   private void checkFieldWriteBindingsAndPointcuts(Domains domains, AdviceBinding[] expectedBindings)
+   {
+      
+      checkExpectedBindingsAndPointcuts(domains, expectedBindings, new BindingsAndPointcutSetup()
+      {
+         public Collection<AdviceBinding> bindings(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getFieldWriteBindings();
+         }
+
+         public Collection<Pointcut> pointcuts(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getFieldWritePointcuts();
+         }
+      
+         public Collection<PointcutInfo> pointcutInfos(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getFieldWritePointcutInfos();
+         }
+      });
+   }
+   
+   private void checkConstructorExecutionBindingsAndPointcuts(Domains domains, AdviceBinding[] expectedBindings)
+   {
+      
+      checkExpectedBindingsAndPointcuts(domains, expectedBindings, new BindingsAndPointcutSetup()
+      {
+         public Collection<AdviceBinding> bindings(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getConstructorExecutionBindings();
+         }
+
+         public Collection<Pointcut> pointcuts(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getConstructorExecutionPointcuts();
+         }
+      
+         public Collection<PointcutInfo> pointcutInfos(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getConstructorExecutionPointcutInfos();
+         }
+      });
+   }
+   
+   private void checkMethodExecutionBindingsAndPointcuts(Domains domains, AdviceBinding[] expectedBindings)
+   {
+      checkExpectedBindingsAndPointcuts(domains, expectedBindings, new BindingsAndPointcutSetup()
+      {
+         public Collection<AdviceBinding> bindings(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getMethodExecutionBindings();
+         }
+
+         public Collection<Pointcut> pointcuts(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getMethodExecutionPointcuts();
+         }
+      
+         public Collection<PointcutInfo> pointcutInfos(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getMethodExecutionPointcutInfos();
+         }
+      });
+   }
+
+   private void checkMethodCallBindingsAndPointcuts(Domains domains, AdviceBinding[] expectedBindings)
+   {
+      checkExpectedBindingsAndPointcuts(domains, expectedBindings, new BindingsAndPointcutSetup()
+      {
+         public Collection<AdviceBinding> bindings(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getMethodCallBindings();
+         }
+
+         public Collection<Pointcut> pointcuts(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getMethodCallPointcuts();
+         }
+      
+         public Collection<PointcutInfo> pointcutInfos(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getMethodCallPointcutInfos();
+         }
+      });
+   }
+
+
+   private void checkConstructorCallBindingsAndPointcuts(Domains domains, AdviceBinding[] expectedBindings)
+   {
+      checkExpectedBindingsAndPointcuts(domains, expectedBindings, new BindingsAndPointcutSetup()
+      {
+         public Collection<AdviceBinding> bindings(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getConstructorCallBindings();
+         }
+
+         public Collection<Pointcut> pointcuts(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getConstructorCallPointcuts();
+         }
+      
+         public Collection<PointcutInfo> pointcutInfos(ClassifiedBindingAndPointcutCollection collection)
+         {
+            return collection.getConstructorCallPointcutInfos();
+         }
+      });
+   }
+
+   private void checkExpectedBindingsAndPointcuts(Domains domains, AdviceBinding[] expectedBindings, BindingsAndPointcutSetup setup)
+   {
+      ClassifiedBindingAndPointcutCollection coll = domains.getBottomA().getBindingCollection();
+      
+      List<AdviceBinding> bindings = collectionToList(setup.bindings(coll));
+      List<Pointcut> pointcuts = collectionToList(setup.pointcuts(coll));
+      List<PointcutInfo> pointcutInfos = collectionToList(setup.pointcutInfos(coll));
+      
+      assertEquals(expectedBindings.length, bindings.size());
+      assertEquals(expectedBindings.length, pointcuts.size());
+      assertEquals(expectedBindings.length, pointcutInfos.size());
+      
+      for (int i = 0 ; i < expectedBindings.length ; i++)
+      {
+         assertSame(expectedBindings[i], bindings.get(i));
+         assertSame(expectedBindings[i].getPointcut(), pointcuts.get(i));
+         assertSame(expectedBindings[i].getPointcut(), pointcutInfos.get(i).getPointcut());
+      }
+   }
+   
+   private interface BindingsAndPointcutSetup
+   {
+      Collection<AdviceBinding> bindings(ClassifiedBindingAndPointcutCollection collection);
+      Collection<Pointcut> pointcuts(ClassifiedBindingAndPointcutCollection collection);
+      Collection<PointcutInfo> pointcutInfos(ClassifiedBindingAndPointcutCollection collection);
+   }
+   
+   private <T> List<T> collectionToList(Collection<T> collection)
+   {
+      ArrayList<T> list = new ArrayList<T>();
+      for (T entry : collection)
+      {
+         list.add(entry);
+      }
+      return list;
+   }
+   
+   public void testAnnotationIntroductionsAndOverrides() throws Exception
+   {
+      Domains domains = new Domains();
+      try
+      {
+         AnnotationIntroduction intro1 = AnnotationIntroduction.createClassAnnotationIntroduction("POJO", "@org.acme.Blah1", true);
+         AnnotationIntroduction intro2A = AnnotationIntroduction.createClassAnnotationIntroduction("POJO", "@org.acme.Blah2A", true);
+         AnnotationIntroduction intro2B = AnnotationIntroduction.createClassAnnotationIntroduction("POJO", "@org.acme.Blah2B", true);
+         AnnotationIntroduction intro3A = AnnotationIntroduction.createClassAnnotationIntroduction("POJO", "@org.acme.Blah3A", true);
+         AnnotationIntroduction intro3B = AnnotationIntroduction.createClassAnnotationIntroduction("POJO", "@org.acme.Blah3B", true);
+   
+         domains.getMain().addAnnotationIntroduction(intro1);
+         domains.getMain().addAnnotationOverride(intro1);
+         
+         Domain domain = domains.getMiddleA();
+         domain.addAnnotationIntroduction(intro2A);
+         domain.addAnnotationOverride(intro2A);
+         
+         domain = domains.getMiddleB();
+         domain.addAnnotationIntroduction(intro2B);
+         domain.addAnnotationOverride(intro2B);
+         
+         domain = domains.getBottomA();
+         domain.addAnnotationIntroduction(intro3A);
+         domain.addAnnotationOverride(intro3A);
+         
+         domain = domains.getBottomB();
+         domain.addAnnotationIntroduction(intro3B);
+         domain.addAnnotationOverride(intro3B);
+         
+         //Don't bother checking the order, it's irrelevant
+         List<AnnotationIntroduction> intros = domains.getBottomA().getAnnotationIntroductions();
+         assertEquals(5, intros.size());
+         assertTrue(intros.contains(intro1));
+         assertTrue(intros.contains(intro2A));
+         assertTrue(intros.contains(intro2B));
+         assertTrue(intros.contains(intro3A));
+         assertTrue(intros.contains(intro3B));
+   
+         intros = domains.getBottomB().getAnnotationIntroductions();
+         assertEquals(5, intros.size());
+         assertTrue(intros.contains(intro1));
+         assertTrue(intros.contains(intro2A));
+         assertTrue(intros.contains(intro2B));
+         assertTrue(intros.contains(intro3A));
+         assertTrue(intros.contains(intro3B));
+         
+         List<AnnotationIntroduction> overrides = domains.getBottomA().getAnnotationOverrides();
+         assertEquals(5, overrides.size());
+         assertTrue(overrides.contains(intro1));
+         assertTrue(overrides.contains(intro2A));
+         assertTrue(overrides.contains(intro2B));
+         assertTrue(overrides.contains(intro3A));
+         assertTrue(overrides.contains(intro3B));
+   
+         overrides = domains.getBottomB().getAnnotationOverrides();
+         assertEquals(5, overrides.size());
+         assertTrue(overrides.contains(intro1));
+         assertTrue(overrides.contains(intro2A));
+         assertTrue(overrides.contains(intro2B));
+         assertTrue(overrides.contains(intro3A));
+         assertTrue(overrides.contains(intro3B));
+   
+         domains.removePoolAndDomain(domains.getMiddlePoolA());
+   
+         intros = domains.getBottomB().getAnnotationIntroductions();
+         assertEquals(4, intros.size());
+         assertTrue(intros.contains(intro1));
+         assertTrue(intros.contains(intro2B));
+         assertTrue(intros.contains(intro3A));
+         assertTrue(intros.contains(intro3B));
+   
+         overrides = domains.getBottomA().getAnnotationOverrides();
+         assertEquals(4, overrides.size());
+         assertTrue(overrides.contains(intro1));
+         assertTrue(overrides.contains(intro2B));
+         assertTrue(overrides.contains(intro3A));
+         assertTrue(overrides.contains(intro3B));
+         
+         domains.getMiddleB().removeAnnotationIntroduction(intro2B);
+         intros = domains.getBottomB().getAnnotationIntroductions();
+         assertEquals(3, intros.size());
+         assertTrue(intros.contains(intro1));
+         assertTrue(intros.contains(intro3A));
+         assertTrue(intros.contains(intro3B));
+         
+         domains.getMiddleB().removeAnnotationOverride(intro2B);
+         overrides = domains.getBottomA().getAnnotationOverrides();
+         assertEquals(3, overrides.size());
+         assertTrue(overrides.contains(intro1));
+         assertTrue(overrides.contains(intro3A));
+         assertTrue(overrides.contains(intro3B));
+         
+         domains.getMiddleB().addAnnotationIntroduction(intro2B);
+         intros = domains.getBottomB().getAnnotationIntroductions();
+         assertEquals(4, intros.size());
+         assertTrue(intros.contains(intro1));
+         assertTrue(intros.contains(intro2B));
+         assertTrue(intros.contains(intro3A));
+         assertTrue(intros.contains(intro3B));
+         
+         domains.getMiddleB().addAnnotationOverride(intro2B);
+         overrides = domains.getBottomA().getAnnotationOverrides();
+         assertEquals(4, overrides.size());
+         assertTrue(overrides.contains(intro1));
+         assertTrue(overrides.contains(intro2B));
+         assertTrue(overrides.contains(intro3A));
+         assertTrue(overrides.contains(intro3B));
+      }
+      finally
+      {
+         domains.cleanup();
+      }
+   }
+   
+   public void testArrayReplacement() throws Exception
+   {
+      Domains domains = new Domains();
+      try
+      {
+         ArrayReplacement rep1 = new ArrayReplacement("1", "class(POJO1)");
+         ArrayReplacement rep2A = new ArrayReplacement("2A", "class(POJO2A)");
+         ArrayReplacement rep2B = new ArrayReplacement("2B", "class(POJO2B)");
+         ArrayReplacement rep3A = new ArrayReplacement("3A", "class(POJO3)");
+         ArrayReplacement rep3B = new ArrayReplacement("3B", "class(POJO3)");
+         
+         domains.getMain().addArrayReplacement(rep1);
+         domains.getMiddleA().addArrayReplacement(rep2A);
+         domains.getMiddleB().addArrayReplacement(rep2B);
+         domains.getBottomA().addArrayReplacement(rep3A);
+         domains.getBottomB().addArrayReplacement(rep3B);
+         
+         //Don't bother checking the order, it's irrelevant
+         Map<String, ArrayReplacement> reps = domains.getBottomB().getArrayReplacements();
+         assertEquals(5, reps.size());
+         assertEquals(rep1, reps.get("1"));
+         assertEquals(rep2A, reps.get("2A"));
+         assertEquals(rep2B, reps.get("2B"));
+         assertEquals(rep3A, reps.get("3A"));
+         assertEquals(rep3B, reps.get("3B"));
+   
+         
+         domains.getMiddleA().removeArrayReplacement("2A");
+         reps = domains.getBottomA().getArrayReplacements();
+         assertEquals(4, reps.size());
+         assertEquals(rep1, reps.get("1"));
+         assertEquals(rep2B, reps.get("2B"));
+         assertEquals(rep3A, reps.get("3A"));
+         assertEquals(rep3B, reps.get("3B"));
+         domains.getMiddleA().addArrayReplacement(rep2A);
+   
+         domains.getMain().removeArrayReplacement("1");
+         reps = domains.getBottomB().getArrayReplacements();
+         assertEquals(4, reps.size());
+         assertEquals(rep2A, reps.get("2A"));
+         assertEquals(rep2B, reps.get("2B"));
+         assertEquals(rep3A, reps.get("3A"));
+         assertEquals(rep3B, reps.get("3B"));
+   
+         domains.removePoolAndDomain(domains.getMiddlePoolA());
+         reps = domains.getBottomB().getArrayReplacements();
+         assertEquals(3, reps.size());
+         assertEquals(rep2B, reps.get("2B"));
+         assertEquals(rep3A, reps.get("3A"));
+         assertEquals(rep3B, reps.get("3B"));
+      }
+      finally
+      {
+         domains.cleanup();
+      }
+   }
+   
+   public void testInterfaceIntroductions() throws Exception
+   {
+      Domains domains = new Domains();
+      try
+      {
+         InterfaceIntroduction intro1 = new InterfaceIntroduction("1", "POJO", new String[] {"X"});
+         InterfaceIntroduction intro2A = new InterfaceIntroduction("2A", "POJO", new String[] {"X"});
+         InterfaceIntroduction intro2B = new InterfaceIntroduction("2B", "POJO", new String[] {"X"});
+         InterfaceIntroduction intro3A = new InterfaceIntroduction("3A", "POJO", new String[] {"X"});
+         InterfaceIntroduction intro3B = new InterfaceIntroduction("3B", "POJO", new String[] {"X"});
+         
+         domains.getMain().addInterfaceIntroduction(intro1);
+         domains.getMiddleA().addInterfaceIntroduction(intro2A);
+         domains.getMiddleB().addInterfaceIntroduction(intro2B);
+         domains.getBottomA().addInterfaceIntroduction(intro3A);
+         domains.getBottomB().addInterfaceIntroduction(intro3B);
+
+         
+         Map<String, InterfaceIntroduction> intros = domains.getBottomA().getInterfaceIntroductions();
+         assertEquals(5, intros.size());
+         assertEquals(intro1, intros.get("1"));
+         assertEquals(intro2A, intros.get("2A"));
+         assertEquals(intro2B, intros.get("2B"));
+         assertEquals(intro3A, intros.get("3A"));
+         assertEquals(intro3B, intros.get("3B"));
+         
+         domains.getMiddleB().removeInterfaceIntroduction("2B");
+         intros = domains.getBottomB().getInterfaceIntroductions();
+         assertEquals(4, intros.size());
+         assertEquals(intro1, intros.get("1"));
+         assertEquals(intro2A, intros.get("2A"));
+         assertEquals(intro3A, intros.get("3A"));
+         assertEquals(intro3B, intros.get("3B"));
+         domains.getMiddleB().addInterfaceIntroduction(intro2B);
+   
+         domains.removePoolAndDomain(domains.getMiddlePoolA());
+         intros = domains.getBottomB().getInterfaceIntroductions();
+         assertEquals(4, intros.size());
+         assertEquals(intro1, intros.get("1"));
+         assertEquals(intro2B, intros.get("2B"));
+         assertEquals(intro3A, intros.get("3A"));
+         assertEquals(intro3B, intros.get("3B"));
+      }
+      finally
+      {
+         domains.cleanup();
+      }
+   }
+   
+   public void testTypedefs() throws Exception
+   {
+      Domains domains = new Domains();
+      try
+      {
+         Typedef typedef1 = new TypedefExpression("1", "class(POJO)");
+         Typedef typedef2A = new TypedefExpression("2A", "class(POJO)");
+         Typedef typedef2B = new TypedefExpression("2B", "class(POJO)");
+         Typedef typedef3A = new TypedefExpression("3A", "class(POJO)");
+         Typedef typedef3B = new TypedefExpression("3B", "class(POJO)");
+   
+         domains.getMain().addTypedef(typedef1);
+         domains.getMiddleA().addTypedef(typedef2A);
+         domains.getMiddleB().addTypedef(typedef2B);
+         domains.getBottomA().addTypedef(typedef3A);
+         domains.getBottomB().addTypedef(typedef3B);
+         
+         Map<String, Typedef> typedefs = domains.getBottomA().getTypedefs();
+         assertEquals(5, typedefs.size());
+         assertEquals(typedef1, typedefs.get("1"));
+         assertEquals(typedef2A, typedefs.get("2A"));
+         assertEquals(typedef2B, typedefs.get("2B"));
+         assertEquals(typedef3A, typedefs.get("3A"));
+         assertEquals(typedef3B, typedefs.get("3B"));
+         
+         assertEquals(typedef1, domains.getMain().getTypedef("1"));
+         assertEquals(typedef1, domains.getMiddleA().getTypedef("1"));
+         assertEquals(typedef2A, domains.getMiddleA().getTypedef("2A"));
+         assertEquals(typedef2B, domains.getMiddleA().getTypedef("2B"));
+         assertEquals(typedef2A, domains.getMiddleB().getTypedef("2A"));
+         assertEquals(typedef2B, domains.getMiddleB().getTypedef("2B"));
+         assertNull(domains.getMiddleA().getTypedef("3A"));
+         assertNull(domains.getMiddleB().getTypedef("3B"));
+         assertEquals(typedef1, domains.getBottomA().getTypedef("1"));
+         assertEquals(typedef2A, domains.getBottomA().getTypedef("2A"));
+         assertEquals(typedef2B, domains.getBottomA().getTypedef("2B"));
+         assertEquals(typedef3A, domains.getBottomA().getTypedef("3A"));
+         assertEquals(typedef3B, domains.getBottomA().getTypedef("3B"));
+         assertEquals(typedef1, domains.getBottomB().getTypedef("1"));
+         assertEquals(typedef2A, domains.getBottomB().getTypedef("2A"));
+         assertEquals(typedef2B, domains.getBottomB().getTypedef("2B"));
+         assertEquals(typedef3A, domains.getBottomB().getTypedef("3A"));
+         assertEquals(typedef3B, domains.getBottomB().getTypedef("3B"));
+         
+         domains.getMiddleA().removeTypedef("2A");
+         typedefs = domains.getBottomA().getTypedefs();
+         assertEquals(4, typedefs.size());
+         assertEquals(typedef1, typedefs.get("1"));
+         assertEquals(typedef2B, typedefs.get("2B"));
+         assertEquals(typedef3A, typedefs.get("3A"));
+         assertEquals(typedef3B, typedefs.get("3B"));
+   
+         assertEquals(typedef1, domains.getMain().getTypedef("1"));
+         assertEquals(typedef1, domains.getBottomB().getTypedef("1"));
+         assertNull(domains.getMiddleA().getTypedef("2A"));
+         assertEquals(typedef2B, domains.getMiddleA().getTypedef("2B"));
+         assertNull(domains.getMiddleB().getTypedef("2A"));
+         assertEquals(typedef2B, domains.getMiddleB().getTypedef("2B"));
+         assertNull(domains.getMiddleA().getTypedef("3A"));
+         assertNull(domains.getMiddleB().getTypedef("3B"));
+         assertEquals(typedef1, domains.getBottomA().getTypedef("1"));
+         assertNull(domains.getBottomA().getTypedef("2A"));
+         assertEquals(typedef2B, domains.getBottomA().getTypedef("2B"));
+         assertEquals(typedef3A, domains.getBottomA().getTypedef("3A"));
+         assertEquals(typedef3B, domains.getBottomA().getTypedef("3B"));
+         assertEquals(typedef1, domains.getBottomB().getTypedef("1"));
+         assertNull(domains.getBottomB().getTypedef("2A"));
+         assertEquals(typedef2B, domains.getBottomB().getTypedef("2B"));
+         assertEquals(typedef3A, domains.getBottomB().getTypedef("3A"));
+         assertEquals(typedef3B, domains.getBottomB().getTypedef("3B"));
+         domains.getMiddleA().addTypedef(typedef2A);
+   
+         domains.removePoolAndDomain(domains.getMiddlePoolB());
+         typedefs = domains.getBottomA().getTypedefs();
+         assertEquals(4, typedefs.size());
+         assertEquals(typedef1, typedefs.get("1"));
+         assertEquals(typedef2A, typedefs.get("2A"));
+         assertEquals(typedef3A, typedefs.get("3A"));
+         assertEquals(typedef3B, typedefs.get("3B"));
+         
+         assertEquals(typedef1, domains.getMain().getTypedef("1"));
+         assertEquals(typedef1, domains.getBottomA().getTypedef("1"));
+         assertEquals(typedef2A, domains.getMiddleA().getTypedef("2A"));
+         assertNull(domains.getMiddleA().getTypedef("2B"));
+         assertNull(domains.getMiddleA().getTypedef("3A"));
+         assertEquals(typedef1, domains.getBottomA().getTypedef("1"));
+         assertEquals(typedef2A, domains.getBottomA().getTypedef("2A"));
+         assertNull(domains.getBottomA().getTypedef("2B"));
+         assertEquals(typedef3A, domains.getBottomA().getTypedef("3A"));
+         assertEquals(typedef3B, domains.getBottomA().getTypedef("3B"));
+         assertEquals(typedef1, domains.getBottomB().getTypedef("1"));
+         assertEquals(typedef2A, domains.getBottomB().getTypedef("2A"));
+         assertNull(domains.getBottomB().getTypedef("2B"));
+         assertEquals(typedef3A, domains.getBottomB().getTypedef("3A"));
+         assertEquals(typedef3B, domains.getBottomB().getTypedef("3B"));
+      }
+      finally
+      {
+         domains.cleanup();
+      }
+   }
+   
+   public void testInterceptorStack() throws Exception
+   {
+      Domains domains = new Domains();
+      try
+      {
+         AdviceStack stack1 = new AdviceStack("1", null);
+         AdviceStack stack2A = new AdviceStack("2A", null);
+         AdviceStack stack2B = new AdviceStack("2B", null);
+         AdviceStack stack3A = new AdviceStack("3A", null);
+         AdviceStack stack3B = new AdviceStack("3B", null);
+   
+         domains.getMain().addAdviceStack(stack1);
+         domains.getMiddleA().addAdviceStack(stack2A);
+         domains.getMiddleB().addAdviceStack(stack2B);
+         domains.getBottomA().addAdviceStack(stack3A);
+         domains.getBottomB().addAdviceStack(stack3B);
+         
+         assertEquals(stack1, domains.getMain().getAdviceStack("1"));
+         assertNull(domains.getMain().getAdviceStack("2A"));
+         assertNull(domains.getMain().getAdviceStack("3A"));
+         assertEquals(stack1, domains.getMiddleA().getAdviceStack("1"));
+         assertEquals(stack2A, domains.getMiddleA().getAdviceStack("2A"));
+         assertEquals(stack2B, domains.getMiddleA().getAdviceStack("2B"));
+         assertEquals(stack1, domains.getMiddleB().getAdviceStack("1"));
+         assertEquals(stack2A, domains.getMiddleB().getAdviceStack("2A"));
+         assertEquals(stack2B, domains.getMiddleB().getAdviceStack("2B"));
+         assertNull(domains.getMiddleA().getAdviceStack("3A"));
+         assertEquals(stack1, domains.getBottomA().getAdviceStack("1"));
+         assertEquals(stack2A, domains.getBottomA().getAdviceStack("2A"));
+         assertEquals(stack2B, domains.getBottomA().getAdviceStack("2B"));
+         assertEquals(stack3A, domains.getBottomA().getAdviceStack("3A"));
+         assertEquals(stack3B, domains.getBottomA().getAdviceStack("3B"));
+         assertEquals(stack1, domains.getBottomB().getAdviceStack("1"));
+         assertEquals(stack2A, domains.getBottomB().getAdviceStack("2A"));
+         assertEquals(stack2B, domains.getBottomB().getAdviceStack("2B"));
+         assertEquals(stack3A, domains.getBottomB().getAdviceStack("3A"));
+         assertEquals(stack3B, domains.getBottomB().getAdviceStack("3B"));
+
+         Map<String, AdviceStack> stacks = domains.getBottomA().getInterceptorStacks();
+         assertEquals(5, stacks.size());
+         assertEquals(stack1, stacks.get("1"));
+         assertEquals(stack2A, stacks.get("2A"));
+         assertEquals(stack2B, stacks.get("2B"));
+         assertEquals(stack3A, stacks.get("3A"));
+         assertEquals(stack3B, stacks.get("3B"));
+         stacks = domains.getBottomB().getInterceptorStacks();
+         assertEquals(5, stacks.size());
+         assertEquals(stack1, stacks.get("1"));
+         assertEquals(stack2A, stacks.get("2A"));
+         assertEquals(stack2B, stacks.get("2B"));
+         assertEquals(stack3A, stacks.get("3A"));
+         assertEquals(stack3B, stacks.get("3B"));
+         
+         domains.getMiddleA().removeInterceptorStack("2A");
+         assertEquals(stack1, domains.getMain().getAdviceStack("1"));
+         assertNull(domains.getMain().getAdviceStack("2A"));
+         assertNull(domains.getMain().getAdviceStack("3A"));
+         assertEquals(stack1, domains.getMiddleA().getAdviceStack("1"));
+         assertNull(domains.getMiddleA().getAdviceStack("2A"));
+         assertNull(domains.getMiddleA().getAdviceStack("3A"));
+         assertEquals(stack1, domains.getBottomA().getAdviceStack("1"));
+         assertNull(domains.getBottomA().getAdviceStack("2A"));
+         assertEquals(stack3A, domains.getBottomA().getAdviceStack("3A"));
+         stacks = domains.getBottomA().getInterceptorStacks();
+         assertEquals(4, stacks.size());
+         assertEquals(stack1, stacks.get("1"));
+         assertEquals(stack2B, stacks.get("2B"));
+         assertEquals(stack3A, stacks.get("3A"));
+         assertEquals(stack3B, stacks.get("3B"));
+         domains.getMiddleA().addAdviceStack(stack2A);
+         
+         domains.removePoolAndDomain(domains.getMiddlePoolB());
+         assertEquals(stack1, domains.getMain().getAdviceStack("1"));
+         assertNull(domains.getMain().getAdviceStack("2B"));
+         assertNull(domains.getMain().getAdviceStack("3A"));
+         assertEquals(stack1, domains.getMiddleA().getAdviceStack("1"));
+         assertNull(domains.getMiddleA().getAdviceStack("2B"));
+         assertNull(domains.getMiddleA().getAdviceStack("3A"));
+         assertEquals(stack1, domains.getBottomA().getAdviceStack("1"));
+         assertEquals(stack2A, domains.getBottomA().getAdviceStack("2A"));
+         assertEquals(stack3A, domains.getBottomA().getAdviceStack("3A"));
+         stacks = domains.getBottomA().getInterceptorStacks();
+         assertEquals(4, stacks.size());
+         assertEquals(stack1, stacks.get("1"));
+         assertEquals(stack2A, stacks.get("2A"));
+         assertEquals(stack3A, stacks.get("3A"));
+         assertEquals(stack3B, stacks.get("3B"));
+         domains.getMiddleA().addAdviceStack(stack2A);
+      }
+      finally
+      {
+         domains.cleanup();
+      }
+   }
+   
+   public void testClassMetaDataLoaders() throws Exception
+   {
+      Domains domains = new Domains();
+      try
+      {
+         SimpleClassMetaDataLoader simple1 = new SimpleClassMetaDataLoader();
+         SimpleClassMetaDataLoader simple2A = new SimpleClassMetaDataLoader();
+         SimpleClassMetaDataLoader simple2B = new SimpleClassMetaDataLoader();
+         SimpleClassMetaDataLoader simple3A = new SimpleClassMetaDataLoader();
+         SimpleClassMetaDataLoader simple3B = new SimpleClassMetaDataLoader();
+         
+         domains.getMain().addClassMetaDataLoader("1", simple1);
+         domains.getMiddleA().addClassMetaDataLoader("2A", simple2A);
+         domains.getMiddleB().addClassMetaDataLoader("2B", simple2B);
+         domains.getBottomA().addClassMetaDataLoader("3A", simple3A);
+         domains.getBottomB().addClassMetaDataLoader("3B", simple3B);
+   
+         assertEquals(simple1, domains.getBottomA().getClassMetaDataLoaders().get("1"));
+         assertEquals(simple2A, domains.getBottomA().getClassMetaDataLoaders().get("2A"));
+         assertEquals(simple2B, domains.getBottomA().getClassMetaDataLoaders().get("2B"));
+         assertEquals(simple3A, domains.getBottomA().getClassMetaDataLoaders().get("3A"));
+         assertEquals(simple3B, domains.getBottomA().getClassMetaDataLoaders().get("3B"));
+         assertEquals(simple1, domains.getMiddleA().getClassMetaDataLoaders().get("1"));
+         assertEquals(simple2A, domains.getMiddleA().getClassMetaDataLoaders().get("2A"));
+         assertEquals(simple2B, domains.getMiddleA().getClassMetaDataLoaders().get("2B"));
+         assertNull(domains.getMiddleA().getClassMetaDataLoaders().get("3A"));
+         assertEquals(simple1, domains.getMain().getClassMetaDataLoaders().get("1"));
+         assertNull(domains.getMain().getClassMetaDataLoaders().get("2A"));
+         assertNull(domains.getMain().getClassMetaDataLoaders().get("2B"));
+         assertNull(domains.getMain().getClassMetaDataLoaders().get("3A"));
+         assertNull(domains.getMain().getClassMetaDataLoaders().get("3B"));
+         
+         domains.getMiddleB().removeClassMetaDataLoader("2B");
+         assertEquals(simple1, domains.getBottomA().getClassMetaDataLoaders().get("1"));
+         assertEquals(simple2A, domains.getBottomA().getClassMetaDataLoaders().get("2A"));
+         assertNull(domains.getBottomA().getClassMetaDataLoaders().get("2B"));
+         assertEquals(simple3A, domains.getBottomA().getClassMetaDataLoaders().get("3A"));
+         assertEquals(simple3B, domains.getBottomA().getClassMetaDataLoaders().get("3B"));
+         assertEquals(simple1, domains.getMiddleA().getClassMetaDataLoaders().get("1"));
+         assertEquals(simple2A, domains.getMiddleA().getClassMetaDataLoaders().get("2A"));
+         assertNull(domains.getMiddleA().getClassMetaDataLoaders().get("2B"));
+         assertNull(domains.getMiddleA().getClassMetaDataLoaders().get("3A"));
+         assertEquals(simple1, domains.getMain().getClassMetaDataLoaders().get("1"));
+         assertNull(domains.getMain().getClassMetaDataLoaders().get("2A"));
+         assertNull(domains.getMain().getClassMetaDataLoaders().get("2B"));
+         assertNull(domains.getMain().getClassMetaDataLoaders().get("3A"));
+         assertNull(domains.getMain().getClassMetaDataLoaders().get("3B"));
+         domains.getMiddleB().addClassMetaDataLoader("2B", simple2B);
+         
+         domains.removePoolAndDomain(domains.getMiddlePoolA());
+         assertEquals(simple1, domains.getBottomA().getClassMetaDataLoaders().get("1"));
+         assertNull(domains.getBottomA().getClassMetaDataLoaders().get("2A"));
+         assertEquals(simple2B, domains.getBottomA().getClassMetaDataLoaders().get("2B"));
+         assertEquals(simple3A, domains.getBottomA().getClassMetaDataLoaders().get("3A"));
+         assertEquals(simple3B, domains.getBottomA().getClassMetaDataLoaders().get("3B"));
+         assertEquals(simple1, domains.getMiddleB().getClassMetaDataLoaders().get("1"));
+         assertNull(domains.getMiddleB().getClassMetaDataLoaders().get("2A"));
+         assertEquals(simple2B, domains.getMiddleB().getClassMetaDataLoaders().get("2B"));
+         assertNull(domains.getMiddleB().getClassMetaDataLoaders().get("3A"));
+         assertEquals(simple1, domains.getMain().getClassMetaDataLoaders().get("1"));
+         assertNull(domains.getMain().getClassMetaDataLoaders().get("2A"));
+         assertNull(domains.getMain().getClassMetaDataLoaders().get("2B"));
+         assertNull(domains.getMain().getClassMetaDataLoaders().get("3A"));
+         assertNull(domains.getMain().getClassMetaDataLoaders().get("3B"));
+         domains.getMiddleB().addClassMetaDataLoader("2B", simple2B);
+      }
+      finally
+      {
+         domains.cleanup();
+      }
+   }
+   
+   public void testCflowStacks() throws Exception
+   {
+      Domains domains = new Domains();
+      try
+      {
+         CFlowStack stack1 = new CFlowStack("1");
+         CFlowStack stack2A = new CFlowStack("2A");
+         CFlowStack stack2B = new CFlowStack("2B");
+         CFlowStack stack3A = new CFlowStack("3A");
+         CFlowStack stack3B = new CFlowStack("3B");
+   
+         domains.getMain().addCFlowStack(stack1);
+         domains.getMiddleA().addCFlowStack(stack2A);
+         domains.getMiddleB().addCFlowStack(stack2B);
+         domains.getBottomA().addCFlowStack(stack3A);
+         domains.getBottomB().addCFlowStack(stack3B);
+   
+         assertEquals(stack1, domains.getMain().getCflowStacks().get("1"));
+         assertNull(domains.getMain().getCflowStacks().get("2A"));
+         assertNull(domains.getMain().getCflowStacks().get("3B"));
+         assertEquals(stack1, domains.getMain().getCFlowStack("1"));
+         assertNull(domains.getMain().getCFlowStack("2B"));
+         assertNull(domains.getMain().getCFlowStack("3A"));
+         assertEquals(stack2A, domains.getMiddleA().getCflowStacks().get("2A"));
+         assertEquals(stack2B, domains.getMiddleA().getCflowStacks().get("2B"));
+         assertEquals(stack2A, domains.getMiddleB().getCflowStacks().get("2A"));
+         assertEquals(stack2B, domains.getMiddleB().getCflowStacks().get("2B"));
+         assertNull(domains.getMiddleA().getCflowStacks().get("3A"));
+         assertNull(domains.getMiddleB().getCflowStacks().get("3A"));
+         assertEquals(stack1, domains.getMiddleA().getCFlowStack("1"));
+         assertEquals(stack2A, domains.getMiddleA().getCFlowStack("2A"));
+         assertEquals(stack2B, domains.getMiddleA().getCFlowStack("2B"));
+         assertEquals(stack2A, domains.getMiddleB().getCFlowStack("2A"));
+         assertEquals(stack2B, domains.getMiddleB().getCFlowStack("2B"));
+         assertNull(domains.getMiddleA().getCFlowStack("3A"));
+         assertNull(domains.getMiddleA().getCFlowStack("3B"));
+         assertNull(domains.getMiddleB().getCFlowStack("3A"));
+         assertNull(domains.getMiddleB().getCFlowStack("3B"));
+         assertEquals(stack1, domains.getBottomA().getCflowStacks().get("1"));
+         assertEquals(stack2A, domains.getBottomA().getCflowStacks().get("2A"));
+         assertEquals(stack2B, domains.getBottomA().getCflowStacks().get("2B"));
+         assertEquals(stack3A, domains.getBottomA().getCflowStacks().get("3A"));
+         assertEquals(stack3B, domains.getBottomA().getCflowStacks().get("3B"));
+         assertEquals(stack1, domains.getBottomB().getCflowStacks().get("1"));
+         assertEquals(stack2A, domains.getBottomB().getCflowStacks().get("2A"));
+         assertEquals(stack2B, domains.getBottomB().getCflowStacks().get("2B"));
+         assertEquals(stack3A, domains.getBottomB().getCflowStacks().get("3A"));
+         assertEquals(stack3B, domains.getBottomB().getCflowStacks().get("3B"));
+         
+         domains.getMiddleA().removeCFlowStack("2A");
+         assertNull(domains.getMiddleA().getCflowStacks().get("2A"));
+         assertEquals(stack2B, domains.getMiddleA().getCflowStacks().get("2B"));
+         assertNull(domains.getMiddleB().getCflowStacks().get("2A"));
+         assertEquals(stack2B, domains.getMiddleB().getCflowStacks().get("2B"));
+         assertNull(domains.getMiddleA().getCflowStacks().get("3A"));
+         assertNull(domains.getMiddleB().getCflowStacks().get("3A"));
+         assertEquals(stack1, domains.getMiddleA().getCFlowStack("1"));
+         assertNull(domains.getMiddleA().getCFlowStack("2A"));
+         assertEquals(stack2B, domains.getMiddleA().getCFlowStack("2B"));
+         assertNull(domains.getMiddleB().getCFlowStack("2A"));
+         assertEquals(stack2B, domains.getMiddleB().getCFlowStack("2B"));
+         assertNull(domains.getMiddleA().getCFlowStack("3A"));
+         assertNull(domains.getMiddleA().getCFlowStack("3B"));
+         assertNull(domains.getMiddleB().getCFlowStack("3A"));
+         assertNull(domains.getMiddleB().getCFlowStack("3B"));
+         assertEquals(stack1, domains.getBottomA().getCflowStacks().get("1"));
+         assertNull(domains.getBottomA().getCflowStacks().get("2A"));
+         assertEquals(stack2B, domains.getBottomA().getCflowStacks().get("2B"));
+         assertEquals(stack3A, domains.getBottomA().getCflowStacks().get("3A"));
+         assertEquals(stack3B, domains.getBottomA().getCflowStacks().get("3B"));
+         assertEquals(stack1, domains.getBottomB().getCflowStacks().get("1"));
+         assertNull(domains.getBottomB().getCflowStacks().get("2A"));
+         assertEquals(stack2B, domains.getBottomB().getCflowStacks().get("2B"));
+         assertEquals(stack3A, domains.getBottomB().getCflowStacks().get("3A"));
+         assertEquals(stack3B, domains.getBottomB().getCflowStacks().get("3B"));
+         domains.getMiddleA().addCFlowStack(stack2A);
+   
+         domains.removePoolAndDomain(domains.getMiddlePoolB());
+         assertEquals(stack2A, domains.getMiddleA().getCflowStacks().get("2A"));
+         assertNull(domains.getMiddleA().getCflowStacks().get("2B"));
+         assertNull(domains.getMiddleA().getCflowStacks().get("3A"));
+         assertEquals(stack1, domains.getMiddleA().getCFlowStack("1"));
+         assertEquals(stack2A, domains.getMiddleA().getCFlowStack("2A"));
+         assertNull(domains.getMiddleA().getCFlowStack("2B"));
+         assertNull(domains.getMiddleA().getCFlowStack("3A"));
+         assertNull(domains.getMiddleA().getCFlowStack("3B"));
+         assertEquals(stack1, domains.getBottomA().getCflowStacks().get("1"));
+         assertEquals(stack2A, domains.getBottomA().getCflowStacks().get("2A"));
+         assertNull(domains.getBottomA().getCflowStacks().get("2B"));
+         assertEquals(stack3A, domains.getBottomA().getCflowStacks().get("3A"));
+         assertEquals(stack3B, domains.getBottomA().getCflowStacks().get("3B"));
+         assertEquals(stack1, domains.getBottomB().getCflowStacks().get("1"));
+         assertEquals(stack2A, domains.getBottomB().getCflowStacks().get("2A"));
+         assertNull(domains.getBottomB().getCflowStacks().get("2B"));
+         assertEquals(stack3A, domains.getBottomB().getCflowStacks().get("3A"));
+         assertEquals(stack3B, domains.getBottomB().getCflowStacks().get("3B"));
+      }
+      finally
+      {
+         domains.cleanup();
+      }
+   }
+   
+   public void testDynamicCflows() throws Exception
+   {
+      Domains domains = new Domains();
+      try
+      {
+         DynamicCFlowDefinition stack1 = new DynamicCFlowDefinition(null, MockDynamicCFlow1.class.getName(), "1");
+         DynamicCFlowDefinition stack2A = new DynamicCFlowDefinition(null, MockDynamicCFlow2A.class.getName(), "2A");
+         DynamicCFlowDefinition stack2B = new DynamicCFlowDefinition(null, MockDynamicCFlow2B.class.getName(), "2B");
+         DynamicCFlowDefinition stack3A = new DynamicCFlowDefinition(null, MockDynamicCFlow3A.class.getName(), "3A");
+         DynamicCFlowDefinition stack3B = new DynamicCFlowDefinition(null, MockDynamicCFlow3B.class.getName(), "3B");
+   
+         domains.getMain().addDynamicCFlow("1", stack1);
+         domains.getMiddleA().addDynamicCFlow("2A", stack2A);
+         domains.getMiddleB().addDynamicCFlow("2B", stack2B);
+         domains.getBottomA().addDynamicCFlow("3A", stack3A);
+         domains.getBottomB().addDynamicCFlow("3B", stack3B);
+   
+         assertEquals(MockDynamicCFlow1.class, domains.getMain().getDynamicCFlow("1").getClass());
+         assertNull(domains.getMain().getDynamicCFlow("2A"));
+         assertNull(domains.getMain().getDynamicCFlow("3A"));
+         assertEquals(stack1, domains.getMain().getDynamicCFlows().get("1"));
+         assertNull(domains.getMain().getDynamicCFlows().get("2A"));
+         assertNull(domains.getMain().getDynamicCFlows().get("3A"));
+         assertEquals(MockDynamicCFlow1.class, domains.getMiddleA().getDynamicCFlow("1").getClass());
+         assertEquals(MockDynamicCFlow2A.class, domains.getMiddleA().getDynamicCFlow("2A").getClass());
+         assertEquals(MockDynamicCFlow2B.class, domains.getMiddleA().getDynamicCFlow("2B").getClass());
+         assertEquals(MockDynamicCFlow1.class, domains.getMiddleB().getDynamicCFlow("1").getClass());
+         assertEquals(MockDynamicCFlow2A.class, domains.getMiddleB().getDynamicCFlow("2A").getClass());
+         assertEquals(MockDynamicCFlow2B.class, domains.getMiddleB().getDynamicCFlow("2B").getClass());
+         assertNull(domains.getMiddleA().getDynamicCFlow("3A"));
+         assertNull(domains.getMiddleA().getDynamicCFlow("3B"));
+         assertNull(domains.getMiddleB().getDynamicCFlow("3A"));
+         assertNull(domains.getMiddleB().getDynamicCFlow("3B"));
+         assertEquals(stack1, domains.getMiddleA().getDynamicCFlows().get("1"));
+         assertEquals(stack2A, domains.getMiddleA().getDynamicCFlows().get("2A"));
+         assertEquals(stack2B, domains.getMiddleA().getDynamicCFlows().get("2B"));
+         assertEquals(stack1, domains.getMiddleB().getDynamicCFlows().get("1"));
+         assertEquals(stack2A, domains.getMiddleB().getDynamicCFlows().get("2A"));
+         assertEquals(stack2B, domains.getMiddleB().getDynamicCFlows().get("2B"));
+         assertNull(domains.getMiddleA().getDynamicCFlows().get("3A"));
+         assertNull(domains.getMiddleA().getDynamicCFlows().get("3B"));
+         assertNull(domains.getMiddleB().getDynamicCFlows().get("3A"));
+         assertNull(domains.getMiddleB().getDynamicCFlows().get("3B"));
+         assertEquals(MockDynamicCFlow1.class, domains.getBottomA().getDynamicCFlow("1").getClass());
+         assertEquals(MockDynamicCFlow2A.class, domains.getBottomA().getDynamicCFlow("2A").getClass());
+         assertEquals(MockDynamicCFlow2B.class, domains.getBottomA().getDynamicCFlow("2B").getClass());
+         assertEquals(MockDynamicCFlow3A.class, domains.getBottomA().getDynamicCFlow("3A").getClass());
+         assertEquals(MockDynamicCFlow3B.class, domains.getBottomA().getDynamicCFlow("3B").getClass());
+         assertEquals(MockDynamicCFlow1.class, domains.getBottomB().getDynamicCFlow("1").getClass());
+         assertEquals(MockDynamicCFlow2A.class, domains.getBottomB().getDynamicCFlow("2A").getClass());
+         assertEquals(MockDynamicCFlow2B.class, domains.getBottomB().getDynamicCFlow("2B").getClass());
+         assertEquals(MockDynamicCFlow3A.class, domains.getBottomB().getDynamicCFlow("3A").getClass());
+         assertEquals(MockDynamicCFlow3B.class, domains.getBottomB().getDynamicCFlow("3B").getClass());
+         assertEquals(stack1, domains.getBottomA().getDynamicCFlows().get("1"));
+         assertEquals(stack2A, domains.getBottomA().getDynamicCFlows().get("2A"));
+         assertEquals(stack2B, domains.getBottomA().getDynamicCFlows().get("2B"));
+         assertEquals(stack3A, domains.getBottomA().getDynamicCFlows().get("3A"));
+         assertEquals(stack3B, domains.getBottomA().getDynamicCFlows().get("3B"));
+         assertEquals(stack1, domains.getBottomB().getDynamicCFlows().get("1"));
+         assertEquals(stack2A, domains.getBottomB().getDynamicCFlows().get("2A"));
+         assertEquals(stack2B, domains.getBottomB().getDynamicCFlows().get("2B"));
+         assertEquals(stack3A, domains.getBottomB().getDynamicCFlows().get("3A"));
+         assertEquals(stack3B, domains.getBottomB().getDynamicCFlows().get("3B"));
+   
+         domains.getMiddleB().removeDynamicCFlow("2B");
+         assertEquals(MockDynamicCFlow1.class, domains.getBottomA().getDynamicCFlow("1").getClass());
+         assertEquals(MockDynamicCFlow2A.class, domains.getBottomA().getDynamicCFlow("2A").getClass());
+         assertNull(domains.getBottomA().getDynamicCFlow("2B"));
+         assertEquals(MockDynamicCFlow3A.class, domains.getBottomA().getDynamicCFlow("3A").getClass());
+         assertEquals(MockDynamicCFlow3B.class, domains.getBottomA().getDynamicCFlow("3B").getClass());
+         assertEquals(MockDynamicCFlow1.class, domains.getBottomB().getDynamicCFlow("1").getClass());
+         assertEquals(MockDynamicCFlow2A.class, domains.getBottomB().getDynamicCFlow("2A").getClass());
+         assertNull(domains.getBottomB().getDynamicCFlow("2B"));
+         assertEquals(MockDynamicCFlow3A.class, domains.getBottomB().getDynamicCFlow("3A").getClass());
+         assertEquals(MockDynamicCFlow3B.class, domains.getBottomB().getDynamicCFlow("3B").getClass());
+         assertEquals(stack1, domains.getBottomA().getDynamicCFlows().get("1"));
+         assertEquals(stack2A, domains.getBottomA().getDynamicCFlows().get("2A"));
+         assertNull(domains.getBottomA().getDynamicCFlows().get("2B"));
+         assertEquals(stack3A, domains.getBottomA().getDynamicCFlows().get("3A"));
+         assertEquals(stack3B, domains.getBottomA().getDynamicCFlows().get("3B"));
+         assertEquals(stack1, domains.getBottomB().getDynamicCFlows().get("1"));
+         assertEquals(stack2A, domains.getBottomB().getDynamicCFlows().get("2A"));
+         assertNull(domains.getBottomB().getDynamicCFlows().get("2B"));
+         assertEquals(stack3A, domains.getBottomB().getDynamicCFlows().get("3A"));
+         assertEquals(stack3B, domains.getBottomB().getDynamicCFlows().get("3B"));
+         domains.getMiddleB().addDynamicCFlow("2B", stack2B);
+         
+         domains.removePoolAndDomain(domains.getMiddlePoolA());
+         assertEquals(MockDynamicCFlow1.class, domains.getBottomA().getDynamicCFlow("1").getClass());
+         assertNull(domains.getBottomA().getDynamicCFlow("2A"));
+         assertEquals(MockDynamicCFlow2B.class, domains.getBottomA().getDynamicCFlow("2B").getClass());
+         assertEquals(MockDynamicCFlow3A.class, domains.getBottomA().getDynamicCFlow("3A").getClass());
+         assertEquals(MockDynamicCFlow3B.class, domains.getBottomA().getDynamicCFlow("3B").getClass());
+         assertEquals(MockDynamicCFlow1.class, domains.getBottomB().getDynamicCFlow("1").getClass());
+         assertNull(domains.getBottomB().getDynamicCFlow("2A"));
+         assertEquals(MockDynamicCFlow2B.class, domains.getBottomB().getDynamicCFlow("2B").getClass());
+         assertEquals(MockDynamicCFlow3A.class, domains.getBottomB().getDynamicCFlow("3A").getClass());
+         assertEquals(MockDynamicCFlow3B.class, domains.getBottomB().getDynamicCFlow("3B").getClass());
+         assertEquals(stack1, domains.getBottomA().getDynamicCFlows().get("1"));
+         assertNull(domains.getBottomA().getDynamicCFlows().get("2A"));
+         assertEquals(stack2B, domains.getBottomA().getDynamicCFlows().get("2B"));
+         assertEquals(stack3A, domains.getBottomA().getDynamicCFlows().get("3A"));
+         assertEquals(stack3B, domains.getBottomA().getDynamicCFlows().get("3B"));
+         assertEquals(stack1, domains.getBottomB().getDynamicCFlows().get("1"));
+         assertNull(domains.getBottomB().getDynamicCFlows().get("2A"));
+         assertEquals(stack2B, domains.getBottomB().getDynamicCFlows().get("2B"));
+         assertEquals(stack3A, domains.getBottomB().getDynamicCFlows().get("3A"));
+         assertEquals(stack3B, domains.getBottomB().getDynamicCFlows().get("3B"));
+         domains.getMiddleB().addDynamicCFlow("2B", stack2B);
+      }
+      finally
+      {
+         domains.cleanup();
+      }
+   }
+
+   public void testPrecedenceDefs() throws Exception
+   {
+      Domains domains = new Domains();
+      try
+      {
+         PrecedenceDef def1 = new PrecedenceDef("1", null); 
+         PrecedenceDef def2A = new PrecedenceDef("2A", null); 
+         PrecedenceDef def2B = new PrecedenceDef("2B", null);
+         PrecedenceDef def3A = new PrecedenceDef("3A", null); 
+         PrecedenceDef def3B = new PrecedenceDef("3B", null);
+         
+         domains.getMain().addPrecedence(def1);
+         domains.getMiddleA().addPrecedence(def2A);
+         domains.getMiddleB().addPrecedence(def2B);
+         domains.getBottomA().addPrecedence(def3A);
+         domains.getBottomA().addPrecedence(def3B);
+         
+         Map<String, PrecedenceDef> defs = domains.getBottomA().getPrecedenceDefs();
+         assertEquals(5, defs.size());
+         assertEquals(def1, defs.get("1"));
+         assertEquals(def2A, defs.get("2A"));
+         assertEquals(def2B, defs.get("2B"));
+         assertEquals(def3A, defs.get("3A"));
+         assertEquals(def3B, defs.get("3B"));
+         
+         domains.getMiddleA().removePrecedence("2A");
+         defs = domains.getBottomB().getPrecedenceDefs();
+         assertEquals(4, defs.size());
+         assertEquals(def1, defs.get("1"));
+         assertEquals(def2B, defs.get("2B"));
+         assertEquals(def3A, defs.get("3A"));
+         assertEquals(def3B, defs.get("3B"));
+         domains.getMiddleA().addPrecedence(def2A);
+   
+         domains.getMain().removePrecedence("1");
+         defs = domains.getBottomB().getPrecedenceDefs();
+         assertEquals(4, defs.size());
+         assertEquals(def2A, defs.get("2A"));
+         assertEquals(def2B, defs.get("2B"));
+         assertEquals(def3A, defs.get("3A"));
+         assertEquals(def3B, defs.get("3B"));
+   
+         domains.removePoolAndDomain(domains.getMiddlePoolB());
+         defs = domains.getBottomB().getPrecedenceDefs();
+         assertEquals(3, defs.size());
+         assertEquals(def2A, defs.get("2A"));
+         assertEquals(def3A, defs.get("3A"));
+         assertEquals(def3B, defs.get("3B"));
+      }
+      finally
+      {
+         domains.cleanup();
+      }
+   }
+   
+   public void testClassMetaData() throws Exception
+   {
+      Domains domains = new Domains();
+      try
+      {
+         ClassMetaDataBinding binding1 = new SimpleClassMetaDataBinding(new SimpleClassMetaDataLoader(), "1", "1", "1");
+         ClassMetaDataBinding binding2A = new SimpleClassMetaDataBinding(new SimpleClassMetaDataLoader(), "2A", "2A", "2A");
+         ClassMetaDataBinding binding2B = new SimpleClassMetaDataBinding(new SimpleClassMetaDataLoader(), "2B", "2B", "2B");
+         ClassMetaDataBinding binding3A = new SimpleClassMetaDataBinding(new SimpleClassMetaDataLoader(), "3A", "3A", "3A");
+         ClassMetaDataBinding binding3B = new SimpleClassMetaDataBinding(new SimpleClassMetaDataLoader(), "3B", "3B", "3B");
+   
+         
+         domains.getMain().addClassMetaData(binding1);
+         domains.getMiddleA().addClassMetaData(binding2A);
+         domains.getMiddleB().addClassMetaData(binding2B);
+         domains.getBottomA().addClassMetaData(binding3A);
+         domains.getBottomB().addClassMetaData(binding3B);
+         
+         Map<String, ClassMetaDataBinding> bindings = domains.getBottomA().getClassMetaData(); 
+         assertEquals(5, bindings.size());
+         assertEquals(binding1, bindings.get("1"));
+         assertEquals(binding2A, bindings.get("2A"));
+         assertEquals(binding2B, bindings.get("2B"));
+         assertEquals(binding3A, bindings.get("3A"));
+         assertEquals(binding3B, bindings.get("3B"));
+         
+         domains.getMiddleA().removeClassMetaData("2A");
+         bindings = domains.getBottomB().getClassMetaData(); 
+         assertEquals(4, bindings.size());
+         assertEquals(binding1, bindings.get("1"));
+         assertEquals(binding2B, bindings.get("2B"));
+         assertEquals(binding3A, bindings.get("3A"));
+         assertEquals(binding3B, bindings.get("3B"));
+         domains.getMiddleA().addClassMetaData(binding2A);
+   
+         domains.removePoolAndDomain(domains.getMiddlePoolB());
+         bindings = domains.getBottomB().getClassMetaData(); 
+         assertEquals(4, bindings.size());
+         assertEquals(binding1, bindings.get("1"));
+         assertEquals(binding2A, bindings.get("2A"));
+         assertEquals(binding3A, bindings.get("3A"));
+         assertEquals(binding3B, bindings.get("3B"));
+      }
+      finally
+      {
+         domains.cleanup();
+      }
+   }
+   
+   public void testInterceptorFactory() throws Exception
+   {
+      Domains domains = new Domains();
+      try
+      {
+         InterceptorFactory fac1 = new ScopedInterceptorFactory(new AspectDefinition("1", Scope.PER_VM, new GenericAspectFactory("Foo", null))); 
+         InterceptorFactory fac2A = new ScopedInterceptorFactory(new AspectDefinition("2A", Scope.PER_VM, new GenericAspectFactory("Foo", null))); 
+         InterceptorFactory fac2B = new ScopedInterceptorFactory(new AspectDefinition("2B", Scope.PER_VM, new GenericAspectFactory("Foo", null))); 
+         InterceptorFactory fac3A = new ScopedInterceptorFactory(new AspectDefinition("3A", Scope.PER_VM, new GenericAspectFactory("Foo", null)));
+         InterceptorFactory fac3B = new ScopedInterceptorFactory(new AspectDefinition("3B", Scope.PER_VM, new GenericAspectFactory("Foo", null)));
+         
+         domains.getMain().addInterceptorFactory("1", fac1);
+         domains.getMiddleA().addInterceptorFactory("2A", fac2A);
+         domains.getMiddleB().addInterceptorFactory("2B", fac2B);
+         domains.getBottomA().addInterceptorFactory("3A", fac3A);
+         domains.getBottomB().addInterceptorFactory("3B", fac3B);
+   
+         assertEquals(fac1, domains.getMain().getInterceptorFactory("1"));
+         assertNull(domains.getMain().getInterceptorFactory("2A"));
+         assertNull(domains.getMain().getInterceptorFactory("2B"));
+         assertNull(domains.getMain().getInterceptorFactory("3A"));
+         assertNull(domains.getMain().getInterceptorFactory("3B"));
+         assertEquals(fac1, domains.getMiddleA().getInterceptorFactory("1"));
+         assertEquals(fac2A, domains.getMiddleA().getInterceptorFactory("2A"));
+         assertEquals(fac2B, domains.getMiddleA().getInterceptorFactory("2B"));
+         assertNull(domains.getMiddleA().getInterceptorFactory("3A"));
+         assertNull(domains.getMiddleA().getInterceptorFactory("3B"));
+         assertEquals(fac1, domains.getMiddleB().getInterceptorFactory("1"));
+         assertEquals(fac2A, domains.getMiddleB().getInterceptorFactory("2A"));
+         assertEquals(fac2B, domains.getMiddleB().getInterceptorFactory("2B"));
+         assertNull(domains.getMiddleB().getInterceptorFactory("3A"));
+         assertNull(domains.getMiddleB().getInterceptorFactory("3B"));
+         assertEquals(fac1, domains.getBottomA().getInterceptorFactory("1"));
+         assertEquals(fac2A, domains.getBottomA().getInterceptorFactory("2A"));
+         assertEquals(fac2B, domains.getBottomA().getInterceptorFactory("2B"));
+         assertEquals(fac3A, domains.getBottomA().getInterceptorFactory("3A"));
+         assertEquals(fac3B, domains.getBottomA().getInterceptorFactory("3B"));
+         assertEquals(fac1, domains.getBottomB().getInterceptorFactory("1"));
+         assertEquals(fac2A, domains.getBottomB().getInterceptorFactory("2A"));
+         assertEquals(fac2B, domains.getBottomB().getInterceptorFactory("2B"));
+         assertEquals(fac3A, domains.getBottomB().getInterceptorFactory("3A"));
+         assertEquals(fac3B, domains.getBottomB().getInterceptorFactory("3B"));
+               
+         domains.getMiddleA().removeInterceptorFactory("2A");
+         assertEquals(fac1, domains.getBottomA().getInterceptorFactory("1"));
+         assertNull(domains.getBottomA().getInterceptorFactory("2A"));
+         assertEquals(fac2B, domains.getBottomA().getInterceptorFactory("2B"));
+         assertEquals(fac3A, domains.getBottomA().getInterceptorFactory("3A"));
+         assertEquals(fac3B, domains.getBottomA().getInterceptorFactory("3B"));
+         assertEquals(fac1, domains.getBottomB().getInterceptorFactory("1"));
+         assertNull(domains.getBottomB().getInterceptorFactory("2A"));
+         assertEquals(fac2B, domains.getBottomB().getInterceptorFactory("2B"));
+         assertEquals(fac3A, domains.getBottomB().getInterceptorFactory("3A"));
+         assertEquals(fac3B, domains.getBottomB().getInterceptorFactory("3B"));
+         domains.getMiddleA().addInterceptorFactory("2A", fac2A);
+
+         domains.removePoolAndDomain(domains.getMiddlePoolB());
+         assertEquals(fac1, domains.getBottomA().getInterceptorFactory("1"));
+         assertEquals(fac2A, domains.getBottomA().getInterceptorFactory("2A"));
+         assertNull(domains.getBottomA().getInterceptorFactory("2B"));
+         assertEquals(fac3A, domains.getBottomA().getInterceptorFactory("3A"));
+         assertEquals(fac3B, domains.getBottomA().getInterceptorFactory("3B"));
+         assertEquals(fac1, domains.getBottomB().getInterceptorFactory("1"));
+         assertEquals(fac2A, domains.getBottomB().getInterceptorFactory("2A"));
+         assertNull(domains.getBottomB().getInterceptorFactory("2B"));
+         assertEquals(fac3A, domains.getBottomB().getInterceptorFactory("3A"));
+         assertEquals(fac3B, domains.getBottomB().getInterceptorFactory("3B"));
+         domains.getMiddleA().addInterceptorFactory("2A", fac2A);
+      }
+      finally
+      {
+         domains.cleanup();
+      }
+   }
+   
+   public void testAspectDefinition() throws Exception
+   {
+      Domains domains = new Domains();
+      try
+      {
+         AspectDefinition def1 = new AspectDefinition("1", Scope.PER_VM, new GenericAspectFactory("Foo", null));
+         AspectDefinition def2A = new AspectDefinition("2A", Scope.PER_VM, new GenericAspectFactory("Foo", null));
+         AspectDefinition def2B = new AspectDefinition("2B", Scope.PER_VM, new GenericAspectFactory("Foo", null));
+         AspectDefinition def3A = new AspectDefinition("3A", Scope.PER_VM, new GenericAspectFactory("Foo", null));
+         AspectDefinition def3B = new AspectDefinition("3B", Scope.PER_VM, new GenericAspectFactory("Foo", null));
+         
+         domains.getMain().addAspectDefinition(def1);
+         domains.getMiddleA().addAspectDefinition(def2A);
+         domains.getMiddleB().addAspectDefinition(def2B);
+         domains.getBottomA().addAspectDefinition(def3A);
+         domains.getBottomB().addAspectDefinition(def3B);
+         
+         assertEquals(def1, domains.getMain().getAspectDefinition("1"));
+         assertNull(domains.getMain().getAspectDefinition("2A"));
+         assertNull(domains.getMain().getAspectDefinition("2B"));
+         assertNull(domains.getMain().getAspectDefinition("3A"));
+         assertNull(domains.getMain().getAspectDefinition("3B"));
+         assertEquals(def1, domains.getMiddleA().getAspectDefinition("1"));
+         assertEquals(def2A, domains.getMiddleA().getAspectDefinition("2A"));
+         assertEquals(def2B, domains.getMiddleA().getAspectDefinition("2B"));
+         assertNull(domains.getMiddleA().getAspectDefinition("3A"));
+         assertNull(domains.getMiddleA().getAspectDefinition("3B"));
+         assertEquals(def1, domains.getMiddleB().getAspectDefinition("1"));
+         assertEquals(def2A, domains.getMiddleB().getAspectDefinition("2A"));
+         assertEquals(def2B, domains.getMiddleB().getAspectDefinition("2B"));
+         assertNull(domains.getMiddleB().getAspectDefinition("3A"));
+         assertNull(domains.getMiddleB().getAspectDefinition("3B"));
+         
+         assertEquals(def1, domains.getBottomA().getAspectDefinition("1"));
+         assertEquals(def2A, domains.getBottomA().getAspectDefinition("2A"));
+         assertEquals(def2B, domains.getBottomA().getAspectDefinition("2B"));
+         assertEquals(def3A, domains.getBottomA().getAspectDefinition("3A"));
+         assertEquals(def3B, domains.getBottomA().getAspectDefinition("3B"));
+         assertEquals(def1, domains.getBottomB().getAspectDefinition("1"));
+         assertEquals(def2A, domains.getBottomB().getAspectDefinition("2A"));
+         assertEquals(def2B, domains.getBottomB().getAspectDefinition("2B"));
+         assertEquals(def3A, domains.getBottomB().getAspectDefinition("3A"));
+         assertEquals(def3B, domains.getBottomB().getAspectDefinition("3B"));
+               
+         domains.getMiddleA().removeAspectDefinition("2A");
+         assertEquals(def1, domains.getBottomA().getAspectDefinition("1"));
+         assertNull(domains.getBottomA().getAspectDefinition("2A"));
+         assertEquals(def2B, domains.getBottomA().getAspectDefinition("2B"));
+         assertEquals(def3A, domains.getBottomA().getAspectDefinition("3A"));
+         assertEquals(def3B, domains.getBottomA().getAspectDefinition("3B"));
+         assertEquals(def1, domains.getBottomB().getAspectDefinition("1"));
+         assertNull(domains.getBottomB().getAspectDefinition("2A"));
+         assertEquals(def2B, domains.getBottomB().getAspectDefinition("2B"));
+         assertEquals(def3A, domains.getBottomB().getAspectDefinition("3A"));
+         assertEquals(def3B, domains.getBottomB().getAspectDefinition("3B"));
+         domains.getMiddleA().addAspectDefinition(def2A);
+         
+         domains.removePoolAndDomain(domains.getMiddlePoolB());
+         assertEquals(def1, domains.getBottomA().getAspectDefinition("1"));
+         assertEquals(def2A, domains.getBottomA().getAspectDefinition("2A"));
+         assertNull(domains.getBottomA().getAspectDefinition("2B"));
+         assertEquals(def3A, domains.getBottomA().getAspectDefinition("3A"));
+         assertEquals(def3B, domains.getBottomA().getAspectDefinition("3B"));
+         assertEquals(def1, domains.getBottomB().getAspectDefinition("1"));
+         assertEquals(def2A, domains.getBottomB().getAspectDefinition("2A"));
+         assertNull(domains.getBottomB().getAspectDefinition("2B"));
+         assertEquals(def3A, domains.getBottomB().getAspectDefinition("3A"));
+         assertEquals(def3B, domains.getBottomB().getAspectDefinition("3B"));
+      }
+      finally
+      {
+         domains.cleanup();
+      }
+   }
+   
+   public void testDomainDefinition() throws Exception
+   {
+      Domains domains = new Domains();
+      try
+      {
+         DomainDefinition def1 = new DomainDefinition("1", domains.getMain(), true, true, true);
+         DomainDefinition def2A = new DomainDefinition("2A", domains.getMiddleA(), true, true, true);
+         DomainDefinition def2B = new DomainDefinition("2B", domains.getMiddleB(), true, true, true);
+         DomainDefinition def3A = new DomainDefinition("3A", domains.getBottomA(), true, true, true);
+         DomainDefinition def3B = new DomainDefinition("3B", domains.getBottomB(), true, true, true);
+         
+         domains.getMain().addContainer(def1);
+         domains.getMiddleA().addContainer(def2A);
+         domains.getMiddleB().addContainer(def2B);
+         domains.getBottomA().addContainer(def3A);
+         domains.getBottomB().addContainer(def3B);
+         
+         assertEquals(def1, domains.getMain().getContainer("1"));
+         assertNull(domains.getMain().getContainer("2A"));
+         assertNull(domains.getMain().getContainer("2B"));
+         assertNull(domains.getMain().getContainer("3A"));
+         assertNull(domains.getMain().getContainer("3B"));
+         assertEquals(def1, domains.getMiddleA().getContainer("1"));
+         assertEquals(def2A, domains.getMiddleA().getContainer("2A"));
+         assertEquals(def2B, domains.getMiddleA().getContainer("2B"));
+         assertNull(domains.getMiddleA().getContainer("3A"));
+         assertNull(domains.getMiddleA().getContainer("3B"));
+         assertEquals(def1, domains.getMiddleB().getContainer("1"));
+         assertEquals(def2A, domains.getMiddleB().getContainer("2A"));
+         assertEquals(def2B, domains.getMiddleB().getContainer("2B"));
+         assertNull(domains.getMiddleB().getContainer("3A"));
+         assertNull(domains.getMiddleB().getContainer("3B"));
+         
+         assertEquals(def1, domains.getBottomA().getContainer("1"));
+         assertEquals(def2A, domains.getBottomA().getContainer("2A"));
+         assertEquals(def2B, domains.getBottomA().getContainer("2B"));
+         assertEquals(def3A, domains.getBottomA().getContainer("3A"));
+         assertEquals(def3B, domains.getBottomA().getContainer("3B"));
+         assertEquals(def1, domains.getBottomB().getContainer("1"));
+         assertEquals(def2A, domains.getBottomB().getContainer("2A"));
+         assertEquals(def2B, domains.getBottomB().getContainer("2B"));
+         assertEquals(def3A, domains.getBottomB().getContainer("3A"));
+         assertEquals(def3B, domains.getBottomB().getContainer("3B"));
+               
+         domains.getMiddleA().removeContainer("2A");
+         assertEquals(def1, domains.getBottomA().getContainer("1"));
+         assertNull(domains.getBottomA().getContainer("2A"));
+         assertEquals(def2B, domains.getBottomA().getContainer("2B"));
+         assertEquals(def3A, domains.getBottomA().getContainer("3A"));
+         assertEquals(def3B, domains.getBottomA().getContainer("3B"));
+         assertEquals(def1, domains.getBottomB().getContainer("1"));
+         assertNull(domains.getBottomB().getContainer("2A"));
+         assertEquals(def2B, domains.getBottomB().getContainer("2B"));
+         assertEquals(def3A, domains.getBottomB().getContainer("3A"));
+         assertEquals(def3B, domains.getBottomB().getContainer("3B"));
+         domains.getMiddleA().addContainer(def2A);
+         
+         domains.removePoolAndDomain(domains.getMiddlePoolB());
+         assertEquals(def1, domains.getBottomA().getContainer("1"));
+         assertEquals(def2A, domains.getBottomA().getContainer("2A"));
+         assertNull(domains.getBottomA().getContainer("2B"));
+         assertEquals(def3A, domains.getBottomA().getContainer("3A"));
+         assertEquals(def3B, domains.getBottomA().getContainer("3B"));
+         assertEquals(def1, domains.getBottomB().getContainer("1"));
+         assertEquals(def2A, domains.getBottomB().getContainer("2A"));
+         assertNull(domains.getBottomB().getContainer("2B"));
+         assertEquals(def3A, domains.getBottomB().getContainer("3A"));
+         assertEquals(def3B, domains.getBottomB().getContainer("3B"));
+         domains.getMiddleA().addContainer(def2A);
+      }
+      finally
+      {
+         domains.cleanup();
+      }
+   }
+   
+   public void testLifecycleCallbacks() throws Exception
+   {
+      Domains domains = new Domains();
+      try
+      {
+         LifecycleCallbackBinding binding1 = new LifecycleCallbackBinding("1", "x", null, null);
+         LifecycleCallbackBinding binding2A = new LifecycleCallbackBinding("2A", "x", null, null);
+         LifecycleCallbackBinding binding2B = new LifecycleCallbackBinding("2B", "x", null, null);
+         LifecycleCallbackBinding binding3A = new LifecycleCallbackBinding("3A", "x", null, null);
+         LifecycleCallbackBinding binding3B = new LifecycleCallbackBinding("3B", "x", null, null);
+         
+         domains.getMain().addLifecycleBinding(binding1);
+         domains.getMiddleA().addLifecycleBinding(binding2A);
+         domains.getMiddleB().addLifecycleBinding(binding2B);
+         domains.getBottomA().addLifecycleBinding(binding3A);
+         domains.getBottomB().addLifecycleBinding(binding3B);
+         
+         assertEquals(binding1, domains.getMain().getLifecycleBindings().get("1"));
+         assertNull(domains.getMain().getLifecycleBindings().get("2A"));
+         assertNull(domains.getMain().getLifecycleBindings().get("2B"));
+         assertEquals(binding1, domains.getMiddleA().getLifecycleBindings().get("1"));
+         assertEquals(binding2A, domains.getMiddleA().getLifecycleBindings().get("2A"));
+         assertEquals(binding2B, domains.getMiddleA().getLifecycleBindings().get("2B"));
+         assertNull(domains.getMiddleA().getLifecycleBindings().get("3A"));
+         assertNull(domains.getMiddleA().getLifecycleBindings().get("3B"));
+         assertEquals(binding1, domains.getMiddleB().getLifecycleBindings().get("1"));
+         assertEquals(binding2A, domains.getMiddleB().getLifecycleBindings().get("2A"));
+         assertEquals(binding2B, domains.getMiddleB().getLifecycleBindings().get("2B"));
+         assertNull(domains.getMiddleB().getLifecycleBindings().get("3A"));
+         assertNull(domains.getMiddleB().getLifecycleBindings().get("3B"));
+         assertEquals(binding1, domains.getBottomA().getLifecycleBindings().get("1"));
+         assertEquals(binding2A, domains.getBottomA().getLifecycleBindings().get("2A"));
+         assertEquals(binding2B, domains.getBottomA().getLifecycleBindings().get("2B"));
+         assertEquals(binding3A, domains.getBottomA().getLifecycleBindings().get("3A"));
+         assertEquals(binding3B, domains.getBottomA().getLifecycleBindings().get("3B"));
+         assertEquals(binding1, domains.getBottomB().getLifecycleBindings().get("1"));
+         assertEquals(binding2A, domains.getBottomB().getLifecycleBindings().get("2A"));
+         assertEquals(binding2B, domains.getBottomB().getLifecycleBindings().get("2B"));
+         assertEquals(binding3A, domains.getBottomB().getLifecycleBindings().get("3A"));
+         assertEquals(binding3B, domains.getBottomB().getLifecycleBindings().get("3B"));
+               
+         domains.getMiddleB().removeLifecycleBinding("2B");
+         assertEquals(binding1, domains.getBottomA().getLifecycleBindings().get("1"));
+         assertEquals(binding2A, domains.getBottomA().getLifecycleBindings().get("2A"));
+         assertNull(domains.getBottomA().getLifecycleBindings().get("2B"));
+         assertEquals(binding3A, domains.getBottomA().getLifecycleBindings().get("3A"));
+         assertEquals(binding3B, domains.getBottomA().getLifecycleBindings().get("3B"));
+         assertEquals(binding1, domains.getBottomB().getLifecycleBindings().get("1"));
+         assertEquals(binding2A, domains.getBottomB().getLifecycleBindings().get("2A"));
+         assertNull(domains.getBottomB().getLifecycleBindings().get("2B"));
+         assertEquals(binding3A, domains.getBottomB().getLifecycleBindings().get("3A"));
+         assertEquals(binding3B, domains.getBottomB().getLifecycleBindings().get("3B"));
+         domains.getMiddleB().addLifecycleBinding(binding2B);
+         
+         domains.removePoolAndDomain(domains.getMiddlePoolA());
+         assertEquals(binding1, domains.getBottomA().getLifecycleBindings().get("1"));
+         assertNull(domains.getBottomA().getLifecycleBindings().get("2A"));
+         assertEquals(binding2B, domains.getBottomA().getLifecycleBindings().get("2B"));
+         assertEquals(binding3A, domains.getBottomA().getLifecycleBindings().get("3A"));
+         assertEquals(binding3B, domains.getBottomA().getLifecycleBindings().get("3B"));
+         assertEquals(binding1, domains.getBottomB().getLifecycleBindings().get("1"));
+         assertNull(domains.getBottomB().getLifecycleBindings().get("2A"));
+         assertEquals(binding2B, domains.getBottomB().getLifecycleBindings().get("2B"));
+         assertEquals(binding3A, domains.getBottomB().getLifecycleBindings().get("3A"));
+         assertEquals(binding3B, domains.getBottomB().getLifecycleBindings().get("3B"));
+      }
+      finally
+      {
+         domains.cleanup();
+      }
+   }
+   
+   public void testPerVmAspects() throws Exception
+   {
+      Domains domains = new Domains();
+      try
+      {
+         AspectDefinition defA1 = new AspectDefinition("A", Scope.PER_VM, new GenericAspectFactory(AspectA1.class.getName(), null));
+         AspectDefinition defA2 = new AspectDefinition("A", Scope.PER_VM, new GenericAspectFactory(AspectA2.class.getName(), null));
+         AspectDefinition defA3 = new AspectDefinition("A", Scope.PER_VM, new GenericAspectFactory(AspectA3.class.getName(), null));
+         AspectDefinition def2A = new AspectDefinition("2A", Scope.PER_VM, new GenericAspectFactory(Aspect2A.class.getName(), null));
+         AspectDefinition def2B = new AspectDefinition("2B", Scope.PER_VM, new GenericAspectFactory(Aspect2B.class.getName(), null));
+         AspectDefinition def3A = new AspectDefinition("3A", Scope.PER_VM, new GenericAspectFactory(Aspect3A.class.getName(), null));
+         AspectDefinition def3B = new AspectDefinition("3B", Scope.PER_VM, new GenericAspectFactory(Aspect3B.class.getName(), null));
+         
+         domains.getMain().addAspectDefinition(defA1);
+         domains.getMiddleA().addAspectDefinition(defA2);
+         domains.getBottomA().addAspectDefinition(defA3);
+         domains.getMiddleA().addAspectDefinition(def2A);
+         domains.getMiddleB().addAspectDefinition(def2B);
+         domains.getBottomA().addAspectDefinition(def3A);
+         domains.getBottomB().addAspectDefinition(def3B);
+         
+         assertPerVmAspect(AspectA1.class, domains.getMain().getPerVMAspect("A", null));
+         assertNull(domains.getMain().getPerVMAspect("2A", null));
+         assertNull(domains.getMain().getPerVMAspect("2B", null));
+         assertNull(domains.getMain().getPerVMAspect("3A", null));
+         assertNull(domains.getMain().getPerVMAspect("3B", null));
+         assertPerVmAspect(AspectA1.class, domains.getMiddleA().getPerVMAspect("A", null));
+         assertPerVmAspect(Aspect2A.class, domains.getMiddleA().getPerVMAspect("2A", null));
+         assertPerVmAspect(Aspect2B.class, domains.getMiddleA().getPerVMAspect("2B", null));
+         assertNull(domains.getMiddleA().getPerVMAspect("3A", null));
+         assertNull(domains.getMiddleA().getPerVMAspect("3B", null));
+         assertPerVmAspect(AspectA1.class, domains.getMiddleB().getPerVMAspect("A", null));
+         assertPerVmAspect(Aspect2A.class, domains.getMiddleB().getPerVMAspect("2A", null));
+         assertPerVmAspect(Aspect2B.class, domains.getMiddleB().getPerVMAspect("2B", null));
+         assertNull(domains.getMiddleB().getPerVMAspect("3A", null));
+         assertNull(domains.getMiddleB().getPerVMAspect("3B", null));
+         
+         assertPerVmAspect(AspectA3.class, domains.getBottomA().getPerVMAspect("A", null));
+         assertPerVmAspect(Aspect2A.class, domains.getBottomA().getPerVMAspect("2A", null));
+         assertPerVmAspect(Aspect2B.class, domains.getBottomA().getPerVMAspect("2B", null));
+         assertPerVmAspect(Aspect3A.class, domains.getBottomA().getPerVMAspect("3A", null));
+         assertPerVmAspect(Aspect3B.class, domains.getBottomA().getPerVMAspect("3B", null));
+         assertPerVmAspect(AspectA3.class, domains.getBottomB().getPerVMAspect("A", null));
+         assertPerVmAspect(Aspect2A.class, domains.getBottomB().getPerVMAspect("2A", null));
+         assertPerVmAspect(Aspect2B.class, domains.getBottomB().getPerVMAspect("2B", null));
+         assertPerVmAspect(Aspect3A.class, domains.getBottomB().getPerVMAspect("3A", null));
+         assertPerVmAspect(Aspect3B.class, domains.getBottomB().getPerVMAspect("3B", null));
+         
+         Map<String, Object> perVmAspects = domains.getMain().getPerVMAspects();
+         assertEquals(1, perVmAspects.size());
+         assertPerVmAspect(AspectA1.class, perVmAspects.get("A"));
+         perVmAspects = domains.getMiddleA().getPerVMAspects();
+         assertEquals(3, perVmAspects.size());
+         assertPerVmAspect(AspectA1.class, perVmAspects.get("A"));
+         assertPerVmAspect(Aspect2A.class, perVmAspects.get("2A"));
+         assertPerVmAspect(Aspect2B.class, perVmAspects.get("2B"));
+         perVmAspects = domains.getMiddleB().getPerVMAspects();
+         assertEquals(3, perVmAspects.size());
+         assertPerVmAspect(AspectA1.class, perVmAspects.get("A"));
+         assertPerVmAspect(Aspect2A.class, perVmAspects.get("2A"));
+         assertPerVmAspect(Aspect2B.class, perVmAspects.get("2B"));
+         
+         perVmAspects = domains.getBottomA().getPerVMAspects();
+         assertEquals(5, perVmAspects.size());
+         assertPerVmAspect(AspectA3.class, perVmAspects.get("A"));
+         assertPerVmAspect(Aspect2A.class, perVmAspects.get("2A"));
+         assertPerVmAspect(Aspect2B.class, perVmAspects.get("2B"));
+         assertPerVmAspect(Aspect3A.class, perVmAspects.get("3A"));
+         assertPerVmAspect(Aspect3B.class, perVmAspects.get("3B"));
+         perVmAspects = domains.getBottomB().getPerVMAspects();
+         assertEquals(5, perVmAspects.size());
+         assertPerVmAspect(AspectA3.class, perVmAspects.get("A"));
+         assertPerVmAspect(Aspect2A.class, perVmAspects.get("2A"));
+         assertPerVmAspect(Aspect2B.class, perVmAspects.get("2B"));
+         assertPerVmAspect(Aspect3A.class, perVmAspects.get("3A"));
+         assertPerVmAspect(Aspect3B.class, perVmAspects.get("3B"));
+         
+         domains.removePoolAndDomain(domains.getMiddlePoolB());
+         assertPerVmAspect(AspectA3.class, domains.getBottomA().getPerVMAspect("A", null));
+         assertPerVmAspect(Aspect2A.class, domains.getBottomA().getPerVMAspect("2A", null));
+         assertPerVmAspect(Aspect2B.class, domains.getBottomA().getPerVMAspect("2B", null));
+         assertPerVmAspect(Aspect3A.class, domains.getBottomA().getPerVMAspect("3A", null));
+         assertPerVmAspect(Aspect3B.class, domains.getBottomA().getPerVMAspect("3B", null));
+         assertPerVmAspect(AspectA3.class, domains.getBottomB().getPerVMAspect("A", null));
+         assertPerVmAspect(Aspect2A.class, domains.getBottomB().getPerVMAspect("2A", null));
+         assertPerVmAspect(Aspect2B.class, domains.getBottomB().getPerVMAspect("2B", null));
+         assertPerVmAspect(Aspect3A.class, domains.getBottomB().getPerVMAspect("3A", null));
+         assertPerVmAspect(Aspect3B.class, domains.getBottomB().getPerVMAspect("3B", null));
+
+         perVmAspects = domains.getBottomA().getPerVMAspects();
+         assertEquals(5, perVmAspects.size());
+         assertPerVmAspect(AspectA3.class, perVmAspects.get("A"));
+         assertPerVmAspect(Aspect2A.class, perVmAspects.get("2A"));
+         assertPerVmAspect(Aspect2B.class, perVmAspects.get("2B"));
+         assertPerVmAspect(Aspect3A.class, perVmAspects.get("3A"));
+         assertPerVmAspect(Aspect3B.class, perVmAspects.get("3B"));
+         perVmAspects = domains.getBottomB().getPerVMAspects();
+         assertEquals(5, perVmAspects.size());
+         assertPerVmAspect(AspectA3.class, perVmAspects.get("A"));
+         assertPerVmAspect(Aspect2A.class, perVmAspects.get("2A"));
+         assertPerVmAspect(Aspect2B.class, perVmAspects.get("2B"));
+         assertPerVmAspect(Aspect3A.class, perVmAspects.get("3A"));
+         assertPerVmAspect(Aspect3B.class, perVmAspects.get("3B"));
+
+         assertPerVmAspect(AspectA1.class, domains.getMiddleA().getPerVMAspect("A", null));
+         assertPerVmAspect(Aspect2A.class, domains.getMiddleA().getPerVMAspect("2A", null));
+         assertNull(domains.getMiddleA().getPerVMAspect("2B", null));
+         assertNull(domains.getMiddleA().getPerVMAspect("3A", null));
+         assertNull(domains.getMiddleA().getPerVMAspect("3B", null));
+
+         perVmAspects = domains.getMiddleA().getPerVMAspects();
+         assertEquals(2, perVmAspects.size());
+         assertPerVmAspect(AspectA1.class, perVmAspects.get("A"));
+         assertPerVmAspect(Aspect2A.class, perVmAspects.get("2A"));
+         
+      }
+      finally
+      {
+         domains.cleanup();
+      }
+   }
+   
+   private void assertPerVmAspect(Class<?> expected, Object aspect)
+   {
+      assertNotNull(aspect);
+      assertEquals(expected, aspect.getClass());
+   }
+
+   private class Domains
+   {
+      ClassPool middlePoolA;
+      ClassPool middlePoolB;
+      ClassPool bottomPoolA;
+      ClassPool bottomPoolB;
+      ClassLoaderDomain middleDomain;
+      ClassLoaderDomain bottomDomain;
+      ScopedVFSClassLoaderDomain middleA;
+      ScopedVFSClassLoaderDomain middleB;
+      ScopedVFSClassLoaderDomain bottomA;
+      ScopedVFSClassLoaderDomain bottomB;
+      
+      //Map<ClassLoader, ScopedVFSClassLoaderDomain> domainsByLoader = new HashMap<ClassLoader, ScopedVFSClassLoaderDomain>();
+      
+      Domains() throws Exception
+      {
+         pushClassLoaderDomainSetup(new ScopedVFSClassLoaderDomainSetup(               
+               "MiddleA", 
+               true, 
+               AspectManager.instance(), 
+               true, 
+               domainRegistry));
+         middlePoolA = createChildDomainParentFirstClassPool("MiddleA", "Middle", true, new URL[]{});
+         middleA = popClassLoaderDomainSetup().getDomain();
+         
+         pushClassLoaderDomainSetup(new ScopedVFSClassLoaderDomainSetup(
+               "MiddleB", 
+               true, 
+               AspectManager.instance(), 
+               true, 
+               domainRegistry));
+         middlePoolB = createChildDomainParentFirstClassPool("MiddleB", "Middle", true, new URL[]{});
+         middleB = popClassLoaderDomainSetup().getDomain();
+
+         pushClassLoaderDomainSetup(new ScopedVFSClassLoaderDomainSetup(
+               "BottomA", 
+               false, 
+               middleB, 
+               false, 
+               domainRegistry));
+         bottomPoolA = createChildDomainParentLastClassPool("BottomA", "Bottom", "Middle", true, new URL[]{});
+         bottomA = popClassLoaderDomainSetup().getDomain();
+         
+         pushClassLoaderDomainSetup(new ScopedVFSClassLoaderDomainSetup(
+               "BottomB", 
+               false, 
+               middleA, 
+               false, 
+               domainRegistry));
+         bottomPoolB = createChildDomainParentLastClassPool("BottomB", "Bottom", "Middle", true, new URL[]{});
+         bottomB = popClassLoaderDomainSetup().getDomain();
+
+         middleDomain = getSystem().getDomain("Middle");
+         bottomDomain = getSystem().getDomain("Bottom");
+      }
+      
+      AspectManager getMain()
+      {
+         return AspectManager.instance();
+      }
+      
+      Domain getMiddleA()
+      {
+         return middleA;
+      }
+      
+      Domain getMiddleB()
+      {
+         return middleB;
+      }
+      
+      Domain getBottomA()
+      {
+         return bottomA;
+      }
+      
+      Domain getBottomB()
+      {
+         return bottomB;
+      }
+      
+      public ClassPool getMiddlePoolA()
+      {
+         return middlePoolA;
+      }
+
+      public ClassPool getMiddlePoolB()
+      {
+         return middlePoolB;
+      }
+
+      public ClassPool getBottomPoolA()
+      {
+         return bottomPoolA;
+      }
+
+      public ClassPool getBottomPoolB()
+      {
+         return bottomPoolB;
+      }
+
+      void removePoolAndDomain(ClassPool pool)
+      {
+         if (pool != null)
+         {
+            try
+            {
+               unregisterClassPool(pool);
+            }
+            catch (Exception e)
+            {
+               getLog().warn("Error unregistering " + pool, e);
+            }
+
+            if (pool == middlePoolA)
+            {
+               middleA = null;
+               middlePoolA = null;
+            }
+            if (pool == middlePoolB)
+            {
+               middleB = null;
+               middlePoolB = null;
+            }
+            if (pool == bottomPoolA)
+            {
+               bottomA = null;
+               bottomPoolA = null;
+            }
+            if (pool == bottomPoolB)
+            {
+               bottomB = null;
+               bottomPoolB = null;
+            }
+         }
+      }
+      
+      void cleanup()
+      {
+         removePoolAndDomain(bottomPoolB);
+         removePoolAndDomain(bottomPoolA);
+         removePoolAndDomain(middlePoolB);
+         removePoolAndDomain(middlePoolA);
+         unregisterDomain(bottomDomain);
+         unregisterDomain(middleDomain);
+      }
+   }
+}
\ No newline at end of file




More information about the jboss-cvs-commits mailing list