Rewrite how we determine when to implicitly boot delegate. (FELIX-2670)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1026512 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java b/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java
index 8502047..6e24757 100644
--- a/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java
@@ -1518,44 +1518,28 @@
             }
             // Break if the current class came from a bundle, since we should
             // not implicitly boot delegate in that case.
-            else if (ModuleClassLoader.class.isInstance(classes[i].getClassLoader()))
+            else if (isClassLoadedFromModule(classes[i]))
             {
                 break;
             }
-            else if (isClassNotLoadedFromBundle(classes[i]))
+            // Break if this goes through BundleImpl because it must be a call
+            // to Bundle.loadClass() which should not implicitly boot delegate.
+            else if (BundleImpl.class.equals(classes[i]))
             {
-                // Check if the current class was loaded from a class loader that
-                // came from a bundle and if so then enforce strict OSGi rules
-                // and do not implicitly boot delegate.
-                boolean delegate = true;
-                ClassLoader last = null;
-                for (ClassLoader cl = classes[i].getClassLoader(); 
-                    (cl != null) && (last != cl);
-                    cl = cl.getClass().getClassLoader())
+                break;
+            }
+            else if (isClassExternal(classes[i]))
+            {
+                try
                 {
-                    last = cl;
-                    if (ModuleClassLoader.class.isInstance(cl))
-                    {
-                        delegate = false;
-                        break;
-                    }
+                    // Return the class or resource from the parent class loader.
+                    return (isClass)
+                        ? (Object) this.getClass().getClassLoader().loadClass(name)
+                            : (Object) this.getClass().getClassLoader().getResource(name);
                 }
-                // Delegate to the parent class loader unless this call
-                // is due to outside code calling a method on the bundle
-                // interface (e.g., Bundle.loadClass()).
-                if (delegate && !Bundle.class.isAssignableFrom(classes[i - 1]))
+                catch (NoClassDefFoundError ex)
                 {
-                    try
-                    {
-                        // Return the class or resource from the parent class loader.
-                        return (isClass)
-                            ? (Object) this.getClass().getClassLoader().loadClass(name)
-                                : (Object) this.getClass().getClassLoader().getResource(name);
-                    }
-                    catch (NoClassDefFoundError ex)
-                    {
-                        // Ignore, will return null
-                    }
+                    // Ignore, will return null
                 }
                 break;
             }
@@ -1564,48 +1548,55 @@
         return null;
     }
 
-    private boolean isClassNotLoadedFromBundle(Class clazz)
+    private boolean isClassLoadedFromModule(Class clazz)
     {
-        // If this is an inner class, try to get the enclosing class
-        // because we can assume that inner classes of class loaders
-        // are really just the class loader and we should ignore them.
-        Class enclosing = getEnclosingClass(clazz);
-        return (this.getClass().getClassLoader() != enclosing.getClassLoader())
-            // Do the test on the enclosing class
-            && !ClassLoader.class.isAssignableFrom(enclosing)
-            && !Class.class.equals(enclosing)
-            && !Proxy.class.equals(enclosing)
-            // Do the test on the class itself
-            && !ClassLoader.class.isAssignableFrom(clazz)
-            && !Class.class.equals(clazz)
-            && !Proxy.class.equals(clazz);
-    }
-
-    private static Class getEnclosingClass(Class clazz)
-    {
-        // This code determines if the class is an inner class and if so
-        // returns the enclosing class. At one point in time this code used
-        // Class.getEnclosingClass() for JDKs > 1.5, but due to a bug in the
-        // JDK which caused  invalid ClassCircularityErrors we had to remove it.
-        int idx = clazz.getName().lastIndexOf('$');
-        if (idx > 0)
+        // The target class is loaded by a module class loader,
+        // then return true.
+        if (ModuleClassLoader.class.isInstance(clazz.getClassLoader()))
         {
-            ClassLoader cl = (clazz.getClassLoader() != null)
-                ? clazz.getClassLoader() : ClassLoader.getSystemClassLoader();
-            try
+            return true;
+        }
+
+        // If the target class was loaded from a class loader that
+        // came from a module, then return true.
+        ClassLoader last = null;
+        for (ClassLoader cl = clazz.getClassLoader();
+            (cl != null) && (last != cl);
+            cl = cl.getClass().getClassLoader())
+        {
+            last = cl;
+            if (ModuleClassLoader.class.isInstance(cl))
             {
-                Class enclosing = cl.loadClass(clazz.getName().substring(0, idx));
-                clazz = (enclosing != null) ? enclosing : clazz;
-            }
-            catch (Throwable t)
-            {
-                // Ignore all problems since we are trying to load a class
-                // inside the class loader and this can lead to
-                // ClassCircularityError, for example.
+                return true;
             }
         }
 
-        return clazz;
+        return false;
+    }
+
+    private boolean isClassExternal(Class clazz)
+    {
+        if (clazz.getName().startsWith("org.apache.felix.framework."))
+        {
+            return false;
+        }
+        else if(clazz.getName().startsWith("org.osgi.framework."))
+        {
+            return false;
+        }
+        else if (ClassLoader.class.equals(clazz))
+        {
+            return false;
+        }
+        else if (Class.class.equals(clazz))
+        {
+            return false;
+        }
+//        else if (Proxy.class.equals(clazz))
+//        {
+//            return false;
+//        }
+        return true;
     }
 
     boolean shouldBootDelegate(String pkgName)