Implemented getBundle() and getBundles() for R4 PackageAdmin (FELIX-35).


git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@418703 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 098afb7..8dfd354 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
@@ -957,35 +957,6 @@
         return (((BundleImpl) bundle).getInfo().getPersistentState() == Bundle.ACTIVE);
     }
 
-    /**
-     * <p>
-     * This method is used to determine if the specified class is from
-     * a bundle installed in the framework instance. This method is used
-     * by the URL Handlers service when determining the framework instance
-     * associated with call stack.
-     * </p>
-     * @param clazz The class to test for whether it comes from a bundle.
-     * @return <tt>true</tt> if the class comes from a bundle installed in
-     *         the framework, <tt>false</tt> otherwise.
-    **/
-    protected boolean isBundleClass(Class clazz)
-    {
-        if (clazz.getClassLoader() instanceof ContentClassLoader)
-        {
-            IContentLoader contentLoader =
-                ((ContentClassLoader) clazz.getClassLoader()).getContentLoader();
-            IModule[] modules = m_factory.getModules();
-            for (int i = 0; i < modules.length; i++)
-            {
-                if (modules[i].getContentLoader() == contentLoader)
-                {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
     //
     // Implementation of Bundle interface methods.
     //
@@ -2554,6 +2525,36 @@
     //
 
     /**
+     * This method returns the bundle associated with the specified class if
+     * the class was loaded from a bundle from this framework instance. If the
+     * class was not loaded from a bundle or was loaded by a bundle in another
+     * framework instance, then <tt>null</tt> is returned.
+     * 
+     * @param clazz the class for which to find its associated bundle.
+     * @return the bundle associated with the specified class or <tt>null</tt>
+     *         if the class was not loaded by a bundle or its associated
+     *         bundle belongs to a different framework instance.
+    **/
+    protected Bundle getBundle(Class clazz)
+    {
+        if (clazz.getClassLoader() instanceof ContentClassLoader)
+        {
+            IContentLoader contentLoader =
+                ((ContentClassLoader) clazz.getClassLoader()).getContentLoader();
+            IModule[] modules = m_factory.getModules();
+            for (int i = 0; i < modules.length; i++)
+            {
+                if (modules[i].getContentLoader() == contentLoader)
+                {
+                    long id = Util.getBundleIdFromModuleId(modules[i].getId());
+                    return getBundle(id);
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
      * Returns the exported package associated with the specified
      * package name. This is used by the PackageAdmin service
      * implementation.
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
index 38a117e..94b94fa 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
@@ -16,7 +16,10 @@
  */
 package org.apache.felix.framework;
 
-import org.osgi.framework.Bundle;
+import java.util.*;
+
+import org.apache.felix.framework.searchpolicy.VersionRange;
+import org.osgi.framework.*;
 import org.osgi.service.packageadmin.*;
 
 class PackageAdminImpl implements PackageAdmin, Runnable
@@ -35,6 +38,71 @@
     }
 
     /**
+     * Returns the bundle associated with this class if the class was
+     * loaded from a bundle, otherwise returns null.
+     * 
+     * @param clazz the class for which to determine its associated bundle.
+     * @return the bundle associated with the specified class, otherwise null.
+    **/
+    public Bundle getBundle(Class clazz)
+    {
+        return m_felix.getBundle(clazz);
+    }
+
+    /**
+     * Returns all bundles that have a specified symbolic name and whose
+     * version is in the specified version range. If no version range is
+     * specified, then all bundles with the specified symbolic name are
+     * returned. The array is sorted in descending version order.
+     * 
+     * @param symbolicName the target symbolic name.
+     * @param versionRange the target version range.
+     * @return an array of matching bundles sorted in descending version order.
+    **/
+    public Bundle[] getBundles(String symbolicName, String versionRange)
+    {
+// TODO: PACKAGEADMIN - This could be made more efficient by reducing object creation.
+        VersionRange vr = (versionRange == null)
+            ? null : VersionRange.parse(versionRange);
+        Bundle[] bundles = m_felix.getBundles();
+        List list = new ArrayList();
+        for (int i = 0; (bundles != null) && (i < bundles.length); i++)
+        {
+            String sym = (String) ((BundleImpl) bundles[i])
+                .getInfo().getCurrentHeader().get(Constants.BUNDLE_SYMBOLICNAME);
+            if ((sym != null) && sym.equals(symbolicName))
+            {
+                String s = (String) ((BundleImpl) bundles[i])
+                    .getInfo().getCurrentHeader().get(Constants.BUNDLE_VERSION);
+                Version v = (s == null) ? new Version("0.0.0") : new Version(s);
+                if ((vr == null) || vr.isInRange(v))
+                {
+                    list.add(bundles[i]);
+                }
+            }
+        }
+        if (list.size() == 0)
+        {
+            return null;
+        }
+        bundles = (Bundle[]) list.toArray(new Bundle[list.size()]);
+        Arrays.sort(bundles, new Comparator() {
+            public int compare(Object o1, Object o2)
+            {
+                String s1 = (String) ((BundleImpl) o1)
+                    .getInfo().getCurrentHeader().get(Constants.BUNDLE_VERSION);
+                String s2 = (String) ((BundleImpl) o2)
+                    .getInfo().getCurrentHeader().get(Constants.BUNDLE_VERSION);
+                Version v1 = (s1 == null) ? new Version("0.0.0") : new Version(s1);
+                Version v2 = (s2 == null) ? new Version("0.0.0") : new Version(s2);
+                // Compare in reverse order to get descending sort.
+                return v2.compareTo(v1);
+            }
+        });
+        return bundles;
+    }
+
+    /**
      * Returns the exported package associated with the specified
      * package name.
      *
@@ -155,12 +223,6 @@
         return null;
     }
 
-    public Bundle[] getBundles(String symbolicName, String versionRange)
-    {
-        // TODO: Implement PackageAdmin.getBundles()
-        return null;
-    }
-
     public Bundle[] getFragments(Bundle bundle)
     {
         // TODO: Implement PackageAdmin.getFragments()
@@ -173,12 +235,6 @@
         return null;
     }
 
-    public Bundle getBundle(Class clazz)
-    {
-        // TODO: Implement PackageAdmin.getBundle()
-        return null;
-    }
-
     public int getBundleType(Bundle bundle)
     {
         // TODO: Implement PackageAdmin.getBundleType()
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/URLHandlers.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/URLHandlers.java
index 3daa31c..8fd43f6 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/URLHandlers.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/URLHandlers.java
@@ -359,7 +359,7 @@
                     // Check the registry of framework instances
                     for (int i = 0; i < m_frameworkList.size(); i++)
                     {
-                        if (((Felix) m_frameworkList.get(i)).isBundleClass(targetClass))
+                        if (((Felix) m_frameworkList.get(i)).getBundle(targetClass) != null)
                         {
                             return (Felix) m_frameworkList.get(i);
                         }