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 2007/02/09 20:46:48 UTC

svn commit: r505459 - in /incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework: Felix.java searchpolicy/R4SearchPolicyCore.java

Author: rickhall
Date: Fri Feb  9 11:46:47 2007
New Revision: 505459

URL: http://svn.apache.org/viewvc?view=rev&rev=505459
Log:
Modified the framework's handling of "removal pending" packages that 
result from bundle updates or uninstalls. Previously the resolver would 
ignore such packages when resolving new bundles, but now it will use 
them. Additionally, the framework now checks to see if a bundle is in 
use when it is updated or uninstalled and if none of its exports are 
used, then it immediately refreshes that bundle.

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

Modified: incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java?view=diff&rev=505459&r1=505458&r2=505459
==============================================================================
--- incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java (original)
+++ incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java Fri Feb  9 11:46:47 2007
@@ -1532,6 +1532,37 @@
                     .setRemovalPending(true);
 
                 fireBundleEvent(BundleEvent.UPDATED, bundle);
+
+                // Determine if the bundle is in use by anyone.
+// TODO: FRAMEWORK - This is really inefficient since it will end up looping
+//       through all bundles and their imports, maybe we should keep track of
+//       wiring.
+                List usedPackages = new ArrayList();
+                getExportedPackages(bundle, usedPackages);
+                boolean used = false;
+                for (int i = 0; !used && (i < usedPackages.size()); i++)
+                {
+                    if (((ExportedPackageImpl) usedPackages.get(i)).getImportingBundles() != null)
+                    {
+                        used = true;
+                    }
+                }
+
+                // If the bundle is not used by anyone, then garbage
+                // collect it now.
+                if (!used)
+                {
+                    try
+                    {
+                        refreshPackages(new Bundle[] { bundle });
+                    }
+                    catch (Exception ex)
+                    {
+                        m_logger.log(
+                            Logger.LOG_ERROR,
+                            "Unable to immediately purge the bundle revisions.", ex);
+                    }
+                }
             }
 
             // Restart bundle, but do not change the persistent state.
@@ -1740,7 +1771,7 @@
             ((ModuleImpl) target.getInfo().getCurrentModule()).setRemovalPending(true);
 
             // Put bundle in uninstalled bundle array.
-            rememberUninstalledBundle(bundle);
+            rememberUninstalledBundle(bundle);               
         }
         else
         {
@@ -1754,6 +1785,37 @@
 
         // Fire bundle event.
         fireBundleEvent(BundleEvent.UNINSTALLED, bundle);
+
+        // Determine if the bundle is in use by anyone.
+// TODO: FRAMEWORK - This is really inefficient since it will end up looping
+//       through all bundles and their imports, maybe we should keep track of
+//       wiring.
+         List usedPackages = new ArrayList();
+         getExportedPackages(bundle, usedPackages);
+         boolean used = false;
+         for (int i = 0; !used && (i < usedPackages.size()); i++)
+         {
+             if (((ExportedPackageImpl) usedPackages.get(i)).getImportingBundles() != null)
+             {
+                 used = true;
+             }
+         }
+
+         // If the bundle is not used by anyone, then garbage
+         // collect it now.
+         if (!used)
+         {
+             try
+             {
+                 refreshPackages(new Bundle[] { bundle });
+             }
+             catch (Exception ex)
+             {
+                 m_logger.log(
+                     Logger.LOG_ERROR,
+                     "Unable to immediately garbage collect the bundle.", ex);
+             }
+         }
     }
 
     //
@@ -2500,8 +2562,7 @@
                     ICapability.PACKAGE_NAMESPACE,
                     null,
                     null,
-                    new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, pkgName, false) }),
-                true);
+                    new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, pkgName, false) }));
 
         if (exporters != null)
         {
@@ -2630,8 +2691,7 @@
                                 ICapability.PACKAGE_NAMESPACE,
                                 null,
                                 null,
-                                new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, ((Capability) caps[capIdx]).getPackageName(), false) }),
-                            true);
+                                new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, ((Capability) caps[capIdx]).getPackageName(), false) }));
     
                         // Search through the current providers to find the target
                         // module.

Modified: incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java?view=diff&rev=505459&r1=505458&r2=505459
==============================================================================
--- incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java (original)
+++ incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java Fri Feb  9 11:46:47 2007
@@ -541,7 +541,7 @@
                         synchronized (m_factory)
                         {
                             // First check "in use" candidates for a match.
-                            PackageSource[] candidates = getInUseCandidates(req, false);
+                            PackageSource[] candidates = getInUseCandidates(req);
                             // If there is an "in use" candidate, just take the first one.
                             if (candidates.length > 0)
                             {
@@ -552,7 +552,7 @@
                             // candidates.
                             if (candidate == null)
                             {
-                                candidates = getUnusedCandidates(req, false);
+                                candidates = getUnusedCandidates(req);
 
                                 // Take the first candidate that can resolve.
                                 for (int candIdx = 0;
@@ -627,7 +627,7 @@
         return null;
     }
 
-    public PackageSource[] getInUseCandidates(IRequirement req, boolean includeRemovalPending)
+    public PackageSource[] getInUseCandidates(IRequirement req)
     {
         // Synchronized on the module manager to make sure that no
         // modules are added, removed, or resolved.
@@ -639,35 +639,30 @@
             {
                 Map.Entry entry = (Map.Entry) i.next();
                 IModule module = (IModule) entry.getKey();
-                // The spec says that we cannot consider modules that
-                // are pending removal, so ignore them.
-                if (includeRemovalPending || !module.isRemovalPending())
+                ICapability[] inUseCaps = (ICapability[]) entry.getValue();
+                for (int capIdx = 0; capIdx < inUseCaps.length; capIdx++)
                 {
-                    ICapability[] inUseCaps = (ICapability[]) entry.getValue();
-                    for (int capIdx = 0; capIdx < inUseCaps.length; capIdx++)
+                    if (req.isSatisfied(inUseCaps[capIdx]))
                     {
-                        if (req.isSatisfied(inUseCaps[capIdx]))
-                        {
 // TODO: RB - Is this permission check correct.
-                            if (inUseCaps[capIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE) &&
-                                (System.getSecurityManager() != null) &&
-                                !((ProtectionDomain) module.getSecurityContext()).implies(
-                                    new PackagePermission(
-                                        (String) inUseCaps[capIdx].getProperties().get(ICapability.PACKAGE_PROPERTY),
-                                        PackagePermission.EXPORT)))
-                            {
-                                m_logger.log(Logger.LOG_DEBUG,
-                                    "PackagePermission.EXPORT denied for "
-                                    + inUseCaps[capIdx].getProperties().get(ICapability.PACKAGE_PROPERTY)
-                                    + "from " + module.getId());
-                            }
-                            else
-                            {
-                                PackageSource[] tmp = new PackageSource[candidates.length + 1];
-                                System.arraycopy(candidates, 0, tmp, 0, candidates.length);
-                                tmp[candidates.length] = new PackageSource(module, inUseCaps[capIdx]);
-                                candidates = tmp;
-                            }
+                        if (inUseCaps[capIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE) &&
+                            (System.getSecurityManager() != null) &&
+                            !((ProtectionDomain) module.getSecurityContext()).implies(
+                                new PackagePermission(
+                                    (String) inUseCaps[capIdx].getProperties().get(ICapability.PACKAGE_PROPERTY),
+                                    PackagePermission.EXPORT)))
+                        {
+                            m_logger.log(Logger.LOG_DEBUG,
+                                "PackagePermission.EXPORT denied for "
+                                + inUseCaps[capIdx].getProperties().get(ICapability.PACKAGE_PROPERTY)
+                                + "from " + module.getId());
+                        }
+                        else
+                        {
+                            PackageSource[] tmp = new PackageSource[candidates.length + 1];
+                            System.arraycopy(candidates, 0, tmp, 0, candidates.length);
+                            tmp[candidates.length] = new PackageSource(module, inUseCaps[capIdx]);
+                            candidates = tmp;
                         }
                     }
                 }
@@ -690,7 +685,7 @@
         return false;
     }
 
-    public PackageSource[] getUnusedCandidates(IRequirement req, boolean includeRemovalPending)
+    public PackageSource[] getUnusedCandidates(IRequirement req)
     {
         // Synchronized on the module manager to make sure that no
         // modules are added, removed, or resolved.
@@ -703,21 +698,16 @@
             PackageSource[] candidates = m_emptySources;
             for (int modIdx = 0; (modules != null) && (modIdx < modules.length); modIdx++)
             {
-                // The spec says that we cannot consider modules that
-                // are pending removal, so ignore them.
-                if (includeRemovalPending || !modules[modIdx].isRemovalPending())
-                {
-                    // Get the module's export package for the target package.
-                    ICapability cap = Util.getSatisfyingCapability(modules[modIdx], req);
-                    // If compatible and it is not currently used, then add
-                    // the available candidate to the list.
-                    if ((cap != null) && !isCapabilityInUse(modules[modIdx], cap))
-                    {
-                        PackageSource[] tmp = new PackageSource[candidates.length + 1];
-                        System.arraycopy(candidates, 0, tmp, 0, candidates.length);
-                        tmp[candidates.length] = new PackageSource(modules[modIdx], cap);
-                        candidates = tmp;
-                    }
+                // Get the module's export package for the target package.
+                ICapability cap = Util.getSatisfyingCapability(modules[modIdx], req);
+                // If compatible and it is not currently used, then add
+                // the available candidate to the list.
+                if ((cap != null) && !isCapabilityInUse(modules[modIdx], cap))
+                {
+                    PackageSource[] tmp = new PackageSource[candidates.length + 1];
+                    System.arraycopy(candidates, 0, tmp, 0, candidates.length);
+                    tmp[candidates.length] = new PackageSource(modules[modIdx], cap);
+                    candidates = tmp;
                 }
             }
             Arrays.sort(candidates);
@@ -829,8 +819,8 @@
             // package maps. Candidates "in use" have higher priority
             // than "available" ones, so put the "in use" candidates
             // at the front of the list of candidates.
-            PackageSource[] inuse = getInUseCandidates(reqs[reqIdx], false);
-            PackageSource[] available = getUnusedCandidates(reqs[reqIdx], false);
+            PackageSource[] inuse = getInUseCandidates(reqs[reqIdx]);
+            PackageSource[] available = getUnusedCandidates(reqs[reqIdx]);
             PackageSource[] candidates = new PackageSource[inuse.length + available.length];
 // TODO: RB - This duplicates "in use" candidates from "available" candidates.
             System.arraycopy(inuse, 0, candidates, 0, inuse.length);
@@ -2410,9 +2400,9 @@
         if (imp != null)
         {
             // Try to see if there is an exporter available.
-            PackageSource[] exporters = getInUseCandidates(imp, true);
+            PackageSource[] exporters = getInUseCandidates(imp);
             exporters = (exporters.length == 0)
-                ? getUnusedCandidates(imp, true) : exporters;
+                ? getUnusedCandidates(imp) : exporters;
 
             // An exporter might be available, but it may have attributes
             // that do not match the importer's required attributes, so
@@ -2424,9 +2414,9 @@
                 {
                     IRequirement pkgReq = new Requirement(
                         ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")");
-                    exporters = getInUseCandidates(pkgReq, true);
+                    exporters = getInUseCandidates(pkgReq);
                     exporters = (exporters.length == 0)
-                        ? getUnusedCandidates(pkgReq, true) : exporters;
+                        ? getUnusedCandidates(pkgReq) : exporters;
                 }
                 catch (InvalidSyntaxException ex)
                 {
@@ -2475,8 +2465,8 @@
         {
             // This should never happen.
         }
-        PackageSource[] exporters = getInUseCandidates(pkgReq, true);
-        exporters = (exporters.length == 0) ? getUnusedCandidates(pkgReq, true) : exporters;
+        PackageSource[] exporters = getInUseCandidates(pkgReq);
+        exporters = (exporters.length == 0) ? getUnusedCandidates(pkgReq) : exporters;
         if (exporters.length > 0)
         {
             boolean classpath = false;