Initial pass at implementing FrameworkWiringImpl. More stress testing is likely
needed, but most of the code was simply stolen from the related PackageAdmin
implementation. (FELIX-2969)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1126616 13f79535-47bb-0310-9956-ffa450edef68
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 a9d65f0..6a519f3 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -74,6 +74,7 @@
 import org.osgi.framework.wiring.BundleRequirement;
 import org.osgi.framework.wiring.BundleRevision;
 import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.FrameworkWiring;
 import org.osgi.service.packageadmin.ExportedPackage;
 import org.osgi.service.startlevel.StartLevel;
 
@@ -85,6 +86,9 @@
     // The extension manager to handle extension bundles
     private final ExtensionManager m_extensionManager;
 
+    // Framework wiring object.
+    private final FrameworkWiringImpl m_fwkWiring;
+
     // Logging related member variables.
     private final Logger m_logger;
     // Immutable config properties.
@@ -168,7 +172,7 @@
 
     // Shutdown gate.
     private volatile ThreadGate m_shutdownGate = null;
-    
+
     // Security Manager created by the framework
     private SecurityManager m_securityManager = null;
 
@@ -384,6 +388,9 @@
             // a runtime exception.
             throw new RuntimeException(ex.getMessage());
         }
+
+        // Create framework wiring object.
+        m_fwkWiring = new FrameworkWiringImpl(this);
     }
 
     Logger getLogger()
@@ -450,6 +457,16 @@
         return this;
     }
 
+    @Override
+    public <A> A adapt(Class<A> type)
+    {
+        if (type == FrameworkWiring.class)
+        {
+            return (A) m_fwkWiring;
+        }
+        return super.adapt(type);
+    }
+
     public long getBundleId()
     {
         return 0;
@@ -550,10 +567,10 @@
                     if (Constants.FRAMEWORK_SECURITY_OSGI.equalsIgnoreCase(security) || (security.length() == 0))
                     {
                         // TODO: SECURITY - we only need our own security manager to convert the exceptions
-                        //       because the 4.2.0 ct does expect them like this in one case. 
+                        //       because the 4.2.0 ct does expect them like this in one case.
                         System.setSecurityManager(m_securityManager = new SecurityManager()
                         {
-                            public void checkPermission(Permission perm) 
+                            public void checkPermission(Permission perm)
                             {
                                 try
                                 {
@@ -570,11 +587,11 @@
                     }
                     else
                     {
-                        try 
+                        try
                         {
-                            System.setSecurityManager(m_securityManager = 
+                            System.setSecurityManager(m_securityManager =
                                 (SecurityManager) Class.forName(security).newInstance());
-                        } 
+                        }
                         catch (Throwable t)
                         {
                             SecurityException se =
@@ -1595,7 +1612,9 @@
         BundleImpl bundle, String path, String filePattern, boolean recurse)
     {
         // Try to resolve the bundle per the spec.
-        resolveBundles(new Bundle[] { bundle });
+        List<Bundle> list = new ArrayList<Bundle>(1);
+        list.add(bundle);
+        resolveBundles(list);
 
         // Get the entry enumeration from the revision content and
         // create a wrapper enumeration to filter it.
@@ -2159,7 +2178,9 @@
                         {
                             try
                             {
-                                refreshPackages(new BundleImpl[] { bundle });
+                                List<Bundle> list = new ArrayList<Bundle>(1);
+                                list.add(bundle);
+                                refreshPackages(list, null);
                             }
                             catch (Exception ex)
                             {
@@ -2499,7 +2520,9 @@
                 {
                     try
                     {
-                        refreshPackages(new BundleImpl[] { bundle });
+                        List<Bundle> list = new ArrayList<Bundle>(1);
+                        list.add(bundle);
+                        refreshPackages(list, null);
                     }
                     catch (Exception ex)
                     {
@@ -3483,7 +3506,7 @@
         return m_dependencies.getRequiringBundles(bundle);
     }
 
-    boolean resolveBundles(Bundle[] targets)
+    boolean resolveBundles(Collection<Bundle> targets)
     {
         // Acquire global lock.
         boolean locked = acquireGlobalLock();
@@ -3502,7 +3525,7 @@
             // specified bundles or all bundles if null.
             if (targets == null)
             {
-                List list = new ArrayList();
+                targets = new ArrayList<Bundle>();
 
                 // Add all unresolved bundles to the list.
                 Iterator iter = m_installedBundles[LOCATION_MAP_IDX].values().iterator();
@@ -3511,30 +3534,27 @@
                     BundleImpl bundle = (BundleImpl) iter.next();
                     if (bundle.getState() == Bundle.INSTALLED)
                     {
-                        list.add(bundle);
+                        targets.add(bundle);
                     }
                 }
-
-                // Create an array.
-                if (list.size() > 0)
-                {
-                    targets = (Bundle[]) list.toArray(new BundleImpl[list.size()]);
-                }
             }
 
             // Now resolve each target bundle.
             boolean result = true;
 
             // If there are targets, then resolve each one.
-            for (int i = 0; (targets != null) && (i < targets.length); i++)
+            if (!targets.isEmpty())
             {
-                try
+                for (Bundle b : targets)
                 {
-                    resolveBundle((BundleImpl) targets[i]);
-                }
-                catch (BundleException ex)
-                {
-                    result = false;
+                    try
+                    {
+                        resolveBundle((BundleImpl) b);
+                    }
+                    catch (BundleException ex)
+                    {
+                        result = false;
+                    }
                 }
             }
 
@@ -3569,7 +3589,7 @@
         }
     }
 
-    void refreshPackages(Bundle[] targets)
+    void refreshPackages(Collection<Bundle> targets, FrameworkListener[] listeners)
     {
         // Acquire global lock.
         boolean locked = acquireGlobalLock();
@@ -3587,10 +3607,10 @@
         // Determine set of bundles to refresh, which is all transitive
         // dependencies of specified set or all transitive dependencies
         // of all bundles if null is specified.
-        Bundle[] newTargets = targets;
+        Collection<Bundle> newTargets = targets;
         if (newTargets == null)
         {
-            List list = new ArrayList();
+            List<Bundle> list = new ArrayList<Bundle>();
 
             // First add all uninstalled bundles.
             for (int i = 0;
@@ -3611,31 +3631,27 @@
                 }
             }
 
-            // Create an array.
-            if (list.size() > 0)
+            if (!list.isEmpty())
             {
-                newTargets = (Bundle[]) list.toArray(new Bundle[list.size()]);
+                newTargets = list;
             }
         }
 
         // If there are targets, then find all dependencies for each one.
-        BundleImpl[] bundles = null;
+        Set<Bundle> bundles = null;
         if (newTargets != null)
         {
             // Create map of bundles that import the packages
             // from the target bundles.
-            Set<Bundle> set = new HashSet<Bundle>();
-            for (int targetIdx = 0; targetIdx < newTargets.length; targetIdx++)
+            bundles = new HashSet<Bundle>();
+            for (Bundle target : newTargets)
             {
                 // Add the current target bundle to the map of
                 // bundles to be refreshed.
-                BundleImpl target = (BundleImpl) newTargets[targetIdx];
-                set.add(target);
+                bundles.add(target);
                 // Add all importing bundles to map.
-                populateDependentGraph(target, set);
+                populateDependentGraph((BundleImpl) target, bundles);
             }
-
-            bundles = (BundleImpl[]) set.toArray(new BundleImpl[set.size()]);
         }
 
         // Now refresh each bundle.
@@ -3648,62 +3664,61 @@
             // We need to restart the framework if either an extension bundle is
             // refreshed or the system bundle is refreshed and any extension bundle
             // has been updated or uninstalled.
-            for (int i = 0; (bundles != null) && !restart && (i < bundles.length); i++)
-            {
-                if (systemBundle == bundles[i])
-                {
-                    Bundle[] allBundles = getBundles();
-                    for (int j = 0; !restart && j < allBundles.length; j++)
-                    {
-                        if (((BundleImpl) allBundles[j]).isExtension() &&
-                            (allBundles[j].getState() == Bundle.INSTALLED))
-                        {
-                            restart = true;
-                        }
-                    }
-                }
-            }
-
-            // Remove any targeted bundles from the uninstalled bundles
-            // array, since they will be removed from the system after
-            // the refresh.
-            // TODO: FRAMEWORK - Is this correct?
-            for (int i = 0; (bundles != null) && (i < bundles.length); i++)
-            {
-                forgetUninstalledBundle(bundles[i]);
-            }
-            // If there are targets, then refresh each one.
             if (bundles != null)
             {
-                // At this point the map contains every bundle that has been
-                // updated and/or removed as well as all bundles that import
+                for (Bundle b : bundles)
+                {
+                    if (systemBundle == b)
+                    {
+                        Bundle[] allBundles = getBundles();
+                        for (int j = 0; !restart && j < allBundles.length; j++)
+                        {
+                            if (((BundleImpl) allBundles[j]).isExtension() &&
+                                (allBundles[j].getState() == Bundle.INSTALLED))
+                            {
+                                restart = true;
+                                break;
+                            }
+                        }
+                    }
+
+                    // Remove any targeted bundles from the uninstalled bundles
+                    // array, since they will be removed from the system after
+                    // the refresh.
+                    // TODO: FRAMEWORK - Is this correct?
+                    forgetUninstalledBundle((BundleImpl) b);
+                }
+
+                // Now we actually need to refresh the affected bundles.
+                // At this point the collection contains every bundle that has
+                // been updated and/or removed as well as all bundles that import
                 // packages from these bundles.
 
                 // Create refresh helpers for each bundle.
-                RefreshHelper[] helpers = new RefreshHelper[bundles.length];
-                for (int i = 0; i < bundles.length; i++)
+                List<RefreshHelper> helpers = new ArrayList<RefreshHelper>(bundles.size());
+                for (Bundle b : bundles)
                 {
-                    helpers[i] = new RefreshHelper(bundles[i]);
+                    helpers.add(new RefreshHelper(b));
                 }
 
                 // Stop, purge or remove, and reinitialize all bundles first.
                 // TODO: FRAMEWORK - this will stop the system bundle if
                 // somebody called refresh 0. Is this what we want?
-                for (int i = 0; i < helpers.length; i++)
+                for (RefreshHelper helper : helpers)
                 {
-                    if (helpers[i] != null)
+                    if (helper != null)
                     {
-                        helpers[i].stop();
-                        helpers[i].refreshOrRemove();
+                        helper.stop();
+                        helper.refreshOrRemove();
                     }
                 }
 
                 // Then restart all bundles that were previously running.
-                for (int i = 0; i < helpers.length; i++)
+                for (RefreshHelper helper : helpers)
                 {
-                    if (helpers[i] != null)
+                    if (helper != null)
                     {
-                        helpers[i].restart();
+                        helper.restart();
                     }
                 }
             }
@@ -3727,8 +3742,69 @@
         }
 
         fireFrameworkEvent(FrameworkEvent.PACKAGES_REFRESHED, this, null);
+
+        if (listeners != null)
+        {
+            FrameworkEvent event = new FrameworkEvent(
+                FrameworkEvent.PACKAGES_REFRESHED, this, null);
+            for (FrameworkListener l : listeners)
+            {
+                try
+                {
+                    l.frameworkEvent(event);
+                }
+                catch (Throwable th)
+                {
+                    m_logger.log(Logger.LOG_ERROR,
+                        "Framework listener delivery error.", th);
+                }
+            }
+        }
     }
 
+    Collection<Bundle> getDependencyClosure(Collection<Bundle> targets)
+    {
+        // Acquire global lock.
+        boolean locked = acquireGlobalLock();
+        if (!locked)
+        {
+            // If the thread calling holds bundle locks, then we might not
+            // be able to get the global lock. However, in practice this
+            // should not happen since the calls to this method have either
+            // already acquired the global lock or it is PackageAdmin which
+            // doesn't hold bundle locks.
+            throw new IllegalStateException(
+                "Unable to acquire global lock for refresh.");
+        }
+
+        try
+        {
+            // If there are targets, then find all dependencies for each one.
+            Set<Bundle> bundles = Collections.EMPTY_SET;
+            if (targets != null)
+            {
+                // Create map of bundles that import the packages
+                // from the target bundles.
+                bundles = new HashSet<Bundle>();
+                for (Bundle target : targets)
+                {
+                    // Add the current target bundle to the map of
+                    // bundles to be refreshed.
+                    bundles.add(target);
+                    // Add all importing bundles to map.
+                    populateDependentGraph((BundleImpl) target, bundles);
+                }
+            }
+            return bundles;
+        }
+        finally
+        {
+            // Always release the global lock.
+            releaseGlobalLock();
+        }
+    }
+
+    // Calls to this method must have the global lock.
     private void populateDependentGraph(BundleImpl exporter, Set<Bundle> set)
     {
         // Get all dependent bundles of this bundle.
@@ -3750,6 +3826,47 @@
         }
     }
 
+    Collection<Bundle> getRemovalPendingBundles()
+    {
+        // Acquire global lock.
+        boolean locked = acquireGlobalLock();
+        if (!locked)
+        {
+            // If the thread calling holds bundle locks, then we might not
+            // be able to get the global lock. However, in practice this
+            // should not happen since the calls to this method have either
+            // already acquired the global lock or it is PackageAdmin which
+            // doesn't hold bundle locks.
+            throw new IllegalStateException(
+                "Unable to acquire global lock for refresh.");
+        }
+
+        try
+        {
+            List<Bundle> bundles = new ArrayList<Bundle>();
+            if (m_uninstalledBundles != null)
+            {
+                for (Bundle b : m_uninstalledBundles)
+                {
+                    bundles.add(b);
+                }
+            }
+            for (Bundle b : getBundles())
+            {
+                if (((BundleImpl) b).isRemovalPending())
+                {
+                    bundles.add(b);
+                }
+            }
+            return bundles;
+        }
+        finally
+        {
+            // Always release the global lock.
+            releaseGlobalLock();
+        }
+    }
+
     //
     // Miscellaneous private methods.
     //
@@ -4473,7 +4590,7 @@
 
                     // Mark revision as resolved.
                     revision.resolve(entry.getValue());
-                    
+
                     // Update resolver state to remove substituted capabilities.
                     if (!Util.isFragment(revision))
                     {
@@ -4666,6 +4783,9 @@
                 // Should never happen.
             }
 
+            // Stop framework wiring thread.
+            m_fwkWiring.stop();
+
             // Shutdown event dispatching queue.
             EventDispatcher.shutdown();
 
@@ -5181,17 +5301,17 @@
     }
 
     private volatile URLHandlersActivator m_urlHandlersActivator;
-    
+
     void setURLHandlersActivator(URLHandlersActivator urlHandlersActivator)
     {
         m_urlHandlersActivator = urlHandlersActivator;
     }
-    
+
     Object getStreamHandlerService(String protocol)
     {
         return m_urlHandlersActivator.getStreamHandlerService(protocol);
     }
-    
+
     Object getContentHandlerService(String mimeType)
     {
         return m_urlHandlersActivator.getContentHandlerService(mimeType);
diff --git a/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java b/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
new file mode 100644
index 0000000..3f8c8a0
--- /dev/null
+++ b/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.osgi.framework.AdminPermission;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.wiring.FrameworkWiring;
+
+class FrameworkWiringImpl implements FrameworkWiring, Runnable
+{
+    private final Felix m_felix;
+    private List<Collection<Bundle>> m_requests = null;
+    private List<FrameworkListener[]> m_requestListeners = null;
+    private Thread m_thread = null;
+
+    public FrameworkWiringImpl(Felix felix)
+    {
+        m_felix = felix;
+    }
+
+    /**
+     * Stops the FelixFrameworkWiring thread on system shutdown. Shutting down the
+     * thread explicitly is required in the embedded case, where Felix may be
+     * stopped without the Java VM being stopped. In this case the
+     * FelixFrameworkWiring thread must be stopped explicitly.
+     * <p>
+     * This method is called by the
+     * {@link PackageAdminActivator#stop(BundleContext)} method.
+     */
+    synchronized void stop()
+    {
+        if (m_thread != null)
+        {
+            // Null thread variable to signal to the thread that
+            // we want it to exit.
+            m_thread = null;
+
+            // Wake up the thread, if it is currently in the wait() state
+            // for more work.
+            notifyAll();
+        }
+    }
+
+    public Bundle getBundle()
+    {
+        return m_felix;
+    }
+
+    public void refreshBundles(Collection<Bundle> bundles, FrameworkListener... listeners)
+    {
+        Object sm = System.getSecurityManager();
+
+        if (sm != null)
+        {
+            ((SecurityManager) sm).checkPermission(
+                new AdminPermission(m_felix, AdminPermission.RESOLVE));
+        }
+        synchronized (this)
+        {
+            // Start a thread to perform asynchronous package refreshes.
+            if (m_thread == null)
+            {
+                m_thread = new Thread(this, "FelixFrameworkWiring");
+                m_thread.setDaemon(true);
+                m_thread.start();
+            }
+
+            // Save our request parameters and notify all.
+            if (m_requests == null)
+            {
+                List<Collection<Bundle>> requests = new ArrayList<Collection<Bundle>>();
+                requests.add(bundles);
+                m_requests = requests;
+                List<FrameworkListener[]> requestListeners =
+                    new ArrayList<FrameworkListener[]>();
+                requestListeners.add(listeners);
+                m_requestListeners = requestListeners;
+            }
+            else
+            {
+                m_requests.add(bundles);
+            }
+            notifyAll();
+        }
+    }
+
+    public boolean resolveBundles(Collection<Bundle> bundles)
+    {
+        Object sm = System.getSecurityManager();
+
+        if (sm != null)
+        {
+            ((SecurityManager) sm).checkPermission(
+                new AdminPermission(m_felix, AdminPermission.RESOLVE));
+        }
+
+        return m_felix.resolveBundles(bundles);
+    }
+
+    public Collection<Bundle> getRemovalPendingBundles()
+    {
+        return m_felix.getRemovalPendingBundles();
+    }
+
+    public Collection<Bundle> getDependencyClosure(Collection<Bundle> targets)
+    {
+        return m_felix.getDependencyClosure(targets);
+    }
+
+    /**
+     * The OSGi specification states that package refreshes happen
+     * asynchronously; this is the run() method for the package
+     * refreshing thread.
+    **/
+    public void run()
+    {
+        // This thread loops forever, thus it should
+        // be a daemon thread.
+        while (true)
+        {
+            Collection<Bundle> bundles = null;
+            FrameworkListener[] listeners = null;
+            synchronized (this)
+            {
+                // Wait for a refresh request.
+                while (m_requests == null)
+                {
+                    // Terminate the thread if requested to do so (see stop()).
+                    if (m_thread == null)
+                    {
+                        return;
+                    }
+
+                    try
+                    {
+                        wait();
+                    }
+                    catch (InterruptedException ex)
+                    {
+                    }
+                }
+
+                // Get the bundles parameter for the current refresh request.
+                bundles = m_requests.get(0);
+                listeners = m_requestListeners.get(0);
+            }
+
+            // Perform refresh.
+            // NOTE: We don't catch any exceptions here, because
+            // the invoked method shields us from exceptions by
+            // catching Throwables when its invokes callbacks.
+            m_felix.refreshPackages(bundles, listeners);
+
+            // Remove the first request since it is now completed.
+            synchronized (this)
+            {
+                m_requests.remove(0);
+                m_requestListeners.remove(0);
+                if (m_requests.isEmpty())
+                {
+                    m_requests = null;
+                    m_requestListeners = null;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/PackageAdminActivator.java b/framework/src/main/java/org/apache/felix/framework/PackageAdminActivator.java
index 5e9175e..786c6b4 100644
--- a/framework/src/main/java/org/apache/felix/framework/PackageAdminActivator.java
+++ b/framework/src/main/java/org/apache/felix/framework/PackageAdminActivator.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -42,6 +42,5 @@
     public void stop(BundleContext context) throws Exception
     {
         m_reg.unregister();
-        m_packageAdmin.stop();
     }
 }
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java b/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
index 73ae668..ef1ca60 100644
--- a/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -27,12 +27,13 @@
 import org.osgi.framework.Version;
 import org.osgi.framework.wiring.BundleRevision;
 import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.FrameworkWiring;
 import org.osgi.service.packageadmin.ExportedPackage;
 import org.osgi.service.packageadmin.PackageAdmin;
 import org.osgi.service.packageadmin.RequiredBundle;
 
 
-class PackageAdminImpl implements PackageAdmin, Runnable
+class PackageAdminImpl implements PackageAdmin
 {
     private static final Comparator COMPARATOR = new Comparator() {
         public int compare(Object o1, Object o2)
@@ -44,48 +45,16 @@
     };
 
     private Felix m_felix = null;
-    private Bundle[][] m_reqBundles = null;
-    private Bundle m_systemBundle = null;
-    private Thread m_thread = null;
 
     public PackageAdminImpl(Felix felix)
     {
         m_felix = felix;
-        m_systemBundle = m_felix.getBundle(0);
-
-        // Start a thread to perform asynchronous package refreshes.
-        m_thread = new Thread(this, "FelixPackageAdmin");
-        m_thread.setDaemon(true);
-        m_thread.start();
     }
 
     /**
-     * Stops the FelixPackageAdmin thread on system shutdown. Shutting down the
-     * thread explicitly is required in the embedded case, where Felix may be
-     * stopped without the Java VM being stopped. In this case the
-     * FelixPackageAdmin thread must be stopped explicitly.
-     * <p>
-     * This method is called by the
-     * {@link PackageAdminActivator#stop(BundleContext)} method.
-     */
-    synchronized void stop()
-    {
-        if (m_thread != null)
-        {
-            // Null thread variable to signal to the thread that
-            // we want it to exit.
-            m_thread = null;
-            
-            // Wake up the thread, if it is currently in the wait() state
-            // for more work.
-            notifyAll();
-        }
-    }
-    
-    /**
      * 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.
     **/
@@ -99,7 +68,7 @@
      * 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.
@@ -121,7 +90,7 @@
                 }
             }
         }
-        if (list.size() == 0)
+        if (list.isEmpty())
         {
             return null;
         }
@@ -279,102 +248,17 @@
     public void refreshPackages(Bundle[] bundles)
         throws SecurityException
     {
-        Object sm = System.getSecurityManager();
-        
-        if (sm != null)
-        {
-            ((SecurityManager) sm).checkPermission(
-                new AdminPermission(m_systemBundle, AdminPermission.RESOLVE));
-        }
-        synchronized (this)
-        {
-            // Save our request parameters and notify all.
-            if (m_reqBundles == null)
-            {
-                m_reqBundles = new Bundle[][] { bundles };
-            }
-            else
-            {
-                Bundle[][] newReqBundles = new Bundle[m_reqBundles.length + 1][];
-                System.arraycopy(m_reqBundles, 0,
-                    newReqBundles, 0, m_reqBundles.length);
-                newReqBundles[m_reqBundles.length] = bundles;
-                m_reqBundles = newReqBundles;
-            }
-            notifyAll();
-        }
+        List<Bundle> list = (bundles == null)
+            ? null
+            : Arrays.asList(bundles);
+        m_felix.adapt(FrameworkWiring.class).refreshBundles(list);
     }
 
     public boolean resolveBundles(Bundle[] bundles)
     {
-        Object sm = System.getSecurityManager();
-        
-        if (sm != null)
-        {
-            ((SecurityManager) sm).checkPermission(
-                new AdminPermission(m_systemBundle, AdminPermission.RESOLVE));
-        }
-        
-        return m_felix.resolveBundles(bundles);
-    }
-
-    /**
-     * The OSGi specification states that package refreshes happen
-     * asynchronously; this is the run() method for the package
-     * refreshing thread.
-    **/
-    public void run()
-    {
-        // This thread loops forever, thus it should
-        // be a daemon thread.
-        while (true)
-        {
-            Bundle[] bundles = null;
-            synchronized (this)
-            {
-                // Wait for a refresh request.
-                while (m_reqBundles == null)
-                {
-                    // Terminate the thread if requested to do so (see stop()).
-                    if (m_thread == null)
-                    {
-                        return;
-                    }
-                    
-                    try
-                    {
-                        wait();
-                    }
-                    catch (InterruptedException ex)
-                    {
-                    }
-                }
-
-                // Get the bundles parameter for the current refresh request.
-                bundles = m_reqBundles[0];
-            }
-
-            // Perform refresh.
-            // NOTE: We don't catch any exceptions here, because
-            // the invoked method shields us from exceptions by
-            // catching Throwables when its invokes callbacks.
-            m_felix.refreshPackages(bundles);
-
-            // Remove the first request since it is now completed.
-            synchronized (this)
-            {
-                if (m_reqBundles.length == 1)
-                {
-                    m_reqBundles = null;
-                }
-                else
-                {
-                    Bundle[][] newReqBundles = new Bundle[m_reqBundles.length - 1][];
-                    System.arraycopy(m_reqBundles, 1,
-                        newReqBundles, 0, m_reqBundles.length - 1);
-                    m_reqBundles = newReqBundles;
-                }
-            }
-        }
+        List<Bundle> list = (bundles == null)
+            ? null
+            : Arrays.asList(bundles);
+        return m_felix.adapt(FrameworkWiring.class).resolveBundles(list);
     }
 }
\ No newline at end of file