felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rickh...@apache.org
Subject svn commit: r904631 - in /felix/trunk/framework/src/main/java/org/apache/felix/framework: BundleImpl.java Felix.java FelixResolverState.java
Date Fri, 29 Jan 2010 21:31:09 GMT
Author: rickhall
Date: Fri Jan 29 21:31:09 2010
New Revision: 904631

URL: http://svn.apache.org/viewvc?rev=904631&view=rev
Log:
If a fragment bundle is uninstalled, it must be unmerged from any unresolved
hosts to avoid causing an exception.

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

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java?rev=904631&r1=904630&r2=904631&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java Fri Jan
29 21:31:09 2010
@@ -134,6 +134,21 @@
         }
     }
 
+    /**
+     * This is sort of a hacky method called after uninstalling a bundle.
+     * If the bundle is a fragment, this will unmerge it from any unresolved
+     * hosts. This is necessary since fragments are pre-merged into unresolved
+     * hosts. If uninstalled fragments are not unmerged from unresolved hosts,
+     * any attempts to subsequently resolve the host will result in an exception.
+     */
+    synchronized void cleanAfterUninstall()
+    {
+        for (int i = 0; i < m_modules.length; i++)
+        {
+            getFramework().getResolverState().unmergeFragment(m_modules[i]);
+        }
+    }
+
     synchronized void refresh() throws Exception
     {
         if (isExtension() && (getFramework().getState() != Bundle.STOPPING))

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=904631&r1=904630&r2=904631&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 Jan 29 21:31:09
2010
@@ -2261,6 +2261,10 @@
             // Set state to uninstalled.
             setBundleStateAndNotify(bundle, Bundle.UNINSTALLED);
             bundle.setLastModified(System.currentTimeMillis());
+
+            // If this bundle is a fragment, unmerge it from any
+            // unresolved hosts.
+            bundle.cleanAfterUninstall();
         }
         finally
         {

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java?rev=904631&r1=904630&r2=904631&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java
(original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java
Fri Jan 29 21:31:09 2010
@@ -288,6 +288,101 @@
         }
     }
 
+    public void unmergeFragment(IModule module)
+    {
+        if (!Util.isFragment(module))
+        {
+            return;
+        }
+
+        // Get fragment list, which may be null for system bundle fragments.
+        List fragList = (List) m_fragmentMap.get(module.getSymbolicName());
+        if (fragList != null)
+        {
+            // Remove from fragment map.
+            fragList.remove(module);
+            if (fragList.size() == 0)
+            {
+                m_fragmentMap.remove(module.getSymbolicName());
+            }
+
+            // If we have any matching hosts, then remove fragment while
+            // removing any older version of the new fragment. Also remove host's
+            // existing capabilities from the package index and reindex its new
+            // ones after attaching the fragment.
+            List matchingHosts = getMatchingHosts(module);
+            for (int hostIdx = 0; hostIdx < matchingHosts.size(); hostIdx++)
+            {
+                IModule host = ((ICapability) matchingHosts.get(hostIdx)).getModule();
+                // Find any unresolved hosts into which the fragment is merged
+                // and unmerge it.
+                IModule[] fragments = ((ModuleImpl) host).getFragments();
+                for (int fragIdx = 0;
+                    !host.isResolved() && (fragments != null) && (fragIdx
< fragments.length);
+                    fragIdx++)
+                {
+                    if (!fragments[fragIdx].equals(module))
+                    {
+                        List fragmentList = getMatchingFragments(host);
+
+                        // Remove host's existing exported packages from index.
+                        ICapability[] caps = host.getCapabilities();
+                        for (int i = 0; (caps != null) && (i < caps.length); i++)
+                        {
+                            if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+                            {
+                                // Get package name.
+                                String pkgName = (String)
+                                    caps[i].getProperties().get(ICapability.PACKAGE_PROPERTY);
+                                // Remove from "unresolved" package map.
+                                List capList = (List) m_unresolvedPkgIndex.get(pkgName);
+                                if (capList != null)
+                                {
+                                    capList.remove(caps[i]);
+                                }
+                            }
+                        }
+
+                        // Check if fragment conflicts with existing metadata.
+                        checkForConflicts(host, fragmentList);
+
+                        // Attach the fragments to the host.
+                        fragments = (fragmentList.size() == 0)
+                            ? null
+                            : (IModule[]) fragmentList.toArray(new IModule[fragmentList.size()]);
+                        try
+                        {
+                            ((ModuleImpl) host).attachFragments(fragments);
+                        }
+                        catch (Exception ex)
+                        {
+                            // Try to clean up by removing all fragments.
+                            try
+                            {
+                                ((ModuleImpl) host).attachFragments(null);
+                            }
+                            catch (Exception ex2)
+                            {
+                            }
+                            m_logger.log(Logger.LOG_ERROR,
+                                "Serious error attaching fragments.", ex);
+                        }
+
+                        // Reindex the host's exported packages.
+                        caps = host.getCapabilities();
+                        for (int i = 0; (caps != null) && (i < caps.length); i++)
+                        {
+                            if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+                            {
+                                indexPackageCapability(m_unresolvedPkgIndex, caps[i]);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     private List getMatchingHosts(IModule fragment)
     {
         // Find the fragment's host requirement.



Mime
View raw message