From b5f4c0d5fc17c1ee69711b3d94594310017cfe4d Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Tue, 25 Jun 2024 23:40:51 +0200 Subject: [PATCH 01/16] 1st draft: fix source lookup for bundle classpath lib jars this is a first rough sketch which solves the problem that the source lookup during a debug session did not work when going into a method (F5) of a class which was coming from a jar inside the bundle classpath which was included via -includeresource: ${repo;bsn;latest}; lib:=true,\ I found out that the reason was that the reason was, that jars in the Bundle Classpath are not considered for source lookup. F3 worked fine though, but that does not help while debugging, because you want to step through the code. this first commit is rough and needs more filtering and fine tuning, since I am adding too many jars. I need to figure out how to select only the few jars added via -includeresource Signed-off-by: Christoph Rueger --- .../BndrunDirectiveSourceContainer.java | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java index f303390de5..8092d5a181 100644 --- a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java +++ b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java @@ -1,7 +1,11 @@ package bndtools.launch.sourcelookup.containers; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Objects; import java.util.Set; @@ -20,6 +24,7 @@ import aQute.bnd.build.Container; import aQute.bnd.build.Container.TYPE; import aQute.bnd.build.Run; +import aQute.bnd.exceptions.Exceptions; import aQute.bnd.exceptions.SupplierWithException; public class BndrunDirectiveSourceContainer extends CompositeSourceContainer { @@ -82,8 +87,9 @@ public ISourceContainerType getType() { @Override protected ISourceContainer[] createSourceContainers() { Set projectsAdded = new HashSet<>(); + Set additionalSourceContainers = new HashSet<>(); try { - return directiveGetter.get() + ISourceContainer[] array = directiveGetter.get() .stream() .map(container -> { if (container.getType() == TYPE.PROJECT) { @@ -94,6 +100,23 @@ protected ISourceContainer[] createSourceContainers() { .getRoot() .getProject(targetProjName); if (targetProj != null) { + + try { + Collection buildpath = container.getProject() + .getBuildpath(); + for (Container bp : buildpath) { + File file = bp.getFile(); + if (file.getName() + .endsWith(".jar")) { + additionalSourceContainers + .add(new ExternalArchiveSourceContainer(file.toString(), false)); + } + + } + } catch (Exception e) { + throw Exceptions.duck(e); + } + IJavaProject targetJavaProj = JavaCore.create(targetProj); return new JavaProjectSourceContainer(targetJavaProj); } @@ -110,6 +133,11 @@ protected ISourceContainer[] createSourceContainers() { }) .filter(Objects::nonNull) .toArray(ISourceContainer[]::new); + + List asList = new ArrayList<>(Arrays.asList(array)); + asList.addAll(additionalSourceContainers); + return asList.toArray(ISourceContainer[]::new); + } catch (Exception e) { logger.logError("Error querying Bnd dependency source containers.", e); } From 471d3deb6513365da5c48fad9e5b2f55fbdb6b69 Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Thu, 27 Jun 2024 20:39:03 +0200 Subject: [PATCH 02/16] consider only REPO and deduplicate Signed-off-by: Christoph Rueger --- .../BndrunDirectiveSourceContainer.java | 43 +++++++++++++++---- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java index 8092d5a181..a3bfc5dbc2 100644 --- a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java +++ b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java @@ -1,13 +1,13 @@ package bndtools.launch.sourcelookup.containers; import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.HashSet; -import java.util.List; +import java.util.LinkedHashSet; import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.bndtools.api.ILogger; import org.bndtools.api.Logger; @@ -23,6 +23,7 @@ import aQute.bnd.build.Container; import aQute.bnd.build.Container.TYPE; +import aQute.bnd.build.Project; import aQute.bnd.build.Run; import aQute.bnd.exceptions.Exceptions; import aQute.bnd.exceptions.SupplierWithException; @@ -93,7 +94,8 @@ protected ISourceContainer[] createSourceContainers() { .stream() .map(container -> { if (container.getType() == TYPE.PROJECT) { - String targetProjName = container.getProject() + Project project = container.getProject(); + String targetProjName = project .getName(); if (projectsAdded.add(targetProjName)) { IProject targetProj = ResourcesPlugin.getWorkspace() @@ -101,11 +103,35 @@ protected ISourceContainer[] createSourceContainers() { .getProject(targetProjName); if (targetProj != null) { + // also add all REPO dependencies of the + // -buildpath + // because they might contain dependencies via + // -includeresource: ${repo;bsn;latest}; + // lib:=true + // which would otherwise not be considered for + // source lookup during debugging try { - Collection buildpath = container.getProject() + Collection buildpath = project .getBuildpath(); + for (Container bp : buildpath) { + + // only consider REPO because we are + // interested in bundles added via + // '-includeresource: + // ${repo;bsn;latest}' + if (TYPE.REPO != bp.getType()) { + continue; + } + File file = bp.getFile(); + + if (file == null) { + // file might not have finished + // downloading or an error + continue; + } + if (file.getName() .endsWith(".jar")) { additionalSourceContainers @@ -134,9 +160,10 @@ protected ISourceContainer[] createSourceContainers() { .filter(Objects::nonNull) .toArray(ISourceContainer[]::new); - List asList = new ArrayList<>(Arrays.asList(array)); - asList.addAll(additionalSourceContainers); - return asList.toArray(ISourceContainer[]::new); + LinkedHashSet set = Stream.of(array) + .collect(Collectors.toCollection(LinkedHashSet::new)); + set.addAll(additionalSourceContainers); + return set.toArray(ISourceContainer[]::new); } catch (Exception e) { logger.logError("Error querying Bnd dependency source containers.", e); From 8bcdf1fe41d21938456bba7db6010d4c6853e730 Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Thu, 27 Jun 2024 20:51:58 +0200 Subject: [PATCH 03/16] use BundleSourceContainer instead this seems to handle downloading of sources Signed-off-by: Christoph Rueger --- .../BndrunDirectiveSourceContainer.java | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java index a3bfc5dbc2..c1774d2583 100644 --- a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java +++ b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java @@ -1,6 +1,5 @@ package bndtools.launch.sourcelookup.containers; -import java.io.File; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashSet; @@ -120,24 +119,12 @@ protected ISourceContainer[] createSourceContainers() { // interested in bundles added via // '-includeresource: // ${repo;bsn;latest}' - if (TYPE.REPO != bp.getType()) { - continue; - } - - File file = bp.getFile(); - - if (file == null) { - // file might not have finished - // downloading or an error - continue; - } - - if (file.getName() - .endsWith(".jar")) { + if (TYPE.REPO == bp.getType()) { additionalSourceContainers - .add(new ExternalArchiveSourceContainer(file.toString(), false)); + .add(new BundleSourceContainer(bp)); } + } } catch (Exception e) { throw Exceptions.duck(e); From 77480487162a5563b6c8621612de45adda263b76 Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Sat, 29 Jun 2024 08:57:28 +0200 Subject: [PATCH 04/16] log exception instead of throwing Signed-off-by: Christoph Rueger --- .../containers/BndrunDirectiveSourceContainer.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java index c1774d2583..7c26fa2e78 100644 --- a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java +++ b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java @@ -24,7 +24,6 @@ import aQute.bnd.build.Container.TYPE; import aQute.bnd.build.Project; import aQute.bnd.build.Run; -import aQute.bnd.exceptions.Exceptions; import aQute.bnd.exceptions.SupplierWithException; public class BndrunDirectiveSourceContainer extends CompositeSourceContainer { @@ -119,7 +118,7 @@ protected ISourceContainer[] createSourceContainers() { // interested in bundles added via // '-includeresource: // ${repo;bsn;latest}' - if (TYPE.REPO == bp.getType()) { + if (bp != null && TYPE.REPO == bp.getType()) { additionalSourceContainers .add(new BundleSourceContainer(bp)); } @@ -127,7 +126,11 @@ protected ISourceContainer[] createSourceContainers() { } } catch (Exception e) { - throw Exceptions.duck(e); + // just log to avoid that + // exceptions interrupt everything else + logger.logError("SourceContainers: Error adding buildpath dependencies of bundle " + + targetProjName, + e); } IJavaProject targetJavaProj = JavaCore.create(targetProj); From 46ccc0b9d9b01f0ba68b111ee842111557845114 Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Wed, 3 Jul 2024 21:23:52 +0200 Subject: [PATCH 05/16] new approach introduced Project.getRepoRefs() Project.getRepoRefs() processes the -includeresource instruction. During this under the hood Project._repo() is called which process the ${repo} macro and there we hooked in to collect the resolved bundle references (Container). Which we then return in Project.getRepoRefs(). This method is then used for source lookup in BndrunDirectiveSourceContainer Signed-off-by: Christoph Rueger --- .../src/aQute/bnd/build/Project.java | 23 +++++++++++++--- .../BndrunDirectiveSourceContainer.java | 27 +++++++++---------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/Project.java b/biz.aQute.bndlib/src/aQute/bnd/build/Project.java index f2a0c2a3a7..f461cbc26a 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/build/Project.java +++ b/biz.aQute.bndlib/src/aQute/bnd/build/Project.java @@ -1,7 +1,5 @@ package aQute.bnd.build; - import static aQute.bnd.build.Container.toPaths; - import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; @@ -157,6 +155,7 @@ public void close() { private final Set dependents = new LinkedHashSet<>(); final Collection classpath = new LinkedHashSet<>(); final Collection buildpath = new LinkedHashSet<>(); + final Collection repoRefs = new LinkedHashSet<>(); final Collection testpath = new LinkedHashSet<>(); final Collection runpath = new LinkedHashSet<>(); final Collection runbundles = new LinkedHashSet<>(); @@ -948,6 +947,22 @@ public Collection getBuildpath() throws Exception { return buildpath; } + /** + * @return repo references used in -includeresource + * @throws Exception + */ + public Collection getRepoRefs() throws Exception { + prepare(); + + // borrowed from aQute.bnd.osgi.Builder.doIncludeResources(Jar) + // because this causes #_repo() to be triggered which in turn + // populates this.repoRefs + Parameters includes = decorated(Constants.INCLUDERESOURCE); + includes.putAll(getMergedParameters(Constants.INCLUDE_RESOURCE)); + + return repoRefs; + } + public Collection getTestpath() throws Exception { prepare(); return testpath; @@ -1671,8 +1686,10 @@ private void add(List paths, Container container) throws Exception { add(paths, sub); } } else { - if (container.getError() == null) + if (container.getError() == null) { paths.add(IO.absolutePath(container.getFile())); + repoRefs.add(container); + } else { paths.add("<<${repo} = " + container.getBundleSymbolicName() + "-" + container.getVersion() + " : " + container.getError() + ">>"); diff --git a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java index 7c26fa2e78..85c5fb4a38 100644 --- a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java +++ b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java @@ -101,36 +101,33 @@ protected ISourceContainer[] createSourceContainers() { .getProject(targetProjName); if (targetProj != null) { - // also add all REPO dependencies of the - // -buildpath - // because they might contain dependencies via - // -includeresource: ${repo;bsn;latest}; - // lib:=true + // also add all -includeresource: + // ${repo;bsn;latest}; + // lib:=true dependencies which are on the + // buildpath // which would otherwise not be considered for // source lookup during debugging try { - Collection buildpath = project - .getBuildpath(); + Collection repoRefs = project.getRepoRefs(); - for (Container bp : buildpath) { - // only consider REPO because we are + for (Container repoRef : repoRefs) { + + // only consider type=REPO because we + // are // interested in bundles added via // '-includeresource: // ${repo;bsn;latest}' - if (bp != null && TYPE.REPO == bp.getType()) { - additionalSourceContainers - .add(new BundleSourceContainer(bp)); + if (repoRef != null && TYPE.REPO == repoRef.getType()) { + additionalSourceContainers.add(new BundleSourceContainer(repoRef)); } - } } catch (Exception e) { // just log to avoid that // exceptions interrupt everything else logger.logError("SourceContainers: Error adding buildpath dependencies of bundle " - + targetProjName, - e); + + targetProjName, e); } IJavaProject targetJavaProj = JavaCore.create(targetProj); From e1bf6d56ae5fece603af47293d0d6d1c432c11ff Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Wed, 3 Jul 2024 21:25:20 +0200 Subject: [PATCH 06/16] extract method Signed-off-by: Christoph Rueger --- .../BndrunDirectiveSourceContainer.java | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java index 85c5fb4a38..1aed148974 100644 --- a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java +++ b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java @@ -100,36 +100,7 @@ protected ISourceContainer[] createSourceContainers() { .getRoot() .getProject(targetProjName); if (targetProj != null) { - - // also add all -includeresource: - // ${repo;bsn;latest}; - // lib:=true dependencies which are on the - // buildpath - // which would otherwise not be considered for - // source lookup during debugging - try { - Collection repoRefs = project.getRepoRefs(); - - - for (Container repoRef : repoRefs) { - - // only consider type=REPO because we - // are - // interested in bundles added via - // '-includeresource: - // ${repo;bsn;latest}' - if (repoRef != null && TYPE.REPO == repoRef.getType()) { - additionalSourceContainers.add(new BundleSourceContainer(repoRef)); - } - - } - } catch (Exception e) { - // just log to avoid that - // exceptions interrupt everything else - logger.logError("SourceContainers: Error adding buildpath dependencies of bundle " - + targetProjName, e); - } - + addRepoRefs(additionalSourceContainers, project); IJavaProject targetJavaProj = JavaCore.create(targetProj); return new JavaProjectSourceContainer(targetJavaProj); } @@ -158,4 +129,33 @@ protected ISourceContainer[] createSourceContainers() { return EMPTY_SOURCE; } + + private void addRepoRefs(Set additionalSourceContainers, Project project) { + // also add all -includeresource: + // ${repo;bsn;latest}; + // lib:=true dependencies which are on the + // buildpath + // which would otherwise not be considered for + // source lookup during debugging + try { + Collection repoRefs = project.getRepoRefs(); + + for (Container repoRef : repoRefs) { + + // only consider type=REPO because we + // are + // interested in bundles added via + // '-includeresource: + // ${repo;bsn;latest}' + if (repoRef != null && TYPE.REPO == repoRef.getType()) { + additionalSourceContainers.add(new BundleSourceContainer(repoRef)); + } + + } + } catch (Exception e) { + // just log to avoid that + // exceptions interrupt everything else + logger.logError("SourceContainers: Error adding buildpath dependencies of bundle " + project.getName(), e); + } + } } From da0a0fc438374e621d7e515372a08f91362c9a4e Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Wed, 3 Jul 2024 21:50:29 +0200 Subject: [PATCH 07/16] remove eclipse warnings Signed-off-by: Christoph Rueger --- biz.aQute.bndlib/src/aQute/bnd/build/Project.java | 1 + 1 file changed, 1 insertion(+) diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/Project.java b/biz.aQute.bndlib/src/aQute/bnd/build/Project.java index f461cbc26a..dc912a0a6f 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/build/Project.java +++ b/biz.aQute.bndlib/src/aQute/bnd/build/Project.java @@ -951,6 +951,7 @@ public Collection getBuildpath() throws Exception { * @return repo references used in -includeresource * @throws Exception */ + @SuppressWarnings("deprecation") public Collection getRepoRefs() throws Exception { prepare(); From 72cc03e992907774ab4fc818706950995bb954a8 Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Thu, 4 Jul 2024 20:45:57 +0200 Subject: [PATCH 08/16] keep insertion order Signed-off-by: Christoph Rueger --- .../sourcelookup/containers/BndrunDirectiveSourceContainer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java index 1aed148974..78f3598b5c 100644 --- a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java +++ b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java @@ -86,7 +86,7 @@ public ISourceContainerType getType() { @Override protected ISourceContainer[] createSourceContainers() { Set projectsAdded = new HashSet<>(); - Set additionalSourceContainers = new HashSet<>(); + Set additionalSourceContainers = new LinkedHashSet<>(); try { ISourceContainer[] array = directiveGetter.get() .stream() From 414373e28a48d2d7b306b851eea6319c5afc42bd Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Fri, 5 Jul 2024 23:13:59 +0200 Subject: [PATCH 09/16] introduce RepoCollector based on call. goal was to reduce additions & complexity in Project, and move this special purpose requirement out of Project. Therefore Project._repo() had to be refactored so that parts could be reused in RepoCollector Signed-off-by: Christoph Rueger --- .../src/aQute/bnd/build/Project.java | 85 +++++++++---------- .../src/aQute/bnd/build/RepoCollector.java | 61 +++++++++++++ .../src/aQute/bnd/service/Strategy.java | 22 +++++ .../BndrunDirectiveSourceContainer.java | 6 +- 4 files changed, 128 insertions(+), 46 deletions(-) create mode 100644 biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/Project.java b/biz.aQute.bndlib/src/aQute/bnd/build/Project.java index dc912a0a6f..b365c84968 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/build/Project.java +++ b/biz.aQute.bndlib/src/aQute/bnd/build/Project.java @@ -155,7 +155,6 @@ public void close() { private final Set dependents = new LinkedHashSet<>(); final Collection classpath = new LinkedHashSet<>(); final Collection buildpath = new LinkedHashSet<>(); - final Collection repoRefs = new LinkedHashSet<>(); final Collection testpath = new LinkedHashSet<>(); final Collection runpath = new LinkedHashSet<>(); final Collection runbundles = new LinkedHashSet<>(); @@ -947,23 +946,6 @@ public Collection getBuildpath() throws Exception { return buildpath; } - /** - * @return repo references used in -includeresource - * @throws Exception - */ - @SuppressWarnings("deprecation") - public Collection getRepoRefs() throws Exception { - prepare(); - - // borrowed from aQute.bnd.osgi.Builder.doIncludeResources(Jar) - // because this causes #_repo() to be triggered which in turn - // populates this.repoRefs - Parameters includes = decorated(Constants.INCLUDERESOURCE); - includes.putAll(getMergedParameters(Constants.INCLUDE_RESOURCE)); - - return repoRefs; - } - public Collection getTestpath() throws Exception { prepare(); return testpath; @@ -1646,54 +1628,54 @@ public String _repo(String args[]) throws Exception { return null; } + Collection containers = repoContainers(args); + if(containers == null) { + return null; + } + + return repoPaths(containers); + } + + Collection repoContainers(String[] args) throws Exception { String spec = args[1]; - String version = null; - Strategy strategy = Strategy.HIGHEST; - - if (args.length > 2) { - version = args[2]; - if (args.length == 4) { - if (args[3].equalsIgnoreCase("HIGHEST")) - strategy = Strategy.HIGHEST; - else if (args[3].equalsIgnoreCase("LOWEST")) - strategy = Strategy.LOWEST; - else if (args[3].equalsIgnoreCase("EXACT")) - strategy = Strategy.EXACT; - else - msgs.InvalidStrategy(_repoHelp, args); - } + String version = args.length > 2 ? args[2] : null; + Strategy strategy = args.length == 4 ? Strategy.parse(args[3]) : Strategy.HIGHEST; + + if (strategy == null) { + msgs.InvalidStrategy(_repoHelp, args); + return null; } Parameters bsns = new Parameters(spec, this); - List paths = new ArrayList<>(); + Collection containers = new LinkedHashSet<>(); for (Entry entry : bsns.entrySet()) { String bsn = removeDuplicateMarker(entry.getKey()); Map attrs = entry.getValue(); Container container = getBundle(bsn, version, strategy, attrs); if (container.getError() != null) { - error("${repo} macro refers to an artifact %s-%s (%s) that has an error: %s", bsn, version, strategy, + error("${repo} macro refers to an artifact %s-%s (%s) that has an error: %s", bsn, version, + strategy, container.getError()); - } else - add(paths, container); + } else { + add(containers, container); + } } - return join(paths); + return containers; } - private void add(List paths, Container container) throws Exception { + + private void add(Collection containers, Container container) throws Exception { if (container.getType() == Container.TYPE.LIBRARY) { List members = container.getMembers(); for (Container sub : members) { - add(paths, sub); + add(containers, sub); } } else { if (container.getError() == null) { - paths.add(IO.absolutePath(container.getFile())); - repoRefs.add(container); + containers.add(container); } else { - paths.add("<<${repo} = " + container.getBundleSymbolicName() + "-" + container.getVersion() + " : " - + container.getError() + ">>"); if (isPedantic()) { warning("Could not expand repo path request: %s ", container); @@ -1703,6 +1685,21 @@ private void add(List paths, Container container) throws Exception { } } + String repoPaths(Collection containers) { + List paths = new ArrayList<>(containers.size()); + for (Container container : containers) { + + if (container.getError() == null) { + paths.add(IO.absolutePath(container.getFile())); + } else { + paths.add("<<${repo} = " + container.getBundleSymbolicName() + "-" + container.getVersion() + " : " + + container.getError() + ">>"); + } + } + + return join(paths); + } + public File getTarget() throws Exception { prepare(); return target; diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java b/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java new file mode 100644 index 0000000000..d27cadb15f --- /dev/null +++ b/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java @@ -0,0 +1,61 @@ +package aQute.bnd.build; + +import java.util.Collection; +import java.util.LinkedHashSet; + +import aQute.bnd.osgi.Constants; +import aQute.bnd.osgi.Processor; + +/** + * Helper which collects ${repo;} references used in -includeresource. + */ +public class RepoCollector extends Processor { + private final Collection repoRefs = new LinkedHashSet<>(); + private final Project project; + + public RepoCollector(Processor parent) { + super(parent); + + while (parent != null && !(parent instanceof Project)) { + parent = parent.getParent(); + } + assert parent != null; + this.project = ((Project) parent); + } + + /** + * @return returns the collected repositories + */ + public Collection getRepoRefs() { + // borrowed from aQute.bnd.osgi.Builder.doIncludeResources(Jar) + // because this causes a call to the _repo() macro below + // in which we populate this.repoRefs + decorated(Constants.INCLUDERESOURCE); + return repoRefs; + } + + /** + * the ${repo} macro, based on {@link Project#_repo(String[])} but here we + * do the actual collection. + */ + public String _repo(String[] args) throws Exception { + if (args.length < 2) { + return null; + } + + Collection containers = project.repoContainers(args); + if (containers == null) { + return null; + } + + // actual collection + repoRefs.addAll(containers); + + return project.repoPaths(containers); + } + + + + + +} diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/Strategy.java b/biz.aQute.bndlib/src/aQute/bnd/service/Strategy.java index 4c4731636b..e54339d83a 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/service/Strategy.java +++ b/biz.aQute.bndlib/src/aQute/bnd/service/Strategy.java @@ -4,4 +4,26 @@ public enum Strategy { LOWEST, EXACT, HIGHEST; + + /** + * @param str the enum as String. + * @return the parsed {@link Strategy} enum. Returns {@link #HIGHEST} if + * null is passed or null if the passed + * string is not one of the valid strategies. + */ + public static Strategy parse(String str) { + if (str == null) { + return Strategy.HIGHEST; + } + + if (str.equalsIgnoreCase("HIGHEST")) + return Strategy.HIGHEST; + else if (str.equalsIgnoreCase("LOWEST")) + return Strategy.LOWEST; + else if (str.equalsIgnoreCase("EXACT")) + return Strategy.EXACT; + else { + return null; + } + } } diff --git a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java index 78f3598b5c..99674520cb 100644 --- a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java +++ b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java @@ -23,6 +23,7 @@ import aQute.bnd.build.Container; import aQute.bnd.build.Container.TYPE; import aQute.bnd.build.Project; +import aQute.bnd.build.RepoCollector; import aQute.bnd.build.Run; import aQute.bnd.exceptions.SupplierWithException; @@ -137,8 +138,9 @@ private void addRepoRefs(Set additionalSourceContainers, Proje // buildpath // which would otherwise not be considered for // source lookup during debugging - try { - Collection repoRefs = project.getRepoRefs(); + try (RepoCollector repoCollector = new RepoCollector(project)) { + + Collection repoRefs = repoCollector.getRepoRefs(); for (Container repoRef : repoRefs) { From 51995582bb6b7c690934e736e296f4555af7a6e4 Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Fri, 5 Jul 2024 23:35:06 +0200 Subject: [PATCH 10/16] add testcase Signed-off-by: Christoph Rueger --- .../test/test/ProjectTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/biz.aQute.bndlib.tests/test/test/ProjectTest.java b/biz.aQute.bndlib.tests/test/test/ProjectTest.java index dcbff8aaab..675ec664b5 100644 --- a/biz.aQute.bndlib.tests/test/test/ProjectTest.java +++ b/biz.aQute.bndlib.tests/test/test/ProjectTest.java @@ -15,6 +15,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.jar.Manifest; @@ -25,6 +26,7 @@ import aQute.bnd.build.Container; import aQute.bnd.build.Project; import aQute.bnd.build.ProjectBuilder; +import aQute.bnd.build.RepoCollector; import aQute.bnd.build.Workspace; import aQute.bnd.osgi.About; import aQute.bnd.osgi.Builder; @@ -713,6 +715,32 @@ public void testRepoMacro() throws Exception { } } + @Test + public void testRepoCollector() throws Exception { + try (Workspace ws = getWorkspace(IO.getFile("testresources/ws")); Project project = ws.getProject("p2")) { + System.err.println(project.getPlugins(FileRepo.class)); + String s = project.getReplacer() + .process(("${repo;libtest}")); + System.err.println(s); + assertThat(s).contains("org.apache.felix.configadmin/org.apache.felix.configadmin-1.8.8", + "org.apache.felix.ipojo/org.apache.felix.ipojo-1.0.0.jar"); + + project.setProperty("-includeresource", + "${repo;org.apache.felix.configadmin;latest},${repo;org.apache.felix.ipojo;latest}"); + + // test RepoCollector + RepoCollector rc = new RepoCollector(project); + Collection repoRefs = rc.getRepoRefs(); + assertThat(repoRefs).hasSize(2); + Iterator iterator = repoRefs.iterator(); + Container one = iterator.next(); + assertThat(one.toString()).endsWith("org.apache.felix.configadmin-1.8.8.jar"); + Container two = iterator.next(); + assertThat(two.toString()).endsWith("org.apache.felix.ipojo-1.0.0.jar"); + + } + } + @Test public void testClasspath() throws Exception { File project = new File("").getAbsoluteFile(); From 3aaca201f65c9fedbc76ce48a623315675e59705 Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Fri, 5 Jul 2024 23:36:03 +0200 Subject: [PATCH 11/16] comments Signed-off-by: Christoph Rueger --- biz.aQute.bndlib.tests/test/test/ProjectTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/biz.aQute.bndlib.tests/test/test/ProjectTest.java b/biz.aQute.bndlib.tests/test/test/ProjectTest.java index 675ec664b5..b70c0de947 100644 --- a/biz.aQute.bndlib.tests/test/test/ProjectTest.java +++ b/biz.aQute.bndlib.tests/test/test/ProjectTest.java @@ -725,6 +725,8 @@ public void testRepoCollector() throws Exception { assertThat(s).contains("org.apache.felix.configadmin/org.apache.felix.configadmin-1.8.8", "org.apache.felix.ipojo/org.apache.felix.ipojo-1.0.0.jar"); + // we expect to see the following two repo references extracted by + // the RepoCollector project.setProperty("-includeresource", "${repo;org.apache.felix.configadmin;latest},${repo;org.apache.felix.ipojo;latest}"); From 93837deee30c35f68ec648689e106f0c139f037e Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Fri, 5 Jul 2024 23:37:12 +0200 Subject: [PATCH 12/16] fine tune Signed-off-by: Christoph Rueger --- biz.aQute.bndlib.tests/test/test/ProjectTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/biz.aQute.bndlib.tests/test/test/ProjectTest.java b/biz.aQute.bndlib.tests/test/test/ProjectTest.java index b70c0de947..3892e28a7c 100644 --- a/biz.aQute.bndlib.tests/test/test/ProjectTest.java +++ b/biz.aQute.bndlib.tests/test/test/ProjectTest.java @@ -717,7 +717,10 @@ public void testRepoMacro() throws Exception { @Test public void testRepoCollector() throws Exception { - try (Workspace ws = getWorkspace(IO.getFile("testresources/ws")); Project project = ws.getProject("p2")) { + try (Workspace ws = getWorkspace(IO.getFile("testresources/ws")); + Project project = ws.getProject("p2"); + RepoCollector rc = new RepoCollector(project);) { + System.err.println(project.getPlugins(FileRepo.class)); String s = project.getReplacer() .process(("${repo;libtest}")); @@ -731,7 +734,6 @@ public void testRepoCollector() throws Exception { "${repo;org.apache.felix.configadmin;latest},${repo;org.apache.felix.ipojo;latest}"); // test RepoCollector - RepoCollector rc = new RepoCollector(project); Collection repoRefs = rc.getRepoRefs(); assertThat(repoRefs).hasSize(2); Iterator iterator = repoRefs.iterator(); From a64093ff066f7092f02f8bfc048660cefc8adbea Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Sat, 6 Jul 2024 10:22:36 +0200 Subject: [PATCH 13/16] moved code to RepoCollector and let Project call this. It seems that this fits better, since all "repo collecting" code now is in the RepoCollector. Project is cleaner and code is reused from two different places. Signed-off-by: Christoph Rueger --- .../test/test/ProjectTest.java | 2 +- .../src/aQute/bnd/build/Project.java | 76 ++--------------- .../src/aQute/bnd/build/RepoCollector.java | 82 +++++++++++++++++-- .../BndrunDirectiveSourceContainer.java | 2 +- 4 files changed, 86 insertions(+), 76 deletions(-) diff --git a/biz.aQute.bndlib.tests/test/test/ProjectTest.java b/biz.aQute.bndlib.tests/test/test/ProjectTest.java index 3892e28a7c..1fcd37cfd1 100644 --- a/biz.aQute.bndlib.tests/test/test/ProjectTest.java +++ b/biz.aQute.bndlib.tests/test/test/ProjectTest.java @@ -734,7 +734,7 @@ public void testRepoCollector() throws Exception { "${repo;org.apache.felix.configadmin;latest},${repo;org.apache.felix.ipojo;latest}"); // test RepoCollector - Collection repoRefs = rc.getRepoRefs(); + Collection repoRefs = rc.repoRefs(); assertThat(repoRefs).hasSize(2); Iterator iterator = repoRefs.iterator(); Container one = iterator.next(); diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/Project.java b/biz.aQute.bndlib/src/aQute/bnd/build/Project.java index b365c84968..120133849c 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/build/Project.java +++ b/biz.aQute.bndlib/src/aQute/bnd/build/Project.java @@ -160,6 +160,7 @@ public void close() { final Collection runbundles = new LinkedHashSet<>(); final Collection runfw = new LinkedHashSet<>(); File runstorage; + private final RepoCollector repoCollector; final Map sourcepath = new LinkedHashMap<>(); final Collection allsourcepath = new LinkedHashSet<>(); final Collection bootclasspath = new LinkedHashSet<>(); @@ -193,6 +194,7 @@ public Project(Workspace workspace, File unused, File buildFile) { // For backward compatibility reasons, we also read readBuildProperties(); + repoCollector = new RepoCollector(this); } public Project(Workspace workspace, File buildDir) { @@ -1628,77 +1630,15 @@ public String _repo(String args[]) throws Exception { return null; } - Collection containers = repoContainers(args); - if(containers == null) { - return null; - } - - return repoPaths(containers); - } - - Collection repoContainers(String[] args) throws Exception { - String spec = args[1]; - String version = args.length > 2 ? args[2] : null; - Strategy strategy = args.length == 4 ? Strategy.parse(args[3]) : Strategy.HIGHEST; - - if (strategy == null) { - msgs.InvalidStrategy(_repoHelp, args); - return null; - } - - Parameters bsns = new Parameters(spec, this); - Collection containers = new LinkedHashSet<>(); - - for (Entry entry : bsns.entrySet()) { - String bsn = removeDuplicateMarker(entry.getKey()); - Map attrs = entry.getValue(); - Container container = getBundle(bsn, version, strategy, attrs); - if (container.getError() != null) { - error("${repo} macro refers to an artifact %s-%s (%s) that has an error: %s", bsn, version, - strategy, - container.getError()); - } else { - add(containers, container); - } - } - return containers; - } - - - private void add(Collection containers, Container container) throws Exception { - if (container.getType() == Container.TYPE.LIBRARY) { - List members = container.getMembers(); - for (Container sub : members) { - add(containers, sub); - } - } else { - if (container.getError() == null) { - containers.add(container); - } - else { - - if (isPedantic()) { - warning("Could not expand repo path request: %s ", container); - } + Collection containers = repoCollector.repoContainers(args); + if(containers == null) { + return null; } - - } + + return repoCollector.repoPaths(containers); } - String repoPaths(Collection containers) { - List paths = new ArrayList<>(containers.size()); - for (Container container : containers) { - - if (container.getError() == null) { - paths.add(IO.absolutePath(container.getFile())); - } else { - paths.add("<<${repo} = " + container.getBundleSymbolicName() + "-" + container.getVersion() + " : " - + container.getError() + ">>"); - } - } - - return join(paths); - } + public File getTarget() throws Exception { prepare(); diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java b/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java index d27cadb15f..fe58f54b22 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java +++ b/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java @@ -1,17 +1,25 @@ package aQute.bnd.build; +import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import aQute.bnd.header.Attrs; +import aQute.bnd.header.Parameters; import aQute.bnd.osgi.Constants; import aQute.bnd.osgi.Processor; +import aQute.bnd.service.Strategy; +import aQute.lib.io.IO; /** * Helper which collects ${repo;} references used in -includeresource. */ public class RepoCollector extends Processor { + private final Project project; private final Collection repoRefs = new LinkedHashSet<>(); - private final Project project; public RepoCollector(Processor parent) { super(parent); @@ -24,12 +32,17 @@ public RepoCollector(Processor parent) { } /** - * @return returns the collected repositories + * Note: This method has side-effects since it does the actual collection. + * Consider storing and reusing the result for performance instead of + * calling it repeatedly. + * + * @return returns the collected repositories referenced in ${repo}-macros + * used in the project's .bnd */ - public Collection getRepoRefs() { + public Collection repoRefs() { // borrowed from aQute.bnd.osgi.Builder.doIncludeResources(Jar) // because this causes a call to the _repo() macro below - // in which we populate this.repoRefs + // in which we populate this.repoRefs in the #add() method decorated(Constants.INCLUDERESOURCE); return repoRefs; } @@ -43,7 +56,7 @@ public String _repo(String[] args) throws Exception { return null; } - Collection containers = project.repoContainers(args); + Collection containers = repoContainers(args); if (containers == null) { return null; } @@ -51,11 +64,68 @@ public String _repo(String[] args) throws Exception { // actual collection repoRefs.addAll(containers); - return project.repoPaths(containers); + return repoPaths(containers); } + Collection repoContainers(String[] args) throws Exception { + String spec = args[1]; + String version = args.length > 2 ? args[2] : null; + Strategy strategy = args.length == 4 ? Strategy.parse(args[3]) : Strategy.HIGHEST; + if (strategy == null) { + project.msgs.InvalidStrategy(Project._repoHelp, args); + return null; + } + + Parameters bsns = new Parameters(spec, this); + Collection containers = new LinkedHashSet<>(); + + for (Entry entry : bsns.entrySet()) { + String bsn = removeDuplicateMarker(entry.getKey()); + Map attrs = entry.getValue(); + Container container = project.getBundle(bsn, version, strategy, attrs); + if (container.getError() != null) { + error("${repo} macro refers to an artifact %s-%s (%s) that has an error: %s", bsn, version, strategy, + container.getError()); + } else { + add(containers, container); + } + } + return containers; + } + + private void add(Collection containers, Container container) throws Exception { + if (container.getType() == Container.TYPE.LIBRARY) { + List members = container.getMembers(); + for (Container sub : members) { + add(containers, sub); + } + } else { + if (container.getError() == null) { + containers.add(container); + } else { + if (isPedantic()) { + warning("Could not expand repo path request: %s ", container); + } + } + } + } + + String repoPaths(Collection containers) { + List paths = new ArrayList<>(containers.size()); + for (Container container : containers) { + + if (container.getError() == null) { + paths.add(IO.absolutePath(container.getFile())); + } else { + paths.add("<<${repo} = " + container.getBundleSymbolicName() + "-" + container.getVersion() + " : " + + container.getError() + ">>"); + } + } + + return join(paths); + } } diff --git a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java index 99674520cb..59fb544927 100644 --- a/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java +++ b/org.bndtools.launch/src/bndtools/launch/sourcelookup/containers/BndrunDirectiveSourceContainer.java @@ -140,7 +140,7 @@ private void addRepoRefs(Set additionalSourceContainers, Proje // source lookup during debugging try (RepoCollector repoCollector = new RepoCollector(project)) { - Collection repoRefs = repoCollector.getRepoRefs(); + Collection repoRefs = repoCollector.repoRefs(); for (Container repoRef : repoRefs) { From 3f1a45a9311bebf90ced6ca8383cf422aebeb570 Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Sat, 6 Jul 2024 10:39:31 +0200 Subject: [PATCH 14/16] fix failing test Signed-off-by: Christoph Rueger formatting Signed-off-by: Christoph Rueger --- .../src/aQute/bnd/build/Project.java | 17 ++++++++--------- .../src/aQute/bnd/build/RepoCollector.java | 3 ++- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/Project.java b/biz.aQute.bndlib/src/aQute/bnd/build/Project.java index 120133849c..90e5665abc 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/build/Project.java +++ b/biz.aQute.bndlib/src/aQute/bnd/build/Project.java @@ -1,4 +1,5 @@ package aQute.bnd.build; + import static aQute.bnd.build.Container.toPaths; import java.io.BufferedInputStream; import java.io.BufferedReader; @@ -160,7 +161,7 @@ public void close() { final Collection runbundles = new LinkedHashSet<>(); final Collection runfw = new LinkedHashSet<>(); File runstorage; - private final RepoCollector repoCollector; + private final RepoCollector repoCollector; final Map sourcepath = new LinkedHashMap<>(); final Collection allsourcepath = new LinkedHashSet<>(); final Collection bootclasspath = new LinkedHashSet<>(); @@ -1630,15 +1631,13 @@ public String _repo(String args[]) throws Exception { return null; } - Collection containers = repoCollector.repoContainers(args); - if(containers == null) { - return null; - } - - return repoCollector.repoPaths(containers); - } + Collection containers = repoCollector.repoContainers(args); + if (containers == null) { + return null; + } - + return repoCollector.repoPaths(containers); + } public File getTarget() throws Exception { prepare(); diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java b/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java index fe58f54b22..0fbbbaffcd 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java +++ b/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java @@ -85,7 +85,8 @@ Collection repoContainers(String[] args) throws Exception { Map attrs = entry.getValue(); Container container = project.getBundle(bsn, version, strategy, attrs); if (container.getError() != null) { - error("${repo} macro refers to an artifact %s-%s (%s) that has an error: %s", bsn, version, strategy, + project.error("${repo} macro refers to an artifact %s-%s (%s) that has an error: %s", bsn, version, + strategy, container.getError()); } else { add(containers, container); From 39f70d9fafdb9ec2ae2a7eae5fa3b6ed8566df25 Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Sat, 6 Jul 2024 13:48:19 +0200 Subject: [PATCH 15/16] handle close() and clear repoRefs. Signed-off-by: Christoph Rueger --- biz.aQute.bndlib/src/aQute/bnd/build/Project.java | 1 + biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/Project.java b/biz.aQute.bndlib/src/aQute/bnd/build/Project.java index 90e5665abc..57fb5d0c18 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/build/Project.java +++ b/biz.aQute.bndlib/src/aQute/bnd/build/Project.java @@ -196,6 +196,7 @@ public Project(Workspace workspace, File unused, File buildFile) { // For backward compatibility reasons, we also read readBuildProperties(); repoCollector = new RepoCollector(this); + addClose(repoCollector); } public Project(Workspace workspace, File buildDir) { diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java b/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java index 0fbbbaffcd..36b6b9207d 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java +++ b/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java @@ -1,5 +1,6 @@ package aQute.bnd.build; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashSet; @@ -129,4 +130,9 @@ String repoPaths(Collection containers) { return join(paths); } + @Override + public void close() throws IOException { + repoRefs.clear(); + super.close(); + } } From bcab3e4845df11abb6217314b64c9c3a371a7322 Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Mon, 8 Jul 2024 20:42:01 +0200 Subject: [PATCH 16/16] clear repoRefs before recollection This way the repoRefs set always contains the actual result of the collection and we do not risk keeping results from a previous collection around Signed-off-by: Christoph Rueger --- biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java b/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java index 36b6b9207d..0558f5667c 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java +++ b/biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java @@ -33,7 +33,7 @@ public RepoCollector(Processor parent) { } /** - * Note: This method has side-effects since it does the actual collection. + * Note: This method does the actual collection and is not thread-safe. * Consider storing and reusing the result for performance instead of * calling it repeatedly. * @@ -44,6 +44,7 @@ public Collection repoRefs() { // borrowed from aQute.bnd.osgi.Builder.doIncludeResources(Jar) // because this causes a call to the _repo() macro below // in which we populate this.repoRefs in the #add() method + repoRefs.clear(); decorated(Constants.INCLUDERESOURCE); return repoRefs; }