package info.freelibrary.maven; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.spi.LocationAwareLogger; /** * @author <a href="mailto:ksclarke@ksclarke.io">Kevin S. Clarke</a> */ public class MavenUtils { private static final Logger LOGGER = LoggerFactory.getLogger(MavenUtils.class); public static final int ERROR_LOG_LEVEL = LocationAwareLogger.ERROR_INT; public static final int WARN_LOG_LEVEL = LocationAwareLogger.WARN_INT; public static final int INFO_LOG_LEVEL = LocationAwareLogger.INFO_INT; public static final int DEBUG_LOG_LEVEL = LocationAwareLogger.DEBUG_INT; public static final int TRACE_LOG_LEVEL = LocationAwareLogger.TRACE_INT; private MavenUtils() { } /** * Set the log level of the supplied loggers to the supplied log level (defined as static ints in the * <code>MavenUtils</code> class). * * @param aLogLevel A log level to set in the supplied loggers * @param aLoggerList A list of names of loggers that need their levels adjusted */ public static final void setLogLevels(final int aLogLevel, final String... aLoggerList) { setLogLevels(aLogLevel, aLoggerList, null, null); } /** * Sets the logging level of the supplied loggers, optionally excluding some and including others. * * @param aLogLevel A log level to set in the supplied loggers * @param aLoggerList A list of names of loggers to have their levels reset * @param aExcludesList A list of names of loggers to exclude from the reset * @param aIncludesList A list of names of additional loggers to include in the reset */ public static final void setLogLevels(final int aLogLevel, final String[] aLoggerList, final String[] aExcludesList, final String[] aIncludesList) { final ArrayList<String> loggerList = new ArrayList<>(Arrays.asList(aLoggerList)); final Class<? extends Logger> simpleLogger = LoggerFactory.getLogger("org.slf4j.impl.SimpleLogger").getClass(); if (aIncludesList != null) { loggerList.addAll(Arrays.asList(aIncludesList)); } for (final String loggerName : loggerList) { if (aExcludesList != null) { boolean skip = false; for (final String element : aExcludesList) { if (loggerName.equals(element)) { skip = true; break; } } if (skip) { continue; } } final Logger loggerObject = LoggerFactory.getLogger(loggerName); final Class<? extends Logger> loggerClass = loggerObject.getClass(); if (simpleLogger.equals(loggerClass)) { try { final Field field = loggerClass.getDeclaredField("currentLogLevel"); field.setAccessible(true); field.setInt(loggerObject, aLogLevel); if (loggerObject.isDebugEnabled()) { LOGGER.debug("'{}' logging level is now set to: {}", loggerName, getLevelName(aLogLevel)); } } catch (NoSuchFieldException | IllegalAccessException details) { LOGGER.error("Has the Maven logger changed?", details); } } else if (LOGGER.isWarnEnabled()) { LOGGER.warn("Supplied logger '{}' isn't a org.slf4j.impl.SimpleLogger", loggerName); } } } /** * Gets a list of names of loggers that Maven uses in a typical build. * * @return A list of names of loggers used by a standard Maven build */ public static final String[] getMavenLoggers() { return new String[] { "org.apache.maven.cli.event.ExecutionEventLogger", "org.apache.maven.tools.plugin.scanner.DefaultMojoScanner", "org.apache.maven.plugin.plugin.DescriptorGeneratorMojo", "org.apache.maven.plugin.dependency.fromConfiguration.UnpackMojo", "org.apache.maven.shared.filtering.DefaultMavenResourcesFiltering", "org.apache.maven.plugin.checkstyle.CheckstyleViolationCheckMojo", "org.apache.maven.plugin.clean.CleanMojo", "org.apache.maven.tools.plugin.annotations.JavaAnnotationsMojoDescriptorExtractor", "org.apache.maven.plugin.failsafe.VerifyMojo", "org.apache.maven.DefaultMaven", "org.apache.maven.plugin.compiler.TestCompilerMojo", "org.apache.maven.plugins.enforcer.EnforceMojo", "org.apache.maven.plugin.compiler.CompilerMojo", "org.codehaus.plexus.archiver.jar.JarArchiver", "org.apache.maven.plugin.surefire.SurefirePlugin", "org.apache.maven.plugin.failsafe.IntegrationTestMojo" }; } /** * Returns a name for the supplied integer value of a log level. * * @param aLogLevel The int value of a log level * @return The human-friendly name value of a log level */ public static final String getLevelName(final int aLogLevel) { switch (aLogLevel) { case ERROR_LOG_LEVEL: return "ERROR"; case WARN_LOG_LEVEL: return "WARN"; case INFO_LOG_LEVEL: return "INFO"; case DEBUG_LOG_LEVEL: return "DEBUG"; case TRACE_LOG_LEVEL: return "TRACE"; default: return "UNKNOWN"; } } /** * Returns the int of the supplied log level or zero if the supplied name doesn't match a known log level. * * @param aLogLevelName The name (error, warn, info, debug, or trace) of a logging level * @return The int code of the supplied level or zero if the supplied name doesn't correspond to a known level */ public static final int getLevelIntCode(final String aLogLevelName) { final String levelName = aLogLevelName.trim().toLowerCase(); if (levelName.equals("error")) { return ERROR_LOG_LEVEL; } else if (levelName.equals("warn")) { return WARN_LOG_LEVEL; } else if (levelName.equals("info")) { return INFO_LOG_LEVEL; } else if (levelName.equals("debug")) { return DEBUG_LOG_LEVEL; } else if (levelName.equals("trace")) { return TRACE_LOG_LEVEL; } else { return 0; } } }