From 63972067fb01be766c6263613288951c5e83abbe Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Thu, 19 Sep 2024 17:03:48 +0200 Subject: [PATCH] #6216 no locations in synthetic resources made for MRJs. Added a content cap in the synthetic resource so equals works. Turned out hashcode did not work well in ResourceImpl so also fixed this. Fixes #6212 --- Signed-off-by: Peter Kriens Signed-off-by: Peter Kriens --- .../test/test/MultiReleaseTest.java | 36 +++++++++++-------- .../bnd/osgi/resource/ResourceBuilder.java | 18 +++++++++- .../aQute/bnd/osgi/resource/ResourceImpl.java | 7 +++- 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/biz.aQute.bndlib.tests/test/test/MultiReleaseTest.java b/biz.aQute.bndlib.tests/test/test/MultiReleaseTest.java index e6435ac290..a24355def9 100644 --- a/biz.aQute.bndlib.tests/test/test/MultiReleaseTest.java +++ b/biz.aQute.bndlib.tests/test/test/MultiReleaseTest.java @@ -7,9 +7,11 @@ import java.io.File; import java.net.URI; import java.nio.charset.StandardCharsets; +import java.util.LinkedHashSet; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.jar.Manifest; import java.util.stream.Collectors; @@ -214,43 +216,47 @@ public void testMultiReleaseIndexing() throws Exception { ResourceBuilder rb = new ResourceBuilder(); boolean identity = rb.addFile(file); assertThat(identity).isTrue(); - SupportingResource r = rb.build(); - assertThat(r.hasIdentity()).isTrue(); + SupportingResource original = rb.build(); + assertThat(original.hasIdentity()).isTrue(); - testResource(r, "(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))", - null, false); - assertThat(r.getSupportingResources()).hasSize(4); - testResource(r.getSupportingResources() - .get(0), null, - "(&(osgi.ee=JavaSE)(&(version>=1.8.0)(!(version>=9.0.0))))", true); + testResource(original, "(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))", null, false); + assertThat(original.getSupportingResources()).hasSize(4); + testResource(original.getSupportingResources() + .get(0), null, "(&(osgi.ee=JavaSE)(&(version>=1.8.0)(!(version>=9.0.0))))", true); - testResource(r.getSupportingResources() + testResource(original.getSupportingResources() .get(1), null, "(&(osgi.ee=JavaSE)(&(version>=9.0.0)(!(version>=12.0.0))))", true); - testResource(r.getSupportingResources() + testResource(original.getSupportingResources() .get(2), "(&(osgi.wiring.package=org.osgi.service.url)(version>=1.0.0)(!(version>=2.0.0)))", "(&(osgi.ee=JavaSE)(&(version>=12.0.0)(!(version>=17.0.0))))", true); - testResource(r.getSupportingResources() + testResource(original.getSupportingResources() .get(3), "(&(osgi.wiring.package=org.osgi.service.startlevel)(version>=1.1.0)(!(version>=2.0.0))),(&(osgi.wiring.package=org.osgi.service.url)(version>=1.0.0)(!(version>=2.0.0)))", "(&(osgi.ee=JavaSE)(version>=17.0.0))", true); // check the expansion of the SupportingResources ResourcesRepository repo = new ResourcesRepository(); - repo.add(r); + repo.add(original); assertThat(repo.getResources()).hasSize(5); // check the expansion of the SupportingResource & roundtrip through XML XMLResourceGenerator xg = new XMLResourceGenerator(); - xg.resource(r); + xg.resource(original); ByteArrayOutputStream bout = new ByteArrayOutputStream(); xg.save(bout); String s = new String(bout.toByteArray(), StandardCharsets.UTF_8); System.out.println(s); - List l = XMLResourceParser + List parsedResources = XMLResourceParser .getResources(new ByteArrayInputStream(bout.toByteArray()), new URI("")); - assertThat(l).hasSize(5); + assertThat(parsedResources).hasSize(5); + // Check if the equals works, when we add the originals and the parsed + // to a set we should have still 5 resources. + + Set duplicatesCheck = new LinkedHashSet<>(repo.getResources()); + duplicatesCheck.addAll(parsedResources); + assertThat(duplicatesCheck).hasSize(5); } final static org.osgi.framework.Version lowest = new org.osgi.framework.Version("0"); diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/ResourceBuilder.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/ResourceBuilder.java index efc09a74d6..07747f65ac 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/ResourceBuilder.java +++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/ResourceBuilder.java @@ -10,6 +10,7 @@ import java.io.File; import java.net.URI; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; @@ -1023,8 +1024,8 @@ public static SupportingResource parse(File file, URI uri) { try (Jar jar = new Jar(file)) { ResourceBuilder rb = new ResourceBuilder(); - boolean hasIdentity = rb.addJar(jar); + boolean hasIdentity = rb.addJar(jar); String mime = hasIdentity ? MIME_TYPE_BUNDLE : MIME_TYPE_JAR; rb.addContentCapability(uri, @@ -1135,9 +1136,24 @@ static SupportingResource buildSupportingResource(JPMSModule jpms, String bsn, V rqb.addFilter(fb); builder.addRequirement(rqb); + builder.addSyntheticContentCapability("urn:osgi-bnd-mrj:" + bsn + ":" + version + ":" + release); return builder.build(); } + /* + * Pass a urn that is unique for this resource. + */ + private void addSyntheticContentCapability(String urn) { + try { + URI uri = URI.create(urn); + String sha = SHA256.digest(urn.getBytes(StandardCharsets.UTF_8)) + .asHex(); + addContentCapability(uri, sha, 0, "application/octetstream"); + } catch (Exception e) { + throw Exceptions.duck(e); + } + } + public boolean addManifest(Manifest m) { return addManifest(Domain.domain(m)); diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/ResourceImpl.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/ResourceImpl.java index 8c7381d4c5..df57a1a03c 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/ResourceImpl.java +++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/ResourceImpl.java @@ -173,7 +173,12 @@ SupportingResource build(Map> capabilities, this.requirementMap = allRequirements.stream() .collect(groupingBy(Requirement::getNamespace, Lists.toList())); this.locations = ResourceUtils.getLocations(this); - this.hashCode = locations.hashCode(); + this.hashCode = this.locations.keySet() + .stream() + .map(URI::toString) + .sorted() + .map(String::hashCode) + .reduce(0, (prev, next) -> prev * 31 + next); return this; }