Fixed a bug in filtering services based on package wirings. If the service
provider did not import the package containing the service interface (e.g.,
perhaps the interface was implemented by an imported superclass), then
filtering would fail because it was only trying to load the class from
the bundle that registered the service object, but it did not have access
to it. Modified the algorithm to use a more exhaustive approach to determine
where the class comes from in such scenarios.


git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@421620 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Felix.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Felix.java
index 33bdd7e..900d063 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -2227,7 +2227,7 @@
             {
                 for (int i = 0; i < classNames.length; i++)
                 {
-                    Class clazz = loadClassUsingClass(svcObj.getClass(), classNames[i]);
+                    Class clazz = Util.loadClassUsingClass(svcObj.getClass(), classNames[i]);
                     if (clazz == null)
                     {
                         throw new IllegalArgumentException(
@@ -2260,86 +2260,6 @@
         return reg;
     }
 
-    /**
-     * <p>
-     * This is a simple utility class that attempts to load the named
-     * class using the class loader of the supplied class or
-     * the class loader of one of its super classes or their implemented
-     * interfaces. This is necessary during service registration to test
-     * whether a given service object implements its declared service
-     * interfaces.
-     * </p>
-     * <p>
-     * To perform this test, the framework must try to load
-     * the classes associated with the declared service interfaces, so
-     * it must choose a class loader. The class loader of the registering
-     * bundle cannot be used, since this disallows third parties to
-     * register service on behalf of another bundle. Consequently, the
-     * class loader of the service object must be used. However, this is
-     * also not sufficient since the class loader of the service object
-     * may not have direct access to the class in question.
-     * </p>
-     * <p>
-     * The service object's class loader may not have direct access to
-     * its service interface if it extends a super class from another
-     * bundle which implements the service interface from an imported
-     * bundle or if it implements an extension of the service interface
-     * from another bundle which imports the base interface from another
-     * bundle. In these cases, the service object's class loader only has
-     * access to the super class's class or the extended service interface,
-     * respectively, but not to the actual service interface.
-     * </p>
-     * <p>
-     * Thus, it is necessary to not only try to load the service interface
-     * class from the service object's class loader, but from the class
-     * loaders of any interfaces it implements and the class loaders of
-     * all super classes.
-     * </p>
-     * @param svcObj the class that is the root of the search.
-     * @param name the name of the class to load.
-     * @return the loaded class or <tt>null</tt> if it could not be
-     *         loaded.
-    **/
-    private static Class loadClassUsingClass(Class clazz, String name)
-    {
-        Class loadedClass = null;
-
-        while (clazz != null)
-        {
-            // Get the class loader of the current class object.
-            ClassLoader loader = clazz.getClassLoader();
-            // A null class loader represents the system class loader.
-            loader = (loader == null) ? ClassLoader.getSystemClassLoader() : loader;
-            try
-            {
-                return loader.loadClass(name);
-            }
-            catch (ClassNotFoundException ex)
-            {
-                // Ignore and try interface class loaders.
-            }
-
-            // Try to see if we can load the class from
-            // one of the class's implemented interface
-            // class loaders.
-            Class[] ifcs = clazz.getInterfaces();
-            for (int i = 0; i < ifcs.length; i++)
-            {
-                loadedClass = loadClassUsingClass(ifcs[i], name);
-                if (loadedClass != null)
-                {
-                    return loadedClass;
-                }
-            }
-
-            // Try to see if we can load the class from
-            // the super class class loader.
-            clazz = clazz.getSuperclass();
-        }
-
-        return null;
-    }
-
     protected ServiceReference[] getServiceReferences(
         BundleImpl bundle, String className, String expr)
         throws InvalidSyntaxException
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
index 035eebd..e24ce70 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
@@ -21,6 +21,7 @@
 import java.util.*;
 
 import org.apache.felix.framework.util.StringMap;
+import org.apache.felix.framework.util.Util;
 import org.osgi.framework.*;
 
 class ServiceRegistrationImpl implements ServiceRegistration
@@ -116,12 +117,11 @@
     **/
     protected boolean isClassAccessible(Class clazz)
     {
-        ClassLoader loader = (m_factory != null)
-            ? m_factory.getClass().getClassLoader()
-            : m_svcObj.getClass().getClassLoader();
+        Class sourceClass = (m_factory != null)
+            ? m_factory.getClass() : m_svcObj.getClass();
         try
         {
-            Class target = loader.loadClass(clazz.getName());
+            Class target = Util.loadClassUsingClass(sourceClass, clazz.getName());
             return (target.getClassLoader() == clazz.getClassLoader());
         }
         catch (Exception ex)
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/Util.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/Util.java
index bf3e922..a9ce699 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/Util.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/Util.java
@@ -108,6 +108,86 @@
         return pkgName;
     }
 
+    /**
+     * <p>
+     * This is a simple utility class that attempts to load the named
+     * class using the class loader of the supplied class or
+     * the class loader of one of its super classes or their implemented
+     * interfaces. This is necessary during service registration to test
+     * whether a given service object implements its declared service
+     * interfaces.
+     * </p>
+     * <p>
+     * To perform this test, the framework must try to load
+     * the classes associated with the declared service interfaces, so
+     * it must choose a class loader. The class loader of the registering
+     * bundle cannot be used, since this disallows third parties to
+     * register service on behalf of another bundle. Consequently, the
+     * class loader of the service object must be used. However, this is
+     * also not sufficient since the class loader of the service object
+     * may not have direct access to the class in question.
+     * </p>
+     * <p>
+     * The service object's class loader may not have direct access to
+     * its service interface if it extends a super class from another
+     * bundle which implements the service interface from an imported
+     * bundle or if it implements an extension of the service interface
+     * from another bundle which imports the base interface from another
+     * bundle. In these cases, the service object's class loader only has
+     * access to the super class's class or the extended service interface,
+     * respectively, but not to the actual service interface.
+     * </p>
+     * <p>
+     * Thus, it is necessary to not only try to load the service interface
+     * class from the service object's class loader, but from the class
+     * loaders of any interfaces it implements and the class loaders of
+     * all super classes.
+     * </p>
+     * @param svcObj the class that is the root of the search.
+     * @param name the name of the class to load.
+     * @return the loaded class or <tt>null</tt> if it could not be
+     *         loaded.
+    **/
+    public static Class loadClassUsingClass(Class clazz, String name)
+    {
+        Class loadedClass = null;
+    
+        while (clazz != null)
+        {
+            // Get the class loader of the current class object.
+            ClassLoader loader = clazz.getClassLoader();
+            // A null class loader represents the system class loader.
+            loader = (loader == null) ? ClassLoader.getSystemClassLoader() : loader;
+            try
+            {
+                return loader.loadClass(name);
+            }
+            catch (ClassNotFoundException ex)
+            {
+                // Ignore and try interface class loaders.
+            }
+    
+            // Try to see if we can load the class from
+            // one of the class's implemented interface
+            // class loaders.
+            Class[] ifcs = clazz.getInterfaces();
+            for (int i = 0; i < ifcs.length; i++)
+            {
+                loadedClass = loadClassUsingClass(ifcs[i], name);
+                if (loadedClass != null)
+                {
+                    return loadedClass;
+                }
+            }
+    
+            // Try to see if we can load the class from
+            // the super class class loader.
+            clazz = clazz.getSuperclass();
+        }
+    
+        return null;
+    }
+
     public static R4Export getExportPackage(IModule m, String name)
     {
         R4Export[] pkgs =