Skip to content

Commit 88117b8

Browse files
committed
Consider dependencies of transitively included fragments
Fixes #1727
1 parent b094c16 commit 88117b8

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/DependencyManager.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.eclipse.pde.core.target.NameVersionDescriptor;
3636
import org.osgi.framework.Constants;
3737
import org.osgi.framework.Version;
38+
import org.osgi.framework.namespace.HostNamespace;
3839
import org.osgi.framework.wiring.BundleRequirement;
3940
import org.osgi.framework.wiring.BundleRevision;
4041
import org.osgi.framework.wiring.BundleWire;
@@ -196,6 +197,19 @@ public static Set<BundleDescription> findRequirementsClosure(Collection<BundleDe
196197
}
197198
}
198199

200+
if (isFragment(wiring.getRevision())) {
201+
// Requirements of a fragment are hosted at the host, which
202+
// therefore requires the corresponding wires: OSGi Core spec,
203+
// chapter 6.4.1 - Hosted Requirements and Capabilities
204+
for (BundleWire hostWire : wiring.getRequiredWires(HostNamespace.HOST_NAMESPACE)) {
205+
// Temporarily remove this fragment's host from the closure
206+
// to ensure it's added again below. In the subsequent
207+
// processing this fragment's requirements will then also be
208+
// considered (before it was discarded).
209+
closure.remove(hostWire.getProvider());
210+
}
211+
}
212+
199213
List<BundleWire> requiredWires = wiring.getRequiredWires(null);
200214
for (BundleWire wire : requiredWires) {
201215
BundleRevision declaringBundle = wire.getRequirement().getRevision();
@@ -222,6 +236,10 @@ private static void addNewRequiredBundle(BundleDescription bundle, Set<BundleDes
222236
}
223237
}
224238

239+
private static boolean isFragment(BundleRevision bundle) {
240+
return (bundle.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0;
241+
}
242+
225243
private static boolean isOptional(BundleRequirement requirement) {
226244
return Constants.RESOLUTION_OPTIONAL.equals(requirement.getDirectives().get(Constants.RESOLUTION_DIRECTIVE));
227245
}

ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/core/tests/internal/DependencyManagerTest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,34 @@ public void testFindRequirementsClosure_includeFragmentsProvidingPackages() thro
308308
assertThat(wClosure).isEqualTo(Set.of(bundleW, bundleB, fragmentB));
309309
}
310310

311+
@Test
312+
public void testFindRequirementsClosure_requirementsOfTransitivlyRequiredFragment() throws Exception {
313+
setTargetPlatform( //
314+
bundle("bundle.host", "1.0.0"),
315+
316+
bundle("bundle.a", "1.0.0", //
317+
entry(REQUIRE_BUNDLE, "bundle.host"), //
318+
entry(REQUIRE_CAPABILITY, "some.test.capability")),
319+
320+
bundle("bundle.fragment", "1.0.0", //
321+
entry(FRAGMENT_HOST, "bundle.host"), //
322+
entry(REQUIRE_BUNDLE, "bundle.b"), //
323+
entry(PROVIDE_CAPABILITY, "some.test.capability")),
324+
325+
bundle("bundle.b", "1.0.0"));
326+
327+
BundleDescription bundleHost = bundleDescription("bundle.host", "1.0.0");
328+
BundleDescription bundleFragment = bundleDescription("bundle.fragment", "1.0.0");
329+
BundleDescription bundleA = bundleDescription("bundle.a", "1.0.0");
330+
BundleDescription bundleB = bundleDescription("bundle.b", "1.0.0");
331+
332+
List<BundleDescription> bundles = List.of(bundleHost, bundleA);
333+
// It's important that the host is first
334+
335+
Set<BundleDescription> noFragmentsClosure = findRequirementsClosure(bundles);
336+
assertThat(noFragmentsClosure).isEqualTo(Set.of(bundleHost, bundleFragment, bundleA, bundleB));
337+
}
338+
311339
@Test
312340
public void testFindRequirementsClosure_includeOptional() throws Exception {
313341

0 commit comments

Comments
 (0)