You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2011/08/12 21:16:21 UTC

svn commit: r1157219 - /felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java

Author: rickhall
Date: Fri Aug 12 19:16:20 2011
New Revision: 1157219

URL: http://svn.apache.org/viewvc?rev=1157219&view=rev
Log:
Refactor bundle install/reload code into separate paths to make its purpose
clearer. (FELIX-2950)

Modified:
    felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java?rev=1157219&r1=1157218&r2=1157219&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java Fri Aug 12 19:16:20 2011
@@ -728,9 +728,7 @@ public class Felix extends BundleImpl im
                         else
                         {
                             // Install the cached bundle.
-                            installBundle(
-                                this, archives[i].getId(), archives[i].getLocation(),
-                                archives[i], null);
+                            reloadBundle(archives[i]);
                         }
                     }
                     catch (Exception ex)
@@ -2600,17 +2598,111 @@ public class Felix extends BundleImpl im
         return (val == null) ? System.getProperty(key) : val;
     }
 
-    Bundle installBundle(
-        Bundle origin, String location, InputStream is)
+    private Bundle reloadBundle(BundleArchive ba)
         throws BundleException
     {
-        return installBundle(origin, -1, location, null, is);
+        BundleImpl bundle = null;
+
+        // Try to purge old revisions before installing;
+        // this is done just in case a "refresh" didn't
+        // occur last session...this would only be due to
+        // an error or system crash.
+        try
+        {
+            if (ba.isRemovalPending())
+            {
+                ba.purge();
+            }
+        }
+        catch (Exception ex)
+        {
+            m_logger.log(
+                Logger.LOG_ERROR,
+                "Could not purge bundle.", ex);
+        }
+
+        try
+        {
+            // Acquire the global lock to create the bundle,
+            // since this impacts the global state.
+            boolean locked = acquireGlobalLock();
+            if (!locked)
+            {
+                throw new BundleException(
+                    "Unable to acquire the global lock to install the bundle.");
+            }
+            try
+            {
+                bundle = new BundleImpl(this, ba);
+            }
+            finally
+            {
+                // Always release the global lock.
+                releaseGlobalLock();
+            }
+
+            if (bundle.isExtension())
+            {
+                m_extensionManager.addExtensionBundle(this, bundle);
+                m_resolver.addRevision(m_extensionManager.getRevision());
+            }
+        }
+        catch (Throwable ex)
+        {
+            if (ex instanceof BundleException)
+            {
+                throw (BundleException) ex;
+            }
+            else if (ex instanceof AccessControlException)
+            {
+                throw (AccessControlException) ex;
+            }
+            else
+            {
+                throw new BundleException("Could not create bundle object.", ex);
+            }
+        }
+
+        // Acquire global lock.
+// TODO: OSGi R4.3 - Could we do this in the above lock block?
+        boolean locked = acquireGlobalLock();
+        if (!locked)
+        {
+            // If the calling thread holds bundle locks, then we might not
+            // be able to get the global lock.
+            throw new IllegalStateException(
+                "Unable to acquire global lock to add bundle.");
+        }
+        try
+        {
+            // Use a copy-on-write approach to add the bundle
+            // to the installed maps.
+            Map[] maps = new Map[] {
+                new HashMap<String, BundleImpl>(m_installedBundles[LOCATION_MAP_IDX]),
+                new TreeMap<Long, BundleImpl>(m_installedBundles[IDENTIFIER_MAP_IDX])
+            };
+            maps[LOCATION_MAP_IDX].put(bundle._getLocation(), bundle);
+            maps[IDENTIFIER_MAP_IDX].put(new Long(bundle.getBundleId()), bundle);
+            m_installedBundles = maps;
+        }
+        finally
+        {
+            releaseGlobalLock();
+        }
+
+        if (bundle.isExtension())
+        {
+            m_extensionManager.startExtensionBundle(this, bundle);
+        }
+
+        return bundle;
     }
 
-    private Bundle installBundle(
-        Bundle origin, long id, String location, BundleArchive ba, InputStream is)
+    Bundle installBundle(
+        Bundle origin, String location, InputStream is)
         throws BundleException
     {
+        BundleArchive ba = null;
         BundleImpl existing, bundle = null;
 
         // Acquire an install lock.
@@ -2630,58 +2722,30 @@ public class Felix extends BundleImpl im
             existing = (BundleImpl) getBundle(location);
             if (existing == null)
             {
-                // Determine if this is a new or existing bundle.
-                boolean isNew = (ba == null);
+                // First generate an identifier for it.
+                long id = getNextId();
 
-                // If the bundle is new we must cache its JAR file.
-                if (isNew)
+                try
                 {
-                    // First generate an identifier for it.
-                    id = getNextId();
-
-                    try
-                    {
-                        // Add the bundle to the cache.
-                        ba = m_cache.create(id, getInitialBundleStartLevel(), location, is);
-                    }
-                    catch (Exception ex)
-                    {
-                        throw new BundleException(
-                            "Unable to cache bundle: " + location, ex);
-                    }
-                    finally
-                    {
-                        try
-                        {
-                            if (is != null) is.close();
-                        }
-                        catch (IOException ex)
-                        {
-                            m_logger.log(
-                                Logger.LOG_ERROR,
-                                "Unable to close input stream.", ex);
-                        }
-                    }
+                    // Add the bundle to the cache.
+                    ba = m_cache.create(id, getInitialBundleStartLevel(), location, is);
                 }
-                else
+                catch (Exception ex)
+                {
+                    throw new BundleException(
+                        "Unable to cache bundle: " + location, ex);
+                }
+                finally
                 {
-                    // If the bundle we are installing is not new,
-                    // then try to purge old revisions before installing
-                    // it; this is done just in case a "refresh"
-                    // didn't occur last session...this would only be
-                    // due to an error or system crash.
                     try
                     {
-                        if (ba.isRemovalPending())
-                        {
-                            ba.purge();
-                        }
+                        if (is != null) is.close();
                     }
-                    catch (Exception ex)
+                    catch (IOException ex)
                     {
                         m_logger.log(
                             Logger.LOG_ERROR,
-                            "Could not purge bundle.", ex);
+                            "Unable to close input stream.", ex);
                     }
                 }
 
@@ -2722,28 +2786,24 @@ public class Felix extends BundleImpl im
                 }
                 catch (Throwable ex)
                 {
-                    // If the bundle is new, then remove it from the cache.
-                    // TODO: FRAMEWORK - Perhaps it should be removed if it is not new too.
-                    if (isNew)
+                    // Remove bundle from the cache.
+                    try
                     {
-                        try
+                        if (bundle != null)
                         {
-                            if (bundle != null)
-                            {
-                                bundle.closeAndDelete();
-                            }
-                            else if (ba != null)
-                            {
-                                ba.closeAndDelete();
-                            }
+                            bundle.closeAndDelete();
                         }
-                        catch (Exception ex1)
+                        else if (ba != null)
                         {
-                            m_logger.log(bundle,
-                                Logger.LOG_ERROR,
-                                "Could not remove from cache.", ex1);
+                            ba.closeAndDelete();
                         }
                     }
+                    catch (Exception ex1)
+                    {
+                        m_logger.log(bundle,
+                            Logger.LOG_ERROR,
+                            "Could not remove from cache.", ex1);
+                    }
                     if (ex instanceof BundleException)
                     {
                         throw (BundleException) ex;