Bundle.loadClass() for the system bundle should obey boot delegation. (FELIX-2335)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@943597 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java b/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
index 1df403d..6cf6cc9 100644
--- a/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
+++ b/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
@@ -652,7 +652,7 @@
         private final Version m_version;
         ExtensionManagerModule(Felix felix)
         {
-            super(m_logger, felix, "0",
+            super(m_logger, felix.getConfig(), felix, "0",
                 felix.getBootPackages(), felix.getBootPackageWildcards());
             m_version = new Version((String)
                 felix.getConfig().get(FelixConstants.FELIX_VERSION_PROPERTY));
@@ -686,15 +686,45 @@
 
         public Class getClassByDelegation(String name) throws ClassNotFoundException
         {
-            synchronized (ExtensionManager.this)
+            Class clazz = null;
+            String pkgName = Util.getClassPackage(name);
+            if (shouldBootDelegate(pkgName))
             {
-                if (!m_exportNames.contains(Util.getClassPackage(name)))
+                try
                 {
-                    throw new ClassNotFoundException(name);
+                    // Get the appropriate class loader for delegation.
+                    ClassLoader bdcl = getBootDelegationClassLoader();
+                    clazz = bdcl.loadClass(name);
+                    // If this is a java.* package, then always terminate the
+                    // search; otherwise, continue to look locally if not found.
+                    if (pkgName.startsWith("java.") || (clazz != null))
+                    {
+                        return clazz;
+                    }
+                }
+                catch (ClassNotFoundException ex)
+                {
+                    // If this is a java.* package, then always terminate the
+                    // search; otherwise, continue to look locally if not found.
+                    if (pkgName.startsWith("java."))
+                    {
+                        throw ex;
+                    }
                 }
             }
+            if (clazz == null)
+            {
+                synchronized (ExtensionManager.this)
+                {
+                    if (!m_exportNames.contains(Util.getClassPackage(name)))
+                    {
+                        throw new ClassNotFoundException(name);
+                    }
+                }
 
-            return getClass().getClassLoader().loadClass(name);
+                clazz = getClass().getClassLoader().loadClass(name);
+            }
+            return clazz;
         }
 
         public URL getResourceByDelegation(String name)
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index c952458..52c7085 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -329,6 +329,25 @@
         // Initialize framework properties.
         initializeFrameworkProperties();
 
+        // Read the boot delegation property and parse it.
+        String s = (m_configMap == null)
+            ? null
+            : (String) m_configMap.get(Constants.FRAMEWORK_BOOTDELEGATION);
+        s = (s == null) ? "java.*" : s + ",java.*";
+        StringTokenizer st = new StringTokenizer(s, " ,");
+        m_bootPkgs = new String[st.countTokens()];
+        m_bootPkgWildcards = new boolean[m_bootPkgs.length];
+        for (int i = 0; i < m_bootPkgs.length; i++)
+        {
+            s = st.nextToken();
+            if (s.equals("*") || s.endsWith(".*"))
+            {
+                m_bootPkgWildcards[i] = true;
+                s = s.substring(0, s.length() - 1);
+            }
+            m_bootPkgs[i] = s;
+        }
+
         // Create default bundle stream handler.
         m_bundleStreamHandler = new URLHandlersBundleStreamHandler(this);
 
@@ -351,25 +370,6 @@
             // a runtime exception.
             throw new RuntimeException(ex.getMessage());
         }
-
-        // Read the boot delegation property and parse it.
-        String s = (m_configMap == null)
-            ? null
-            : (String) m_configMap.get(Constants.FRAMEWORK_BOOTDELEGATION);
-        s = (s == null) ? "java.*" : s + ",java.*";
-        StringTokenizer st = new StringTokenizer(s, " ,");
-        m_bootPkgs = new String[st.countTokens()];
-        m_bootPkgWildcards = new boolean[m_bootPkgs.length];
-        for (int i = 0; i < m_bootPkgs.length; i++)
-        {
-            s = st.nextToken();
-            if (s.equals("*") || s.endsWith(".*"))
-            {
-                m_bootPkgWildcards[i] = true;
-                s = s.substring(0, s.length() - 1);
-            }
-            m_bootPkgs[i] = s;
-        }
     }
 
     Logger getLogger()
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 dde8b67..ec53b78 100644
--- a/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java
@@ -163,11 +163,11 @@
      * @throws org.osgi.framework.BundleException
      */
     public ModuleImpl(
-        Logger logger, Bundle bundle, String id,
+        Logger logger, Map configMap, Bundle bundle, String id,
         String[] bootPkgs, boolean[] bootPkgWildcards)
     {
         m_logger = logger;
-        m_configMap = null;
+        m_configMap = configMap;
         m_resolver = null;
         m_bundle = bundle;
         m_id = id;
@@ -680,12 +680,10 @@
                     try
                     {
                         // Get the appropriate class loader for delegation.
-                        ClassLoader parent = (m_classLoader == null)
-                            ? determineParentClassLoader() : m_classLoader.getParent();
-                        parent = (parent == null) ? m_bootClassLoader : parent;
+                        ClassLoader bdcl = getBootDelegationClassLoader();
                         result = (isClass)
-                            ? (Object) parent.loadClass(name)
-                            : (Object) parent.getResource(name);
+                            ? (Object) bdcl.loadClass(name)
+                            : (Object) bdcl.getResource(name);
                         // If this is a java.* package, then always terminate the
                         // search; otherwise, continue to look locally if not found.
                         if (pkgName.startsWith("java.") || (result != null))
@@ -865,10 +863,8 @@
             try
             {
                 // Get the appropriate class loader for delegation.
-                ClassLoader parent = (m_classLoader == null)
-                    ? determineParentClassLoader() : m_classLoader.getParent();
-                parent = (parent == null) ? m_bootClassLoader : parent;
-                urls = parent.getResources(name);
+                ClassLoader bdcl = getBootDelegationClassLoader();
+                urls = bdcl.getResources(name);
             }
             catch (IOException ex)
             {
@@ -1511,7 +1507,7 @@
         return clazz;
     }
 
-    private boolean shouldBootDelegate(String pkgName)
+    boolean shouldBootDelegate(String pkgName)
     {
         // Always boot delegate if the bundle has a configured
         // boot class loader.
@@ -1548,6 +1544,14 @@
         return result;
     }
 
+    ClassLoader getBootDelegationClassLoader()
+    {
+        // Get the appropriate class loader for delegation.
+        ClassLoader parent = (m_classLoader == null)
+            ? determineParentClassLoader() : m_classLoader.getParent();
+        return (parent == null) ? m_bootClassLoader : parent;
+    }
+
     private static final Constructor m_dexFileClassConstructor;
     private static final Method m_dexFileClassLoadDex;
     private static final Method m_dexFileClassLoadClass;