Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regenerate OSGi capabilities after some have been removed #74

Open
nedtwigg opened this issue Feb 7, 2023 · 0 comments
Open

Regenerate OSGi capabilities after some have been removed #74

nedtwigg opened this issue Feb 7, 2023 · 0 comments
Labels
atomos bug Something isn't working

Comments

@nedtwigg
Copy link
Collaborator

nedtwigg commented Feb 7, 2023

EDIT @nedtwigg : The following has been implemented by

so it is fixed for pure-Solstice. Integrating this fix fully into the Atomos integration will require a little more work.


We finally added full startup-ordering based on OSGi capabilities in

but there's something missing from how we did it. Set aside capabilities for now look instead at packages and bundles. For those, we do the following:

  1. calculate what is missing

var missingBundles = calculateMissingBundles(bySymbolicName.keySet());
missingBundles.forEach(
(missing, neededBy) -> {
logger.warn("Missing required bundle " + missing + " needed by " + neededBy);
});
var missingPackages = calculateMissingPackages(byExportedPackage.keySet());
missingPackages.forEach(
(missing, neededBy) -> {

  1. remove those requirements from all SolsticeManifests

for (var bundle : bundles) {
bundle.removeFromRequiredBundles(missingBundles.keySet());
bundle.removeFromPkgImports(missingPackages.keySet());
}

  1. problem solved for BundleContextSolstice, but for BundleContextAtomos we have to regenerate the header string from the SolsticeManifest metadata

public Map<String, String> atomosHeaders(SolsticeManifest manifest) {
Map<String, String> atomos = new LinkedHashMap<>(manifest.getHeadersOriginal());
setHeader(atomos, Constants.IMPORT_PACKAGE, manifest.pkgImports);
setHeader(atomos, Constants.EXPORT_PACKAGE, manifest.pkgExports);
setHeader(atomos, Constants.REQUIRE_BUNDLE, manifest.requiredBundles);
return atomos;
}


When it comes to capabilities, we can calculate what to remove

// warn about missing requirements. TODO: remove missing requirements and set them in Atomos
var allCapabilities = new Capability.SupersetSet();
for (var bundle : bundles) {
allCapabilities.addAll(bundle.capProvides);
}
for (var bundle : bundles) {
for (var cap : bundle.capRequires) {
if (!allCapabilities.containsAnySupersetOf(cap)) {
logger.warn("Missing capability " + cap + " required by " + bundle);

But we don't remove it from SolsticeManifest. Because we don't remove it from the manifests, we have to tolerate missing requirements like this, but we should really throw the commented out exception.

Capability cap;
while ((cap = missingCap(manifest)) != null) {
var bundles = unactivatedBundlesForCap(cap);
if (bundles.isEmpty()) {
logger.warn("{} requires missing capability {}", manifest, cap);
caps.add(cap);
// throw new IllegalArgumentException(manifest + " requires missing capability " + cap);

It's easy to fix within SolsticeManifest and BundleContextSolstice, but it's alot harder for BundleContextAtomos because there we will have to regenerate the full header string. The tricky thing is that the Capability we parse does not have everything that the OSGi runtime needs. We could expand the capability to do that, but all we actually need is full deletion of a matched capability, so probably it's easier to do removeCapabilities(Collection<Capability> cap) and have that operate on these implementation-details linked below

private List<CapabilityParsed> parseAndStripCapability(String header) {
try {
String capability = headersOriginal.get(header);
if (capability == null) {
return Collections.emptyList();
}
// org.eclipse.ecf.identity has these gunky quotes
capability = capability.replace('”', '"');
ManifestElement[] elements = ManifestElement.parseHeader(header, capability);
List<CapabilityParsed> capabilities = new ArrayList<>(elements.length);
for (ManifestElement element : elements) {
if (Capability.IGNORED_NAMESPACES.contains(element.getValue())) {
continue;
}
capabilities.add(new CapabilityParsed(element));
}
if (capabilities.isEmpty()) {
return Collections.emptyList();
} else {
return capabilities;
}
} catch (BundleException e) {
throw Unchecked.wrap(e);
}
}
private static class CapabilityParsed {
String namespace;
Map<String, String> attributes = new TreeMap<>();
Map<String, String> directives = new TreeMap<>();
public CapabilityParsed(ManifestElement element) {
namespace = element.getValue();
var keys = element.getKeys();
if (keys != null) {
while (keys.hasMoreElements()) {
String key = keys.nextElement();
if (!Capability.IGNORED_ATTRIBUTES.contains(key)) {
this.attributes.put(key, element.getAttribute(key));
}
}
}
var directives = element.getDirectiveKeys();
if (directives != null) {
while (directives.hasMoreElements()) {
String key = directives.nextElement();
if (key.equals(Constants.FILTER_DIRECTIVE)) {
this.directives.put(

@nedtwigg nedtwigg added solstice-osgi enhancement New feature or request labels Feb 7, 2023
@nedtwigg nedtwigg added atomos bug Something isn't working and removed enhancement New feature or request solstice-osgi labels Feb 13, 2023
@nedtwigg nedtwigg changed the title Modify and regenerate OSGi capabilities Regenerate OSGi capabilities after some have been removed Feb 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
atomos bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant