[jboss-cvs] JBossAS SVN: r101714 - in projects/jboss-cl/trunk/classloading/src: main/java/org/jboss/classloading/spi/dependency/policy and 8 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Mar 2 08:11:15 EST 2010


Author: adrian at jboss.org
Date: 2010-03-02 08:11:14 -0500 (Tue, 02 Mar 2010)
New Revision: 101714

Added:
   projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/ClassLoadingAdmin.java
   projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/ExportPackage.java
   projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/ImportModule.java
   projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/test/ClassLoadingAdminLazyShutdownUnitTestCase.java
   projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/test/ClassLoadingAdminUnitTestCase.java
   projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/test/RefreshModulesUnitTestCase.java
Modified:
   projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/ClassLoading.java
   projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/Domain.java
   projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/LifeCycle.java
   projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/Module.java
   projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/RequirementDependencyItem.java
   projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/policy/ClassLoaderPolicyModule.java
   projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/policy/mock/MockClassLoaderPolicyModule.java
   projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/version/Version.java
   projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/version/VersionRange.java
   projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/DependencyTestSuite.java
   projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/test/AbstractMockClassLoaderUnitTest.java
   projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/LifeCycleTestSuite.java
   projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/support/a/MockLifeCycle.java
   projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/support/a/MockLifeCycleClassLoaderPolicyModule.java
   projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/test/AbstractMockLifeCycleUnitTest.java
   projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/test/LifeCycleUnitTestCase.java
   projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/version/test/VersionRangeUnitTestCase.java
Log:
[JBCL-129][JBCL-131][JBCL-154][JBCL-155] - Complete LifeCycle handling and Implement ClassLoadingAdmin. Also add String parsing for VersionRanges.

Modified: projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/ClassLoading.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/ClassLoading.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/ClassLoading.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -21,6 +21,7 @@
  */
 package org.jboss.classloading.spi.dependency;
 
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -30,6 +31,7 @@
 
 import org.jboss.classloader.spi.ClassLoaderSystem;
 import org.jboss.classloading.spi.metadata.Capability;
+import org.jboss.classloading.spi.version.VersionRange;
 import org.jboss.logging.Logger;
 import org.jboss.util.collection.ConcurrentSet;
 
@@ -40,7 +42,7 @@
  * @author <a href="ales.justin at jboss.org">Ales Justin</a>
  * @version $Revision: 1.1 $
  */
-public class ClassLoading implements Resolver
+public class ClassLoading implements Resolver, ClassLoadingAdmin
 {
    /** The log */
    private static final Logger log = Logger.getLogger(ClassLoading.class);
@@ -223,7 +225,7 @@
       // FINDBUGS: This synchronization is correct - more than addIfNotPresent behaviour
       synchronized (domains)
       {
-         domain = getDomain(domainName);
+         domain = domains.get(domainName);
          if (domain == null)
          {
             domain = createDomain(domainName, parentDomainName, parentFirst);
@@ -268,6 +270,58 @@
       return new Domain(this, domainName, parentDomainName, parentFirst);
    }
    
+   public Module getModuleForClass(Class<?> clazz)
+   {
+      return Module.getModuleForClass(clazz);
+   }
+   
+   public Collection<Module> getModules(String name, VersionRange range)
+   {
+      if (name == null)
+         throw new IllegalArgumentException("Null name");
+      
+      Collection<Module> result = new HashSet<Module>();
+      for (Domain domain : domains.values())
+         domain.getModulesInternal(name, range, result);
+      return result;
+   }
+   
+   public Collection<ImportModule> getImportedModules(String name, VersionRange range)
+   {
+      Collection<ImportModule> result = new HashSet<ImportModule>();
+      for (Domain domain : domains.values())
+         domain.getImportingModulesInternal(name, range, result);
+      return result;
+   }
+   
+   public Collection<ExportPackage> getExportedPackages(Module module)
+   {
+      if (module == null)
+         throw new IllegalArgumentException("Null modules");
+      return module.getExportedPackages();
+   }
+
+   public Collection<ExportPackage> getExportedPackages(String name, VersionRange range)
+   {
+      if (name == null)
+         throw new IllegalArgumentException("Null name");
+      
+      Collection<ExportPackage> result = new HashSet<ExportPackage>();
+      for (Domain domain : domains.values())
+         domain.getExportedPackagesInternal(name, range, result);
+      return result;
+   }
+
+   public void refreshModules(Module... modules) throws Exception
+   {
+      Module.refreshModules(modules);
+   }
+
+   public boolean resolveModules(Module... modules) throws Exception
+   {
+      return Module.resolveModules(modules);
+   }
+
    /**
     * Find the module for a classloader
     * 

Added: projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/ClassLoadingAdmin.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/ClassLoadingAdmin.java	                        (rev 0)
+++ projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/ClassLoadingAdmin.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -0,0 +1,73 @@
+package org.jboss.classloading.spi.dependency;
+
+import java.util.Collection;
+
+import org.jboss.classloading.spi.version.VersionRange;
+
+/**
+ * ClassLoading admin
+ *
+ * @author adrian at jboss.org
+ */
+public interface ClassLoadingAdmin
+{
+   /**
+    * Get the module for a class
+    * 
+    * @param clazz the class
+    * @return the module or null if there is no such module
+    */
+   Module getModuleForClass(Class<?> clazz);
+
+   /**
+    * Get the modules matching the name and version range
+    * 
+    * @param name the name
+    * @param range the version range or null if all are required
+    * @return the modules
+    */
+   Collection<Module> getModules(String name, VersionRange range);
+   
+   /**
+    * Get the exported packages for a module
+    * 
+    * @param module the module
+    * @return the exported packages
+    */
+   Collection<ExportPackage> getExportedPackages(Module module);
+   
+   /**
+    * Get the exported packages by name and version
+    * 
+    * @param name the name of the package
+    * @param range the version range or null if all are required
+    * @return the exported packages
+    */
+   Collection<ExportPackage> getExportedPackages(String name, VersionRange range);
+   
+   /**
+    * Get the imported modules for a module
+    * 
+    * @param name the name of the module or null for all
+    * @param range the version range or null if all are required
+    * @return the imported modules
+    */
+   Collection<ImportModule> getImportedModules(String name, VersionRange range);
+   
+   /**
+    * Resolve the specified modules
+    * 
+    * @param modules the modules
+    * @return the true if all the modules are resolved
+    * @throws Exception for any error
+    */
+   boolean resolveModules(Module... modules) throws Exception;
+   
+   /**
+    * Refresh stale modules
+    * 
+    * @param modules the modules
+    * @throws Exception for any error
+    */
+   void refreshModules(Module... modules) throws Exception;
+}

Modified: projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/Domain.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/Domain.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/Domain.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -21,13 +21,19 @@
  */
 package org.jboss.classloading.spi.dependency;
 
+import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+import org.jboss.classloading.plugins.metadata.ModuleRequirement;
+import org.jboss.classloading.plugins.metadata.PackageCapability;
+import org.jboss.classloading.plugins.metadata.PackageRequirement;
 import org.jboss.classloading.spi.metadata.Capability;
 import org.jboss.classloading.spi.metadata.Requirement;
+import org.jboss.classloading.spi.version.VersionRange;
 import org.jboss.logging.Logger;
 
 /**
@@ -38,7 +44,7 @@
  * @author Thomas.Diesler at jboss.com
  * @version $Revision: 1.1 $
  */
-public class Domain
+public class Domain implements ClassLoadingAdmin
 {
    /** The log */
    private static final Logger log = Logger.getLogger(Domain.class);
@@ -242,7 +248,16 @@
       {
          LifeCycle lifeCycle = result.getLifeCycle();
          if (lifeCycle != null && lifeCycle.isLazyResolve() && lifeCycle.isResolved() == false)
-            lifeCycle.doResolve();
+         {
+            try
+            {
+               lifeCycle.resolve();
+            }
+            catch (Throwable t)
+            {
+               log.warn("Error in resolve for " + result, t);
+            }
+         }
       }
       
       return result;
@@ -307,6 +322,162 @@
       return null;
    }
    
+   public Module getModuleForClass(Class<?> clazz)
+   {
+      return Module.getModuleForClass(clazz);
+   }
+   
+   public Collection<Module> getModules(String name, VersionRange range)
+   {
+      if (name == null)
+         throw new IllegalArgumentException("Null name");
+      
+      Collection<Module> result = new HashSet<Module>();
+      getModulesInternal(name, range, result);
+      return result;
+   }
+   
+   /**
+    * Get the modules matching the name and range
+    * 
+    * @param name the name
+    * @param range the range
+    * @param result the matching modules
+    */
+   void getModulesInternal(String name, VersionRange range, Collection<Module> result)
+   {
+      if (range == null)
+         range = VersionRange.ALL_VERSIONS;
+      
+      for (Module module : modules)
+      {
+         List<Capability> capabilities = module.getCapabilitiesRaw();
+         if (capabilities != null && capabilities.isEmpty() == false)
+         {
+            ModuleRequirement requirement = new ModuleRequirement(name, range);
+            for (Capability capability : capabilities)
+            {
+               if (capability.resolves(module, requirement))
+               {
+                  result.add(module);
+                  break;
+               }
+            }
+         }
+         else
+         {
+            if (name.equals(module.getName()) && range.isInRange(module.getVersion()))
+            {
+               result.add(module);
+               return;
+            }
+         }
+      }
+   }
+   
+   public Collection<ImportModule> getImportedModules(String name, VersionRange range)
+   {
+      Collection<ImportModule> result = new HashSet<ImportModule>();
+      getImportingModulesInternal(name, range, result);
+      return result;
+   }
+   
+   /**
+    * Get the importing modules matching the name and range
+    * 
+    * @param name the name
+    * @param range the range
+    * @param result the matching modules
+    */
+   void getImportingModulesInternal(String name, VersionRange range, Collection<ImportModule> result)
+   {
+      if (range == null)
+         range = VersionRange.ALL_VERSIONS;
+      
+      for (Module module : modules)
+      {
+         List<RequirementDependencyItem> requirementDependencyItems = module.getDependencies();
+         if (requirementDependencyItems != null && requirementDependencyItems.isEmpty() == false)
+         {
+            for (RequirementDependencyItem dependencyItem : requirementDependencyItems)
+            {
+               Requirement requirement = dependencyItem.getRequirement();
+               if (requirement instanceof ModuleRequirement && dependencyItem.isResolved())
+               {
+                  ModuleRequirement moduleRequirement = (ModuleRequirement) requirement;
+                  if (name == null || name.equals(moduleRequirement.getName()))
+                  {
+                     if (range.isConsistent(moduleRequirement.getVersionRange()))
+                     {
+                        Module other = module.resolveModule(dependencyItem, true);
+                        ImportModule importModule = new ImportModule(other);
+                        result.add(importModule);
+                     }
+                  }
+               }
+            }
+         }
+      }
+   }
+   
+   public Collection<ExportPackage> getExportedPackages(Module module)
+   {
+      if (module == null)
+         throw new IllegalArgumentException("Null module");
+      return module.getExportedPackages();
+   }
+   
+   public Collection<ExportPackage> getExportedPackages(String name, VersionRange range)
+   {
+      if (name == null)
+         throw new IllegalArgumentException("Null name");
+      
+      Collection<ExportPackage> result = new HashSet<ExportPackage>();
+      getExportedPackagesInternal(name, range, result);
+      return result;
+   }
+   
+   /**
+    * Get the exported packages matching the name and range
+    * 
+    * @param name the name
+    * @param range the range
+    * @param result the matching modules
+    */
+   void getExportedPackagesInternal(String name, VersionRange range, Collection<ExportPackage> result)
+   {
+      if (range == null)
+         range = VersionRange.ALL_VERSIONS;
+      
+      for (Module module : modules)
+      {
+         List<Capability> capabilities = module.getCapabilitiesRaw();
+         if (capabilities != null && capabilities.isEmpty() == false)
+         {
+            PackageRequirement requirement = new PackageRequirement(name, range);
+            for (Capability capability : capabilities)
+            {
+               if (capability instanceof PackageCapability && capability.resolves(module, requirement))
+               {
+                  ExportPackage exportPackage = new ExportPackage(module, (PackageCapability) capability);
+                  result.add(exportPackage);
+                  break;
+               }
+            }
+         }
+      }
+   }
+
+   public void refreshModules(Module... modules) throws Exception
+   {
+      Module.refreshModules(modules);
+   }
+
+   public boolean resolveModules(Module... modules) throws Exception
+   {
+      return Module.resolveModules(modules);
+   }
+
    @Override
    public String toString()
    {

Added: projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/ExportPackage.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/ExportPackage.java	                        (rev 0)
+++ projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/ExportPackage.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -0,0 +1,105 @@
+package org.jboss.classloading.spi.dependency;
+
+import java.util.Collection;
+
+import org.jboss.classloading.plugins.metadata.PackageCapability;
+import org.jboss.classloading.plugins.metadata.PackageRequirement;
+
+/**
+ * An exported package
+ *
+ * @author adrian at jboss.org
+ */
+public class ExportPackage
+{
+   /** The module exporting the package */
+   private Module module;
+   
+   /** The package capability */
+   private PackageCapability capability;
+
+   /**
+    * Create a new ExportPackage
+    *
+    * @param module the module
+    * @param capability the capability
+    */
+   ExportPackage(Module module, PackageCapability capability)
+   {
+      this.module = module;
+      this.capability = capability;
+   }
+
+   /**
+    * Get the module
+    *
+    * @return the module
+    */
+   public Module getModule()
+   {
+      return module;
+   }
+
+   /**
+    * Get the name
+    * 
+    * @return the name
+    */
+   public String getName()
+   {
+      return capability.getName();
+   }
+   
+   /**
+    * Get the version
+    * 
+    * @return the version
+    */
+   public Object getVersion()
+   {
+      return capability.getVersion();
+   }
+   
+   /**
+    * Get the importing modules
+    * 
+    * @return the importing modules
+    */
+   public Collection<Module> getImportingModules()
+   {
+      return module.getImportingModules(PackageRequirement.class);
+   }
+
+   /**
+    * Whether the package is unregistered
+    * 
+    * @return true when unregistered
+    */
+   public boolean isUnregistered()
+   {
+      return module.getClassLoader() == null;
+   }
+   
+   public boolean equals(Object obj)
+   {
+      if (obj == this)
+         return true;
+      if (obj == null || obj instanceof ExportPackage == false)
+         return false;
+
+      ExportPackage other = (ExportPackage) obj;
+      if (module.equals(other.getModule()) == false)
+         return false;
+      return capability.equals(other.capability);
+   }
+   
+   public int hashCode()
+   {
+      return capability.hashCode();
+   }
+   
+   public String toString()
+   {
+      return module + "/" + capability;
+   }
+}

Added: projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/ImportModule.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/ImportModule.java	                        (rev 0)
+++ projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/ImportModule.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -0,0 +1,102 @@
+package org.jboss.classloading.spi.dependency;
+
+import java.util.Collection;
+
+import org.jboss.classloading.plugins.metadata.ModuleRequirement;
+
+
+/**
+ * An imported module
+ *
+ * @author adrian at jboss.org
+ */
+public class ImportModule
+{
+   /** The module */
+   private Module module;
+
+   /**
+    * Create a new ExportPackage
+    *
+    * @param module the module
+    */
+   ImportModule(Module module)
+   {
+      this.module = module;
+   }
+
+   /**
+    * Get the module
+    *
+    * @return the module
+    */
+   public Module getModule()
+   {
+      return module;
+   }
+
+   /**
+    * Get the name
+    * 
+    * @return the name
+    */
+   public String getName()
+   {
+      return module.getName();
+   }
+   
+   /**
+    * Get the version
+    * 
+    * @return the version
+    */
+   public Object getVersion()
+   {
+      return module.getVersion();
+   }
+   
+   /**
+    * Get the importing modules
+    * 
+    * @return the importing modules
+    */
+   public Collection<Module> getImportingModules()
+   {
+      return module.getImportingModules(ModuleRequirement.class);
+   }
+
+   /**
+    * Whether the module is unregistered
+    * 
+    * @return true when unregistered
+    */
+   public boolean isUnregistered()
+   {
+      return module.getClassLoader() == null;
+   }
+   
+   @Override
+   public String toString()
+   {
+      return module.toString();
+   }
+   
+   @Override
+   public int hashCode()
+   {
+      return module.hashCode();
+   }
+   
+   @Override
+   public boolean equals(Object obj)
+   {
+      if (this == obj)
+         return true;
+      if (obj == null || obj instanceof ImportModule == false)
+
+         return false;
+      
+      ImportModule other = (ImportModule) obj;
+      return module.equals(other.module);
+   }
+}

Modified: projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/LifeCycle.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/LifeCycle.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/LifeCycle.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -24,6 +24,8 @@
 import org.jboss.classloader.spi.ClassFoundEvent;
 import org.jboss.classloader.spi.ClassFoundHandler;
 import org.jboss.classloader.spi.ClassLoaderPolicy;
+import org.jboss.classloader.spi.filter.ClassFilter;
+import org.jboss.classloader.spi.filter.ClassFilterUtils;
 import org.jboss.classloading.spi.dependency.policy.ClassLoaderPolicyModule;
 import org.jboss.dependency.spi.Controller;
 import org.jboss.dependency.spi.ControllerContext;
@@ -45,12 +47,17 @@
    /** The module associated with this lifecycle */
    private Module module;
    
+   /** Whether to lazy start */
+   private boolean lazyStart = false;
+   
+   /** Whether to lazy resolve */
+   private boolean lazyResolve = false;
+   
    /** Any lazy start handler */
-   private LazyStartHandler lazyStart;
+   private LazyStartHandler lazyStartHandler;
    
-   /** Whether we are already in the lifecycle */
-   // TODO FIX THIS IN THE MC?
-   private boolean lifeCycle = false;
+   /** The lazy start filter */
+   private ClassFilter lazyStartFilter = ClassFilterUtils.EVERYTHING;
    
    /**
     * Create a new LifeCycle.
@@ -73,8 +80,53 @@
    {
       return module;
    }
+   
+   /**
+    * Whether the context associated with the classloader is lazy start,
+    * i.e. the start method will be invoked on first class load
+    * 
+    * @return true if it is lazy start
+    */
+   public boolean isLazyStart()
+   {
+      return lazyStart;
+   }
 
    /**
+    * Set the lazyStart 
+    *
+    * @param lazyStart the lazyStart to set
+    */
+   public void setLazyStart(boolean lazyStart)
+   {
+      this.lazyStart = lazyStart;
+      if (lazyStart)
+         setUpLazyStart();
+   }
+
+   /**
+    * Get the lazyStartFilter
+    *
+    * @return the lazyStartFilter
+    */
+   public ClassFilter getLazyStartFilter()
+   {
+      return lazyStartFilter;
+   }
+
+   /**
+    * Set the lazyStartFilter 
+    *
+    * @param lazyStartFilter the lazyStartFilter to set
+    */
+   public void setLazyStartFilter(ClassFilter lazyStartFilter)
+   {
+      if (lazyStartFilter == null)
+         lazyStartFilter = ClassFilterUtils.EVERYTHING;
+      this.lazyStartFilter = lazyStartFilter;
+   }
+
+   /**
     * Whether the module is resolved
     * 
     * @return true when resolved
@@ -92,44 +144,69 @@
     */
    public boolean isLazyResolve()
    {
-      return false;
+      return lazyResolve;
    }
    
    /**
+    * Set the lazyResolve 
+    *
+    * @param lazyResolve the lazyResolve to set
+    */
+   public void setLazyResolve(boolean lazyResolve)
+   {
+      this.lazyResolve = lazyResolve;
+   }
+
+   /**
     * Resolve the classloader
+    * 
+    * @throws Exception for any error
     */
-   void doResolve()
+   public void resolve() throws Exception
    {
-      if (lifeCycle == false)
+   }
+   
+   /**
+    * Resolve lots of lifecycles
+    * 
+    * @param lifecycles the lifecycles to resolve
+    * @throws Exception for any error
+    */
+   public void resolve(LifeCycle... lifecycles) throws Exception
+   {
+      if (lifecycles == null || lifecycles.length == 0)
+         return;
+      for (LifeCycle lifecycle : lifecycles)
       {
-         lifeCycle = true;
-         try
-         {
-            resolve();
-         }
-         catch (Throwable t)
-         {
-            log.warn("Error in resolve: " + this, t);
-         }
-         finally
-         {
-            lifeCycle = false;
-         }
+         if (lifecycle.isResolved() == false)
+            lifecycle.resolve();
       }
    }
    
    /**
-    * Resolve the classloader
+    * Unresolve the classloader
+    * 
+    * @throws Exception for any error
     */
-   public void resolve()
+   public void unresolve() throws Exception
    {
    }
    
    /**
-    * Unresolve the classloader
+    * Unresolve lots of lifecycles
+    * 
+    * @param lifecycles the lifecycles to unresolve
+    * @throws Exception for any error
     */
-   public void unresolve()
+   public void unresolve(LifeCycle... lifecycles) throws Exception
    {
+      if (lifecycles == null || lifecycles.length == 0)
+         return;
+      for (LifeCycle lifecycle : lifecycles)
+      {
+         if (lifecycle.isResolved())
+            lifecycle.unresolve();
+      }
    }
    
    /**
@@ -147,6 +224,29 @@
    }
    
    /**
+    * Bounce the classloader
+    * 
+    * @throws Exception for any error
+    */
+   public void bounce() throws Exception
+   {
+   }
+   
+   /**
+    * Bounce lots of lifecycles
+    * 
+    * @param lifecycles the lifecycles to bounce
+    * @throws Exception for any error
+    */
+   public void bounce(LifeCycle... lifecycles) throws Exception
+   {
+      if (lifecycles == null || lifecycles.length == 0)
+         return;
+      for (LifeCycle lifecycle : lifecycles)
+         lifecycle.bounce();
+   }
+   
+   /**
     * Whether the module is started
     * 
     * @return true when started
@@ -164,73 +264,54 @@
    
    /**
     * Start the context associated with the classloader
+    * 
+    * @throws Exception for any error
     */
-   void doStart()
+   public void start() throws Exception
    {
-      if (lifeCycle == false)
-      {
-         lifeCycle = true;
-         try
-         {
-            start();
-         }
-         catch (Throwable t)
-         {
-            log.warn("Error in start: " + this, t);
-         }
-         finally
-         {
-            lifeCycle = false;
-         }
-      }
    }
    
    /**
-    * Start the context associated with the classloader
+    * Start lots of lifecycles
+    * 
+    * @param lifecycles the lifecycles to start
+    * @throws Exception for any error
     */
-   public void start()
+   public void start(LifeCycle... lifecycles) throws Exception
    {
-   }
-   
-   /**
-    * Stop the context associated with the classloader
-    */
-   void doStop()
-   {
-      if (lifeCycle == false)
+      if (lifecycles == null || lifecycles.length == 0)
+         return;
+      for (LifeCycle lifecycle : lifecycles)
       {
-         lifeCycle = true;
-         try
-         {
-            start();
-         }
-         catch (Throwable t)
-         {
-            log.warn("Error in stop: " + this, t);
-         }
-         finally
-         {
-            lifeCycle = false;
-         }
+         if (lifecycle.isStarted() == false)
+            lifecycle.start();
       }
    }
    
    /**
     * Stop the context associated with the classloader
+    * 
+    * @throws Exception for any error
     */
-   public void stop()
+   public void stop() throws Exception
    {
    }
    
    /**
-    * Whether the context associated with the classloader is lazy start,
-    * i.e. the start method will be invoked on first class load
+    * Stop lots of lifecycles
     * 
-    * @return true if it is lazy start
+    * @param lifecycles the lifecycles to stop
+    * @throws Exception for any error
     */
-   public boolean isLazyStart()
+   public void stop(LifeCycle... lifecycles) throws Exception
    {
-      return false;
+      if (lifecycles == null || lifecycles.length == 0)
+         return;
+      for (LifeCycle lifecycle : lifecycles)
+      {
+         if (lifecycle.isResolved())
+            lifecycle.stop();
+      }
    }
 
    /**
@@ -238,12 +319,14 @@
     */
    protected void setUpLazyStart()
    {
-      if (isStarted())
+      if (isResolved() == false || isStarted())
          return;
+      if (lazyStartHandler != null)
+         return;
       if (module instanceof ClassLoaderPolicyModule)
       {
          ClassLoaderPolicy policy = ((ClassLoaderPolicyModule) module).getPolicy();
-         lazyStart = new LazyStartHandler(policy);
+         lazyStartHandler = new LazyStartHandler(policy);
       }
       else
       {
@@ -256,11 +339,11 @@
     */
    protected void removeLazyStart()
    {
-      if (lazyStart == null)
+      if (lazyStartHandler == null)
          return;
 
-      lazyStart.cleanup();
-      lazyStart = null;
+      lazyStartHandler.cleanup();
+      lazyStartHandler = null;
    }
    
    void fireResolved()
@@ -297,9 +380,21 @@
       
       public void classFound(ClassFoundEvent event)
       {
+         if (getLazyStartFilter().matchesClassName(event.getClassName()) == false)
+            return;
+         
          removeLazyStart();
          if (isStarted() == false)
-            start();
+         {
+            try
+            {
+               start();
+            }
+            catch (Throwable t)
+            {
+               log.warn("Error in lazy start for " + this, t);
+            }
+         }
       }
       
       public void cleanup()

Modified: projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/Module.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/Module.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/Module.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -26,6 +26,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashSet;
@@ -36,6 +37,7 @@
 import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CopyOnWriteArraySet;
 
 import org.jboss.classloader.spi.ClassLoaderPolicy;
 import org.jboss.classloader.spi.ClassLoaderSystem;
@@ -57,10 +59,12 @@
 import org.jboss.classloading.spi.metadata.Requirement;
 import org.jboss.classloading.spi.visitor.ResourceFilter;
 import org.jboss.classloading.spi.visitor.ResourceVisitor;
+import org.jboss.dependency.spi.Controller;
 import org.jboss.dependency.spi.ControllerContext;
 import org.jboss.dependency.spi.ControllerState;
 import org.jboss.dependency.spi.DependencyInfo;
 import org.jboss.dependency.spi.DependencyItem;
+import org.jboss.logging.Logger;
 
 /**
  * Module.
@@ -73,9 +77,15 @@
    /** The serialVersionUID */
    private static final long serialVersionUID = 1L;
 
+   /** The log */
+   private static final Logger log = Logger.getLogger(Module.class);
+   
    /** The modules by classloader */
    private static Map<ClassLoader, Module> modulesByClassLoader = new ConcurrentHashMap<ClassLoader, Module>();
    
+   /** The lazily shutdown modules */
+   private static Set<Module> lazyShutdownModules = new CopyOnWriteArraySet<Module>();
+   
    /** The context name */
    private String contextName;
    
@@ -100,6 +110,12 @@
    /** Any lifecycle associated with the classloader */
    private LifeCycle lifeCycle;
    
+   /** The remembered policy for cascade shutdown */
+   private Boolean cascadeShutdown;
+   
+   /** Requirements resolved to us */
+   private Set<RequirementDependencyItem> depends = new CopyOnWriteArraySet<RequirementDependencyItem>();
+   
    /**
     * Register a classloader for a module
     * 
@@ -118,7 +134,8 @@
 
       // This is hack - we might not know until the classloader gets constructed whether
       // it is in a domain that specifies lazy shutdown of the classloader
-      if (module.isCascadeShutdown() == false)
+      module.cascadeShutdown = module.isCascadeShutdown();
+      if (module.cascadeShutdown == false)
          module.enableLazyShutdown();
       
       LifeCycle lifeCycle = module.getLifeCycle();
@@ -141,10 +158,15 @@
          throw new IllegalArgumentException("Null classloader");
 
       modulesByClassLoader.remove(classLoader);
-
+      
+      module.unresolveDependencies();
+      
       LifeCycle lifeCycle = module.getLifeCycle();
       if (lifeCycle != null)
          lifeCycle.fireUnresolved();
+      
+      if (module.isCascadeShutdown() == false && module.depends.isEmpty() == false)
+         lazyShutdownModules.add(module);
    }
    
    /**
@@ -211,7 +233,7 @@
       this.domain = domain;
    }
 
-   Domain checkDomain()
+   protected Domain checkDomain()
    {
       Domain result = domain;
       if (result == null)
@@ -325,6 +347,10 @@
     */
    public boolean isCascadeShutdown()
    {
+      // Has it been determined?
+      if (cascadeShutdown != null)
+         return cascadeShutdown;
+      
       // This is ugly
       ClassLoader cl = getClassLoader();
       if (cl != null && cl instanceof BaseClassLoader)
@@ -458,6 +484,28 @@
    /**
     * Find the module that loads a class
     * 
+    * @param clazz the class
+    * @return the module or null if the class is not loaded by a registered module classloader
+    * @throws IllegalStateException when the module is not associated with a classloader
+    */
+   public static Module getModuleForClass(Class<?> clazz)
+   {
+      SecurityManager sm = System.getSecurityManager();
+      if (sm != null)
+         sm.checkPermission(new RuntimePermission("getClassLoader"));
+
+      ClassLoader cl = getClassLoaderForClass(clazz);
+
+      // Determine the module (if any) for the classloader 
+      if (cl != null)
+         return modulesByClassLoader.get(cl);
+      // Unknown
+      return null;
+   }
+   
+   /**
+    * Find the module that loads a class
+    * 
     * @param className the class name
     * @return the module or null if the class is not loaded by a registered module classloader
     * @throws ClassNotFoundException when the class is not found
@@ -479,6 +527,32 @@
    }
 
    /**
+    * Get the classloader for a class 
+    * 
+    * @param clazz the class
+    * @return the classloader
+    */
+   protected static ClassLoader getClassLoaderForClass(final Class<?> clazz)
+   {
+      if (clazz == null)
+         throw new IllegalArgumentException("Null class");
+      
+      // Determine the classloader for this class
+      SecurityManager sm = System.getSecurityManager();
+      if (sm != null)
+      {
+         return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>()
+         {
+            public ClassLoader run()
+            {
+               return clazz.getClassLoader(); 
+            }
+        });
+      }
+      return clazz.getClassLoader();
+   }
+
+   /**
     * Get the classloader for a class name 
     * 
     * @param className the class name
@@ -751,6 +825,116 @@
    public abstract DelegateLoader getDelegateLoader(Module requiringModule, Requirement requirement);
 
    /**
+    * Get the exported packages
+    * 
+    * @return the exported packages
+    */
+   public Collection<ExportPackage> getExportedPackages()
+   {
+      Collection<ExportPackage> result = new HashSet<ExportPackage>();
+      List<Capability> capabilities = getCapabilitiesRaw();
+      if (capabilities != null && capabilities.isEmpty() == false)
+      {
+         for (Capability capability : capabilities)
+         {
+            if (capability instanceof PackageCapability)
+            {
+               ExportPackage exportPackage = new ExportPackage(this, (PackageCapability) capability);
+               result.add(exportPackage);
+            }
+         }
+      }
+      return result;
+   }
+
+   /**
+    * Refresh the specified modules<p>
+    * 
+    * Pass null to refresh any undeployed lazy shutdown modules dependencies
+    * 
+    * @param modules the modules
+    * @throws Exception for any error
+    */
+   public static void refreshModules(Module... modules) throws Exception
+   {
+      if (modules == null || modules.length == 0)
+      {
+         Set<Module> snapshot = new HashSet<Module>(lazyShutdownModules);
+         modules = snapshot.toArray(new Module[snapshot.size()]);
+      }
+      
+      if (modules.length == 0)
+         return;
+      
+      Set<LifeCycle> lifecycles = new HashSet<LifeCycle>();
+      Set<Module> processed = new HashSet<Module>();
+      for (Module module : modules)
+      {
+         if (module == null)
+            throw new IllegalArgumentException("Null module");
+         module.addRefreshModule(lifecycles, processed);
+      }
+      
+      if (lifecycles.isEmpty() == false)
+      {
+         LifeCycle[] result = lifecycles.toArray(new LifeCycle[lifecycles.size()]);
+         result[0].bounce(result);
+      }
+   }
+   
+   private void addRefreshModule(Set<LifeCycle> lifecycles, Set<Module> processed)
+   {
+      // Avoid recursion
+      if (processed.contains(this))
+         return;
+      processed.add(this);
+      
+      // Add our lifecycle - if we have a classloader
+      if (getClassLoader() != null)
+      {
+         LifeCycle lifeCycle = getLifeCycle();
+         if (lifeCycle != null)
+            lifecycles.add(lifeCycle);
+         else
+            log.warn(this + " has no lifecycle, don't know how to refresh it.");
+      }
+      
+      // Add dependencies that are not already managed
+      if (isCascadeShutdown() == false && depends.isEmpty() == false)
+      {
+         for (RequirementDependencyItem item : depends)
+            item.getModule().addRefreshModule(lifecycles, processed);
+      }
+   }
+
+   public static boolean resolveModules(Module... modules) throws Exception
+   {
+      if (modules == null || modules.length == 0)
+         return true;
+
+      LifeCycle[] lifeCycles = new LifeCycle[modules.length]; 
+      for (int i = 0; i < modules.length; ++i)
+      {
+         Module module = modules[i];
+         if (module == null)
+            throw new IllegalArgumentException("Null module");
+         LifeCycle lifeCycle = module.getLifeCycle();
+         if (lifeCycle == null)
+            log.warn(module + " has no lifecycle, don't know how to resolve it.");
+         lifeCycles[i] = lifeCycle; 
+      }
+
+      lifeCycles[0].resolve(lifeCycles);
+      
+      for (LifeCycle lifeCycle : lifeCycles)
+      {
+         if (lifeCycle.isResolved() == false)
+            return false;
+      }
+      return true;
+   }
+
+   /**
     * Get the capabilities.
     * 
     * @return the capabilities.
@@ -802,6 +986,11 @@
       return capabilities;
    }
 
+   List<Capability> getCapabilitiesRaw()
+   {
+      return capabilities;
+   }
+   
    /**
     * Get the package names
     * 
@@ -927,6 +1116,16 @@
    }
 
    /**
+    * Get the requirements as they are now.
+    * 
+    * @return the requirements.
+    */
+   List<Requirement> getRequirementsRaw()
+   {
+      return requirements;
+   }
+
+   /**
     * Return a URL where dynamic classes can be stored
     * 
     * @return the url or null if there isn't one
@@ -976,6 +1175,19 @@
    }
 
    /**
+    * Unresolve dependencies
+    */
+   protected void unresolveDependencies()
+   {
+      Controller controller = context.getController();
+      if (requirementDependencies != null && requirementDependencies.isEmpty() == false)
+      {
+         for (RequirementDependencyItem item : requirementDependencies)
+            item.unresolved(controller);
+      }
+   }
+
+   /**
     * Get the controller context.
     * 
     * @return the controller context.
@@ -1018,14 +1230,7 @@
          throw new IllegalStateException("No controller context");
       
       // Remove the DependsOnMe part of this item
-      Object iDependOn = item.getIDependOn();
-      if (iDependOn != null)
-      {
-         // TODO - we need a better way to cleanup
-         Module otherModule = domain.getModule(iDependOn.toString());
-         if (otherModule != null)
-            otherModule.removeDependsOnMe(item);
-      }
+      item.setResolved(false);
       
       // Remove the IDependOn part of this item
       DependencyInfo dependencyInfo = context.getDependencyInfo();
@@ -1041,12 +1246,55 @@
    {
       if (context == null)
          return;
-
+      
       DependencyInfo dependencyInfo = context.getDependencyInfo();
       dependencyInfo.removeDependsOnMe(item);
    }
 
    /**
+    * Add a dependency resolved against us
+    * 
+    * @param item the dependency
+    */
+   void addDepends(RequirementDependencyItem item)
+   {
+      depends.add(item);
+   }
+
+   /**
+    * Remove a dependency resolved against us
+    * 
+    * @param item the dependency
+    */
+   void removeDepends(RequirementDependencyItem item)
+   {
+      depends.remove(item);
+      if (depends.isEmpty())
+         lazyShutdownModules.remove(this);
+   }
+   
+   /**
+    * Get the importing modules
+    * 
+    * @param type the requirement type to filter on or null for all
+    * @return the importing modules
+    */
+   public Collection<Module> getImportingModules(Class<? extends Requirement> type)
+   {
+      Set<Module> result = new HashSet<Module>();
+      if (depends.isEmpty() == false)
+      {
+         for (RequirementDependencyItem item : depends)
+         {
+            Requirement requirement = item.getRequirement();
+            if (type == null || type.isInstance(requirement))
+               result.add(item.getModule());
+         }
+      }
+      return result;
+   }
+   
+   /**
     * Resolve a requirement
     * 
     * @param dependency the dependency the dependency

Modified: projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/RequirementDependencyItem.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/RequirementDependencyItem.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/RequirementDependencyItem.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -47,6 +47,9 @@
    /** The requirement */
    private Requirement requirement;
 
+   /** The module we resolved to */
+   private Module resolvedModule;
+   
    /**
     * Create a new RequirementDependencyItem.
     * 
@@ -100,6 +103,16 @@
       return requirement;
    }
 
+   /**
+    * Get the resolvedModule
+    *
+    * @return the resolvedModule
+    */
+   public Module getResolvedModule()
+   {
+      return resolvedModule;
+   }
+
    public boolean resolve(Controller controller)
    {
       Requirement requirement = getRequirement();
@@ -128,6 +141,8 @@
       if (context != null)
       {
          setIDependOn(context.getName());
+         resolvedModule = module;
+         module.addDepends(this);
          if (module.isCascadeShutdown())
             addDependsOnMe(controller, context);
          setResolved(true);
@@ -148,6 +163,18 @@
       return true;
    }
 
+   @Override
+   protected void setResolved(boolean resolved)
+   {
+      if (resolved == false && resolvedModule != null)
+      {
+         resolvedModule.removeDepends(this);
+         resolvedModule.removeDependsOnMe(this);
+         resolvedModule = null;
+      }
+      super.setResolved(resolved);
+   }
+
    public void toString(JBossStringBuilder buffer)
    {
       super.toString(buffer);

Modified: projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/policy/ClassLoaderPolicyModule.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/policy/ClassLoaderPolicyModule.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/policy/ClassLoaderPolicyModule.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -290,6 +290,7 @@
    public void reset()
    {
       super.reset();
+      classLoader = null;
       system = null;
       policy = null;
    }

Modified: projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/policy/mock/MockClassLoaderPolicyModule.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/policy/mock/MockClassLoaderPolicyModule.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/policy/mock/MockClassLoaderPolicyModule.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -34,6 +34,7 @@
 import org.jboss.classloader.test.support.MockClassLoaderHelper;
 import org.jboss.classloader.test.support.MockClassLoaderPolicy;
 import org.jboss.classloading.plugins.visitor.DefaultResourceContext;
+import org.jboss.classloading.spi.dependency.Domain;
 import org.jboss.classloading.spi.dependency.policy.ClassLoaderPolicyModule;
 import org.jboss.classloading.spi.metadata.Capability;
 import org.jboss.classloading.spi.metadata.ClassLoadingMetaDataFactory;
@@ -65,6 +66,12 @@
       super(classLoadingMetaData, contextName);
    }
 
+   @Override
+   public Domain checkDomain()
+   {
+      return super.checkDomain();
+   }
+   
    /**
     * Get collection from string array.
     *
@@ -278,4 +285,10 @@
       policy.setDelegates(getDelegates());
       return policy;
    }
+
+   @Override
+   public ClassLoader getClassLoader()
+   {
+      return super.getClassLoader();
+   }
 }

Modified: projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/version/Version.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/version/Version.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/version/Version.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -65,6 +65,17 @@
 
    /** The qualifier part of the version */
    private String qualifier;
+   
+   /**
+    * Get the version from a string
+    * 
+    * @param string the string
+    * @return the version 
+    */
+   public static Version valueOf(String string)
+   {
+      return parseVersion(string);
+   }
 
    /**
     * Create a new Version.
@@ -147,7 +158,7 @@
       }
       catch (NumberFormatException e)
       {
-         throw new IllegalArgumentException("Invalid version format: " + version);
+         throw new IllegalArgumentException("Invalid version format: " + version, e);
       }
 
       this.major = major;

Modified: projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/version/VersionRange.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/version/VersionRange.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/version/VersionRange.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -22,6 +22,7 @@
 package org.jboss.classloading.spi.version;
 
 import java.io.Serializable;
+import java.util.StringTokenizer;
 
 /**
  * VersionRange.
@@ -50,6 +51,95 @@
    public static final VersionRange ALL_VERSIONS = new VersionRange(Version.DEFAULT_VERSION);
    
    /**
+    * Get the version range from a string
+    * 
+    * @param rangeSpec the range spec
+    * @return the version range
+    */
+   public static VersionRange valueOf(String rangeSpec)
+   {
+      return parseRangeSpec(rangeSpec);
+   }
+
+   /**
+    * Parse a range spec
+    * 
+    * @param rangeSpec
+    * @return the version range
+    */
+   public static VersionRange parseRangeSpec(String rangeSpec)
+   {
+      if (rangeSpec == null)
+         throw new IllegalArgumentException("Null rangeSpec");
+      
+      rangeSpec = rangeSpec.trim();
+
+      int length = rangeSpec.length();
+      if (length == 0)
+         return ALL_VERSIONS;
+
+      char start = rangeSpec.charAt(0);
+      // Single version?
+      if (start != '[' && start != '(')
+      {
+         Version version = Version.parseVersion(rangeSpec);
+         return new VersionRange(version, true, version, true);
+      }
+      
+      if (length < 2)
+         throw new IllegalArgumentException("Expected a closing ] or ) for version range: " + rangeSpec);
+
+      boolean floorIsInclusive = true;
+      boolean ceilingIsInclusive = true;
+
+      if (start == '(')
+         floorIsInclusive = false;
+      
+      char end = rangeSpec.charAt(length-1);
+      if (end == ')')
+         ceilingIsInclusive = false;
+      else if (end != ']')
+         throw new IllegalArgumentException("Expected a closing ] or ) for version range: " + rangeSpec);
+
+      Version floor = null;
+      Version ceiling = null;
+      StringTokenizer st = new StringTokenizer(rangeSpec.substring(1, length-1), ",", true);
+      boolean mid = false;
+      while (st.hasMoreTokens())
+      {
+         String token = st.nextToken();
+         if (token.equals(","))
+         {
+            if (mid == true)
+               throw new IllegalArgumentException("Expected only one , in version range: " + rangeSpec);
+            mid = true;
+         }
+         else
+         {
+            try
+            {
+               // A version token
+               if (mid == false)
+                  floor = Version.parseVersion(token);
+               else
+                  ceiling = Version.parseVersion(token);
+            }
+            catch (RuntimeException e)
+            {
+               throw new IllegalArgumentException("Error parsing version '" + token + "' in " + rangeSpec, e);
+            }
+         }
+
+      }
+
+      // This is a hack to support [1.0.0] as a specified version
+      if (ceiling == null && ceilingIsInclusive)
+         ceiling = floor;
+      
+      return new VersionRange(floor, floorIsInclusive, ceiling, ceilingIsInclusive);
+   }
+   
+   /**
     * Create a new VersionRange with just a low inclusive check
     * 
     * @param low the low range (null for no lower bound)

Modified: projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/DependencyTestSuite.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/DependencyTestSuite.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/DependencyTestSuite.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -25,6 +25,8 @@
 import junit.framework.TestSuite;
 import junit.textui.TestRunner;
 
+import org.jboss.test.classloading.dependency.test.ClassLoadingAdminLazyShutdownUnitTestCase;
+import org.jboss.test.classloading.dependency.test.ClassLoadingAdminUnitTestCase;
 import org.jboss.test.classloading.dependency.test.ConflictingPackageUnitTestCase;
 import org.jboss.test.classloading.dependency.test.ConflictingRequirementUnitTestCase;
 import org.jboss.test.classloading.dependency.test.DependencyUnitTestCase;
@@ -42,7 +44,7 @@
 import org.jboss.test.classloading.dependency.test.MockResourceVisitorUnitTestCase;
 
 /**
- * Version Test Suite.
+ * Dependency Test Suite.
  * 
  * @author <a href="adrian at jboss.com">Adrian Brock</a>
  * @version $Revision: 37459 $
@@ -83,6 +85,8 @@
       suite.addTest(ConflictingRequirementUnitTestCase.suite());
       suite.addTest(SplitPackageDependencyUnitTestCase.suite());
       suite.addTest(SelfImportPackageDependencyUnitTestCase.suite());
+      suite.addTest(ClassLoadingAdminUnitTestCase.suite());
+      suite.addTest(ClassLoadingAdminLazyShutdownUnitTestCase.suite());
 
       return suite;
    }

Modified: projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/test/AbstractMockClassLoaderUnitTest.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/test/AbstractMockClassLoaderUnitTest.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/test/AbstractMockClassLoaderUnitTest.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -53,6 +53,8 @@
 
    protected ClassLoaderSystem system;
    
+   protected ClassLoading classLoading;
+   
    public static Test suite()
    {
       return suite(AbstractMockClassLoaderUnitTest.class);
@@ -89,10 +91,16 @@
 
    protected void assertNoClassLoader(KernelControllerContext context) throws Exception
    {
-      assertNoModule(context);
+      MockClassLoaderPolicyModule module = assertNoModule(context);
+      if (module != null)
+      {
+         ClassLoader cl = module.getClassLoader();
+         if (cl != null)
+            fail("Should not have classloader: " + cl);
+      }
    }
 
-   protected void assertNoModule(KernelControllerContext context) throws Exception
+   protected MockClassLoaderPolicyModule assertNoModule(KernelControllerContext context) throws Exception
    {
       boolean test = ControllerState.INSTALLED.equals(context.getState());
       if (test)
@@ -107,7 +115,9 @@
          catch (IllegalStateException expected)
          {
          }
+         return module;
       }
+      return null;
    }
    
    protected KernelControllerContext install(MockClassLoadingMetaData metaData) throws Exception
@@ -170,6 +180,9 @@
       builder.addMethodUninstallCallback("removeModule", null, null, ControllerState.CONFIGURED, null);
 
       install(builder.getBeanMetaData());
+      
+      ControllerContext ctx = controller.getInstalledContext("ClassLoading");
+      classLoading = (ClassLoading) ctx.getTarget();
    }
 
    protected void tearDown() throws Exception

Added: projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/test/ClassLoadingAdminLazyShutdownUnitTestCase.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/test/ClassLoadingAdminLazyShutdownUnitTestCase.java	                        (rev 0)
+++ projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/test/ClassLoadingAdminLazyShutdownUnitTestCase.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -0,0 +1,42 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, 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.classloading.dependency.test;
+
+import junit.framework.Test;
+
+/**
+ * ClassLoadingAdmin unit tests
+ *
+ * @author adrian at jboss.org
+ */
+public class ClassLoadingAdminLazyShutdownUnitTestCase extends ClassLoadingAdminUnitTestCase
+{
+   public static Test suite()
+   {
+      return suite(ClassLoadingAdminLazyShutdownUnitTestCase.class);
+   }
+
+   public ClassLoadingAdminLazyShutdownUnitTestCase(String name)
+   {
+      super(name, true);
+   }
+}

Added: projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/test/ClassLoadingAdminUnitTestCase.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/test/ClassLoadingAdminUnitTestCase.java	                        (rev 0)
+++ projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/test/ClassLoadingAdminUnitTestCase.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -0,0 +1,577 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, 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.classloading.dependency.test;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.Test;
+
+import org.jboss.classloader.plugins.ClassLoaderUtils;
+import org.jboss.classloader.spi.ShutdownPolicy;
+import org.jboss.classloading.spi.dependency.Domain;
+import org.jboss.classloading.spi.dependency.ExportPackage;
+import org.jboss.classloading.spi.dependency.ImportModule;
+import org.jboss.classloading.spi.dependency.Module;
+import org.jboss.classloading.spi.dependency.policy.mock.MockClassLoaderPolicyModule;
+import org.jboss.classloading.spi.dependency.policy.mock.MockClassLoadingMetaData;
+import org.jboss.classloading.spi.metadata.ClassLoadingMetaDataFactory;
+import org.jboss.classloading.spi.version.VersionRange;
+import org.jboss.kernel.spi.dependency.KernelControllerContext;
+import org.jboss.test.classloading.dependency.support.a.A;
+import org.jboss.test.classloading.dependency.support.b.B;
+
+/**
+ * ClassLoadingAdmin unit tests
+ *
+ * @author adrian at jboss.org
+ */
+public class ClassLoadingAdminUnitTestCase extends AbstractMockClassLoaderUnitTest
+{
+   static String PACKAGEA = ClassLoaderUtils.getClassPackageName(A.class.getName());
+   static String PACKAGEB = ClassLoaderUtils.getClassPackageName(B.class.getName());
+   
+   boolean lazyShutdown;
+   
+   public static Test suite()
+   {
+      return suite(ClassLoadingAdminUnitTestCase.class);
+   }
+
+   public ClassLoadingAdminUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public ClassLoadingAdminUnitTestCase(String name, boolean lazyShutdown)
+   {
+      super(name);
+      this.lazyShutdown = lazyShutdown;
+   }
+
+   ClassLoadingMetaDataFactory factory = ClassLoadingMetaDataFactory.getInstance();
+   
+   MockClassLoaderPolicyModule moduleA;
+   Class<?> classA;
+   Domain domainA;
+   KernelControllerContext contextA;
+   
+   MockClassLoaderPolicyModule moduleA2;
+   Class<?> classA2;
+   Domain domainA2;
+   KernelControllerContext contextA2;
+
+   MockClassLoaderPolicyModule moduleB;
+   Class<?> classB;
+   Domain domainB;
+   KernelControllerContext contextB;
+
+   MockClassLoaderPolicyModule moduleC;
+   KernelControllerContext contextC;
+
+   MockClassLoaderPolicyModule moduleD;
+   MockClassLoaderPolicyModule moduleE;
+
+   @Override
+   protected KernelControllerContext install(MockClassLoadingMetaData metaData) throws Exception
+   {
+      if (lazyShutdown)
+         metaData.setShutdownPolicy(ShutdownPolicy.GARBAGE_COLLECTION);
+      return super.install(metaData);
+   }
+
+   protected void setUpAB() throws Exception
+   {
+      MockClassLoadingMetaData a = new MockClassLoadingMetaData("a", "1.0.0");
+      a.getCapabilities().addCapability(factory.createModule("ModuleA", "1.0.0"));
+      a.getCapabilities().addCapability(factory.createPackage(PACKAGEA, "1.0.0"));
+      a.setPathsAndPackageNames(A.class);
+      a.setDomain("main");
+      contextA = install(a);
+      moduleA = assertModule(contextA);
+      ClassLoader clA = assertClassLoader(contextA);
+      classA = clA.loadClass(A.class.getName());
+      domainA = moduleA.checkDomain();
+
+      MockClassLoadingMetaData a2 = new MockClassLoadingMetaData("a", "2.0.0");
+      a2.getCapabilities().addCapability(factory.createModule("ModuleA", "2.0.0"));
+      a2.getCapabilities().addCapability(factory.createPackage(PACKAGEA, "2.0.0"));
+      a2.getCapabilities().addCapability(factory.createPackage(PACKAGEB, "2.0.0"));
+      a2.setPathsAndPackageNames(A.class);
+      a2.setDomain("main");
+      contextA2 = install(a2);
+      moduleA2 = assertModule(contextA2);
+      ClassLoader clA2 = assertClassLoader(contextA2);
+      classA2 = clA2.loadClass(A.class.getName());
+      domainA2 = moduleA2.checkDomain();
+
+      MockClassLoadingMetaData b = new MockClassLoadingMetaData("b", "2.0.0");
+      b.setDomain("other");
+      b.getCapabilities().addCapability(factory.createModule("ModuleBAlias", "3.0.0"));
+      b.getCapabilities().addCapability(factory.createModule("ModuleB", "2.0.0"));
+      b.getCapabilities().addCapability(factory.createPackage(PACKAGEB, "2.0.0"));
+      b.setPathsAndPackageNames(B.class);
+      contextB = install(b);
+      moduleB = assertModule(contextB);
+      ClassLoader clB = assertClassLoader(contextB);
+      classB = clB.loadClass(B.class.getName());
+      domainB = moduleB.checkDomain();
+   }
+
+   protected void setUpABCDE() throws Exception
+   {
+      setUpAB();
+      
+      MockClassLoadingMetaData c = new MockClassLoadingMetaData("c", "2.0.0");
+      c.getRequirements().addRequirement(factory.createRequireModule("ModuleA", VersionRange.valueOf("1.0.0")));
+      c.getRequirements().addRequirement(factory.createRequirePackage(PACKAGEA, VersionRange.valueOf("1.0.0")));
+      c.setDomain("main");
+      contextC = install(c);
+      moduleC = assertModule(contextC);
+      ClassLoader clC = assertClassLoader(contextC);
+      clC.loadClass(A.class.getName());
+
+      MockClassLoadingMetaData d = new MockClassLoadingMetaData("d", "5.0.0");
+      d.getRequirements().addRequirement(factory.createRequireModule("ModuleB", new VersionRange("2.0.0")));
+      d.getRequirements().addRequirement(factory.createRequirePackage(PACKAGEB, new VersionRange("2.0.0")));
+      d.setDomain("other");
+      KernelControllerContext contextD = install(d);
+      moduleD = assertModule(contextD);
+      ClassLoader clD = assertClassLoader(contextD);
+      clD.loadClass(B.class.getName());
+
+      MockClassLoadingMetaData e = new MockClassLoadingMetaData("e", "5.0.0");
+      e.getRequirements().addRequirement(factory.createRequireModule("ModuleB", new VersionRange("2.0.0")));
+      e.setDomain("other");
+      KernelControllerContext contextE = install(e);
+      moduleE = assertModule(contextE);
+      ClassLoader clE = assertClassLoader(contextE);
+      clE.loadClass(B.class.getName());
+   }
+   
+   public void testGetModuleForClass() throws Exception
+   {
+      setUpAB();
+      
+      assertEquals(moduleA, classLoading.getModuleForClass(classA));
+      assertEquals(moduleA, domainA.getModuleForClass(classA));
+      
+      assertEquals(moduleB, classLoading.getModuleForClass(classB));
+      assertEquals(moduleB, domainB.getModuleForClass(classB));
+      
+      assertNull(classLoading.getModuleForClass(Object.class));
+      assertNull(domainA.getModuleForClass(Object.class));
+      
+      uninstall(contextB);
+      
+      assertNull(classLoading.getModuleForClass(classB));
+      assertNull(domainB.getModuleForClass(classB));
+   }
+   
+   public void testGetModules() throws Exception
+   {
+      setUpAB();
+      
+      assertGetModules("ModuleA", null, moduleA, moduleA2);
+      assertGetModules(domainA, "ModuleA", null, moduleA, moduleA2);
+      assertGetModules(domainB, "ModuleA", null);
+      
+      assertGetModules("ModuleB", null, moduleB);
+      assertGetModules(domainA, "ModuleB", null);
+      assertGetModules(domainB, "ModuleB", null, moduleB);
+      
+      assertGetModules("ModuleA", "[1.0.0,1.0.0]", moduleA);
+      assertGetModules(domainA, "ModuleA", "[1.0.0,1.0.0]", moduleA);
+      assertGetModules(domainB, "ModuleA", "[1.0.0,1.0.0]");
+      
+      assertGetModules("ModuleA", "[1.0.0,2.0.0]", moduleA, moduleA2);
+      assertGetModules(domainA, "ModuleA", "[1.0.0,2.0.0]", moduleA, moduleA2);
+      assertGetModules(domainB, "ModuleA", "[1.0.0,2.0.0]");
+      
+      assertGetModules("ModuleA", "[0.0.0,0.0.0]");
+      assertGetModules(domainA, "ModuleA", "[0.0.0,0.0.0]");
+      assertGetModules(domainB, "ModuleA", "[0.0.0,0.0.0]");
+      
+      assertGetModules("ModuleBAlias", null, moduleB);
+      assertGetModules(domainA, "ModuleBAlias", null);
+      assertGetModules(domainB, "ModuleBAlias", null, moduleB);
+      
+      assertGetModules("ModuleBAlias", "[3.0.0,4.0.0]", moduleB);
+      assertGetModules(domainA, "ModuleBAlias", "[3.0.0,4.0.0]");
+      assertGetModules(domainB, "ModuleBAlias", "[3.0.0,4.0.0]", moduleB);
+      
+      uninstall(contextA2);
+      
+      assertGetModules("ModuleA", null, moduleA);
+      assertGetModules(domainA, "ModuleA", null, moduleA);
+      assertGetModules(domainB, "ModuleA", null);
+      
+      assertGetModules("ModuleA", "[1.0.0,2.0.0]", moduleA);
+      assertGetModules(domainA, "ModuleA", "[1.0.0,2.0.0]", moduleA);
+      assertGetModules(domainB, "ModuleA", "[1.0.0,2.0.0]");
+   }
+   
+   public void testModuleExportingPackages() throws Exception
+   {
+      setUpAB();
+
+      assertModuleExportingPackages(moduleA, new ExportingPackage(moduleA, PACKAGEA, "1.0.0"));
+      assertModuleExportingPackages(domainA, moduleA, new ExportingPackage(moduleA, PACKAGEA, "1.0.0"));
+
+      assertModuleExportingPackages(moduleA2, new ExportingPackage(moduleA2, PACKAGEA, "2.0.0"), new ExportingPackage(moduleA2, PACKAGEB, "2.0.0"));
+      assertModuleExportingPackages(domainA2, moduleA2, new ExportingPackage(moduleA2, PACKAGEA, "2.0.0"), new ExportingPackage(moduleA2, PACKAGEB, "2.0.0"));
+
+      uninstall(contextA2);
+
+      assertModuleExportingPackages(moduleA2); 
+      assertModuleExportingPackages(domainA2, moduleA2);
+   }
+   
+   public void testExportingPackages() throws Exception
+   {
+      setUpABCDE();
+
+      assertExportingPackages(PACKAGEA, null, new ExportingPackage(moduleA, PACKAGEA, "1.0.0"), new ExportingPackage(moduleA2, PACKAGEA, "2.0.0"));
+      assertExportingPackages(domainA, PACKAGEA, null, new ExportingPackage(moduleA, PACKAGEA, "1.0.0"), new ExportingPackage(moduleA2, PACKAGEA, "2.0.0"));
+      assertExportingPackages(domainB, PACKAGEA, null);
+
+      assertExportingPackages(PACKAGEA, "[0.0.0,1.0.0]", new ExportingPackage(moduleA, PACKAGEA, "1.0.0"));
+      assertExportingPackages(domainA, PACKAGEA, "[0.0.0,1.0.0]", new ExportingPackage(moduleA, PACKAGEA, "1.0.0"));
+      assertExportingPackages(domainB, PACKAGEA, "[0.0.0,1.0.0]");
+
+      assertExportingPackages(PACKAGEB, null, new ExportingPackage(moduleB, PACKAGEB, "2.0.0"), new ExportingPackage(moduleA2, PACKAGEB, "2.0.0"));
+      assertExportingPackages(domainA, PACKAGEB, null, new ExportingPackage(moduleA2, PACKAGEB, "2.0.0"));
+      assertExportingPackages(domainB, PACKAGEB, null, new ExportingPackage(moduleB, PACKAGEB, "2.0.0"));
+
+      assertExportedPackageImporting(PACKAGEA, VersionRange.valueOf("1.0.0"), moduleC);
+      assertExportedPackageImporting(PACKAGEA, VersionRange.valueOf("2.0.0"));
+      assertExportedPackageImporting(domainA, PACKAGEB, VersionRange.valueOf("2.0.0"));
+      assertExportedPackageImporting(domainB, PACKAGEB, VersionRange.valueOf("2.0.0"), moduleD);
+      
+      uninstall(contextA2);
+
+      assertExportingPackages(PACKAGEA, null, new ExportingPackage(moduleA, PACKAGEA, "1.0.0"));
+      assertExportingPackages(domainA, PACKAGEA, null, new ExportingPackage(moduleA, PACKAGEA, "1.0.0"));
+      assertExportingPackages(domainB, PACKAGEA, null);
+      
+      uninstall(contextC);
+      
+      assertExportedPackageImporting(PACKAGEA, VersionRange.valueOf("1.0.0"));
+   }
+   
+   public void testImportingModules() throws Exception
+   {
+      setUpABCDE();
+
+      assertImportingModule("ModuleA", null, new ImportingModule(moduleA));
+      assertImportingModule(domainA, "ModuleA", null, new ImportingModule(moduleA));
+      assertImportingModule(domainB, "ModuleA", null);
+
+      assertImportingModule("ModuleA", "[0.0.0,1.0.0]", new ImportingModule(moduleA));
+      assertImportingModule(domainA, "ModuleA", "[0.0.0,1.0.0]", new ImportingModule(moduleA));
+      assertImportingModule(domainB, "ModuleA", "[0.0.0,1.0.0]");
+
+      assertImportingModule("ModuleA", "[0.0.0,0.0.0]");
+      assertImportingModule(domainA, "ModuleA", "[0.0.0,0.0.0]");
+      assertImportingModule(domainB, "ModuleA", "[0.0.0,0.0.0]");
+
+      assertImportingModule(null, null, new ImportingModule(moduleA), new ImportingModule(moduleB));
+      assertImportingModule(domainA, null, null, new ImportingModule(moduleA));
+      assertImportingModule(domainB, null, null, new ImportingModule(moduleB));
+
+      assertImportedModulesImporting("ModuleA", moduleC);
+      assertImportedModulesImporting("ModuleB", moduleD, moduleE);
+      
+      uninstall(contextC);
+
+      assertImportingModule("ModuleA", null);
+      assertImportingModule(domainA, "ModuleA", null);
+      assertImportingModule(domainB, "ModuleA", null);
+
+      assertNoImportedModules("ModuleA");
+   }
+   
+   protected void assertGetModules(String name, String versionRange, Module... modules) throws Exception
+   {
+      Collection<Module> expected = new HashSet<Module>();
+      for (Module module : modules)
+         expected.add(module);
+      
+      VersionRange range = null;
+      if (versionRange != null)
+         range = VersionRange.parseRangeSpec(versionRange);
+      Collection<Module> actual = classLoading.getModules(name, range);
+      
+      assertEquals(expected, actual);
+   }
+   
+   protected void assertGetModules(Domain domain, String name, String versionRange, Module... modules) throws Exception
+   {
+      Collection<Module> expected = new HashSet<Module>();
+      for (Module module : modules)
+         expected.add(module);
+      
+      VersionRange range = null;
+      if (versionRange != null)
+         range = VersionRange.parseRangeSpec(versionRange);
+      Collection<Module> actual = domain.getModules(name, range);
+      
+      assertEquals(expected, actual);
+   }
+
+   protected void assertModuleExportingPackages(Module module, ExportingPackage... expect) throws Exception
+   {
+      Set<ExportingPackage> expected = new HashSet<ExportingPackage>();
+      for (ExportingPackage e : expect)
+         expected.add(e);
+      
+      Set<ExportingPackage> actual = new HashSet<ExportingPackage>();
+      Collection<ExportPackage> exported = classLoading.getExportedPackages(module);
+      for (ExportPackage export : exported)
+         actual.add(new ExportingPackage(export.getModule(), export.getName(), export.getVersion()));
+      
+      assertEquals(expected, actual);
+   }
+
+   protected void assertModuleExportingPackages(Domain domain, Module module, ExportingPackage... expect) throws Exception
+   {
+      Set<ExportingPackage> expected = new HashSet<ExportingPackage>();
+      for (ExportingPackage e : expect)
+         expected.add(e);
+      
+      Set<ExportingPackage> actual = new HashSet<ExportingPackage>();
+      Collection<ExportPackage> exported = domain.getExportedPackages(module);
+      for (ExportPackage export : exported)
+         actual.add(new ExportingPackage(export.getModule(), export.getName(), export.getVersion()));
+      
+      assertEquals(expected, actual);
+   }
+
+   protected void assertExportingPackages(String name, String versionRange, ExportingPackage... expect) throws Exception
+   {
+      Set<ExportingPackage> expected = new HashSet<ExportingPackage>();
+      for (ExportingPackage e : expect)
+         expected.add(e);
+      
+      VersionRange range = null;
+      if (versionRange != null)
+         range = VersionRange.parseRangeSpec(versionRange);
+      
+      Set<ExportingPackage> actual = new HashSet<ExportingPackage>();
+      Collection<ExportPackage> exported = classLoading.getExportedPackages(name, range);
+      for (ExportPackage export : exported)
+         actual.add(new ExportingPackage(export.getModule(), export.getName(), export.getVersion()));
+      
+      assertEquals(expected, actual);
+   }
+
+   protected void assertExportingPackages(Domain domain, String name, String versionRange, ExportingPackage... expect) throws Exception
+   {
+      Set<ExportingPackage> expected = new HashSet<ExportingPackage>();
+      for (ExportingPackage e : expect)
+         expected.add(e);
+      
+      VersionRange range = null;
+      if (versionRange != null)
+         range = VersionRange.parseRangeSpec(versionRange);
+      
+      Set<ExportingPackage> actual = new HashSet<ExportingPackage>();
+      Collection<ExportPackage> exported = domain.getExportedPackages(name, range);
+      for (ExportPackage export : exported)
+         actual.add(new ExportingPackage(export.getModule(), export.getName(), export.getVersion()));
+      
+      assertEquals(expected, actual);
+   }
+   
+   protected void assertExportedPackageImporting(String name, Module... expected) throws Exception
+   {
+      assertExportedPackageImporting(name, null, expected);
+   }
+      
+   protected void assertExportedPackageImporting(String name, VersionRange range, Module... expected) throws Exception
+   {
+      Collection<ExportPackage> exportPackages = classLoading.getExportedPackages(name, range);
+      assertTrue(exportPackages.toString(), exportPackages.size() == 1);
+      ExportPackage exportPackage = exportPackages.iterator().next();
+      assertModules(exportPackage.getImportingModules(), expected);
+   }
+   
+   protected void assertExportedPackageImporting(Domain domain, String name, Module... expected) throws Exception
+   {
+      assertExportedPackageImporting(domain, name, null, expected);
+   }
+      
+   protected void assertExportedPackageImporting(Domain domain, String name, VersionRange range, Module... expected) throws Exception
+   {
+      Collection<ExportPackage> exportPackages = domain.getExportedPackages(name, range);
+      assertTrue(exportPackages.toString(), exportPackages.size() == 1);
+      ExportPackage exportPackage = exportPackages.iterator().next();
+      assertModules(exportPackage.getImportingModules(), expected);
+   }
+
+   protected void assertImportingModule(String name, String versionRange, ImportingModule... expect) throws Exception
+   {
+      Set<ImportingModule> expected = new HashSet<ImportingModule>();
+      for (ImportingModule e : expect)
+         expected.add(e);
+      
+      VersionRange range = null;
+      if (versionRange != null)
+         range = VersionRange.parseRangeSpec(versionRange);
+      
+      Set<ImportingModule> actual = new HashSet<ImportingModule>();
+      Collection<ImportModule> imported = classLoading.getImportedModules(name, range);
+      for (ImportModule imp : imported)
+         actual.add(new ImportingModule(imp.getModule()));
+      
+      assertEquals(expected, actual);
+   }
+
+   protected void assertImportingModule(Domain domain, String name, String versionRange, ImportingModule... expect) throws Exception
+   {
+      Set<ImportingModule> expected = new HashSet<ImportingModule>();
+      for (ImportingModule e : expect)
+         expected.add(e);
+      
+      VersionRange range = null;
+      if (versionRange != null)
+         range = VersionRange.parseRangeSpec(versionRange);
+      
+      Set<ImportingModule> actual = new HashSet<ImportingModule>();
+      Collection<ImportModule> imported = domain.getImportedModules(name, range);
+      for (ImportModule imp : imported)
+         actual.add(new ImportingModule(imp.getModule()));
+      
+      assertEquals(expected, actual);
+   }
+   
+   protected void assertNoImportedModules(String name) throws Exception
+   {
+      Collection<ImportModule> importedModules = classLoading.getImportedModules(name, null);
+      assertTrue(importedModules.toString(), importedModules.isEmpty());
+   }
+   
+   protected void assertImportedModulesImporting(String name, Module... expected) throws Exception
+   {
+      Collection<ImportModule> importedModules = classLoading.getImportedModules(name, null);
+      assertTrue(importedModules.toString(), importedModules.size() == 1);
+      ImportModule importModule = importedModules.iterator().next();
+      assertModules(importModule.getImportingModules(), expected);
+   }
+   
+   protected void assertModules(Collection<Module> actual, Module... expected) throws Exception
+   {
+      Set<Module> expect = new HashSet<Module>();
+      for (Module module : expected)
+         expect.add(module);
+      
+      Set<Module> act = new HashSet<Module>(actual);
+      
+      assertEquals(expect, act);
+   }
+   
+   private class ExportingPackage
+   {
+      Module module;
+      String name;
+      Object version;
+      
+      public ExportingPackage(Module module, String name, Object version)
+      {
+         this.module = module;
+         this.name = name;
+         this.version = version;
+      }
+      
+      public boolean equals(Object obj)
+      {
+         if (obj == this)
+            return true;
+         if (obj == null || obj instanceof ExportingPackage == false)
+            return false;
+
+         ExportingPackage other = (ExportingPackage) obj;
+         if (notEquals(module, other.module))
+            return false;
+         if (notEquals(name, other.name))
+            return false;
+         if (notEquals(version, other.version))
+            return false;
+         return true;
+      }
+      
+      public int hashCode()
+      {
+         return name.hashCode();
+      }
+      
+      public String toString()
+      {
+         if (version != null)
+            return module + "/" + name + ":" + version;
+         return module + "/" + name;
+      }
+   }
+   
+   private class ImportingModule
+   {
+      Module module;
+      
+      public ImportingModule(Module module)
+      {
+         this.module = module;
+      }
+      
+      public boolean equals(Object obj)
+      {
+         if (obj == this)
+            return true;
+         if (obj == null || obj instanceof ImportingModule == false)
+            return false;
+
+         ImportingModule other = (ImportingModule) obj;
+         if (notEquals(module, other.module))
+            return false;
+         return true;
+      }
+      
+      public int hashCode()
+      {
+         return module.hashCode();
+      }
+      
+      public String toString()
+      {
+         return module.toString();
+      }
+   }
+   
+   static boolean notEquals(Object one, Object two)
+   {
+      if (one == null && two == null)
+         return false;
+      if (one == null && two != null)
+         return true;
+      return one.equals(two) == false;
+   }
+}

Modified: projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/LifeCycleTestSuite.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/LifeCycleTestSuite.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/LifeCycleTestSuite.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -26,6 +26,7 @@
 import junit.textui.TestRunner;
 
 import org.jboss.test.classloading.lifecycle.test.LifeCycleUnitTestCase;
+import org.jboss.test.classloading.lifecycle.test.RefreshModulesUnitTestCase;
 
 /**
  * LifeCycle Test Suite.
@@ -55,6 +56,7 @@
       TestSuite suite = new TestSuite("LifeCycle Tests");
 
       suite.addTest(LifeCycleUnitTestCase.suite());
+      suite.addTest(RefreshModulesUnitTestCase.suite());
 
       return suite;
    }

Modified: projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/support/a/MockLifeCycle.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/support/a/MockLifeCycle.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/support/a/MockLifeCycle.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -36,11 +36,9 @@
    public boolean gotUnresolved = false;
    public boolean gotResolve = false;
    public boolean gotUnresolve = false;
+   public boolean gotBounce = false;
    public boolean gotStart= false;
    public boolean gotStop = false;
-
-   public boolean lazyResolve = false;
-   public boolean lazyStart = false;
    
    public MockLifeCycle(Module module)
    {
@@ -58,6 +56,7 @@
       gotUnresolved = false;
       gotResolve = false;
       gotUnresolve = false;
+      gotBounce = false;
       gotStart = false;
       gotStop = false;
    }
@@ -70,9 +69,11 @@
    }
 
    @Override
-   public void resolved()
+   public void bounce()
    {
-      gotResolved = true;
+      gotBounce = true;
+      getModule().unresolveIt();
+      getModule().resolveIt();
    }
 
    @Override
@@ -91,23 +92,18 @@
    public void unresolve()
    {
       gotUnresolve = true;
+      getModule().unresolveIt();
    }
 
    @Override
-   public void unresolved()
+   public void resolved()
    {
-      gotUnresolved = true;
+      gotResolved = true;
    }
 
    @Override
-   public boolean isLazyResolve()
+   public void unresolved()
    {
-      return lazyResolve;
+      gotUnresolved = true;
    }
-
-   @Override
-   public boolean isLazyStart()
-   {
-      return lazyStart;
-   }
 }

Modified: projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/support/a/MockLifeCycleClassLoaderPolicyModule.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/support/a/MockLifeCycleClassLoaderPolicyModule.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/support/a/MockLifeCycleClassLoaderPolicyModule.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -70,4 +70,18 @@
          throw new Error("Error", t);
       }
    }
+   
+   void unresolveIt()
+   {
+      ControllerContext context = getControllerContext();
+      Controller controller = context.getController();
+      try
+      {
+         controller.change(context, ControllerState.CONFIGURED);
+      }
+      catch (Throwable t)
+      {
+         throw new Error("Error", t);
+      }
+   }
 }

Modified: projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/test/AbstractMockLifeCycleUnitTest.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/test/AbstractMockLifeCycleUnitTest.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/test/AbstractMockLifeCycleUnitTest.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -29,6 +29,7 @@
 import org.jboss.classloader.spi.ParentPolicy;
 import org.jboss.classloading.spi.dependency.ClassLoading;
 import org.jboss.classloading.spi.dependency.policy.mock.MockClassLoadingMetaData;
+import org.jboss.dependency.spi.ControllerContext;
 import org.jboss.dependency.spi.ControllerMode;
 import org.jboss.dependency.spi.ControllerState;
 import org.jboss.kernel.Kernel;
@@ -51,6 +52,8 @@
    private KernelController controller;
 
    protected ClassLoaderSystem system;
+   
+   protected ClassLoading classLoading;
 
    public AbstractMockLifeCycleUnitTest(String name)
    {
@@ -101,6 +104,14 @@
       return assertClassLoader(context);
    }
    
+   protected ClassLoader assertIsResolved(KernelControllerContext context) throws Exception
+   {
+      MockLifeCycle lifeCycle = assertLifeCycle(context);
+      assertTrue(context.getName() + " should be resolved: " + context.getDependencyInfo().getUnresolvedDependencies(null), lifeCycle.isResolved());
+      assertFalse(context.getName() + " should not be started", lifeCycle.isStarted());
+      return assertClassLoader(context);
+   }
+   
    protected ClassLoader assertStarted(KernelControllerContext context) throws Exception
    {
       MockLifeCycle lifeCycle = assertLifeCycle(context);
@@ -228,6 +239,9 @@
       builder.addMethodUninstallCallback("removeModule", null, null, ControllerState.CONFIGURED, null);
 
       install(builder.getBeanMetaData());
+      
+      ControllerContext ctx = controller.getInstalledContext("ClassLoading");
+      classLoading = (ClassLoading) ctx.getTarget();
    }
 
    protected void tearDown() throws Exception

Modified: projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/test/LifeCycleUnitTestCase.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/test/LifeCycleUnitTestCase.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/test/LifeCycleUnitTestCase.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -24,12 +24,14 @@
 import junit.framework.Test;
 
 import org.jboss.classloader.plugins.ClassLoaderUtils;
+import org.jboss.classloader.spi.filter.ClassFilterUtils;
 import org.jboss.classloading.plugins.metadata.PackageRequirement;
 import org.jboss.classloading.spi.dependency.policy.mock.MockClassLoadingMetaData;
 import org.jboss.classloading.spi.metadata.ClassLoadingMetaDataFactory;
 import org.jboss.kernel.spi.dependency.KernelControllerContext;
 import org.jboss.test.classloading.lifecycle.support.a.A;
 import org.jboss.test.classloading.lifecycle.support.a.MockLifeCycle;
+import org.jboss.test.classloading.lifecycle.support.a.MockLifeCycleClassLoaderPolicyModule;
 
 /**
  * LifeCycleUnitTestCase.
@@ -82,6 +84,70 @@
       }
    }
    
+   public void testResolveUsingClassLoadingAdmin() throws Exception
+   {
+      MockClassLoadingMetaData metaData1 = new MockClassLoadingMetaData("test1");
+      KernelControllerContext context1 = install(metaData1);
+      try
+      {
+         MockLifeCycleClassLoaderPolicyModule module1 = assertMockClassPolicyModule(context1);
+         assertNotResolved(context1);
+
+         MockClassLoadingMetaData metaData2 = new MockClassLoadingMetaData("test2");
+         KernelControllerContext context2 = install(metaData2);
+         try
+         {
+            MockLifeCycleClassLoaderPolicyModule module2 = assertMockClassPolicyModule(context2);
+            assertNotResolved(context2);
+         
+            assertTrue(classLoading.resolveModules(module1, module2));
+            assertResolved(context1);
+            assertResolved(context2);
+         }
+         finally
+         {
+            uninstall(context2);
+         }
+      }
+      finally
+      {
+         uninstall(context1);
+      }
+   }
+   
+   public void testNotResolvedUsingClassLoadingAdmin() throws Exception
+   {
+      MockClassLoadingMetaData metaData1 = new MockClassLoadingMetaData("test1");
+      KernelControllerContext context1 = install(metaData1);
+      try
+      {
+         MockLifeCycleClassLoaderPolicyModule module1 = assertMockClassPolicyModule(context1);
+         assertNotResolved(context1);
+
+         ClassLoadingMetaDataFactory factory = ClassLoadingMetaDataFactory.getInstance();
+         MockClassLoadingMetaData metaData2 = new MockClassLoadingMetaData("test2");
+         metaData2.getRequirements().addRequirement(factory.createRequireModule("doesNotExist"));
+         KernelControllerContext context2 = install(metaData2);
+         try
+         {
+            MockLifeCycleClassLoaderPolicyModule module2 = assertMockClassPolicyModule(context2);
+            assertNotResolved(context2);
+         
+            assertFalse(classLoading.resolveModules(module1, module2));
+            assertResolved(context1);
+            assertNotResolved(context2);
+         }
+         finally
+         {
+            uninstall(context2);
+         }
+      }
+      finally
+      {
+         uninstall(context1);
+      }
+   }
+   
    public void testUnresolve() throws Exception
    {
       MockClassLoadingMetaData metaData = new MockClassLoadingMetaData("test");
@@ -177,7 +243,7 @@
       {
          assertNotResolved(context);
          MockLifeCycle lifeCycleA = assertNotResolved(contextA);
-         lifeCycleA.lazyResolve = true;
+         lifeCycleA.setLazyResolve(true);
          
          resolve(context);
          ClassLoader cl = assertResolved(context);
@@ -213,6 +279,30 @@
       }
    }
    
+   public void testNotLazyStartWithFilter() throws Exception
+   {
+      MockClassLoadingMetaData metaData = new MockClassLoadingMetaData("test");
+      metaData.setPathsAndPackageNames(A.class);
+      KernelControllerContext context = install(metaData);
+      try
+      {
+         assertNotResolved(context);
+         MockLifeCycle lifeCycle = assertNotResolved(context);
+         lifeCycle.setLazyStart(true);
+         lifeCycle.setLazyStartFilter(ClassFilterUtils.NOTHING);
+         
+         resolve(context);
+         ClassLoader cl = assertResolved(context);
+         assertLoadClass(A.class, cl);
+         assertResolved(context);
+         assertFalse("Should NOT get start invocation", lifeCycle.gotStart);
+      }
+      finally
+      {
+         uninstall(context);
+      }
+   }
+   
    public void testLazyStart() throws Exception
    {
       MockClassLoadingMetaData metaData = new MockClassLoadingMetaData("test");
@@ -221,7 +311,7 @@
       try
       {
          MockLifeCycle lifeCycle = assertNotResolved(context);
-         lifeCycle.lazyStart = true;
+         lifeCycle.setLazyStart(true);
          
          resolve(context);
          ClassLoader cl = assertResolved(context);
@@ -233,4 +323,27 @@
          uninstall(context);
       }
    }
+   
+   public void testLazyStartWithFilter() throws Exception
+   {
+      MockClassLoadingMetaData metaData = new MockClassLoadingMetaData("test");
+      metaData.setPathsAndPackageNames(A.class);
+      KernelControllerContext context = install(metaData);
+      try
+      {
+         assertNotResolved(context);
+         MockLifeCycle lifeCycle = assertNotResolved(context);
+         lifeCycle.setLazyStart(true);
+         lifeCycle.setLazyStartFilter(ClassFilterUtils.createPackageClassFilter(ClassLoaderUtils.getClassPackageName(A.class.getName())));
+         
+         resolve(context);
+         ClassLoader cl = assertResolved(context);
+         assertLoadClass(A.class, cl);
+         assertTrue("Should get start invocation", lifeCycle.gotStart);
+      }
+      finally
+      {
+         uninstall(context);
+      }
+   }
 }

Added: projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/test/RefreshModulesUnitTestCase.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/test/RefreshModulesUnitTestCase.java	                        (rev 0)
+++ projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/lifecycle/test/RefreshModulesUnitTestCase.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -0,0 +1,630 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, 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.classloading.lifecycle.test;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.Test;
+
+import org.jboss.classloader.plugins.ClassLoaderUtils;
+import org.jboss.classloader.spi.ShutdownPolicy;
+import org.jboss.classloading.spi.dependency.Domain;
+import org.jboss.classloading.spi.dependency.ExportPackage;
+import org.jboss.classloading.spi.dependency.Module;
+import org.jboss.classloading.spi.dependency.policy.mock.MockClassLoaderPolicyModule;
+import org.jboss.classloading.spi.dependency.policy.mock.MockClassLoadingMetaData;
+import org.jboss.classloading.spi.metadata.ClassLoadingMetaDataFactory;
+import org.jboss.classloading.spi.version.VersionRange;
+import org.jboss.kernel.spi.dependency.KernelControllerContext;
+import org.jboss.test.classloading.dependency.support.a.A;
+import org.jboss.test.classloading.dependency.support.b.B;
+import org.jboss.test.classloading.lifecycle.support.a.MockLifeCycle;
+
+/**
+ * ClassLoadingAdmin unit tests
+ *
+ * @author adrian at jboss.org
+ */
+public class RefreshModulesUnitTestCase extends AbstractMockLifeCycleUnitTest
+{
+   static String PACKAGEA = ClassLoaderUtils.getClassPackageName(A.class.getName());
+   static String PACKAGEB = ClassLoaderUtils.getClassPackageName(B.class.getName());
+   
+   boolean lazyShutdown;
+   
+   public static Test suite()
+   {
+      return suite(RefreshModulesUnitTestCase.class);
+   }
+
+   public RefreshModulesUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public RefreshModulesUnitTestCase(String name, boolean lazyShutdown)
+   {
+      super(name);
+      this.lazyShutdown = lazyShutdown;
+   }
+
+   ClassLoadingMetaDataFactory factory = ClassLoadingMetaDataFactory.getInstance();
+   
+   MockClassLoaderPolicyModule moduleA;
+   MockLifeCycle lifecycleA;
+   Class<?> classA;
+   Domain domainA;
+   KernelControllerContext contextA;
+   
+   MockClassLoaderPolicyModule moduleA2;
+   MockLifeCycle lifecycleA2;
+   Class<?> classA2;
+   Domain domainA2;
+   KernelControllerContext contextA2;
+
+   MockClassLoaderPolicyModule moduleB;
+   MockLifeCycle lifecycleB;
+   Class<?> classB;
+   Domain domainB;
+   KernelControllerContext contextB;
+
+   MockClassLoaderPolicyModule moduleC;
+   MockLifeCycle lifecycleC;
+   KernelControllerContext contextC;
+
+   MockClassLoaderPolicyModule moduleD;
+   MockLifeCycle lifecycleD;
+   KernelControllerContext contextD;
+   
+   MockClassLoaderPolicyModule moduleE;
+   MockLifeCycle lifecycleE;
+   KernelControllerContext contextE;
+
+   @Override
+   protected KernelControllerContext install(MockClassLoadingMetaData metaData) throws Exception
+   {
+      if (lazyShutdown)
+         metaData.setShutdownPolicy(ShutdownPolicy.GARBAGE_COLLECTION);
+      return super.install(metaData);
+   }
+   
+   protected void setUpA() throws Exception
+   {
+      MockClassLoadingMetaData a = new MockClassLoadingMetaData("a", "1.0.0");
+      a.getCapabilities().addCapability(factory.createModule("ModuleA", "1.0.0"));
+      a.getCapabilities().addCapability(factory.createPackage(PACKAGEA, "1.0.0"));
+      a.setPathsAndPackageNames(A.class);
+      a.setDomain("main");
+      contextA = install(a);
+      moduleA = assertMockClassPolicyModule(contextA);
+      lifecycleA = assertLifeCycle(contextA);
+      resolve(contextA);
+      ClassLoader clA = assertClassLoader(contextA);
+      classA = clA.loadClass(A.class.getName());
+      domainA = moduleA.checkDomain();
+   }
+   
+   protected void setUpB() throws Exception
+   {
+      MockClassLoadingMetaData b = new MockClassLoadingMetaData("b", "2.0.0");
+      b.setDomain("other");
+      b.getCapabilities().addCapability(factory.createModule("ModuleBAlias", "3.0.0"));
+      b.getCapabilities().addCapability(factory.createModule("ModuleB", "2.0.0"));
+      b.getCapabilities().addCapability(factory.createPackage(PACKAGEB, "2.0.0"));
+      b.setPathsAndPackageNames(B.class);
+      contextB = install(b);
+      moduleB = assertMockClassPolicyModule(contextB);
+      lifecycleB = assertLifeCycle(contextB);
+      resolve(contextB);
+      ClassLoader clB = assertClassLoader(contextB);
+      classB = clB.loadClass(B.class.getName());
+      domainB = moduleB.checkDomain();
+   }
+   
+   protected void setUpAB() throws Exception
+   {
+      setUpA();
+
+      MockClassLoadingMetaData a2 = new MockClassLoadingMetaData("a", "2.0.0");
+      a2.getCapabilities().addCapability(factory.createModule("ModuleA", "2.0.0"));
+      a2.getCapabilities().addCapability(factory.createPackage(PACKAGEA, "2.0.0"));
+      a2.getCapabilities().addCapability(factory.createPackage(PACKAGEB, "2.0.0"));
+      a2.setPathsAndPackageNames(A.class);
+      a2.setDomain("main");
+      contextA2 = install(a2);
+      moduleA2 = assertMockClassPolicyModule(contextA2);
+      lifecycleA2 = assertLifeCycle(contextA2);
+      resolve(contextA2);
+      ClassLoader clA2 = assertClassLoader(contextA2);
+      classA2 = clA2.loadClass(A.class.getName());
+      domainA2 = moduleA2.checkDomain();
+
+      setUpB();
+   }
+
+   protected void setUpABCDE() throws Exception
+   {
+      setUpAB();
+      
+      MockClassLoadingMetaData c = new MockClassLoadingMetaData("c", "2.0.0");
+      c.getRequirements().addRequirement(factory.createRequireModule("ModuleA", VersionRange.valueOf("1.0.0")));
+      c.getRequirements().addRequirement(factory.createRequirePackage(PACKAGEA, VersionRange.valueOf("1.0.0")));
+      c.setDomain("main");
+      contextC = install(c);
+      moduleC = assertMockClassPolicyModule(contextC);
+      lifecycleC = assertLifeCycle(contextC);
+      resolve(contextC);
+      ClassLoader clC = assertClassLoader(contextC);
+      clC.loadClass(A.class.getName());
+
+      MockClassLoadingMetaData d = new MockClassLoadingMetaData("d", "5.0.0");
+      d.getRequirements().addRequirement(factory.createRequireModule("ModuleB", new VersionRange("2.0.0")));
+      d.getRequirements().addRequirement(factory.createRequirePackage(PACKAGEB, new VersionRange("2.0.0")));
+      d.setDomain("other");
+      contextD = install(d);
+      moduleD = assertMockClassPolicyModule(contextD);
+      lifecycleD = assertLifeCycle(contextD);
+      resolve(contextD);
+      ClassLoader clD = assertClassLoader(contextD);
+      clD.loadClass(B.class.getName());
+
+      MockClassLoadingMetaData e = new MockClassLoadingMetaData("e", "5.0.0");
+      e.getRequirements().addRequirement(factory.createRequireModule("ModuleB", new VersionRange("2.0.0")));
+      e.setDomain("other");
+      contextE = install(e);
+      moduleE = assertMockClassPolicyModule(contextB);
+      lifecycleE = assertLifeCycle(contextE);
+      resolve(contextE);
+      moduleE = assertMockClassPolicyModule(contextE);
+      ClassLoader clE = assertClassLoader(contextE);
+      clE.loadClass(B.class.getName());
+   }
+   
+   public void testRefreshModulesSimple() throws Exception
+   {
+      setUpAB();
+      
+      resetFlags();
+      classLoading.refreshModules(moduleA);
+      assertBounce(contextA);
+      assertNoBounce(contextA2);
+      assertNoBounce(contextB);
+   }
+   
+   public void testRefreshModulesMultiple() throws Exception
+   {
+      setUpAB();
+      
+      resetFlags();
+      classLoading.refreshModules(moduleA, moduleB);
+      assertBounce(contextA);
+      assertNoBounce(contextA2);
+      assertBounce(contextB);
+   }
+   
+   public void testRefreshModulesNothing() throws Exception
+   {
+      setUpAB();
+      
+      resetFlags();
+      classLoading.refreshModules();
+      assertNoBounce(contextA);
+      assertNoBounce(contextA2);
+      assertNoBounce(contextB);
+   }
+   
+   public void testRefreshModulesCascaded() throws Exception
+   {
+      setUpABCDE();
+      
+      resetFlags();
+      classLoading.refreshModules(moduleA);
+      assertBounce(contextA);
+      assertNoBounce(contextA2);
+      assertNoBounce(contextB);
+      assertReResolved(contextC);
+      assertNoBounce(contextD);
+      assertNoBounce(contextE);
+   }
+   
+   public void testRefreshModulesNonCascaded() throws Exception
+   {
+      lazyShutdown = true;
+      setUpABCDE();
+      
+      resetFlags();
+      classLoading.refreshModules(moduleA);
+      assertBounce(contextA);
+      assertNoBounce(contextA2);
+      assertNoBounce(contextB);
+      assertBounce(contextC);
+      assertNoBounce(contextD);
+      assertNoBounce(contextE);
+   }
+   
+   public void testRefreshModulesNotResolvedCascaded() throws Exception
+   {
+      setUpABCDE();
+      
+      resetFlags();
+      unresolve(contextA);
+      assertNotResolved(contextA);
+      assertNotResolved(contextC);
+
+      resetFlags();
+      classLoading.refreshModules(moduleA);
+      assertNotResolved(contextA);
+      assertNoBounce(contextA);
+      assertNoBounce(contextA2);
+      assertNoBounce(contextB);
+      assertNotResolved(contextC);
+      assertNoBounce(contextC);
+      assertNoBounce(contextD);
+      assertNoBounce(contextE);
+   }
+   
+   public void testRefreshModulesNotResolvedNonCascaded() throws Exception
+   {
+      lazyShutdown = true;
+      setUpABCDE();
+      
+      resetFlags();
+      unresolve(contextA);
+      assertNotResolved(contextA);
+      assertIsResolved(contextC);
+
+      resetFlags();
+      classLoading.refreshModules(moduleA);
+      assertNotResolved(contextA);
+      assertNoBounce(contextA);
+      assertNoBounce(contextA2);
+      assertNoBounce(contextB);
+      assertFailedBounce(contextC);
+      assertNoBounce(contextD);
+      assertNoBounce(contextE);
+   }
+   
+   public void testRefreshModulesUninstalledCascaded() throws Exception
+   {
+      setUpABCDE();
+      
+      resetFlags();
+      uninstall(contextA);
+      assertNotResolved(contextC);
+
+      resetFlags();
+      classLoading.refreshModules(moduleA);
+      assertNoBounce(contextA2);
+      assertNoBounce(contextB);
+      assertNoBounce(contextC);
+      assertNotResolved(contextC);
+      assertNoBounce(contextD);
+      assertNoBounce(contextE);
+   }
+   
+   public void testRefreshModulesUninstalledNonCascaded() throws Exception
+   {
+      lazyShutdown = true;
+      setUpABCDE();
+      
+      resetFlags();
+      uninstall(contextA);
+      assertIsResolved(contextC);
+
+      resetFlags();
+      classLoading.refreshModules(moduleA);
+      assertNoBounce(contextA2);
+      assertNoBounce(contextB);
+      assertFailedBounce(contextC);
+      assertNoBounce(contextD);
+      assertNoBounce(contextE);
+   }
+   
+   public void testRefreshModulesAllCascaded() throws Exception
+   {
+      setUpABCDE();
+      
+      resetFlags();
+      uninstall(contextA);
+      assertNotResolved(contextC);
+
+      resetFlags();
+      classLoading.refreshModules();
+      assertNoBounce(contextA2);
+      assertNoBounce(contextB);
+      assertNoBounce(contextC);
+      assertNoBounce(contextD);
+      assertNoBounce(contextE);
+   }
+   
+   public void testRefreshModulesAllNonCascaded() throws Exception
+   {
+      lazyShutdown = true;
+      setUpABCDE();
+      
+      resetFlags();
+      uninstall(contextA);
+      assertIsResolved(contextC);
+
+      resetFlags();
+      classLoading.refreshModules();
+      assertNoBounce(contextA2);
+      assertNoBounce(contextB);
+      assertFailedBounce(contextC);
+      assertNoBounce(contextD);
+      assertNoBounce(contextE);
+
+      // Shouldn't do it twice
+      resetFlags();
+      classLoading.refreshModules();
+      assertNoBounce(contextA2);
+      assertNoBounce(contextB);
+      assertNoBounce(contextC);
+      assertNoBounce(contextD);
+      assertNoBounce(contextE);
+   }
+   
+   public void testRefreshModulesAllMultipleCascaded() throws Exception
+   {
+      setUpABCDE();
+      
+      resetFlags();
+      uninstall(contextA);
+      uninstall(contextB);
+      assertIsResolved(contextA2);
+      assertNotResolved(contextC);
+      assertNotResolved(contextD);
+      assertNotResolved(contextE);
+
+      resetFlags();
+      classLoading.refreshModules();
+      assertNoBounce(contextA2);
+      assertNoBounce(contextC);
+      assertNoBounce(contextD);
+      assertNoBounce(contextE);
+   }
+   
+   public void testRefreshModulesAllMultipleNonCascaded() throws Exception
+   {
+      lazyShutdown = true;
+      setUpABCDE();
+      
+      resetFlags();
+      uninstall(contextA);
+      uninstall(contextB);
+      assertIsResolved(contextA2);
+      assertIsResolved(contextC);
+      assertIsResolved(contextD);
+      assertIsResolved(contextE);
+
+      resetFlags();
+      classLoading.refreshModules();
+      assertNoBounce(contextA2);
+      assertFailedBounce(contextC);
+      assertFailedBounce(contextD);
+      assertFailedBounce(contextE);
+
+      // Shouldn't do it twice
+      resetFlags();
+      classLoading.refreshModules();
+      assertNoBounce(contextA2);
+      assertNoBounce(contextC);
+      assertNoBounce(contextD);
+      assertNoBounce(contextE);
+   }
+   
+   public void testRefreshModulesReinstalledCascaded() throws Exception
+   {
+      setUpABCDE();
+
+      assertExportedPackageImporting(PACKAGEA, VersionRange.valueOf("1.0.0"), moduleC);
+      
+      resetFlags();
+      uninstall(contextA);
+      assertNotResolved(contextC);
+
+      setUpA();
+      assertResolved(contextA);
+      assertResolved(contextC);
+
+      ExportPackage result = assertExportedPackageImporting(PACKAGEA, VersionRange.valueOf("1.0.0"), moduleC);
+      assertEquals(moduleA, result.getModule());
+
+      resetFlags();
+      classLoading.refreshModules(moduleA);
+      assertBounce(contextA);
+      assertNoBounce(contextA2);
+      assertNoBounce(contextB);
+      assertReResolved(contextC);
+      assertNoBounce(contextD);
+      assertNoBounce(contextE);
+
+      result = assertExportedPackageImporting(PACKAGEA, VersionRange.valueOf("1.0.0"), moduleC);
+      assertEquals(moduleA, result.getModule());
+   }
+   
+   public void testRefreshModulesReinstalledNonCascaded() throws Exception
+   {
+      lazyShutdown = true;
+      setUpABCDE();
+
+      assertExportedPackageImporting(PACKAGEA, VersionRange.valueOf("1.0.0"), moduleC);
+      
+      resetFlags();
+      Module oldModuleA = moduleA;
+      uninstall(contextA);
+      assertIsResolved(contextC);
+
+      setUpA();
+      assertResolved(contextA);
+      assertNoBounce(contextC);
+
+      ExportPackage result = assertExportedPackageImporting(PACKAGEA, VersionRange.valueOf("1.0.0"));
+      assertEquals(moduleA, result.getModule());
+      
+      resetFlags();
+      classLoading.refreshModules(oldModuleA);
+      assertNoBounce(contextA);
+      assertNoBounce(contextA2);
+      assertNoBounce(contextB);
+      assertBounce(contextC);
+      assertNoBounce(contextD);
+      assertNoBounce(contextE);
+   }
+   
+   public void testRefreshModulesAllReinstalledCascaded() throws Exception
+   {
+      setUpABCDE();
+
+      assertExportedPackageImporting(PACKAGEA, VersionRange.valueOf("1.0.0"), moduleC);
+      
+      resetFlags();
+      uninstall(contextA);
+      assertNotResolved(contextC);
+
+      setUpA();
+      assertResolved(contextA);
+      assertResolved(contextC);
+
+      ExportPackage result = assertExportedPackageImporting(PACKAGEA, VersionRange.valueOf("1.0.0"), moduleC);
+      assertEquals(moduleA, result.getModule());
+
+      resetFlags();
+      classLoading.refreshModules();
+      assertNoBounce(contextA);
+      assertNoBounce(contextA2);
+      assertNoBounce(contextB);
+      assertNoBounce(contextC);
+      assertNoBounce(contextD);
+      assertNoBounce(contextE);
+
+      result = assertExportedPackageImporting(PACKAGEA, VersionRange.valueOf("1.0.0"), moduleC);
+      assertEquals(moduleA, result.getModule());
+   }
+   
+   public void testRefreshModulesAllReinstalledNonCascaded() throws Exception
+   {
+      lazyShutdown = true;
+      setUpABCDE();
+
+      assertExportedPackageImporting(PACKAGEA, VersionRange.valueOf("1.0.0"), moduleC);
+      
+      resetFlags();
+      uninstall(contextA);
+      assertIsResolved(contextC);
+
+      setUpA();
+      assertResolved(contextA);
+      assertNoBounce(contextC);
+
+      ExportPackage result = assertExportedPackageImporting(PACKAGEA, VersionRange.valueOf("1.0.0"));
+      assertEquals(moduleA, result.getModule());
+
+      resetFlags();
+      classLoading.refreshModules();
+      assertNoBounce(contextA);
+      assertNoBounce(contextA2);
+      assertNoBounce(contextB);
+      assertBounce(contextC);
+      assertNoBounce(contextD);
+      assertNoBounce(contextE);
+      
+      // Should not do it twice
+      resetFlags();
+      classLoading.refreshModules();
+      assertNoBounce(contextA);
+      assertNoBounce(contextA2);
+      assertNoBounce(contextB);
+      assertNoBounce(contextC);
+      assertNoBounce(contextD);
+      assertNoBounce(contextE);
+
+      result = assertExportedPackageImporting(PACKAGEA, VersionRange.valueOf("1.0.0"), moduleC);
+      assertEquals(moduleA, result.getModule());
+   }
+
+   protected void assertBounce(KernelControllerContext context) throws Exception
+   {
+      MockLifeCycle lifecycle = assertLifeCycle(context);
+      assertTrue(context.getName() + " should have bounced", lifecycle.gotBounce);
+      assertTrue(context.getName() + " should have unresolved", lifecycle.gotUnresolved);
+      assertResolved(context);
+   }
+
+   protected void assertReResolved(KernelControllerContext context) throws Exception
+   {
+      MockLifeCycle lifecycle = assertLifeCycle(context);
+      assertTrue(context.getName() + " should have unresolved", lifecycle.gotUnresolved);
+      assertResolved(context);
+   }
+
+   protected void assertFailedBounce(KernelControllerContext context) throws Exception
+   {
+      MockLifeCycle lifecycle = assertLifeCycle(context);
+      assertTrue(context.getName() + " should have bounced", lifecycle.gotBounce);
+      assertTrue(context.getName() + " should have unresolved", lifecycle.gotUnresolved);
+      assertNotResolved(context);
+   }
+
+   protected void assertNoBounce(KernelControllerContext context) throws Exception
+   {
+      MockLifeCycle lifecycle = assertLifeCycle(context);
+      assertFalse(context.getName() + " should not have bounced", lifecycle.gotBounce);
+      assertFalse(context.getName() + " should not have unresolved", lifecycle.gotUnresolved);
+      assertFalse(context.getName() + " should not have resolved", lifecycle.gotResolved);
+   }
+      
+   protected ExportPackage assertExportedPackageImporting(String name, VersionRange range, Module... expected) throws Exception
+   {
+      Collection<ExportPackage> exportPackages = classLoading.getExportedPackages(name, range);
+      assertTrue(exportPackages.toString(), exportPackages.size() == 1);
+      ExportPackage exportPackage = exportPackages.iterator().next();
+      assertModules(exportPackage.getImportingModules(), expected);
+      return exportPackage;
+   }
+   
+   protected void assertModules(Collection<Module> actual, Module... expected) throws Exception
+   {
+      Set<Module> expect = new HashSet<Module>();
+      for (Module module : expected)
+         expect.add(module);
+      
+      Set<Module> act = new HashSet<Module>(actual);
+      
+      assertEquals(expect, act);
+   }
+
+   protected void resetFlags()
+   {
+      lifecycleA.resetFlags();
+      lifecycleA2.resetFlags();
+      lifecycleB.resetFlags();
+      if (lifecycleC != null)
+         lifecycleC.resetFlags();
+      if (lifecycleD != null)
+         lifecycleD.resetFlags();
+      if (lifecycleE != null)
+         lifecycleE.resetFlags();
+   }
+}

Modified: projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/version/test/VersionRangeUnitTestCase.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/version/test/VersionRangeUnitTestCase.java	2010-03-02 13:00:00 UTC (rev 101713)
+++ projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/version/test/VersionRangeUnitTestCase.java	2010-03-02 13:11:14 UTC (rev 101714)
@@ -235,6 +235,70 @@
       assertEquals(range, other);
    }
    
+   public void testParseVersionRange() throws Exception
+   {
+      testParseVersionRange("", null, true, null, true);
+
+      testParseVersionRange("[,]", null, true, null, true);
+      testParseVersionRange("[,)", null, true, null, false);
+      testParseVersionRange("(,]", null, false, null, true);
+      testParseVersionRange("(,)", null, false, null, false);
+      
+      testParseVersionRange("2.0.0", "2.0.0", true, "2.0.0", true);
+      testParseVersionRange("[2.0.0]", "2.0.0", true, "2.0.0", true);
+      testParseVersionRange("[2.0.0)", "2.0.0", true, null, false);
+      testParseVersionRange("(2.0.0)", "2.0.0", false, null, false);
+
+      testParseVersionRange("[,2.0.0]", null, true, "2.0.0", true);
+      testParseVersionRange("[1.0.0,]", "1.0.0", true, "1.0.0", true);
+
+      testParseVersionRange("[1.0.0,1.0.0]", "1.0.0", true, "1.0.0", true);
+
+      testParseVersionRange("[1.0.0,2.0.0]", "1.0.0", true, "2.0.0", true);
+      testParseVersionRange("[1.0.0,2.0.0)", "1.0.0", true, "2.0.0", false);
+      testParseVersionRange("(1.0.0,2.0.0]", "1.0.0", false, "2.0.0", true);
+      testParseVersionRange("(1.0.0,2.0.0)", "1.0.0", false, "2.0.0", false);
+
+      testParseVersionRange(" (1.0.0,2.0.0)", "1.0.0", false, "2.0.0", false);
+      testParseVersionRange("( 1.0.0,2.0.0)", "1.0.0", false, "2.0.0", false);
+      testParseVersionRange("(1.0.0 ,2.0.0)", "1.0.0", false, "2.0.0", false);
+      testParseVersionRange("(1.0.0, 2.0.0)", "1.0.0", false, "2.0.0", false);
+      testParseVersionRange("(1.0.0,2.0.0 )", "1.0.0", false, "2.0.0", false);
+      testParseVersionRange("(1.0.0,2.0.0) ", "1.0.0", false, "2.0.0", false);
+
+      testBadParseVersionRange(null, IllegalArgumentException.class);
+      testBadParseVersionRange("x", IllegalArgumentException.class);
+      testBadParseVersionRange("1,", IllegalArgumentException.class);
+      testBadParseVersionRange(",1", IllegalArgumentException.class);
+      testBadParseVersionRange("1,x", IllegalArgumentException.class);
+      testBadParseVersionRange("x,1", IllegalArgumentException.class);
+
+      testBadParseVersionRange("[", IllegalArgumentException.class);
+      testBadParseVersionRange("(", IllegalArgumentException.class);
+      testBadParseVersionRange("]", IllegalArgumentException.class);
+      testBadParseVersionRange(")", IllegalArgumentException.class);
+      testBadParseVersionRange(",", IllegalArgumentException.class);
+      testBadParseVersionRange("[1,2", IllegalArgumentException.class);
+      testBadParseVersionRange("(1,2", IllegalArgumentException.class);
+      testBadParseVersionRange("1,2]", IllegalArgumentException.class);
+      testBadParseVersionRange("1,2)", IllegalArgumentException.class);
+      testBadParseVersionRange("[x]", IllegalArgumentException.class);
+      testBadParseVersionRange("[1,x]", IllegalArgumentException.class);
+      testBadParseVersionRange("[x,1]", IllegalArgumentException.class);
+
+      testBadParseVersionRangeWrongPlace("[");
+      testBadParseVersionRangeWrongPlace("(");
+      testBadParseVersionRangeWrongPlace("]");
+      testBadParseVersionRangeWrongPlace(")");
+      testBadParseVersionRangeWrongPlace(",");
+
+      testBadParseVersionRange("(1.0.0]", IllegalArgumentException.class);
+      testBadParseVersionRange("(1.0.0,0.0.0)", IllegalArgumentException.class);
+      testBadParseVersionRange("(1.0.0,1.0.0)", IllegalArgumentException.class);
+      testBadParseVersionRange("[1.0.0,1.0.0)", IllegalArgumentException.class);
+      testBadParseVersionRange("(1.0.0,1.0.0]", IllegalArgumentException.class);
+   }
+   
    protected void testVersionRangeFromString(String low)
    {
       testVersionRange(low);
@@ -554,4 +618,42 @@
       else
          assertFalse("Expected " + range1 + ".isConsistent(" + range2 + ") to be false", range1.isConsistent(range2));
    }
+   
+   protected void testParseVersionRange(String range, String low, boolean lowInclusive, String high, boolean highInclusive) throws Exception
+   {
+      VersionRange expected = new VersionRange(low, lowInclusive, high, highInclusive);
+      VersionRange actual = VersionRange.parseRangeSpec(range);
+      assertEquals(expected, actual);
+   }
+   
+   protected void testBadParseVersionRange(String range, Class<? extends Throwable> expected) throws Exception
+   {
+      try
+      {
+         VersionRange.parseRangeSpec(range);
+         fail("Should not be here: " + range);
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(expected, t);
+      }
+   }
+   
+   protected void testBadParseVersionRangeWrongPlace(String wrong) throws Exception
+   {
+      testBadParseVersionRangeWrongPlace("[", "]", wrong);
+      testBadParseVersionRangeWrongPlace("[", ")", wrong);
+      testBadParseVersionRangeWrongPlace("(", "]", wrong);
+      testBadParseVersionRangeWrongPlace("(", ")", wrong);
+   }
+   
+   protected void testBadParseVersionRangeWrongPlace(String start, String end, String wrong) throws Exception
+   {
+      testBadParseVersionRange(wrong + start + "1,2" + end, IllegalArgumentException.class);
+      testBadParseVersionRange(start + wrong + "1,2" + end, IllegalArgumentException.class);
+      testBadParseVersionRange(start + "1" + wrong + ",2" + end, IllegalArgumentException.class);
+      testBadParseVersionRange(start + "1," + wrong + "2" + end, IllegalArgumentException.class);
+      testBadParseVersionRange(start + "1,2" + wrong + end, IllegalArgumentException.class);
+      testBadParseVersionRange(start + "1,2" + end + wrong, IllegalArgumentException.class);
+   }
 }




More information about the jboss-cvs-commits mailing list