Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.eclipse.pde.core.target.NameVersionDescriptor;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
import org.osgi.framework.namespace.HostNamespace;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWire;
Expand Down Expand Up @@ -196,6 +197,19 @@ public static Set<BundleDescription> findRequirementsClosure(Collection<BundleDe
}
}

if (isFragment(wiring.getRevision())) {
// Requirements of a fragment are hosted at the host, which
// therefore requires the corresponding wires: OSGi Core spec,
// chapter 6.4.1 - Hosted Requirements and Capabilities
for (BundleWire hostWire : wiring.getRequiredWires(HostNamespace.HOST_NAMESPACE)) {
// Temporarily remove this fragment's host from the closure
// to ensure it's added again below. In the subsequent
// processing this fragment's requirements will then also be
// considered (before it was discarded).
closure.remove(hostWire.getProvider());
}
}

List<BundleWire> requiredWires = wiring.getRequiredWires(null);
for (BundleWire wire : requiredWires) {
BundleRevision declaringBundle = wire.getRequirement().getRevision();
Expand All @@ -222,6 +236,10 @@ private static void addNewRequiredBundle(BundleDescription bundle, Set<BundleDes
}
}

private static boolean isFragment(BundleRevision bundle) {
return (bundle.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0;
}

private static boolean isOptional(BundleRequirement requirement) {
return Constants.RESOLUTION_OPTIONAL.equals(requirement.getDirectives().get(Constants.RESOLUTION_DIRECTIVE));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,34 @@ public void testFindRequirementsClosure_includeFragmentsProvidingPackages() thro
assertThat(wClosure).isEqualTo(Set.of(bundleW, bundleB, fragmentB));
}

@Test
public void testFindRequirementsClosure_requirementsOfTransitivlyRequiredFragment() throws Exception {
setTargetPlatform( //
bundle("bundle.host", "1.0.0"),

bundle("bundle.a", "1.0.0", //
entry(REQUIRE_BUNDLE, "bundle.host"), //
entry(REQUIRE_CAPABILITY, "some.test.capability")),

bundle("bundle.fragment", "1.0.0", //
entry(FRAGMENT_HOST, "bundle.host"), //
entry(REQUIRE_BUNDLE, "bundle.b"), //
entry(PROVIDE_CAPABILITY, "some.test.capability")),

bundle("bundle.b", "1.0.0"));

BundleDescription bundleHost = bundleDescription("bundle.host", "1.0.0");
BundleDescription bundleFragment = bundleDescription("bundle.fragment", "1.0.0");
BundleDescription bundleA = bundleDescription("bundle.a", "1.0.0");
BundleDescription bundleB = bundleDescription("bundle.b", "1.0.0");

List<BundleDescription> bundles = List.of(bundleHost, bundleA);
// It's important that the host is first

Set<BundleDescription> noFragmentsClosure = findRequirementsClosure(bundles);
assertThat(noFragmentsClosure).isEqualTo(Set.of(bundleHost, bundleFragment, bundleA, bundleB));
}

@Test
public void testFindRequirementsClosure_includeOptional() throws Exception {

Expand Down
Loading