Move checking of mandatory revisions into the Candidates.prepare() method, since
it must always be done after a prepare. (FELIX-2950)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1156240 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/resolver/Candidates.java b/framework/src/main/java/org/apache/felix/framework/resolver/Candidates.java
index e291772..76e8e18 100644
--- a/framework/src/main/java/org/apache/felix/framework/resolver/Candidates.java
+++ b/framework/src/main/java/org/apache/felix/framework/resolver/Candidates.java
@@ -50,6 +50,8 @@
     public static final int OPTIONAL = 1;
     public static final int ON_DEMAND = 2;
 
+    // Set of all mandatory bundle revisions.
+    private final Set<BundleRevision> m_mandatoryRevisions;
     // Set of all involved bundle revisions.
     private final Set<BundleRevision> m_involvedRevisions;
     // Maps a capability to requirements that match it.
@@ -79,13 +81,14 @@
      * @param wrappedHosts the wrapped hosts map.
     **/
     private Candidates(
-        Set<BundleRevision> involvedRevisions,
+        Set<BundleRevision> mandatoryRevisions, Set<BundleRevision> involvedRevisions,
         Map<BundleCapability, Set<BundleRequirement>> dependentMap,
         Map<BundleRequirement, SortedSet<BundleCapability>> candidateMap,
         Map<BundleCapability, Map<String, Map<Version, List<BundleRequirement>>>> hostFragments,
         Map<BundleRevision, HostBundleRevision> wrappedHosts, Map<BundleRevision, Object> populateResultCache,
         boolean fragmentsPresent)
     {
+        m_mandatoryRevisions = mandatoryRevisions;
         m_involvedRevisions = involvedRevisions;
         m_dependentMap = dependentMap;
         m_candidateMap = candidateMap;
@@ -100,6 +103,7 @@
     **/
     public Candidates()
     {
+        m_mandatoryRevisions = new HashSet<BundleRevision>();
         m_involvedRevisions = new HashSet<BundleRevision>();
         m_dependentMap = new HashMap<BundleCapability, Set<BundleRequirement>>();
         m_candidateMap = new HashMap<BundleRequirement, SortedSet<BundleCapability>>();
@@ -158,6 +162,10 @@
         if ((resolution != ON_DEMAND)
             || (isFragment && populateFragment(state, revision)))
         {
+            if (resolution == MANDATORY)
+            {
+                m_mandatoryRevisions.add(revision);
+            }
             try
             {
                 // Try to populate candidates for the optional revision.
@@ -489,6 +497,10 @@
         ResolverState state, BundleRevision revision,
         BundleRequirement req, SortedSet<BundleCapability> candidates)
     {
+        // Record the revision associated with the dynamic require
+        // as a mandatory revision.
+        m_mandatoryRevisions.add(revision);
+
         // Add the dynamic imports candidates.
         add(req, candidates);
 
@@ -820,6 +832,17 @@
                 }
             }
         }
+
+        // Lastly, verify that all mandatory revisions are still
+        // populated, since some might have become unresolved after
+        // selecting fragments/singletons.
+        for (BundleRevision br : m_mandatoryRevisions)
+        {
+            if (!isPopulated(br))
+            {
+                throw getResolveException(br);
+            }
+        }
     }
 
     private void populateDependents()
@@ -1034,7 +1057,7 @@
         }
 
         return new Candidates(
-            m_involvedRevisions, dependentMap, candidateMap,
+            m_mandatoryRevisions, m_involvedRevisions, dependentMap, candidateMap,
             m_hostFragments, m_allWrappedHosts, m_populateResultCache,
             m_fragmentsPresent);
     }
diff --git a/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java b/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java
index 68c9c72..1a10f3f 100644
--- a/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java
@@ -119,18 +119,6 @@
                 // Merge any fragments into hosts.
                 allCandidates.prepare(getResolvedSingletons(state));
 
-                // Make sure mandatory revisions are still resolved,
-                // since they could fail due to fragment and/or singleton
-                // selection.
-// TODO: OSGi R4.3 - Could this be merged back into Candidates?
-                for (BundleRevision br : mandatoryRevisions)
-                {
-                    if (!allCandidates.isPopulated(br))
-                    {
-                        throw allCandidates.getResolveException(br);
-                    }
-                }
-
                 // Create a combined list of populated revisions; for
                 // optional revisions. We do not need to consider ondemand
                 // fragments, since they will only be pulled in if their
@@ -317,14 +305,6 @@
                     // Merge any fragments into hosts.
                     allCandidates.prepare(getResolvedSingletons(state));
 
-                    // Make sure revision is still valid, since it could
-                    // fail due to fragment and/or singleton selection.
-// TODO: OSGi R4.3 - Could this be merged back into Candidates?
-                    if (!allCandidates.isPopulated(revision))
-                    {
-                        throw allCandidates.getResolveException(revision);
-                    }
-
                     // Record the initial candidate permutation.
                     m_usesPermutations.add(allCandidates);