[jboss-cvs] JBossAS SVN: r102060 - in projects/jboss-cl/trunk: classloader/src/main/java/org/jboss/classloader/spi and 4 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon Mar 8 08:07:27 EST 2010


Author: adrian at jboss.org
Date: 2010-03-08 08:07:26 -0500 (Mon, 08 Mar 2010)
New Revision: 102060

Modified:
   projects/jboss-cl/trunk/classloader/src/main/java/org/jboss/classloader/spi/ClassLoaderPolicy.java
   projects/jboss-cl/trunk/classloader/src/main/java/org/jboss/classloader/spi/base/BaseDelegateLoader.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/test/java/org/jboss/test/classloading/dependency/test/DependencyUnitTestCase.java
   projects/jboss-cl/trunk/pom.xml
Log:
[JBCL-156] - Add circular dependency checking - fix the delegate construction so it is back to being lazy.

Modified: projects/jboss-cl/trunk/classloader/src/main/java/org/jboss/classloader/spi/ClassLoaderPolicy.java
===================================================================
--- projects/jboss-cl/trunk/classloader/src/main/java/org/jboss/classloader/spi/ClassLoaderPolicy.java	2010-03-08 12:32:07 UTC (rev 102059)
+++ projects/jboss-cl/trunk/classloader/src/main/java/org/jboss/classloader/spi/ClassLoaderPolicy.java	2010-03-08 13:07:26 UTC (rev 102060)
@@ -449,7 +449,20 @@
    @Override
    protected void toLongString(StringBuilder builder)
    {
-      builder.append(" delegates=").append(getDelegates());
+      List<? extends DelegateLoader> delegates = getDelegates();
+      if (delegates != null && delegates.isEmpty() == false)
+      {
+         builder.append(" delegates=[");
+         boolean first = true;
+         for (DelegateLoader delegate : delegates)
+         {
+            if (first == false)
+               builder.append(',');
+            first = false;
+            builder.append(delegate.toLongString());
+         }
+         builder.append(']');
+      }
       String[] packageNames = getPackageNames();
       if (packageNames != null)
          builder.append(" exported=").append(Arrays.asList(packageNames));

Modified: projects/jboss-cl/trunk/classloader/src/main/java/org/jboss/classloader/spi/base/BaseDelegateLoader.java
===================================================================
--- projects/jboss-cl/trunk/classloader/src/main/java/org/jboss/classloader/spi/base/BaseDelegateLoader.java	2010-03-08 12:32:07 UTC (rev 102059)
+++ projects/jboss-cl/trunk/classloader/src/main/java/org/jboss/classloader/spi/base/BaseDelegateLoader.java	2010-03-08 13:07:26 UTC (rev 102060)
@@ -113,15 +113,9 @@
    BaseClassLoader getBaseClassLoader(String message, String context)
    {
       BaseClassLoader result = null;
-      try
-      {
-         BaseClassLoaderPolicy policy = getPolicy();
-         if (policy != null)
-            result = policy.getClassLoader();
-      }
-      catch (IllegalStateException ignored)
-      {
-      }
+      BaseClassLoaderPolicy policy = getPolicy();
+      if (policy != null)
+         result = policy.getClassLoaderUnchecked();
       if (result == null)
          log.warn("Not " + message + context + " from policy that has no classLoader: " + toLongString());
       return result;
@@ -185,7 +179,7 @@
       builder.append(getClass().getSimpleName());
       builder.append("@").append(Integer.toHexString(System.identityHashCode(this)));
       if (delegate != null)
-         builder.append("{delegate=").append(delegate.toLongString());
+         builder.append("{delegate=").append(delegate);
       else
          builder.append("{factory=").append(factory);
       toLongString(builder);

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-08 12:32:07 UTC (rev 102059)
+++ projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/Module.java	2010-03-08 13:07:26 UTC (rev 102060)
@@ -39,15 +39,12 @@
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CopyOnWriteArraySet;
 
-import org.jboss.classloader.spi.ClassLoaderPolicy;
 import org.jboss.classloader.spi.ClassLoaderSystem;
 import org.jboss.classloader.spi.DelegateLoader;
 import org.jboss.classloader.spi.ParentPolicy;
 import org.jboss.classloader.spi.ShutdownPolicy;
 import org.jboss.classloader.spi.base.BaseClassLoader;
 import org.jboss.classloader.spi.filter.ClassFilter;
-import org.jboss.classloader.spi.filter.FilteredDelegateLoader;
-import org.jboss.classloader.spi.filter.PackageClassFilter;
 import org.jboss.classloading.plugins.metadata.PackageCapability;
 import org.jboss.classloading.plugins.metadata.PackageRequirement;
 import org.jboss.classloading.spi.helpers.NameAndVersionSupport;
@@ -59,6 +56,7 @@
 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.plugins.ResolvedState;
 import org.jboss.dependency.spi.Controller;
 import org.jboss.dependency.spi.ControllerContext;
 import org.jboss.dependency.spi.ControllerState;
@@ -728,8 +726,8 @@
       if (dependencies == null || dependencies.isEmpty())
          return;
       
-      // Maps the ClassLoaderPolicy that we get from the iDependOnModule to the list of package names that we are importing
-      Map<ClassLoaderPolicy, List<String>> delegateToRequiredPackages = new LinkedHashMap<ClassLoaderPolicy, List<String>>();
+      // Maps the iDependOnModule to the list of package names that we are importing
+      Map<Module, List<String>> delegateToRequiredPackages = new LinkedHashMap<Module, List<String>>();
       
       for (RequirementDependencyItem item : dependencies)
       {
@@ -749,26 +747,22 @@
                dynamic.add(delegate);
                continue;
             }
-
-            String name = (String) item.getIDependOn();
-            if (name == null)
+            
+            Module iDependOnModule = item.getResolvedModule();
+            if (iDependOnModule == null)
             {
-               // Optional requirement, just ignore
-               if (requirement.isOptional())
-                  continue;
-               // Something has gone wrong
-               throw new IllegalStateException("No iDependOn for item: " + item);
+               // Do it the hard way - probably optional or a self dependency?
+               String name = (String) item.getIDependOn();
+               if (name != null)
+                  iDependOnModule = checkDomain().getModule(name);
+               if (iDependOnModule == null)
+               {
+                  if (requirement.isOptional())
+                     continue;
+                  throw new IllegalStateException("Module not found for requirement: " + item);
+               }
             }
-            
-            Module iDependOnModule = checkDomain().getModule(name);
-            if (iDependOnModule == null)
-               throw new IllegalStateException("Module not found with name: " + name);
 
-            // Determine the delegate loader for the module
-            DelegateLoader delegate = iDependOnModule.getDelegateLoader(module, requirement);
-            if (delegate == null)
-               throw new IllegalStateException("Cannot obtain delegate for: " + requirement); 
-
             // Check for re-export by the module
             if (requirement.wantReExports())
                addDelegates(iDependOnModule, delegates, dynamic, visited, true);
@@ -779,12 +773,11 @@
                // If we are connecting to another module we collect the imported package names per delegate
                if (requirement instanceof PackageRequirement)
                {
-                  ClassLoaderPolicy policy = delegate.getPolicy();
-                  List<String> packageNames = delegateToRequiredPackages.get(policy);
+                  List<String> packageNames = delegateToRequiredPackages.get(iDependOnModule);
                   if (packageNames == null)
                   {
                      packageNames = new ArrayList<String>();
-                     delegateToRequiredPackages.put(policy, packageNames);
+                     delegateToRequiredPackages.put(iDependOnModule, packageNames);
                   }
                   
                   PackageRequirement packageRequirement = (PackageRequirement)requirement;
@@ -792,6 +785,10 @@
                }
                else
                {
+                  // Determine the delegate loader for the module
+                  DelegateLoader delegate = iDependOnModule.getDelegateLoader(module, requirement);
+                  if (delegate == null)
+                     throw new IllegalStateException("Cannot obtain delegate for: " + requirement); 
                   delegates.add(delegate);
                }
             }
@@ -799,10 +796,11 @@
       }
       
       // Add FilteredDelegateLoaders for all collected package requirements
-      for (Entry<ClassLoaderPolicy, List<String>> entry : delegateToRequiredPackages.entrySet())
+      for (Entry<Module, List<String>> entry : delegateToRequiredPackages.entrySet())
       {
-         PackageClassFilter filter = PackageClassFilter.createPackageClassFilter(entry.getValue());
-         delegates.add(new FilteredDelegateLoader(entry.getKey(), filter));
+         Module iDependOnModule = entry.getKey();
+         DelegateLoader delegate = iDependOnModule.getDelegateLoader(module, entry.getValue());
+         delegates.add(delegate);
       }
    }
 
@@ -825,6 +823,15 @@
    public abstract DelegateLoader getDelegateLoader(Module requiringModule, Requirement requirement);
 
    /**
+    * Get a delegate loader filtered by packages
+    * 
+    * @param requiringModule the requiring module
+    * @param packages the packages to filter on
+    * @return the delegate loader
+    */
+   public abstract DelegateLoader getDelegateLoader(Module requiringModule, List<String> packages);
+
+   /**
     * Get the exported packages
     * 
     * @return the exported packages
@@ -1223,7 +1230,7 @@
          throw new IllegalStateException("No controller context");
       
       // Remove the DependsOnMe part of this item
-      item.setResolved(false);
+      item.setResolved(ResolvedState.UNRESOLVED);
       
       // Remove the IDependOn part of this item
       DependencyInfo dependencyInfo = context.getDependencyInfo();

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-08 12:32:07 UTC (rev 102059)
+++ projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/RequirementDependencyItem.java	2010-03-08 13:07:26 UTC (rev 102060)
@@ -23,6 +23,7 @@
 
 import org.jboss.classloading.spi.metadata.Requirement;
 import org.jboss.dependency.plugins.AbstractDependencyItem;
+import org.jboss.dependency.plugins.ResolvedState;
 import org.jboss.dependency.spi.Controller;
 import org.jboss.dependency.spi.ControllerContext;
 import org.jboss.dependency.spi.ControllerState;
@@ -48,7 +49,7 @@
    private Requirement requirement;
 
    /** The module we resolved to */
-   private Module resolvedModule;
+   private volatile Module resolvedModule;
    
    /**
     * Create a new RequirementDependencyItem.
@@ -128,26 +129,26 @@
       // Self dependency
       if (module == this.module)
       {
-         Object iDependOn = module.getContextName();
-         ControllerContext context = controller.getContext(iDependOn, null);
+         ControllerContext context = module.getControllerContext();
          setIDependOn(context.getName());
          setResolved(true);
-         return isResolved();
+         return true;
       }
 
-      // Resolved against a context in the dependent state  
-      Object iDependOn = module.getContextName();
-      ControllerContext context = controller.getContext(iDependOn, getDependentState());
+      resolvedModule = module;
+
+      // Use semi-resolve to avoid circular references  
+      ControllerContext context = module.getControllerContext();
       if (context != null)
       {
-         setIDependOn(context.getName());
-         resolvedModule = module;
-         module.addDepends(this);
-         if (module.isCascadeShutdown())
-            addDependsOnMe(controller, context);
-         setResolved(true);
-         if (module.getClassLoadingSpace() == null)
-            log.warn(getModule() + " resolved " + getRequirement() + " to " + module + " which has import-all=true. Cannot check its consistency.");
+         boolean resolved = semiResolve(context);
+         if (resolved)
+         {
+            setIDependOn(context.getName());
+            module.addDepends(this);
+            if (module.getClassLoadingSpace() == null)
+               log.warn(getModule() + " resolved " + getRequirement() + " to " + module + " which has import-all=true. Cannot check its consistency.");
+         }
          return isResolved();
       }
 
@@ -156,6 +157,15 @@
    }
 
    @Override
+   protected void addDependsOnMe(Controller controller, ControllerContext context)
+   {
+      Module resolvedModule = getResolvedModule();
+      if (resolvedModule != null && resolvedModule.isCascadeShutdown() == false)
+         return;
+      super.addDependsOnMe(controller, context);
+   }
+
+   @Override
    public boolean unresolved(Controller controller)
    {
       setIDependOn(null);
@@ -164,9 +174,10 @@
    }
 
    @Override
-   protected void setResolved(boolean resolved)
+   public void setResolved(ResolvedState resolved)
    {
-      if (resolved == false && resolvedModule != null)
+      Module resolvedModule = getResolvedModule();
+      if (resolved == ResolvedState.UNRESOLVED && resolvedModule != null)
       {
          resolvedModule.removeDepends(this);
          resolvedModule.removeDependsOnMe(this);

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-08 12:32:07 UTC (rev 102059)
+++ projects/jboss-cl/trunk/classloading/src/main/java/org/jboss/classloading/spi/dependency/policy/ClassLoaderPolicyModule.java	2010-03-08 13:07:26 UTC (rev 102060)
@@ -24,6 +24,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
+import java.util.List;
 
 import org.jboss.classloader.plugins.loader.ClassLoaderToLoaderAdapter;
 import org.jboss.classloader.spi.ClassLoaderPolicy;
@@ -33,7 +34,9 @@
 import org.jboss.classloader.spi.Loader;
 import org.jboss.classloader.spi.ParentPolicy;
 import org.jboss.classloader.spi.base.BaseClassLoader;
+import org.jboss.classloader.spi.filter.FilteredDelegateLoader;
 import org.jboss.classloader.spi.filter.LazyFilteredDelegateLoader;
+import org.jboss.classloader.spi.filter.PackageClassFilter;
 import org.jboss.classloading.spi.dependency.Domain;
 import org.jboss.classloading.spi.dependency.Module;
 import org.jboss.classloading.spi.dependency.RequirementDependencyItem;
@@ -266,24 +269,31 @@
    @Override
    public DelegateLoader getDelegateLoader(Module requiringModule, Requirement requirement)
    {
-      // self dependency
-      if (this == requiringModule)
+      ClassLoaderPolicyFactory clpf = new ClassLoaderPolicyFactory()
       {
-         ClassLoaderPolicyFactory clpf = new ClassLoaderPolicyFactory()
+         public ClassLoaderPolicy createClassLoaderPolicy()
          {
-            public ClassLoaderPolicy createClassLoaderPolicy()
-            {
-               if (policy == null)
-                  throw new IllegalStateException("ClassLoaderPolicy not available");
-               return policy;
-            }
-         };
-         return new DelegateLoader(clpf);
-      }
-      else
+            if (policy == null)
+               throw new IllegalStateException("ClassLoaderPolicy not available");
+            return policy;
+         }
+      };
+      PackageClassFilter filter = PackageClassFilter.createPackageClassFilter(determinePackageNames(true));
+      return new FilteredDelegateLoader(clpf, filter);
+   }
+
+   @Override
+   public DelegateLoader getDelegateLoader(Module requiringModule, List<String> packages)
+   {
+      ClassLoaderPolicyFactory clpf = new ClassLoaderPolicyFactory()
       {
-         return getPolicy().getExported();
-      }
+         public ClassLoaderPolicy createClassLoaderPolicy()
+         {
+            return getPolicy();
+         }
+      };
+      PackageClassFilter filter = PackageClassFilter.createPackageClassFilter(packages);
+      return new FilteredDelegateLoader(clpf, filter);
    }
 
    @Override

Modified: projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/test/DependencyUnitTestCase.java
===================================================================
--- projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/test/DependencyUnitTestCase.java	2010-03-08 12:32:07 UTC (rev 102059)
+++ projects/jboss-cl/trunk/classloading/src/test/java/org/jboss/test/classloading/dependency/test/DependencyUnitTestCase.java	2010-03-08 13:07:26 UTC (rev 102060)
@@ -37,6 +37,7 @@
 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.dependency.support.c.C;
 
 /**
  * DependencyUnitTestCase.
@@ -404,4 +405,136 @@
       }
       assertNoClassLoader(contextA);
    }
+   
+   public void testCircularModule() throws Exception
+   {
+      ClassLoadingMetaDataFactory factory = ClassLoadingMetaDataFactory.getInstance();
+      MockClassLoadingMetaData a = new MockClassLoadingMetaData("a");
+      a.setPathsAndPackageNames(A.class);
+      a.getRequirements().addRequirement(factory.createRequireModule("b"));
+      KernelControllerContext contextA = install(a);
+      try
+      {
+         assertNoClassLoader(contextA);
+
+         MockClassLoadingMetaData b = new MockClassLoadingMetaData("b");
+         b.setPathsAndPackageNames(B.class);
+         b.getRequirements().addRequirement(factory.createRequireModule("a"));
+         KernelControllerContext contextB = install(b);
+         try
+         {
+            ClassLoader clA = assertClassLoader(contextA);
+            assertLoadClass(A.class, clA);
+            assertLoadClassFail(B.class, clA);
+            ClassLoader clB = assertClassLoader(contextB);
+            assertLoadClass(B.class, clB);
+            assertLoadClass(A.class, clB, clA);
+         }
+         finally
+         {
+            uninstall(contextB);
+         }
+         assertNoClassLoader(contextA);
+         assertNoClassLoader(contextB);
+      }
+      finally
+      {
+         uninstall(contextA);
+      }
+      assertNoClassLoader(contextA);
+   }
+
+   public void testCircularPackage() throws Exception
+   {
+      ClassLoadingMetaDataFactory factory = ClassLoadingMetaDataFactory.getInstance();
+      MockClassLoadingMetaData a = new MockClassLoadingMetaData("a");
+      a.setPathsAndPackageNames(A.class);
+      a.getRequirements().addRequirement(factory.createRequirePackage(B.class.getPackage().getName()));
+      KernelControllerContext contextA = install(a);
+      try
+      {
+         assertNoClassLoader(contextA);
+
+         MockClassLoadingMetaData b = new MockClassLoadingMetaData("b");
+         b.setPathsAndPackageNames(B.class);
+         b.getRequirements().addRequirement(factory.createRequirePackage(A.class.getPackage().getName()));
+         KernelControllerContext contextB = install(b);
+         try
+         {
+            ClassLoader clA = assertClassLoader(contextA);
+            assertLoadClass(A.class, clA);
+            assertLoadClassFail(B.class, clA);
+            ClassLoader clB = assertClassLoader(contextB);
+            assertLoadClass(B.class, clB);
+            assertLoadClass(A.class, clB, clA);
+         }
+         finally
+         {
+            uninstall(contextB);
+         }
+         assertNoClassLoader(contextA);
+         assertNoClassLoader(contextB);
+      }
+      finally
+      {
+         uninstall(contextA);
+      }
+      assertNoClassLoader(contextA);
+   }
+
+   public void testTransitiveCircularPackage() throws Exception
+   {
+      ClassLoadingMetaDataFactory factory = ClassLoadingMetaDataFactory.getInstance();
+      MockClassLoadingMetaData a = new MockClassLoadingMetaData("a");
+      a.setPathsAndPackageNames(A.class);
+      a.getRequirements().addRequirement(factory.createRequirePackage(B.class.getPackage().getName()));
+      KernelControllerContext contextA = install(a);
+      try
+      {
+         assertNoClassLoader(contextA);
+
+         MockClassLoadingMetaData b = new MockClassLoadingMetaData("b");
+         b.setPathsAndPackageNames(B.class);
+         b.getRequirements().addRequirement(factory.createRequirePackage(C.class.getPackage().getName()));
+         KernelControllerContext contextB = install(b);
+         try
+         {
+            assertNoClassLoader(contextB);
+
+            MockClassLoadingMetaData c = new MockClassLoadingMetaData("c");
+            c.setPathsAndPackageNames(C.class);
+            c.getRequirements().addRequirement(factory.createRequirePackage(A.class.getPackage().getName()));
+            KernelControllerContext contextC = install(c);
+            try
+            {
+               ClassLoader clA = assertClassLoader(contextA);
+               assertLoadClass(A.class, clA);
+               assertLoadClassFail(B.class, clA);
+               ClassLoader clB = assertClassLoader(contextB);
+               assertLoadClass(B.class, clB);
+               assertLoadClass(B.class, clA, clB);
+               ClassLoader clC = assertClassLoader(contextC);
+               assertLoadClass(C.class, clB, clC);
+               assertLoadClass(C.class, clC);
+               assertLoadClass(A.class, clC, clA);
+            }
+            finally
+            {
+               uninstall(contextC);
+            }
+            assertNoClassLoader(contextA);
+            assertNoClassLoader(contextB);
+            assertNoClassLoader(contextC);
+         }
+         finally
+         {
+            uninstall(contextB);
+         }
+      }
+      finally
+      {
+         uninstall(contextA);
+      }
+      assertNoClassLoader(contextA);
+   }
 }

Modified: projects/jboss-cl/trunk/pom.xml
===================================================================
--- projects/jboss-cl/trunk/pom.xml	2010-03-08 12:32:07 UTC (rev 102059)
+++ projects/jboss-cl/trunk/pom.xml	2010-03-08 13:07:26 UTC (rev 102060)
@@ -33,7 +33,7 @@
     <version.jboss.vfs>3.0.0.CR1</version.jboss.vfs>
     <version.jboss.man>2.1.1.SP1</version.jboss.man>
     <version.jboss.mdr>2.2.0.Alpha1</version.jboss.mdr>
-    <version.jboss.kernel>2.2.0.Alpha6</version.jboss.kernel>
+    <version.jboss.kernel>2.2.0-SNAPSHOT</version.jboss.kernel>
     <version.jboss.common.core>2.2.17.GA</version.jboss.common.core>
     <version.jboss.logging.spi>2.2.0.CR1</version.jboss.logging.spi>
     <version.jboss.classloading.spi>6.0.0-Alpha8</version.jboss.classloading.spi>




More information about the jboss-cvs-commits mailing list