Skip to content

Commit 3a164bf

Browse files
committed
Do not follow generic requirements when computing the classpath
OSGi uses a generic Provide-Capability/Require-Capability model that allows to declare requirements beyond the classic Import-Package and Require-Bunlde. A common example is a bundle that provides a DS component and needs an extender to actually construct the component and inject the services. Another is a logging API that needs a provider. These are especially needed because in such scenario a provider/consumer do not know each other and should not depend directly (only loosely coupled). Currently such providers are still pulled in even though they are not contribute to the compilation classpath as they are completely invisible at runtime - there is a wiring but no classloader access granted. This now adds a new option to the DependencyManager to exclude generic requirements from the computation of the dependency closure and the RequiredPluginsClasspathContainer is using that option to avoid follow such generic wiring contracts.
1 parent d69eff9 commit 3a164bf

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

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

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@
3636
import org.osgi.framework.Bundle;
3737
import org.osgi.framework.Constants;
3838
import org.osgi.framework.Version;
39+
import org.osgi.framework.namespace.BundleNamespace;
40+
import org.osgi.framework.namespace.ExecutionEnvironmentNamespace;
3941
import org.osgi.framework.namespace.HostNamespace;
42+
import org.osgi.framework.namespace.PackageNamespace;
43+
import org.osgi.framework.wiring.BundleCapability;
4044
import org.osgi.framework.wiring.BundleRequirement;
4145
import org.osgi.framework.wiring.BundleRevision;
4246
import org.osgi.framework.wiring.BundleWire;
@@ -80,7 +84,12 @@ public enum Options {
8084
* that define an {@link ICoreConstants#PLATFORM_FILTER} in their
8185
* manifest.
8286
*/
83-
INCLUDE_EXTENSIBLE_FRAGMENTS;
87+
INCLUDE_EXTENSIBLE_FRAGMENTS,
88+
/**
89+
* Option that can be set to exclude generic capabilities on which the
90+
* bundle depends.
91+
*/
92+
EXCLUDE_REQUIRED_CAPABILITY;
8493
}
8594

8695
/**
@@ -177,6 +186,7 @@ public static Set<BundleDescription> findRequirementsClosure(Collection<BundleDe
177186
Options... options) {
178187

179188
Set<Options> optionSet = Set.of(options);
189+
boolean excludeGenericRequiredCapability = optionSet.contains(Options.EXCLUDE_REQUIRED_CAPABILITY);
180190
boolean includeOptional = optionSet.contains(Options.INCLUDE_OPTIONAL_DEPENDENCIES);
181191
boolean includeAllFragments = optionSet.contains(Options.INCLUDE_ALL_FRAGMENTS);
182192
boolean includeNonTestFragments = optionSet.contains(Options.INCLUDE_NON_TEST_FRAGMENTS);
@@ -242,7 +252,19 @@ public static Set<BundleDescription> findRequirementsClosure(Collection<BundleDe
242252
// not included into the closure.
243253
continue;
244254
}
245-
BundleRevision provider = wire.getCapability().getRevision();
255+
BundleCapability capability = wire.getCapability();
256+
if (excludeGenericRequiredCapability) {
257+
String namespace = capability.getNamespace();
258+
if (!BundleNamespace.BUNDLE_NAMESPACE.equals(namespace)
259+
&& !PackageNamespace.PACKAGE_NAMESPACE.equals(namespace)
260+
&& !HostNamespace.HOST_NAMESPACE.equals(namespace)
261+
&& !ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE.equals(namespace)) {
262+
// If it is not one of the framework namespaces it is a
263+
// generic one see https://docs.osgi.org/specification/osgi.core/8.0.0/framework.namespaces.html
264+
continue;
265+
}
266+
}
267+
BundleRevision provider = capability.getRevision();
246268
// Use revision of required capability to support the case if
247269
// fragments contribute new packages to their host's API.
248270
if (provider instanceof BundleDescription requiredBundle && (includeOptional || !isOptional(wire.getRequirement()))) {

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*******************************************************************************/
1515
package org.eclipse.pde.internal.core;
1616

17+
import static org.eclipse.pde.internal.core.DependencyManager.Options.EXCLUDE_REQUIRED_CAPABILITY;
1718
import static org.eclipse.pde.internal.core.DependencyManager.Options.INCLUDE_OPTIONAL_DEPENDENCIES;
1819

1920
import java.io.File;
@@ -684,7 +685,7 @@ private void addImplicitDependencies(BundleDescription desc, Set<BundleDescripti
684685
private void addTransitiveDependenciesWithForbiddenAccess(Set<BundleDescription> added,
685686
List<IClasspathEntry> entries) throws CoreException {
686687
Set<BundleDescription> closure = DependencyManager.findRequirementsClosure(added,
687-
INCLUDE_OPTIONAL_DEPENDENCIES);
688+
INCLUDE_OPTIONAL_DEPENDENCIES, EXCLUDE_REQUIRED_CAPABILITY);
688689
String systemBundleBSN = TargetPlatformHelper.getPDEState().getSystemBundle();
689690
Iterator<BundleDescription> transitiveDeps = closure.stream()
690691
.filter(desc -> !desc.getSymbolicName().equals(systemBundleBSN))

0 commit comments

Comments
 (0)