More attempts to make resolver state handling more consistent. (FELIX-851)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@737912 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
index 80ef6fa..d532af7 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
@@ -33,7 +33,8 @@
 
 class BundleImpl implements Bundle
 {
-    private final Felix m_felix;
+    // No one should use this field directly, use getFramework() instead.
+    private final Felix _m_felix;
 
     private final BundleArchive m_archive;
     private IModule[] m_modules = new IModule[0];
@@ -61,7 +62,7 @@
 
     BundleImpl(Felix felix, BundleArchive archive) throws Exception
     {
-        m_felix = felix;
+        _m_felix = felix;
         m_archive = archive;
         m_state = Bundle.INSTALLED;
         m_stale = false;
@@ -74,7 +75,6 @@
         {
             IModule module = createModule();
             addModule(module);
-            m_felix.getResolverState().addModule(module);
         }
     }
 
@@ -84,19 +84,24 @@
     // not access the field directly.
     Felix getFramework()
     {
-        return m_felix;
+        return _m_felix;
+    }
+
+    synchronized void dispose()
+    {
+        // Remove the bundle's associated modules from the resolver state
+        // and close them.
+        for (int i = 0; i < m_modules.length; i++)
+        {
+            getFramework().getResolverState().removeModule(m_modules[i]);
+            ((ModuleImpl) m_modules[i]).close();
+        }
     }
 
     synchronized void refresh() throws Exception
     {
-        // We are refreshing the bundle. First, we must remove all existing
-        // modules from the resolver state and close them. Closing the modules
-        // is important, since we will likely be deleting their associated files.
-        for (int i = 0; i < m_modules.length; i++)
-        {
-            m_felix.getResolverState().removeModule(m_modules[i]);
-            ((ModuleImpl) m_modules[i]).close();
-        }
+        // Dispose of the current modules.
+        dispose();
 
         // Now we will purge all old revisions, only keeping the newest one.
         m_archive.purge();
@@ -106,7 +111,6 @@
         m_modules = new IModule[0];
         final IModule module = createModule();
         addModule(module);
-        m_felix.getResolverState().addModule(module);
         m_state = Bundle.INSTALLED;
         m_stale = false;
         m_cachedHeaders.clear();
@@ -899,7 +903,6 @@
         m_archive.revise(location, is);
         IModule module = createModule();
         addModule(module);
-        m_felix.addModule(module);
     }
 
     synchronized boolean rollbackRevise() throws Exception
@@ -918,7 +921,7 @@
         {
             sp.checkBundle(this);
         }
-        module.setSecurityContext(new BundleProtectionDomain(m_felix, this));
+        module.setSecurityContext(new BundleProtectionDomain(getFramework(), this));
 
         ((ModuleImpl) module).setBundle(this);
 
@@ -926,6 +929,10 @@
         System.arraycopy(m_modules, 0, dest, 0, m_modules.length);
         dest[m_modules.length] = module;
         m_modules = dest;
+
+        // Now that the module is added to the bundle, we can update
+        // the resolver's module state.
+        getFramework().getResolverState().addModule(module);
     }
 
     private IModule createModule() throws Exception
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 32050f4..aa9983a 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -297,7 +297,6 @@
         // definition for creating the system bundle module.
         m_extensionManager = new ExtensionManager(m_logger, m_configMap);
         addModule(m_extensionManager.getModule());
-        m_resolverState.addModule(getCurrentModule());
     }
 
     Logger getLogger()
@@ -3121,15 +3120,8 @@
         // because this method is only called during shutdown or a
         // refresh operation and these are already guarded by locks.
 
-        // Remove the bundle's associated modules from
-        // the module manager.
-        IModule[] modules = bundle.getModules();
-        for (int i = 0; i < modules.length; i++)
-        {
-            m_resolverState.removeModule(modules[i]);
-        }
-
-        // Remove the bundle from the cache.
+        // Remove the bundle from memory and the cache.
+        bundle.dispose();
         m_cache.remove(m_cache.getArchive(bundle.getBundleId()));
     }
 
@@ -3594,34 +3586,12 @@
             // Shutdown event dispatching queue.
             EventDispatcher.shutdown();
 
-            // Remove all bundles from the module factory so that any
-            // open resources will be closed.
-            Bundle[] bundles = getBundles();
-            for (int i = 0; i < bundles.length; i++)
-            {
-                BundleImpl bundle = (BundleImpl) bundles[i];
-                IModule[] modules = bundle.getModules();
-                for (int j = 0; j < modules.length; j++)
-                {
-                    try
-                    {
-                        m_resolverState.removeModule(modules[j]);
-                    }
-                    catch (Exception ex)
-                    {
-                        m_logger.log(Logger.LOG_ERROR,
-                           "Unable to clean up " + bundle._getLocation(), ex);
-                    }
-                }
-            }
-
             // Since there may be updated and uninstalled bundles that
             // have not been refreshed, we will take care of refreshing
             // them during shutdown.
 
-            // First loop through all bundled and purge old revisions
-            // from updated bundles.
-            bundles = getBundles();
+            // Refresh all updated bundles.
+            Bundle[] bundles = getBundles();
             for (int i = 0; i < bundles.length; i++)
             {
                 BundleImpl bundle = (BundleImpl) bundles[i];
@@ -3640,7 +3610,7 @@
                 }
             }
 
-            // Next garbage collection any uninstalled bundles.
+            // Garbage collect uninstalled bundles.
             for (int i = 0;
                 (m_uninstalledBundles != null) && (i < m_uninstalledBundles.length);
                 i++)
@@ -3658,7 +3628,14 @@
                 }
             }
 
-            // Next, stop all system bundle activators.
+            // Dispose of the bundles to close their associated contents.
+            bundles = getBundles();
+            for (int i = 0; i < bundles.length; i++)
+            {
+                ((BundleImpl) bundles[i]).dispose();
+            }
+
+            // Stop all system bundle activators.
             for (int i = 0; i < m_activatorList.size(); i++)
             {
                 try
@@ -3733,16 +3710,14 @@
                 // current state.
                 if (m_bundle.getState() == Bundle.UNINSTALLED)
                 {
-                    // This physically removes the bundle from memory
-                    // as well as the bundle cache.
                     garbageCollectBundle(m_bundle);
                     m_bundle = null;
                 }
                 else
                 {
-                    // This physically removes all old bundle modules from
-                    // from memory and all old revisions from disk. It only
-                    // maintains the newest version in the bundle cache.
+                    // This removes all old bundle modules from memory and
+                    // all old revisions from disk. It only maintains the
+                    // newest version in the bundle cache.
                     refreshBundle(m_bundle);
                 }
             }