Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ void loadFramework(ResourceBuilder system) throws Exception {
String version = bsn.getValue()
.getVersion();

log.log(LogService.LOG_INFO, "Using frameowork " + name + ";" + version);
log.log(LogService.LOG_INFO, "Using framework " + name + ";" + version);

if ("none".equals(name))
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package biz.aQute.resolve;

import org.apache.felix.resolver.Logger;
import org.apache.felix.resolver.ResolutionError;
import org.osgi.resource.Resource;

class InternalResolverLogger extends Logger {

Expand All @@ -15,4 +17,10 @@ public InternalResolverLogger(ResolverLogger logger) {
protected void doLog(int level, String msg, Throwable throwable) {
logger.log(level, msg, throwable);
}

@Override
public void logUsesConstraintViolation(Resource resource, ResolutionError error) {
logger.log(logger.getLogLevel(), String.format("Resource: %s, ResolutionError: %s", resource, error),
error.toException());
}
}
58 changes: 58 additions & 0 deletions biz.aQute.resolve/src/biz/aQute/resolve/ResolverLogger.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,19 @@

import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import aQute.bnd.exceptions.Exceptions;
import aQute.bnd.osgi.Constants;
import aQute.bnd.osgi.Processor;
import aQute.lib.converter.Converter;
import aQute.lib.io.IO;

public class ResolverLogger implements LogService, AutoCloseable {

private static final Logger logger = LoggerFactory.getLogger(ResolverLogger.class);

public static final int DEFAULT_LEVEL = 4;

public static final int LOG_ERROR = 1;
Expand Down Expand Up @@ -52,6 +60,7 @@ public ResolverLogger(int level, PrintStream out) {
printer = IO.writer(out, UTF_8);
}


@Override
public void log(int level, String msg, Throwable throwable) {
switch (level) {
Expand All @@ -64,6 +73,7 @@ public void log(int level, String msg, Throwable throwable) {
printLog(msg, throwable);
if (throwable != null) {
throwable.printStackTrace(printer);
logger.debug("", throwable);
}
break;
case LOG_INFO :
Expand All @@ -87,10 +97,13 @@ public void log(int level, String msg, Throwable throwable) {

private void printLog(String msg, Throwable throwable) {
printer.print(msg);
logger.debug(msg);
if (throwable != null) {
printer.print(" (");
printer.print(throwable);
printer.print(")");

logger.debug("({})", String.valueOf(throwable));
}
printer.println();
}
Expand All @@ -106,6 +119,9 @@ public String getLog() {
} else {
StringBuilder sb = new StringBuilder(10000);

sb.append("Log level:")
.append(getLogLevel())
.append(" ");
sb.append("Log too large. Split from ")
.append(file.getAbsolutePath())
.append("\nsize ")
Expand Down Expand Up @@ -140,6 +156,17 @@ public void close() {
}
}

/**
* like {@link #close()} but it deletes the logfile regardless of
* {@link #keepLogFile}
*/
public void closeAndDeleteLogfile() {
IO.close(printer);
if (file != null) {
IO.delete(file);
}
}

public void setKeepLogFileTillExit(boolean keep) {
this.keepLogFile = keep;
}
Expand All @@ -162,4 +189,35 @@ public void log(ServiceReference sr, int level, String message) {
public void log(ServiceReference sr, int level, String message, Throwable exception) {
log(level, message, exception);
}

/**
* @param processor
* @param keepLogFileTillJvmExit if <code>true</code> the logfile is kept
* until JVM exit, otherwise deleted immediately after resolve
* finishes
* @return a new logger
*/
public static ResolverLogger newLogger(Processor processor, boolean keepLogFileTillJvmExit) {
if (processor == null) {
ResolverLogger logger = new ResolverLogger();
logger.setKeepLogFileTillExit(keepLogFileTillJvmExit);
return logger;
}

try {
Integer level = Converter.cnv(Integer.class,
processor.getProperty(Constants.RESOLVEDEBUG, Integer.toString(DEFAULT_LEVEL)));
if (level != null) {
ResolverLogger logger = new ResolverLogger(level);
logger.setKeepLogFileTillExit(keepLogFileTillJvmExit);
return logger;
}
ResolverLogger logger = new ResolverLogger(DEFAULT_LEVEL);
logger.setKeepLogFileTillExit(keepLogFileTillJvmExit);
return logger;
} catch (Exception e) {
throw Exceptions.duck(e);
}

}
}
3 changes: 2 additions & 1 deletion biz.aQute.resolve/src/biz/aQute/resolve/RunResolution.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ public static RunResolution resolve(Project project, Processor actualProperties,
Collection<ResolutionCallback> callbacks, ResolverLogger resolverLogger) {
if (callbacks == null)
callbacks = Collections.emptyList();
ResolverLogger logger = resolverLogger == null ? new ResolverLogger() : resolverLogger;
ResolverLogger logger = resolverLogger == null ? ResolverLogger.newLogger(actualProperties, false)
: resolverLogger;
try {
try {
ResolveProcess resolve = new ResolveProcess();
Expand Down
29 changes: 29 additions & 0 deletions biz.aQute.resolve/test/biz/aQute/resolve/ResolveTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
Expand Down Expand Up @@ -765,4 +766,32 @@ public void testDot() throws Exception {
}
}

/**
* This test triggers a Uses constraint violation. And we want to check that
* it gets logged via
* {@link InternalResolverLogger#logUsesConstraintViolation(Resource, org.apache.felix.resolver.ResolutionError)}
*/
@Test
public void testResolveUsesConstraintErrorLogging() throws Exception {
File f = IO.getFile("testdata/repo-usesconstrainterror/run.bndrun");

try (Run run = Run.createRun(null, f)) {

RunResolution resolution = RunResolution.resolve(run, null);
assertFalse(resolution.isOK());
assertNotNull(resolution.exception);
System.out.println(resolution.exception);
assertTrue(resolution.exception.getMessage()
.contains(
"Uses constraint violation. Unable to resolve resource BundleC [BundleC version=1.0.0.SNAPSHOT] "
+ "because it is exposed to package 'com.example.util.internal' from resources "
+ "BundleA2 [BundleA2 version=1.0.0.SNAPSHOT] and "
+ "BundleA [BundleA version=1.0.0.SNAPSHOT] via two dependency chains."),
resolution.exception.getMessage());

// Log level set via -resolvedebug: 1 in run.bndrun
assertTrue(resolution.log.startsWith("Log level:1"));
}
}

}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
165 changes: 165 additions & 0 deletions biz.aQute.resolve/testdata/repo-usesconstrainterror/index.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
<?xml version='1.0' encoding='UTF-8'?>
<repository xmlns="http://www.osgi.org/xmlns/repository/v1.0.0">
<resource>
<capability namespace="osgi.identity">
<attribute name="osgi.identity" value="BundleA2"/>
<attribute name="type" value="osgi.bundle"/>
<attribute name="version" value="1.0.0.SNAPSHOT" type="Version"/>
</capability>
<capability namespace="osgi.wiring.package">
<attribute name="bundle-symbolic-name" value="BundleA2"/>
<attribute name="bundle-version" value="1.0.0.SNAPSHOT" type="Version"/>
<attribute name="osgi.wiring.package" value="com.example.util.internal"/>
<attribute name="version" value="1.1.0" type="Version"/>
<attribute name="bnd.hashes" value="-2137064498" type="List&lt;Long&gt;"/>
</capability>
<capability namespace="osgi.wiring.bundle">
<attribute name="bundle-version" value="1.0.0.SNAPSHOT" type="Version"/>
<attribute name="osgi.wiring.bundle" value="BundleA2"/>
</capability>
<capability namespace="osgi.wiring.host">
<attribute name="bundle-version" value="1.0.0.SNAPSHOT" type="Version"/>
<attribute name="osgi.wiring.host" value="BundleA2"/>
</capability>
<capability namespace="osgi.content">
<attribute name="size" value="2910" type="Long"/>
<attribute name="mime" value="application/vnd.osgi.bundle"/>
<attribute name="url" value="BundleA2.jar"/>
<attribute name="osgi.content" value="DFAB4E25280519ED3ACCDCD1888B7D20B3B4C34550CC3A27B731F43779CF15BF"/>
</capability>
<requirement namespace="osgi.wiring.package">
<directive name="filter" value="(osgi.wiring.package=java.lang)"/>
<attribute name="osgi.wiring.package" value="java.lang"/>
</requirement>
<requirement namespace="osgi.ee">
<directive name="filter" value="(&amp;(osgi.ee=JavaSE)(version=17))"/>
</requirement>
</resource>
<resource>
<capability namespace="osgi.identity">
<attribute name="osgi.identity" value="BundleC"/>
<attribute name="type" value="osgi.bundle"/>
<attribute name="version" value="1.0.0.SNAPSHOT" type="Version"/>
</capability>
<capability namespace="osgi.wiring.bundle">
<attribute name="bundle-version" value="1.0.0.SNAPSHOT" type="Version"/>
<attribute name="osgi.wiring.bundle" value="BundleC"/>
</capability>
<capability namespace="osgi.wiring.host">
<attribute name="bundle-version" value="1.0.0.SNAPSHOT" type="Version"/>
<attribute name="osgi.wiring.host" value="BundleC"/>
</capability>
<capability namespace="osgi.content">
<attribute name="size" value="2739" type="Long"/>
<attribute name="mime" value="application/vnd.osgi.bundle"/>
<attribute name="url" value="BundleC.jar"/>
<attribute name="osgi.content" value="FA8920C3FB90C52E19B41250A16FDAAE353C028A0F9FB5217D314C5225E0A286"/>
</capability>
<requirement namespace="osgi.wiring.package">
<directive name="filter" value="(&amp;(osgi.wiring.package=com.example.util)(version&gt;=1.0.0)(!(version&gt;=2.0.0)))"/>
<attribute name="osgi.wiring.package" value="com.example.util"/>
</requirement>
<requirement namespace="osgi.wiring.package">
<directive name="filter" value="(&amp;(osgi.wiring.package=com.example.util.internal)(version&gt;=1.1.0)(!(version&gt;=2.0.0)))"/>
<attribute name="osgi.wiring.package" value="com.example.util.internal"/>
</requirement>
<requirement namespace="osgi.wiring.package">
<directive name="filter" value="(osgi.wiring.package=java.io)"/>
<attribute name="osgi.wiring.package" value="java.io"/>
</requirement>
<requirement namespace="osgi.wiring.package">
<directive name="filter" value="(osgi.wiring.package=java.lang)"/>
<attribute name="osgi.wiring.package" value="java.lang"/>
</requirement>
<requirement namespace="osgi.ee">
<directive name="filter" value="(&amp;(osgi.ee=JavaSE)(version=17))"/>
</requirement>
</resource>
<resource>
<capability namespace="osgi.identity">
<attribute name="osgi.identity" value="BundleA"/>
<attribute name="type" value="osgi.bundle"/>
<attribute name="version" value="1.0.0.SNAPSHOT" type="Version"/>
</capability>
<capability namespace="osgi.wiring.package">
<directive name="uses" value="com.example.util.internal"/>
<attribute name="bundle-symbolic-name" value="BundleA"/>
<attribute name="bundle-version" value="1.0.0.SNAPSHOT" type="Version"/>
<attribute name="osgi.wiring.package" value="com.example.util"/>
<attribute name="version" value="1.0.0" type="Version"/>
<attribute name="bnd.hashes" value="1549674828" type="List&lt;Long&gt;"/>
</capability>
<capability namespace="osgi.wiring.package">
<attribute name="bundle-symbolic-name" value="BundleA"/>
<attribute name="bundle-version" value="1.0.0.SNAPSHOT" type="Version"/>
<attribute name="osgi.wiring.package" value="com.example.util.internal"/>
<attribute name="version" value="1.0.0" type="Version"/>
<attribute name="bnd.hashes" value="-2137064498" type="List&lt;Long&gt;"/>
</capability>
<capability namespace="osgi.wiring.bundle">
<attribute name="bundle-version" value="1.0.0.SNAPSHOT" type="Version"/>
<attribute name="osgi.wiring.bundle" value="BundleA"/>
</capability>
<capability namespace="osgi.wiring.host">
<attribute name="bundle-version" value="1.0.0.SNAPSHOT" type="Version"/>
<attribute name="osgi.wiring.host" value="BundleA"/>
</capability>
<capability namespace="osgi.content">
<attribute name="size" value="3514" type="Long"/>
<attribute name="mime" value="application/vnd.osgi.bundle"/>
<attribute name="url" value="BundleA.jar"/>
<attribute name="osgi.content" value="B585003C523C4EAEFFC514B1221E42062457194CA6CE90277DD979CFB37465C2"/>
</capability>
<requirement namespace="osgi.wiring.package">
<directive name="filter" value="(&amp;(osgi.wiring.package=com.example.util.internal)(version&gt;=1.0.0)(!(version&gt;=2.0.0)))"/>
<attribute name="osgi.wiring.package" value="com.example.util.internal"/>
</requirement>
<requirement namespace="osgi.wiring.package">
<directive name="filter" value="(osgi.wiring.package=java.lang)"/>
<attribute name="osgi.wiring.package" value="java.lang"/>
</requirement>
<requirement namespace="osgi.ee">
<directive name="filter" value="(&amp;(osgi.ee=JavaSE)(version=17))"/>
</requirement>
</resource>
<resource>
<capability namespace="osgi.identity">
<attribute name="osgi.identity" value="BundleB"/>
<attribute name="type" value="osgi.bundle"/>
<attribute name="version" value="1.0.0.SNAPSHOT" type="Version"/>
</capability>
<capability namespace="osgi.wiring.bundle">
<attribute name="bundle-version" value="1.0.0.SNAPSHOT" type="Version"/>
<attribute name="osgi.wiring.bundle" value="BundleB"/>
</capability>
<capability namespace="osgi.wiring.host">
<attribute name="bundle-version" value="1.0.0.SNAPSHOT" type="Version"/>
<attribute name="osgi.wiring.host" value="BundleB"/>
</capability>
<capability namespace="osgi.content">
<attribute name="size" value="2591" type="Long"/>
<attribute name="mime" value="application/vnd.osgi.bundle"/>
<attribute name="url" value="BundleB.jar"/>
<attribute name="osgi.content" value="EAB180226DC4FB10F9EF2E895CC57F6EEE6028660A43465B7520DCA5609E5BE2"/>
</capability>
<requirement namespace="osgi.wiring.package">
<directive name="filter" value="(&amp;(osgi.wiring.package=com.example.util)(version&gt;=1.0.0)(version&lt;=1.0.0))"/>
<attribute name="osgi.wiring.package" value="com.example.util"/>
</requirement>
<requirement namespace="osgi.wiring.package">
<directive name="filter" value="(osgi.wiring.package=java.io)"/>
<attribute name="osgi.wiring.package" value="java.io"/>
</requirement>
<requirement namespace="osgi.wiring.package">
<directive name="filter" value="(osgi.wiring.package=java.lang)"/>
<attribute name="osgi.wiring.package" value="java.lang"/>
</requirement>
<requirement namespace="osgi.wiring.package">
<directive name="filter" value="(&amp;(osgi.wiring.package=com.example.util.internal)(version&gt;=1.0.0)(version&lt;=1.0.0))"/>
<attribute name="osgi.wiring.package" value="com.example.util.internal"/>
</requirement>
<requirement namespace="osgi.ee">
<directive name="filter" value="(&amp;(osgi.ee=JavaSE)(version=17))"/>
</requirement>
</resource>
</repository>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-standalone: ${.}/index.xml
-runfw: org.apache.felix.framework
-runee: JavaSE-17
-resolvedebug: 1
-runrequires: \
bnd.identity;id=BundleC,\
bnd.identity;id=BundleB
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,14 @@ public void run(IProgressMonitor monitor) {

try {
coordinate(() -> {
logger = new ResolverLogger();
Project run = model.getOwner(Project.class)
.orElse(null);

logger = ResolverLogger.newLogger(run, true);
List<ResolutionCallback> operationCallbacks = new ArrayList<>(callbacks.size() + 1);
operationCallbacks.addAll(callbacks);
operationCallbacks.add(new ResolutionProgressCallback(monitor));

Project run = model.getOwner(Project.class)
.orElse(null);

RunResolution resolution = RunResolution.resolve(run,
model.getProperties(),
Expand Down Expand Up @@ -115,4 +116,5 @@ private void coordinate(RunnableWithException inCoordination) throws Exception {
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ else if (composite.isDisposed())
// kind of silly
//
String diagnostic = ResolveProcess.format(resolutionException, false);
diagnostic += "\n\nresolvedebug log: " + resolutionResult.getLog();

processingErrorsText.setText(diagnostic);
sectUnresolved.setExpanded(true);
Expand Down
Loading