Apply patch (FELIX-4762) to eliminate excessive memory consumption when
resolving some require-bundle scenarios.


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1652174 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java b/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java
index 230912a..27d641f 100644
--- a/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java
+++ b/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java
@@ -732,7 +732,7 @@
 
             mergeCandidatePackages(
                 session.getContext(), resource, req, cap, resourcePkgMap, allCandidates,
-                new HashMap<Resource, List<Capability>>());
+                new HashMap<Resource, List<Capability>>(), new HashMap<Resource, List<Resource>>());
         }
 
         // Third, have all candidates to calculate their package spaces.
@@ -829,7 +829,7 @@
     private void mergeCandidatePackages(
         ResolveContext rc, Resource current, Requirement currentReq,
         Capability candCap, Map<Resource, Packages> resourcePkgMap,
-        Candidates allCandidates, Map<Resource, List<Capability>> cycles)
+        Candidates allCandidates, Map<Resource, List<Capability>> cycles, HashMap<Resource, List<Resource>> visitedRequiredBundlesMap)
     {
         List<Capability> cycleCaps = cycles.get(current);
         if (cycleCaps == null)
@@ -858,16 +858,27 @@
             // will be visible to the current resource.
             Packages candPkgs = resourcePkgMap.get(candCap.getResource());
 
-            // We have to merge all exported packages from the candidate,
-            // since the current resource requires it.
-            for (Entry<String, Blame> entry : candPkgs.m_exportedPkgs.entrySet())
+            List<Resource> visitedRequiredBundles = visitedRequiredBundlesMap.get(current);
+            if (visitedRequiredBundles == null)
             {
-                mergeCandidatePackage(
-                    current,
-                    true,
-                    currentReq,
-                    entry.getValue().m_cap,
-                    resourcePkgMap);
+                visitedRequiredBundles = new ArrayList<Resource>();
+                visitedRequiredBundlesMap.put(current, visitedRequiredBundles);
+            }
+            if (!visitedRequiredBundles.contains(candCap.getResource()))
+            {
+                visitedRequiredBundles.add(candCap.getResource());
+
+                // We have to merge all exported packages from the candidate,
+                // since the current resource requires it.
+                for (Entry<String, Blame> entry : candPkgs.m_exportedPkgs.entrySet())
+                {
+                    mergeCandidatePackage(
+                        current,
+                        true,
+                        currentReq,
+                        entry.getValue().m_cap,
+                        resourcePkgMap);
+                }
             }
 
             // If the candidate requires any other bundles with reexport visibility,
@@ -893,7 +904,7 @@
                                 w.getCapability(),
                                 resourcePkgMap,
                                 allCandidates,
-                                cycles);
+                                cycles, visitedRequiredBundlesMap);
                         }
                     }
                 }
@@ -918,7 +929,7 @@
                                 allCandidates.getCandidates(req).iterator().next(),
                                 resourcePkgMap,
                                 allCandidates,
-                                cycles);
+                                cycles, visitedRequiredBundlesMap);
                         }
                     }
                 }