Repository: maven Updated Branches: refs/heads/MNG-6093 [created] 6d8d0e1d8
MNG-6093 implemented a little slf4j-simple extension to support color Project: http://git-wip-us.apache.org/repos/asf/maven/repo Commit: http://git-wip-us.apache.org/repos/asf/maven/commit/6d8d0e1d Tree: http://git-wip-us.apache.org/repos/asf/maven/tree/6d8d0e1d Diff: http://git-wip-us.apache.org/repos/asf/maven/diff/6d8d0e1d Branch: refs/heads/MNG-6093 Commit: 6d8d0e1d8e4f4c6ad0597ee52f785ce96a17806f Parents: 34aca1a Author: Hervé Boutemy <hbout...@apache.org> Authored: Thu Sep 22 17:46:53 2016 +0200 Committer: Hervé Boutemy <hbout...@apache.org> Committed: Thu Sep 22 17:46:53 2016 +0200 ---------------------------------------------------------------------- apache-maven/pom.xml | 4 +- maven-slf4j-provider/pom.xml | 52 ++ .../java/org/slf4j/impl/MavenSimpleLogger.java | 117 ++++ .../slf4j/impl/MavenSimpleLoggerFactory.java | 21 + .../main/java/org/slf4j/impl/SimpleLogger.java | 663 +++++++++++++++++++ .../org/slf4j/impl/SimpleLoggerFactory.java | 73 ++ .../java/org/slf4j/impl/StaticLoggerBinder.java | 81 +++ .../java/org/slf4j/impl/StaticMDCBinder.java | 66 ++ .../java/org/slf4j/impl/StaticMarkerBinder.java | 78 +++ pom.xml | 6 + 10 files changed, 1159 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven/blob/6d8d0e1d/apache-maven/pom.xml ---------------------------------------------------------------------- diff --git a/apache-maven/pom.xml b/apache-maven/pom.xml index ec11cc2..437fc43 100644 --- a/apache-maven/pom.xml +++ b/apache-maven/pom.xml @@ -92,8 +92,8 @@ under the License. <artifactId>aether-transport-wagon</artifactId> </dependency> <dependency> - <groupId>com.planet57.gossip</groupId> - <artifactId>gossip-slf4j</artifactId> + <groupId>org.apache.maven</groupId> + <artifactId>maven-slf4j-provider</artifactId> </dependency> <dependency> <groupId>org.fusesource.jansi</groupId> http://git-wip-us.apache.org/repos/asf/maven/blob/6d8d0e1d/maven-slf4j-provider/pom.xml ---------------------------------------------------------------------- diff --git a/maven-slf4j-provider/pom.xml b/maven-slf4j-provider/pom.xml new file mode 100644 index 0000000..4688de8 --- /dev/null +++ b/maven-slf4j-provider/pom.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.maven</groupId> + <artifactId>maven</artifactId> + <version>3.4.0-SNAPSHOT</version> + </parent> + + <artifactId>maven-slf4j-provider</artifactId> + + <name>Maven SLF4J Simple Provider</name> + <description>Maven SLF4J provider based on SLF4J's simple provider extended to support colors.</description> + + <properties> + <!-- disable rat and Checkstyle --> + <rat.skip>true</rat.skip> + <checkstyle.skip>true</checkstyle.skip> + </properties> + + <dependencies> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-shared-utils</artifactId> + </dependency> + </dependencies> +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/maven/blob/6d8d0e1d/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLogger.java ---------------------------------------------------------------------- diff --git a/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLogger.java b/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLogger.java new file mode 100644 index 0000000..0c3ad47 --- /dev/null +++ b/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLogger.java @@ -0,0 +1,117 @@ +package org.slf4j.impl; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static org.apache.maven.shared.utils.logging.MessageUtils.buffer; + +import java.io.PrintStream; + +/** + * Logger for Maven, that support colorization of levels and stacktraces. + * This class implements 2 methods introduced in slf4j-simple provider local copy. + * @since 3.4.0 + */ +public class MavenSimpleLogger + extends SimpleLogger +{ + private static final String NEWLINE = System.getProperty( "line.separator" ); + + MavenSimpleLogger( String name ) + { + super( name ); + } + + @Override + protected String renderLevel( int level ) + { + switch ( level ) + { + case LOG_LEVEL_TRACE: + return buffer().debug( "TRACE" ).toString(); + case LOG_LEVEL_DEBUG: + return buffer().debug( "DEBUG" ).toString(); + case LOG_LEVEL_INFO: + return buffer().info( "INFO" ).toString(); + case LOG_LEVEL_WARN: + return buffer().warning( "WARNING" ).toString(); + case LOG_LEVEL_ERROR: + default: + return buffer().error( "ERROR" ).toString(); + } + } + + @Override + protected void renderThrowable( Throwable t, PrintStream stream ) + { + stream.append( buffer().failure( t.getClass().getName() ).toString() ); + if ( t.getMessage() != null ) + { + stream.append( ": " ); + stream.append( buffer().failure( t.getMessage() ).toString() ); + } + stream.append( NEWLINE ); + + while ( t != null ) + { + for ( StackTraceElement e : t.getStackTrace() ) + { + stream.append( " " ); + stream.append( buffer().strong( "at" ).toString() ); + stream.append( " " + e.getClassName() + "." + e.getMethodName() ); + stream.append( buffer().a( " (" ).strong( getLocation( e ) ).a( ")" ).toString() ); + stream.append( NEWLINE ); + } + + t = t.getCause(); + if ( t != null ) + { + stream.append( buffer().strong( "td by" ).a( ": " ).a( t.getClass().getName() ).toString() ); + if ( t.getMessage() != null ) + { + stream.append( ": " ); + stream.append( buffer().failure( t.getMessage() ).toString() ); + } + stream.append( NEWLINE ); + } + } + } + + protected String getLocation( final StackTraceElement e ) + { + assert e != null; + + if ( e.isNativeMethod() ) + { + return "Native Method"; + } + else if ( e.getFileName() == null ) + { + return "Unknown Source"; + } + else if ( e.getLineNumber() >= 0 ) + { + return String.format( "%s:%s", e.getFileName(), e.getLineNumber() ); + } + else + { + return e.getFileName(); + } + } +} http://git-wip-us.apache.org/repos/asf/maven/blob/6d8d0e1d/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLoggerFactory.java ---------------------------------------------------------------------- diff --git a/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLoggerFactory.java b/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLoggerFactory.java new file mode 100644 index 0000000..401d20c --- /dev/null +++ b/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLoggerFactory.java @@ -0,0 +1,21 @@ +package org.slf4j.impl; + +import org.slf4j.Logger; + +public class MavenSimpleLoggerFactory + extends SimpleLoggerFactory +{ + /** + * Return an appropriate {@link SimpleLogger} instance by name. + */ + public Logger getLogger(String name) { + Logger simpleLogger = loggerMap.get(name); + if (simpleLogger != null) { + return simpleLogger; + } else { + Logger newInstance = new MavenSimpleLogger(name); + Logger oldInstance = loggerMap.putIfAbsent(name, newInstance); + return oldInstance == null ? newInstance : oldInstance; + } + } +} http://git-wip-us.apache.org/repos/asf/maven/blob/6d8d0e1d/maven-slf4j-provider/src/main/java/org/slf4j/impl/SimpleLogger.java ---------------------------------------------------------------------- diff --git a/maven-slf4j-provider/src/main/java/org/slf4j/impl/SimpleLogger.java b/maven-slf4j-provider/src/main/java/org/slf4j/impl/SimpleLogger.java new file mode 100644 index 0000000..7f77332 --- /dev/null +++ b/maven-slf4j-provider/src/main/java/org/slf4j/impl/SimpleLogger.java @@ -0,0 +1,663 @@ +/** + * Copyright (c) 2004-2012 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package org.slf4j.impl; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.PrintStream; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.event.LoggingEvent; +import org.slf4j.helpers.FormattingTuple; +import org.slf4j.helpers.MarkerIgnoringBase; +import org.slf4j.helpers.MessageFormatter; +import org.slf4j.helpers.Util; +import org.slf4j.spi.LocationAwareLogger; + +/** + * <p>Simple implementation of {@link Logger} that sends all enabled log messages, + * for all defined loggers, to the console ({@code System.err}). + * The following system properties are supported to configure the behavior of this logger:</p> + * + * <ul> + * <li><code>org.slf4j.simpleLogger.logFile</code> - The output target which can be the <em>path</em> to a file, or + * the special values "System.out" and "System.err". Default is "System.err". + * + * <li><code>org.slf4j.simpleLogger.defaultLogLevel</code> - Default log level for all instances of SimpleLogger. + * Must be one of ("trace", "debug", "info", "warn", or "error"). If not specified, defaults to "info". </li> + * + * <li><code>org.slf4j.simpleLogger.log.<em>a.b.c</em></code> - Logging detail level for a SimpleLogger instance + * named "a.b.c". Right-side value must be one of "trace", "debug", "info", "warn", or "error". When a SimpleLogger + * named "a.b.c" is initialized, its level is assigned from this property. If unspecified, the level of nearest parent + * logger will be used, and if none is set, then the value specified by + * <code>org.slf4j.simpleLogger.defaultLogLevel</code> will be used.</li> + * + * <li><code>org.slf4j.simpleLogger.showDateTime</code> - Set to <code>true</code> if you want the current date and + * time to be included in output messages. Default is <code>false</code></li> + * + * <li><code>org.slf4j.simpleLogger.dateTimeFormat</code> - The date and time format to be used in the output messages. + * The pattern describing the date and time format is defined by + * <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/text/SimpleDateFormat.html"><code>SimpleDateFormat</code></a>. + * If the format is not specified or is invalid, the number of milliseconds since start up will be output. </li> + * + * <li><code>org.slf4j.simpleLogger.showThreadName</code> -Set to <code>true</code> if you want to output the current + * thread name. Defaults to <code>true</code>.</li> + * + * <li><code>org.slf4j.simpleLogger.showLogName</code> - Set to <code>true</code> if you want the Logger instance name + * to be included in output messages. Defaults to <code>true</code>.</li> + * + * <li><code>org.slf4j.simpleLogger.showShortLogName</code> - Set to <code>true</code> if you want the last component + * of the name to be included in output messages. Defaults to <code>false</code>.</li> + * + * <li><code>org.slf4j.simpleLogger.levelInBrackets</code> - Should the level string be output in brackets? Defaults + * to <code>false</code>.</li> + * + * <li><code>org.slf4j.simpleLogger.warnLevelString</code> - The string value output for the warn level. Defaults + * to <code>WARN</code>.</li> + + * </ul> + * + * <p>In addition to looking for system properties with the names specified above, this implementation also checks for + * a class loader resource named <code>"simplelogger.properties"</code>, and includes any matching definitions + * from this resource (if it exists).</p> + * + * <p>With no configuration, the default output includes the relative time in milliseconds, thread name, the level, + * logger name, and the message followed by the line separator for the host. In log4j terms it amounts to the "%r [%t] + * %level %logger - %m%n" pattern. </p> + * <p>Sample output follows.</p> + * <pre> + * 176 [main] INFO examples.Sort - Populating an array of 2 elements in reverse order. + * 225 [main] INFO examples.SortAlgo - Entered the sort method. + * 304 [main] INFO examples.SortAlgo - Dump of integer array: + * 317 [main] INFO examples.SortAlgo - Element [0] = 0 + * 331 [main] INFO examples.SortAlgo - Element [1] = 1 + * 343 [main] INFO examples.Sort - The next log statement should be an error message. + * 346 [main] ERROR examples.SortAlgo - Tried to dump an uninitialized array. + * at org.log4j.examples.SortAlgo.dump(SortAlgo.java:58) + * at org.log4j.examples.Sort.main(Sort.java:64) + * 467 [main] INFO examples.Sort - Exiting main method. + * </pre> + * + * <p>This implementation is heavily inspired by + * <a href="http://commons.apache.org/logging/">Apache Commons Logging</a>'s SimpleLog.</p> + * + * @author Ceki Gülcü + * @author <a href="mailto:sand...@apache.org">Scott Sanders</a> + * @author Rod Waldhoff + * @author Robert Burrell Donkin + * @author Cédrik LIME + */ +public class SimpleLogger extends MarkerIgnoringBase { + + private static final long serialVersionUID = -632788891211436180L; + private static final String CONFIGURATION_FILE = "simplelogger.properties"; + + private static long START_TIME = System.currentTimeMillis(); + private static final Properties SIMPLE_LOGGER_PROPS = new Properties(); + + protected static final int LOG_LEVEL_TRACE = LocationAwareLogger.TRACE_INT; + protected static final int LOG_LEVEL_DEBUG = LocationAwareLogger.DEBUG_INT; + protected static final int LOG_LEVEL_INFO = LocationAwareLogger.INFO_INT; + protected static final int LOG_LEVEL_WARN = LocationAwareLogger.WARN_INT; + protected static final int LOG_LEVEL_ERROR = LocationAwareLogger.ERROR_INT; + + private static boolean INITIALIZED = false; + + private static int DEFAULT_LOG_LEVEL = LOG_LEVEL_INFO; + private static boolean SHOW_DATE_TIME = false; + private static String DATE_TIME_FORMAT_STR = null; + private static DateFormat DATE_FORMATTER = null; + private static boolean SHOW_THREAD_NAME = true; + private static boolean SHOW_LOG_NAME = true; + private static boolean SHOW_SHORT_LOG_NAME = false; + private static String LOG_FILE = "System.err"; + private static PrintStream TARGET_STREAM = null; + private static boolean LEVEL_IN_BRACKETS = false; + private static String WARN_LEVEL_STRING = "WARN"; + + /** All system properties used by <code>SimpleLogger</code> start with this prefix */ + public static final String SYSTEM_PREFIX = "org.slf4j.simpleLogger."; + + public static final String DEFAULT_LOG_LEVEL_KEY = SYSTEM_PREFIX + "defaultLogLevel"; + public static final String SHOW_DATE_TIME_KEY = SYSTEM_PREFIX + "showDateTime"; + public static final String DATE_TIME_FORMAT_KEY = SYSTEM_PREFIX + "dateTimeFormat"; + public static final String SHOW_THREAD_NAME_KEY = SYSTEM_PREFIX + "showThreadName"; + public static final String SHOW_LOG_NAME_KEY = SYSTEM_PREFIX + "showLogName"; + public static final String SHOW_SHORT_LOG_NAME_KEY = SYSTEM_PREFIX + "showShortLogName"; + public static final String LOG_FILE_KEY = SYSTEM_PREFIX + "logFile"; + public static final String LEVEL_IN_BRACKETS_KEY = SYSTEM_PREFIX + "levelInBrackets"; + public static final String WARN_LEVEL_STRING_KEY = SYSTEM_PREFIX + "warnLevelString"; + + public static final String LOG_KEY_PREFIX = SYSTEM_PREFIX + "log."; + + private static String getStringProperty(String name) { + String prop = null; + try { + prop = System.getProperty(name); + } catch (SecurityException e) { + ; // Ignore + } + return (prop == null) ? SIMPLE_LOGGER_PROPS.getProperty(name) : prop; + } + + private static String getStringProperty(String name, String defaultValue) { + String prop = getStringProperty(name); + return (prop == null) ? defaultValue : prop; + } + + private static boolean getBooleanProperty(String name, boolean defaultValue) { + String prop = getStringProperty(name); + return (prop == null) ? defaultValue : "true".equalsIgnoreCase(prop); + } + + // Initialize class attributes. + // Load properties file, if found. + // Override with system properties. + static void init() { + INITIALIZED = true; + loadProperties(); + + String defaultLogLevelString = getStringProperty(DEFAULT_LOG_LEVEL_KEY, null); + if (defaultLogLevelString != null) + DEFAULT_LOG_LEVEL = stringToLevel(defaultLogLevelString); + + SHOW_LOG_NAME = getBooleanProperty(SHOW_LOG_NAME_KEY, SHOW_LOG_NAME); + SHOW_SHORT_LOG_NAME = getBooleanProperty(SHOW_SHORT_LOG_NAME_KEY, SHOW_SHORT_LOG_NAME); + SHOW_DATE_TIME = getBooleanProperty(SHOW_DATE_TIME_KEY, SHOW_DATE_TIME); + SHOW_THREAD_NAME = getBooleanProperty(SHOW_THREAD_NAME_KEY, SHOW_THREAD_NAME); + DATE_TIME_FORMAT_STR = getStringProperty(DATE_TIME_FORMAT_KEY, DATE_TIME_FORMAT_STR); + LEVEL_IN_BRACKETS = getBooleanProperty(LEVEL_IN_BRACKETS_KEY, LEVEL_IN_BRACKETS); + WARN_LEVEL_STRING = getStringProperty(WARN_LEVEL_STRING_KEY, WARN_LEVEL_STRING); + + LOG_FILE = getStringProperty(LOG_FILE_KEY, LOG_FILE); + TARGET_STREAM = computeTargetStream(LOG_FILE); + + if (DATE_TIME_FORMAT_STR != null) { + try { + DATE_FORMATTER = new SimpleDateFormat(DATE_TIME_FORMAT_STR); + } catch (IllegalArgumentException e) { + Util.report("Bad date format in " + CONFIGURATION_FILE + "; will output relative time", e); + } + } + } + + private static PrintStream computeTargetStream(String logFile) { + if ("System.err".equalsIgnoreCase(logFile)) + return System.err; + else if ("System.out".equalsIgnoreCase(logFile)) { + return System.out; + } else { + try { + FileOutputStream fos = new FileOutputStream(logFile); + PrintStream printStream = new PrintStream(fos); + return printStream; + } catch (FileNotFoundException e) { + Util.report("Could not open [" + logFile + "]. Defaulting to System.err", e); + return System.err; + } + } + } + + private static void loadProperties() { + // Add props from the resource simplelogger.properties + InputStream in = AccessController.doPrivileged(new PrivilegedAction<InputStream>() { + public InputStream run() { + ClassLoader threadCL = Thread.currentThread().getContextClassLoader(); + if (threadCL != null) { + return threadCL.getResourceAsStream(CONFIGURATION_FILE); + } else { + return ClassLoader.getSystemResourceAsStream(CONFIGURATION_FILE); + } + } + }); + if (null != in) { + try { + SIMPLE_LOGGER_PROPS.load(in); + in.close(); + } catch (java.io.IOException e) { + // ignored + } + } + } + + /** The current log level */ + protected int currentLogLevel = LOG_LEVEL_INFO; + /** The short name of this simple log instance */ + private transient String shortLogName = null; + + /** + * Package access allows only {@link SimpleLoggerFactory} to instantiate + * SimpleLogger instances. + */ + SimpleLogger(String name) { + if (!INITIALIZED) { + init(); + } + this.name = name; + + String levelString = recursivelyComputeLevelString(); + if (levelString != null) { + this.currentLogLevel = stringToLevel(levelString); + } else { + this.currentLogLevel = DEFAULT_LOG_LEVEL; + } + } + + String recursivelyComputeLevelString() { + String tempName = name; + String levelString = null; + int indexOfLastDot = tempName.length(); + while ((levelString == null) && (indexOfLastDot > -1)) { + tempName = tempName.substring(0, indexOfLastDot); + levelString = getStringProperty(LOG_KEY_PREFIX + tempName, null); + indexOfLastDot = String.valueOf(tempName).lastIndexOf("."); + } + return levelString; + } + + private static int stringToLevel(String levelStr) { + if ("trace".equalsIgnoreCase(levelStr)) { + return LOG_LEVEL_TRACE; + } else if ("debug".equalsIgnoreCase(levelStr)) { + return LOG_LEVEL_DEBUG; + } else if ("info".equalsIgnoreCase(levelStr)) { + return LOG_LEVEL_INFO; + } else if ("warn".equalsIgnoreCase(levelStr)) { + return LOG_LEVEL_WARN; + } else if ("error".equalsIgnoreCase(levelStr)) { + return LOG_LEVEL_ERROR; + } + // assume INFO by default + return LOG_LEVEL_INFO; + } + + /** + * This is our internal implementation for logging regular (non-parameterized) + * log messages. + * + * @param level One of the LOG_LEVEL_XXX constants defining the log level + * @param message The message itself + * @param t The exception whose stack trace should be logged + */ + private void log(int level, String message, Throwable t) { + if (!isLevelEnabled(level)) { + return; + } + + StringBuilder buf = new StringBuilder(32); + + // Append date-time if so configured + if (SHOW_DATE_TIME) { + if (DATE_FORMATTER != null) { + buf.append(getFormattedDate()); + buf.append(' '); + } else { + buf.append(System.currentTimeMillis() - START_TIME); + buf.append(' '); + } + } + + // Append current thread name if so configured + if (SHOW_THREAD_NAME) { + buf.append('['); + buf.append(Thread.currentThread().getName()); + buf.append("] "); + } + + if (LEVEL_IN_BRACKETS) + buf.append('['); + + // Append a readable representation of the log level + buf.append(renderLevel(level)); + if (LEVEL_IN_BRACKETS) + buf.append(']'); + buf.append(' '); + + // Append the name of the log instance if so configured + if (SHOW_SHORT_LOG_NAME) { + if (shortLogName == null) + shortLogName = computeShortName(); + buf.append(String.valueOf(shortLogName)).append(" - "); + } else if (SHOW_LOG_NAME) { + buf.append(String.valueOf(name)).append(" - "); + } + + // Append the message + buf.append(message); + + write(buf, t); + + } + + protected String renderLevel(int level) { + switch (level) { + case LOG_LEVEL_TRACE: + return "TRACE"; + case LOG_LEVEL_DEBUG: + return"DEBUG"; + case LOG_LEVEL_INFO: + return "INFO"; + case LOG_LEVEL_WARN: + return WARN_LEVEL_STRING; + case LOG_LEVEL_ERROR: + default: + return "ERROR"; + } + } + + protected void renderThrowable(Throwable t, PrintStream stream) { + t.printStackTrace(stream); + } + + void write(StringBuilder buf, Throwable t) { + TARGET_STREAM.println(buf.toString()); + if (t != null) { + renderThrowable(t, TARGET_STREAM); + } + TARGET_STREAM.flush(); + } + + private String getFormattedDate() { + Date now = new Date(); + String dateText; + synchronized (DATE_FORMATTER) { + dateText = DATE_FORMATTER.format(now); + } + return dateText; + } + + private String computeShortName() { + return name.substring(name.lastIndexOf(".") + 1); + } + + /** + * For formatted messages, first substitute arguments and then log. + * + * @param level + * @param format + * @param arg1 + * @param arg2 + */ + private void formatAndLog(int level, String format, Object arg1, Object arg2) { + if (!isLevelEnabled(level)) { + return; + } + FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); + log(level, tp.getMessage(), tp.getThrowable()); + } + + /** + * For formatted messages, first substitute arguments and then log. + * + * @param level + * @param format + * @param arguments a list of 3 ore more arguments + */ + private void formatAndLog(int level, String format, Object... arguments) { + if (!isLevelEnabled(level)) { + return; + } + FormattingTuple tp = MessageFormatter.arrayFormat(format, arguments); + log(level, tp.getMessage(), tp.getThrowable()); + } + + /** + * Is the given log level currently enabled? + * + * @param logLevel is this level enabled? + */ + protected boolean isLevelEnabled(int logLevel) { + // log level are numerically ordered so can use simple numeric + // comparison + return (logLevel >= currentLogLevel); + } + + /** Are {@code trace} messages currently enabled? */ + public boolean isTraceEnabled() { + return isLevelEnabled(LOG_LEVEL_TRACE); + } + + /** + * A simple implementation which logs messages of level TRACE according + * to the format outlined above. + */ + public void trace(String msg) { + log(LOG_LEVEL_TRACE, msg, null); + } + + /** + * Perform single parameter substitution before logging the message of level + * TRACE according to the format outlined above. + */ + public void trace(String format, Object param1) { + formatAndLog(LOG_LEVEL_TRACE, format, param1, null); + } + + /** + * Perform double parameter substitution before logging the message of level + * TRACE according to the format outlined above. + */ + public void trace(String format, Object param1, Object param2) { + formatAndLog(LOG_LEVEL_TRACE, format, param1, param2); + } + + /** + * Perform double parameter substitution before logging the message of level + * TRACE according to the format outlined above. + */ + public void trace(String format, Object... argArray) { + formatAndLog(LOG_LEVEL_TRACE, format, argArray); + } + + /** Log a message of level TRACE, including an exception. */ + public void trace(String msg, Throwable t) { + log(LOG_LEVEL_TRACE, msg, t); + } + + /** Are {@code debug} messages currently enabled? */ + public boolean isDebugEnabled() { + return isLevelEnabled(LOG_LEVEL_DEBUG); + } + + /** + * A simple implementation which logs messages of level DEBUG according + * to the format outlined above. + */ + public void debug(String msg) { + log(LOG_LEVEL_DEBUG, msg, null); + } + + /** + * Perform single parameter substitution before logging the message of level + * DEBUG according to the format outlined above. + */ + public void debug(String format, Object param1) { + formatAndLog(LOG_LEVEL_DEBUG, format, param1, null); + } + + /** + * Perform double parameter substitution before logging the message of level + * DEBUG according to the format outlined above. + */ + public void debug(String format, Object param1, Object param2) { + formatAndLog(LOG_LEVEL_DEBUG, format, param1, param2); + } + + /** + * Perform double parameter substitution before logging the message of level + * DEBUG according to the format outlined above. + */ + public void debug(String format, Object... argArray) { + formatAndLog(LOG_LEVEL_DEBUG, format, argArray); + } + + /** Log a message of level DEBUG, including an exception. */ + public void debug(String msg, Throwable t) { + log(LOG_LEVEL_DEBUG, msg, t); + } + + /** Are {@code info} messages currently enabled? */ + public boolean isInfoEnabled() { + return isLevelEnabled(LOG_LEVEL_INFO); + } + + /** + * A simple implementation which logs messages of level INFO according + * to the format outlined above. + */ + public void info(String msg) { + log(LOG_LEVEL_INFO, msg, null); + } + + /** + * Perform single parameter substitution before logging the message of level + * INFO according to the format outlined above. + */ + public void info(String format, Object arg) { + formatAndLog(LOG_LEVEL_INFO, format, arg, null); + } + + /** + * Perform double parameter substitution before logging the message of level + * INFO according to the format outlined above. + */ + public void info(String format, Object arg1, Object arg2) { + formatAndLog(LOG_LEVEL_INFO, format, arg1, arg2); + } + + /** + * Perform double parameter substitution before logging the message of level + * INFO according to the format outlined above. + */ + public void info(String format, Object... argArray) { + formatAndLog(LOG_LEVEL_INFO, format, argArray); + } + + /** Log a message of level INFO, including an exception. */ + public void info(String msg, Throwable t) { + log(LOG_LEVEL_INFO, msg, t); + } + + /** Are {@code warn} messages currently enabled? */ + public boolean isWarnEnabled() { + return isLevelEnabled(LOG_LEVEL_WARN); + } + + /** + * A simple implementation which always logs messages of level WARN according + * to the format outlined above. + */ + public void warn(String msg) { + log(LOG_LEVEL_WARN, msg, null); + } + + /** + * Perform single parameter substitution before logging the message of level + * WARN according to the format outlined above. + */ + public void warn(String format, Object arg) { + formatAndLog(LOG_LEVEL_WARN, format, arg, null); + } + + /** + * Perform double parameter substitution before logging the message of level + * WARN according to the format outlined above. + */ + public void warn(String format, Object arg1, Object arg2) { + formatAndLog(LOG_LEVEL_WARN, format, arg1, arg2); + } + + /** + * Perform double parameter substitution before logging the message of level + * WARN according to the format outlined above. + */ + public void warn(String format, Object... argArray) { + formatAndLog(LOG_LEVEL_WARN, format, argArray); + } + + /** Log a message of level WARN, including an exception. */ + public void warn(String msg, Throwable t) { + log(LOG_LEVEL_WARN, msg, t); + } + + /** Are {@code error} messages currently enabled? */ + public boolean isErrorEnabled() { + return isLevelEnabled(LOG_LEVEL_ERROR); + } + + /** + * A simple implementation which always logs messages of level ERROR according + * to the format outlined above. + */ + public void error(String msg) { + log(LOG_LEVEL_ERROR, msg, null); + } + + /** + * Perform single parameter substitution before logging the message of level + * ERROR according to the format outlined above. + */ + public void error(String format, Object arg) { + formatAndLog(LOG_LEVEL_ERROR, format, arg, null); + } + + /** + * Perform double parameter substitution before logging the message of level + * ERROR according to the format outlined above. + */ + public void error(String format, Object arg1, Object arg2) { + formatAndLog(LOG_LEVEL_ERROR, format, arg1, arg2); + } + + /** + * Perform double parameter substitution before logging the message of level + * ERROR according to the format outlined above. + */ + public void error(String format, Object... argArray) { + formatAndLog(LOG_LEVEL_ERROR, format, argArray); + } + + /** Log a message of level ERROR, including an exception. */ + public void error(String msg, Throwable t) { + log(LOG_LEVEL_ERROR, msg, t); + } + + public void log(LoggingEvent event) { + int levelInt = event.getLevel().toInt(); + + if (!isLevelEnabled(levelInt)) { + return; + } + FormattingTuple tp = MessageFormatter.arrayFormat(event.getMessage(), event.getArgumentArray(), event.getThrowable()); + log(levelInt, tp.getMessage(), event.getThrowable()); + } +} http://git-wip-us.apache.org/repos/asf/maven/blob/6d8d0e1d/maven-slf4j-provider/src/main/java/org/slf4j/impl/SimpleLoggerFactory.java ---------------------------------------------------------------------- diff --git a/maven-slf4j-provider/src/main/java/org/slf4j/impl/SimpleLoggerFactory.java b/maven-slf4j-provider/src/main/java/org/slf4j/impl/SimpleLoggerFactory.java new file mode 100644 index 0000000..4c59f2d --- /dev/null +++ b/maven-slf4j-provider/src/main/java/org/slf4j/impl/SimpleLoggerFactory.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package org.slf4j.impl; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.slf4j.Logger; +import org.slf4j.ILoggerFactory; + +/** + * An implementation of {@link ILoggerFactory} which always returns + * {@link SimpleLogger} instances. + * + * @author Ceki Gülcü + */ +public class SimpleLoggerFactory implements ILoggerFactory { + + ConcurrentMap<String, Logger> loggerMap; + + public SimpleLoggerFactory() { + loggerMap = new ConcurrentHashMap<String, Logger>(); + } + + /** + * Return an appropriate {@link SimpleLogger} instance by name. + */ + public Logger getLogger(String name) { + Logger simpleLogger = loggerMap.get(name); + if (simpleLogger != null) { + return simpleLogger; + } else { + Logger newInstance = new SimpleLogger(name); + Logger oldInstance = loggerMap.putIfAbsent(name, newInstance); + return oldInstance == null ? newInstance : oldInstance; + } + } + + /** + * Clear the internal logger cache. + * + * This method is intended to be called by classes (in the same package) for + * testing purposes. This method is internal. It can be modified, renamed or + * removed at any time without notice. + * + * You are strongly discouraged from calling this method in production code. + */ + void reset() { + loggerMap.clear(); + } +} http://git-wip-us.apache.org/repos/asf/maven/blob/6d8d0e1d/maven-slf4j-provider/src/main/java/org/slf4j/impl/StaticLoggerBinder.java ---------------------------------------------------------------------- diff --git a/maven-slf4j-provider/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/maven-slf4j-provider/src/main/java/org/slf4j/impl/StaticLoggerBinder.java new file mode 100644 index 0000000..0d214b7 --- /dev/null +++ b/maven-slf4j-provider/src/main/java/org/slf4j/impl/StaticLoggerBinder.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package org.slf4j.impl; + +import org.slf4j.ILoggerFactory; +import org.slf4j.LoggerFactory; +import org.slf4j.spi.LoggerFactoryBinder; + +/** + * The binding of {@link LoggerFactory} class with an actual instance of + * {@link ILoggerFactory} is performed using information returned by this class. + * + * + * @author Ceki Gülcü + */ +public class StaticLoggerBinder implements LoggerFactoryBinder { + + /** + * The unique instance of this class. + * + */ + private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder(); + + /** + * Return the singleton of this class. + * + * @return the StaticLoggerBinder singleton + */ + public static final StaticLoggerBinder getSingleton() { + return SINGLETON; + } + + /** + * Declare the version of the SLF4J API this implementation is compiled against. + * The value of this field is modified with each major release. + */ + // to avoid constant folding by the compiler, this field must *not* be final + public static String REQUESTED_API_VERSION = "1.6.99"; // !final + + private static final String loggerFactoryClassStr = MavenSimpleLoggerFactory.class.getName(); + + /** + * The ILoggerFactory instance returned by the {@link #getLoggerFactory} + * method should always be the same object + */ + private final ILoggerFactory loggerFactory; + + private StaticLoggerBinder() { + loggerFactory = new SimpleLoggerFactory(); + } + + public ILoggerFactory getLoggerFactory() { + return loggerFactory; + } + + public String getLoggerFactoryClassStr() { + return loggerFactoryClassStr; + } +} http://git-wip-us.apache.org/repos/asf/maven/blob/6d8d0e1d/maven-slf4j-provider/src/main/java/org/slf4j/impl/StaticMDCBinder.java ---------------------------------------------------------------------- diff --git a/maven-slf4j-provider/src/main/java/org/slf4j/impl/StaticMDCBinder.java b/maven-slf4j-provider/src/main/java/org/slf4j/impl/StaticMDCBinder.java new file mode 100644 index 0000000..a88f2bf --- /dev/null +++ b/maven-slf4j-provider/src/main/java/org/slf4j/impl/StaticMDCBinder.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package org.slf4j.impl; + +import org.slf4j.helpers.NOPMDCAdapter; +import org.slf4j.spi.MDCAdapter; + +/** + * This implementation is bound to {@link NOPMDCAdapter}. + * + * @author Ceki Gülcü + */ +public class StaticMDCBinder { + + /** + * The unique instance of this class. + */ + public static final StaticMDCBinder SINGLETON = new StaticMDCBinder(); + + private StaticMDCBinder() { + } + + /** + * Return the singleton of this class. + * + * @return the StaticMDCBinder singleton + * @since 1.7.14 + */ + public static final StaticMDCBinder getSingleton() { + return SINGLETON; + } + + /** + * Currently this method always returns an instance of + * {@link StaticMDCBinder}. + */ + public MDCAdapter getMDCA() { + return new NOPMDCAdapter(); + } + + public String getMDCAdapterClassStr() { + return NOPMDCAdapter.class.getName(); + } +} http://git-wip-us.apache.org/repos/asf/maven/blob/6d8d0e1d/maven-slf4j-provider/src/main/java/org/slf4j/impl/StaticMarkerBinder.java ---------------------------------------------------------------------- diff --git a/maven-slf4j-provider/src/main/java/org/slf4j/impl/StaticMarkerBinder.java b/maven-slf4j-provider/src/main/java/org/slf4j/impl/StaticMarkerBinder.java new file mode 100644 index 0000000..ef1a9d9 --- /dev/null +++ b/maven-slf4j-provider/src/main/java/org/slf4j/impl/StaticMarkerBinder.java @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package org.slf4j.impl; + +import org.slf4j.IMarkerFactory; +import org.slf4j.MarkerFactory; +import org.slf4j.helpers.BasicMarkerFactory; +import org.slf4j.spi.MarkerFactoryBinder; + +/** + * + * The binding of {@link MarkerFactory} class with an actual instance of + * {@link IMarkerFactory} is performed using information returned by this class. + * + * @author Ceki Gülcü + */ +public class StaticMarkerBinder implements MarkerFactoryBinder { + + /** + * The unique instance of this class. + */ + public static final StaticMarkerBinder SINGLETON = new StaticMarkerBinder(); + + final IMarkerFactory markerFactory = new BasicMarkerFactory(); + + private StaticMarkerBinder() { + } + + /** + * Return the singleton of this class. + * + * @return the StaticMarkerBinder singleton + * @since 1.7.14 + */ + public static StaticMarkerBinder getSingleton() { + return SINGLETON; + } + + /** + * Currently this method always returns an instance of + * {@link BasicMarkerFactory}. + */ + public IMarkerFactory getMarkerFactory() { + return markerFactory; + } + + /** + * Currently, this method returns the class name of + * {@link BasicMarkerFactory}. + */ + public String getMarkerFactoryClassStr() { + return BasicMarkerFactory.class.getName(); + } + +} http://git-wip-us.apache.org/repos/asf/maven/blob/6d8d0e1d/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 861b915..ec82598 100644 --- a/pom.xml +++ b/pom.xml @@ -91,6 +91,7 @@ under the License. <module>maven-artifact</module> <module>maven-aether-provider</module> <module>maven-repository-metadata</module> + <module>maven-slf4j-provider</module> <module>maven-embedder</module> <module>maven-compat</module> <module>apache-maven</module> @@ -227,6 +228,11 @@ under the License. <artifactId>maven-builder-support</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-slf4j-provider</artifactId> + <version>${project.version}</version> + </dependency> <!--bootstrap-end-comment--> <!-- Plexus --> <dependency>