forked from phoedos/pmd
[core] Add support for Gradle's AntLoggingAdapter, default fallback loglevel is WARN
Fixes #1288
This commit is contained in:
@ -30,6 +30,7 @@ This is a minor release.
|
||||
|
||||
* core
|
||||
* [#1191](https://github.com/pmd/pmd/issues/1191): \[core] Test Framework: Sort violations by line/column
|
||||
* [#1288](https://github.com/pmd/pmd/issues/1288): \[core] No supported build listeners found with Gradle
|
||||
* java-bestpractices
|
||||
* [#1267](https://github.com/pmd/pmd/pull/1267): \[java] MissingOverrideRule: Avoid NoClassDefFoundError with incomplete classpath
|
||||
* java-codestyle
|
||||
|
@ -7,6 +7,7 @@ package net.sourceforge.pmd.util.log;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
@ -27,9 +28,17 @@ import org.apache.tools.ant.taskdefs.RecorderEntry;
|
||||
public class AntLogHandler extends Handler {
|
||||
private Project project;
|
||||
|
||||
private static final Level DEFAULT_LEVEL = Level.WARNING;
|
||||
|
||||
private static final Formatter FORMATTER = new PmdLogFormatter();
|
||||
|
||||
// Maps from ant's Project.MSG_* to java.util.logging.Level
|
||||
private static final Level[] LOG_LEVELS = {
|
||||
Level.SEVERE, Level.WARNING, Level.INFO, Level.CONFIG, Level.FINEST,
|
||||
Level.SEVERE, // Project.MSG_ERR=0
|
||||
Level.WARNING, // Project.MSG_WARN=1
|
||||
Level.INFO, // Project.MSG_INFO=2
|
||||
Level.CONFIG, // Project.MSG_VERBOSE=3
|
||||
Level.FINEST, // Project.MSG_DEBUG=4
|
||||
};
|
||||
|
||||
public AntLogHandler(Project project) {
|
||||
@ -46,9 +55,15 @@ public class AntLogHandler extends Handler {
|
||||
declaredField = XmlLogger.class.getDeclaredField("msgOutputLevel");
|
||||
} else if (l instanceof RecorderEntry) {
|
||||
declaredField = RecorderEntry.class.getDeclaredField("loglevel");
|
||||
} else if (l.getClass().getName().equals("org.gradle.api.internal.project.ant.AntLoggingAdapter")) {
|
||||
return determineGradleLogLevel(l);
|
||||
} else {
|
||||
try {
|
||||
declaredField = l.getClass().getDeclaredField("logLevel");
|
||||
if (declaredField.getType() != Integer.class && declaredField.getType() != int.class) {
|
||||
declaredField = null;
|
||||
project.log("Unsupported build listener: " + l.getClass(), Project.MSG_DEBUG);
|
||||
}
|
||||
} catch (final NoSuchFieldException e) {
|
||||
project.log("Unsupported build listener: " + l.getClass(), Project.MSG_DEBUG);
|
||||
}
|
||||
@ -58,15 +73,16 @@ public class AntLogHandler extends Handler {
|
||||
declaredField.setAccessible(true);
|
||||
return LOG_LEVELS[declaredField.getInt(l)];
|
||||
}
|
||||
} catch (final NoSuchFieldException | IllegalArgumentException | IllegalAccessException ignored) {
|
||||
|
||||
} catch (final ReflectiveOperationException ignored) {
|
||||
// Just ignore it
|
||||
}
|
||||
}
|
||||
|
||||
project.log("Could not determine ant log level, no supported build listeners found. "
|
||||
+ "Log level is set to FINEST", Project.MSG_WARN);
|
||||
+ "Log level is set to " + DEFAULT_LEVEL, Project.MSG_WARN);
|
||||
|
||||
return Level.FINEST;
|
||||
return DEFAULT_LEVEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -110,4 +126,42 @@ public class AntLogHandler extends Handler {
|
||||
public void flush() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
private Level determineGradleLogLevel(BuildListener l) {
|
||||
try {
|
||||
project.log("Detected gradle AntLoggingAdapter", Project.MSG_DEBUG);
|
||||
Field loggerField = l.getClass().getDeclaredField("logger");
|
||||
loggerField.setAccessible(true);
|
||||
// org.gradle.internal.logging.slf4j.OutputEventListenerBackedLogger
|
||||
Object logger = loggerField.get(l);
|
||||
|
||||
Class<?> gradleLogLevel = l.getClass().getClassLoader().loadClass("org.gradle.api.logging.LogLevel");
|
||||
|
||||
Method isLevelAtMostMethod = logger.getClass().getDeclaredMethod("isLevelAtMost", gradleLogLevel);
|
||||
isLevelAtMostMethod.setAccessible(true);
|
||||
|
||||
Object[] logLevels = gradleLogLevel.getEnumConstants();
|
||||
// the log levels in gradle are declared in the order DEBUG, INFO, LIFECYCLE, WARN, QUIET, ERROR
|
||||
Level[] mapping = new Level[] {
|
||||
Level.FINEST, // DEBUG
|
||||
Level.CONFIG, // INFO
|
||||
Level.INFO, // LIFECYCLE
|
||||
Level.WARNING, // WARN
|
||||
Level.SEVERE, // QUIET
|
||||
Level.SEVERE, // ERROR
|
||||
};
|
||||
|
||||
for (int i = 0; i < Math.min(logLevels.length, mapping.length); i++) {
|
||||
boolean enabled = (boolean) isLevelAtMostMethod.invoke(logger, logLevels[i]);
|
||||
if (enabled) {
|
||||
project.log("Current log level: " + logLevels[i] + " -> " + mapping[i], Project.MSG_DEBUG);
|
||||
return mapping[i];
|
||||
}
|
||||
}
|
||||
} catch (ReflectiveOperationException ignored) {
|
||||
// ignored
|
||||
}
|
||||
project.log("Could not determine log level, falling back to default: " + DEFAULT_LEVEL, Project.MSG_WARN);
|
||||
return DEFAULT_LEVEL;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user