Skip to content

Commit

Permalink
Merge pull request #6165 from chrisrueger/fix-sourcelookup-for-includ…
Browse files Browse the repository at this point in the history
…eresource-with-repo-macro

fix source lookup for bundle classpath lib jars during debugging
  • Loading branch information
pkriens authored Jul 12, 2024
2 parents 75d7743 + bcab3e4 commit 27421c3
Show file tree
Hide file tree
Showing 5 changed files with 246 additions and 54 deletions.
32 changes: 32 additions & 0 deletions biz.aQute.bndlib.tests/test/test/ProjectTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -713,6 +715,36 @@ public void testRepoMacro() throws Exception {
}
}

@Test
public void testRepoCollector() throws Exception {
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}"));
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");

// 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}");

// test RepoCollector
Collection<Container> repoRefs = rc.repoRefs();
assertThat(repoRefs).hasSize(2);
Iterator<Container> 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();
Expand Down
59 changes: 7 additions & 52 deletions biz.aQute.bndlib/src/aQute/bnd/build/Project.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package aQute.bnd.build;

import static aQute.bnd.build.Container.toPaths;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
Expand Down Expand Up @@ -162,6 +161,7 @@ public void close() {
final Collection<Container> runbundles = new LinkedHashSet<>();
final Collection<Container> runfw = new LinkedHashSet<>();
File runstorage;
private final RepoCollector repoCollector;
final Map<File, Attrs> sourcepath = new LinkedHashMap<>();
final Collection<File> allsourcepath = new LinkedHashSet<>();
final Collection<Container> bootclasspath = new LinkedHashSet<>();
Expand Down Expand Up @@ -195,6 +195,8 @@ 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) {
Expand Down Expand Up @@ -1630,59 +1632,12 @@ public String _repo(String args[]) throws Exception {
return null;
}

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);
}
}

Parameters bsns = new Parameters(spec, this);
List<String> paths = new ArrayList<>();

for (Entry<String, Attrs> entry : bsns.entrySet()) {
String bsn = removeDuplicateMarker(entry.getKey());
Map<String, String> 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(paths, container);
Collection<Container> containers = repoCollector.repoContainers(args);
if (containers == null) {
return null;
}
return join(paths);
}

private void add(List<String> paths, Container container) throws Exception {
if (container.getType() == Container.TYPE.LIBRARY) {
List<Container> members = container.getMembers();
for (Container sub : members) {
add(paths, sub);
}
} else {
if (container.getError() == null)
paths.add(IO.absolutePath(container.getFile()));
else {
paths.add("<<${repo} = " + container.getBundleSymbolicName() + "-" + container.getVersion() + " : "
+ container.getError() + ">>");

if (isPedantic()) {
warning("Could not expand repo path request: %s ", container);
}
}

}
return repoCollector.repoPaths(containers);
}

public File getTarget() throws Exception {
Expand Down
139 changes: 139 additions & 0 deletions biz.aQute.bndlib/src/aQute/bnd/build/RepoCollector.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package aQute.bnd.build;

import java.io.IOException;
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<Container> repoRefs = new LinkedHashSet<>();

public RepoCollector(Processor parent) {
super(parent);

while (parent != null && !(parent instanceof Project)) {
parent = parent.getParent();
}
assert parent != null;
this.project = ((Project) parent);
}

/**
* 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.
*
* @return returns the collected repositories referenced in ${repo}-macros
* used in the project's .bnd
*/
public Collection<Container> 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;
}

/**
* 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<Container> containers = repoContainers(args);
if (containers == null) {
return null;
}

// actual collection
repoRefs.addAll(containers);

return repoPaths(containers);
}

Collection<Container> 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<Container> containers = new LinkedHashSet<>();

for (Entry<String, Attrs> entry : bsns.entrySet()) {
String bsn = removeDuplicateMarker(entry.getKey());
Map<String, String> attrs = entry.getValue();
Container container = project.getBundle(bsn, version, strategy, attrs);
if (container.getError() != null) {
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);
}
}
return containers;
}

private void add(Collection<Container> containers, Container container) throws Exception {
if (container.getType() == Container.TYPE.LIBRARY) {
List<Container> 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<Container> containers) {
List<String> 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);
}

@Override
public void close() throws IOException {
repoRefs.clear();
super.close();
}
}
22 changes: 22 additions & 0 deletions biz.aQute.bndlib/src/aQute/bnd/service/Strategy.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
* <code>null</code> is passed or <code>null</code> 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;
}
}
}
Loading

0 comments on commit 27421c3

Please sign in to comment.