Skip to content

Commit

Permalink
Extend StateBuilder to handle EE from Require-Capability header
Browse files Browse the repository at this point in the history
With this change, the BundleDescription instance that is returned by the
StateBuilder now also contains the execution environments that are
required by the Require-Capability header, rather than only the
Bundle-RequireExecutionEnvironment header.

Previously, a call to getExecutionEnvironments() would always return an
empty array, if a bundle lacks the Bundle-RequireExecutionEnvironment
header, even though a minimum version is required as a capability.

Resolves eclipse-equinox#643
  • Loading branch information
ptziegler committed Jun 17, 2024
1 parent c8ce736 commit 3fcea02
Showing 1 changed file with 59 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2003, 2020 IBM Corporation and others.
* Copyright (c) 2003, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand All @@ -25,7 +25,9 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Stream;
import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.eclipse.osgi.internal.framework.FilterImpl;
import org.eclipse.osgi.internal.messages.Msg;
Expand All @@ -47,6 +49,7 @@
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.Version;
import org.osgi.framework.namespace.BundleNamespace;
import org.osgi.framework.namespace.ExecutionEnvironmentNamespace;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.resource.Namespace;

Expand Down Expand Up @@ -128,7 +131,7 @@ static BundleDescription createBundleDescription(StateImpl state, Dictionary<Str
}
result.setLocation(location);
result.setPlatformFilter(manifest.get(StateImpl.ECLIPSE_PLATFORMFILTER));
String[] brees = ManifestElement.getArrayFromList(manifest.get(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT));
String[] brees = getDeclaredRequiredEE(manifest);
result.setExecutionEnvironments(brees);
ManifestElement[] host = ManifestElement.parseHeader(Constants.FRAGMENT_HOST, manifest.get(Constants.FRAGMENT_HOST));
if (host != null)
Expand Down Expand Up @@ -941,4 +944,58 @@ static GenericDescription createOsgiIdentityCapability(BundleDescription descrip
result.setDirectives(directives);
return result;
}

/**
* The required execution environment can either be declared via the
* {@link Constants#BUNDLE_REQUIREDEXECUTIONENVIRONMENT} or the
* {@link Constants#REQUIRE_CAPABILITY} header. A manifest is expected to
* have one or the other, but not both. In such case, the former takes
* priority.
*
* @see {@link #getEEFromFilter(String)}
*/
private static String[] getDeclaredRequiredEE(Dictionary<String, String> manifest) throws BundleException {
@SuppressWarnings("deprecation")
String requiredEE = manifest.get(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT);
if (requiredEE != null) {
return ManifestElement.getArrayFromList(requiredEE);
}
String requiredCapability = manifest.get(Constants.REQUIRE_CAPABILITY);
ManifestElement[] headers = ManifestElement.parseHeader(Constants.REQUIRE_CAPABILITY, requiredCapability);
if (headers != null) {
return Stream.of(headers) //
.map(header -> header.getDirective(Constants.FILTER_DIRECTIVE)) //
.map(StateBuilder::getEEFromFilter) //
.filter(Objects::nonNull) //
.toArray(String[]::new);
}
return null;
}

/**
* Extracts the execution environment of the given filter specification
* using the environment namespace (e.g. JavaSE) and version attribute
* (e.g. 17). Both values are joined with a '-'. If the filter doesn't
* contain either value or if the filter is otherwise invalid, {@code null}
* is returned.
*
* @see ExecutionEnvironmentNamespace#EXECUTION_ENVIRONMENT_NAMESPACE
* @see ExecutionEnvironmentNamespace#CAPABILITY_VERSION_ATTRIBUTE
*/
private static String getEEFromFilter(String filterSpec) {
if (filterSpec == null) {
return null;
}
try {
FilterImpl filter = FilterImpl.newInstance(filterSpec);
String ee = filter.getPrimaryKeyValue(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE);
String version = filter.getPrimaryKeyValue(ExecutionEnvironmentNamespace.CAPABILITY_VERSION_ATTRIBUTE);
if (ee != null && version != null) {
return ee + '-' + version;
}
} catch (InvalidSyntaxException e) {
// TODO Special handling needed?
}
return null;
}
}

0 comments on commit 3fcea02

Please sign in to comment.