You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by gn...@apache.org on 2015/08/20 14:32:32 UTC

svn commit: r1696779 - in /felix/trunk/resolver/src: main/java/org/apache/felix/resolver/Candidates.java main/java/org/apache/felix/resolver/ResolverImpl.java test/java/org/apache/felix/resolver/test/ResolverTest.java

Author: gnodet
Date: Thu Aug 20 12:32:32 2015
New Revision: 1696779

URL: http://svn.apache.org/r1696779
Log:
[FELIX-4987] Dynamic package resolution with unresolvable or fragment package exports can lead to invalid wirings

Modified:
    felix/trunk/resolver/src/main/java/org/apache/felix/resolver/Candidates.java
    felix/trunk/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java
    felix/trunk/resolver/src/test/java/org/apache/felix/resolver/test/ResolverTest.java

Modified: felix/trunk/resolver/src/main/java/org/apache/felix/resolver/Candidates.java
URL: http://svn.apache.org/viewvc/felix/trunk/resolver/src/main/java/org/apache/felix/resolver/Candidates.java?rev=1696779&r1=1696778&r2=1696779&view=diff
==============================================================================
--- felix/trunk/resolver/src/main/java/org/apache/felix/resolver/Candidates.java (original)
+++ felix/trunk/resolver/src/main/java/org/apache/felix/resolver/Candidates.java Thu Aug 20 12:32:32 2015
@@ -123,6 +123,29 @@ class Candidates
         return m_populateResultCache.size();
     }
 
+    public Map<Resource, Resource> getHosts()
+    {
+        Map<Resource, Resource> hosts = new HashMap<Resource, Resource>();
+        for (Resource res : m_mandatoryResources)
+        {
+            if (res instanceof WrappedResource)
+            {
+                res = ((WrappedResource) res).getDeclaredResource();
+            }
+            hosts.put(res, getWrappedHost(res));
+        }
+        for (Capability cap : m_dependentMap.keySet())
+        {
+            Resource res = cap.getResource();
+            if (res instanceof WrappedResource)
+            {
+                res = ((WrappedResource) res).getDeclaredResource();
+            }
+            hosts.put(res, getWrappedHost(res));
+        }
+        return hosts;
+    }
+
     /**
      * Returns the delta which is the differences in the candidates from the
      * original Candidates permutation.
@@ -460,7 +483,6 @@ class Candidates
         // cannot resolve.
         // TODO: verify the two following statements
         LinkedList<Resource> toPopulate = new LinkedList<Resource>();
-        toPopulate.add(resource);
         ResolutionError rethrow = processCandidates(rc, toPopulate, req, candidates);
 
         // Add the dynamic imports candidates.
@@ -468,6 +490,18 @@ class Candidates
         // fragment candidates are properly hosted before adding the candidates list which makes a copy
         addCandidates(req, candidates);
 
+        populate(rc, toPopulate);
+
+        CopyOnWriteList<Capability> caps = m_candidateMap.get(req);
+        if (caps != null)
+        {
+            candidates.retainAll(caps);
+        }
+        else
+        {
+            candidates.clear();
+        }
+
         if (candidates.isEmpty())
         {
             if (rethrow == null)
@@ -1092,9 +1126,12 @@ class Candidates
                     if (!Util.isOptional(r))
                     {
                         PopulateResult result = m_populateResultCache.get(r.getResource());
-                        result.success = false;
-                        result.error =
-                            new MissingRequirementError(r, m_populateResultCache.get(c.getResource()).error);
+                        if (result != null)
+                        {
+                            result.success = false;
+                            result.error =
+                                    new MissingRequirementError(r, m_populateResultCache.get(c.getResource()).error);
+                        }
                         unresolvedResources.add(r.getResource());
                     }
                 }

Modified: felix/trunk/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java?rev=1696779&r1=1696778&r2=1696779&view=diff
==============================================================================
--- felix/trunk/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java (original)
+++ felix/trunk/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java Thu Aug 20 12:32:32 2015
@@ -572,7 +572,7 @@ public class ResolverImpl implements Res
                                 new DumbExecutor(),
                                 session, usesPermutations, importPermutations, allCandidates,
                                 new OpenHashMap<Resource, ResolutionError>(resourcePkgMap.size()),
-                                Collections.singletonMap(host, allCandidates.getWrappedHost(host)),
+                                allCandidates.getHosts(),
                                 true);
                     }
                     while ((rethrow != null)

Modified: felix/trunk/resolver/src/test/java/org/apache/felix/resolver/test/ResolverTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/resolver/src/test/java/org/apache/felix/resolver/test/ResolverTest.java?rev=1696779&r1=1696778&r2=1696779&view=diff
==============================================================================
--- felix/trunk/resolver/src/test/java/org/apache/felix/resolver/test/ResolverTest.java (original)
+++ felix/trunk/resolver/src/test/java/org/apache/felix/resolver/test/ResolverTest.java Thu Aug 20 12:32:32 2015
@@ -426,7 +426,155 @@ public class ResolverTest
         // should be wired to A and C1
         assertEquals(resA, wiresB.get(0).getProvider());
         assertEquals(resC1, wiresB.get(1).getProvider());
+    }
+
+    /**
+     * Test dynamic resolution with a resolved fragment
+     */
+    @Test
+    public void testScenario10() throws Exception
+    {
+        ResolverImpl resolver = new ResolverImpl(new Logger(Logger.LOG_DEBUG), 1);
+
+        Map<Resource, Wiring> wirings = new HashMap<Resource, Wiring>();
+        Map<Requirement, List<Capability>> candMap = new HashMap<Requirement, List<Capability>>();
+
+        ResourceImpl a1 = new ResourceImpl("A");
+        Capability a1_hostCap = addCap(a1, HostNamespace.HOST_NAMESPACE, "A");
+
+        ResourceImpl f1 = new ResourceImpl("F1", IdentityNamespace.TYPE_FRAGMENT);
+        Requirement f1_hostReq = addReq(f1, HostNamespace.HOST_NAMESPACE, "A");
+        Capability f1_pkgCap = addCap(f1, PackageNamespace.PACKAGE_NAMESPACE, "org.foo.a");
+
+        ResourceImpl b1 = new ResourceImpl("B");
+        Requirement b_pkgReq1 = addReq(b1, PackageNamespace.PACKAGE_NAMESPACE, "org.foo.a");
+
+        candMap.put(b_pkgReq1, Collections.singletonList(f1_pkgCap));
+
+        Map<Resource, List<Wire>> wires = new HashMap<Resource, List<Wire>>();
+        wires.put(a1, new ArrayList<Wire>());
+        wires.put(b1, new ArrayList<Wire>());
+        wires.put(f1, new ArrayList<Wire>());
+        wires.get(f1).add(new SimpleWire(f1_hostReq, a1_hostCap));
+
+        Map<Resource, List<Wire>> invertedWires = new HashMap<Resource, List<Wire>>();
+        invertedWires.put(a1, new ArrayList<Wire>());
+        invertedWires.put(b1, new ArrayList<Wire>());
+        invertedWires.put(f1, new ArrayList<Wire>());
+        invertedWires.get(a1).add(new SimpleWire(f1_hostReq, a1_hostCap));
+
+        wirings.put(a1, new SimpleWiring(a1, Arrays.asList(a1_hostCap, f1_pkgCap), wires, invertedWires));
+        wirings.put(b1, new SimpleWiring(b1, Collections.<Capability>emptyList(), wires, invertedWires));
+        wirings.put(f1, new SimpleWiring(f1, Collections.<Capability>emptyList(), wires, invertedWires));
+
+        ResolveContextImpl rci = new ResolveContextImpl(wirings, candMap, Collections.<Resource>emptyList(), Collections.<Resource> emptyList());
+
+        List<Capability> caps = new ArrayList<Capability>();
+        caps.add(f1_pkgCap);
+        Map<Resource, List<Wire>> wireMap = resolver.resolve(rci, b1, b_pkgReq1, caps);
+
+        assertEquals(1, wireMap.size());
+        List<Wire> wiresB = wireMap.get(b1);
+        assertNotNull(wiresB);
+        assertEquals(1, wiresB.size());
+        // should be wired to A through the fragment capability
+        assertEquals(a1, wiresB.get(0).getProvider());
+        assertEquals(f1_pkgCap, wiresB.get(0).getCapability());
+    }
+
+    /**
+     * Test dynamic resolution with an unresolved fragment
+     */
+    @Test
+    public void testScenario11() throws Exception
+    {
+        ResolverImpl resolver = new ResolverImpl(new Logger(Logger.LOG_DEBUG), 1);
+
+        Map<Resource, Wiring> wirings = new HashMap<Resource, Wiring>();
+        Map<Requirement, List<Capability>> candMap = new HashMap<Requirement, List<Capability>>();
+
+        ResourceImpl a1 = new ResourceImpl("A");
+        Capability a1_hostCap = addCap(a1, HostNamespace.HOST_NAMESPACE, "A");
+
+        ResourceImpl f1 = new ResourceImpl("F1", IdentityNamespace.TYPE_FRAGMENT);
+        Requirement f1_hostReq = addReq(f1, HostNamespace.HOST_NAMESPACE, "A");
+        Capability f1_pkgCap = addCap(f1, PackageNamespace.PACKAGE_NAMESPACE, "org.foo.a");
+
+        ResourceImpl b1 = new ResourceImpl("B");
+        Requirement b_pkgReq1 = addReq(b1, PackageNamespace.PACKAGE_NAMESPACE, "org.foo.a");
+
+        candMap.put(b_pkgReq1, Collections.singletonList(f1_pkgCap));
+        candMap.put(f1_hostReq, Collections.singletonList(a1_hostCap));
+
+        Map<Resource, List<Wire>> wires = new HashMap<Resource, List<Wire>>();
+        wires.put(a1, new ArrayList<Wire>());
+        wires.put(b1, new ArrayList<Wire>());
+
+        Map<Resource, List<Wire>> invertedWires = new HashMap<Resource, List<Wire>>();
+        invertedWires.put(a1, new ArrayList<Wire>());
+        invertedWires.put(b1, new ArrayList<Wire>());
+
+        wirings.put(a1, new SimpleWiring(a1, Collections.<Capability>emptyList(), wires, invertedWires));
+        wirings.put(b1, new SimpleWiring(b1, Collections.<Capability>emptyList(), wires, invertedWires));
+
+        ResolveContextImpl rci = new ResolveContextImpl(wirings, candMap, Collections.<Resource>emptyList(), Collections.<Resource> emptyList());
+
+        List<Capability> caps = new ArrayList<Capability>();
+        caps.add(f1_pkgCap);
+        Map<Resource, List<Wire>> wireMap = resolver.resolve(rci, b1, b_pkgReq1, caps);
+
+        assertEquals(1, wireMap.size());
+        List<Wire> wiresB = wireMap.get(b1);
+        assertNotNull(wiresB);
+        assertEquals(1, wiresB.size());
+        // should be wired to A through the fragment capability
+        assertEquals(a1, wiresB.get(0).getProvider());
+        assertEquals(f1_pkgCap, wiresB.get(0).getCapability());
+    }
+
+    /**
+     * Test dynamic resolution with an unresolvable host
+     */
+    @Test(expected = ResolutionException.class)
+    public void testScenario12() throws Exception
+    {
+        ResolverImpl resolver = new ResolverImpl(new Logger(Logger.LOG_DEBUG), 1);
+
+        Map<Resource, Wiring> wirings = new HashMap<Resource, Wiring>();
+        Map<Requirement, List<Capability>> candMap = new HashMap<Requirement, List<Capability>>();
+
+        ResourceImpl a1 = new ResourceImpl("A");
+        Capability a1_hostCap = addCap(a1, HostNamespace.HOST_NAMESPACE, "A");
+
+        ResourceImpl b1 = new ResourceImpl("B");
+        Requirement b_pkgReq1 = addReq(b1, PackageNamespace.PACKAGE_NAMESPACE, "org.foo.a");
+
+        ResourceImpl c1 = new ResourceImpl("C");
+        Capability c_hostCap = addCap(c1, HostNamespace.HOST_NAMESPACE, "A");
+        Capability c_pkgCap = addCap(c1, PackageNamespace.PACKAGE_NAMESPACE, "org.foo.a");
+        Requirement c_pkgReq1 = addReq(c1, PackageNamespace.PACKAGE_NAMESPACE, "org.foo.b");
+
+        candMap.put(b_pkgReq1, Collections.singletonList(c_pkgCap));
+        candMap.put(c_pkgReq1, Collections.<Capability>emptyList());
+
+        Map<Resource, List<Wire>> wires = new HashMap<Resource, List<Wire>>();
+        wires.put(a1, new ArrayList<Wire>());
+        wires.put(b1, new ArrayList<Wire>());
+
+        Map<Resource, List<Wire>> invertedWires = new HashMap<Resource, List<Wire>>();
+        invertedWires.put(a1, new ArrayList<Wire>());
+        invertedWires.put(b1, new ArrayList<Wire>());
+
+        wirings.put(a1, new SimpleWiring(a1, Collections.<Capability>emptyList(), wires, invertedWires));
+        wirings.put(b1, new SimpleWiring(b1, Collections.<Capability>emptyList(), wires, invertedWires));
+
+        ResolveContextImpl rci = new ResolveContextImpl(wirings, candMap, Collections.<Resource>emptyList(), Collections.<Resource> emptyList());
+
+        List<Capability> caps = new ArrayList<Capability>();
+        caps.add(c_pkgCap);
+        Map<Resource, List<Wire>> wireMap = resolver.resolve(rci, b1, b_pkgReq1, caps);
 
+        assertEquals(0, wireMap.size());
     }
 
     private static String getResourceName(Resource r)