[slf4j-dev] svn commit: r1013 - in slf4j/trunk: slf4j-log4j12/src/main/java/org/slf4j/impl slf4j-log4j12/src/test/java/org/slf4j slf4j-site/src/site/pages

ceki at slf4j.org ceki at slf4j.org
Tue May 27 18:23:13 CEST 2008


Author: ceki
Date: Tue May 27 18:23:12 2008
New Revision: 1013

Added:
   slf4j/trunk/slf4j-log4j12/src/test/java/org/slf4j/ListAppender.java
Modified:
   slf4j/trunk/slf4j-log4j12/src/main/java/org/slf4j/impl/Log4jLoggerAdapter.java
   slf4j/trunk/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
   slf4j/trunk/slf4j-log4j12/src/test/java/org/slf4j/InvocationTest.java
   slf4j/trunk/slf4j-site/src/site/pages/codes.html
   slf4j/trunk/slf4j-site/src/site/pages/news.html

Log:
- fixed bug 68. If log4j version in use is older than 1.2.12, then 
  SLF4J's Log4jLoggerAdapter will map trace as debug.
- updated the docs as such.

See also http://bugzilla.slf4j.org/show_bug.cgi?id=68

Modified: slf4j/trunk/slf4j-log4j12/src/main/java/org/slf4j/impl/Log4jLoggerAdapter.java
==============================================================================
--- slf4j/trunk/slf4j-log4j12/src/main/java/org/slf4j/impl/Log4jLoggerAdapter.java	(original)
+++ slf4j/trunk/slf4j-log4j12/src/main/java/org/slf4j/impl/Log4jLoggerAdapter.java	Tue May 27 18:23:12 2008
@@ -33,7 +33,6 @@
 
 package org.slf4j.impl;
 
-
 import org.apache.log4j.Level;
 import org.slf4j.Logger;
 import org.slf4j.Marker;
@@ -41,133 +40,171 @@
 import org.slf4j.helpers.MessageFormatter;
 import org.slf4j.spi.LocationAwareLogger;
 
-
 /**
- * A wrapper over {@link org.apache.log4j.Logger
- * org.apache.log4j.Logger} in conformance with the {@link Logger}
- * interface. Note that the logging levels mentioned in this class
- * refer to those defined in the 
- * <a href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/Level.html"><code>org.apache.log4j.Level</code></a>
+ * A wrapper over {@link org.apache.log4j.Logger org.apache.log4j.Logger} in
+ * conforming to the {@link Logger} interface. 
+ * 
+ * <p>Note that the logging levels mentioned in this class refer to those defined in the <a
+ * href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/Level.html"><code>org.apache.log4j.Level</code></a>
  * class.
-
+ * 
+ * <p>
+ * The TRACE level was introduced in log4j version 1.2.12. In order to avoid
+ * crashing the host application, in the case the log4j version in use predates
+ * 1.2.12, the TRACE level will be mapped as DEBUG. See also <a
+ * href="http://bugzilla.slf4j.org/show_bug.cgi?id=68">bug 68</a>.
+ * 
  * @author Ceki G&uuml;lc&uuml;
  */
-public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements LocationAwareLogger {
+public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
+    LocationAwareLogger {
   final org.apache.log4j.Logger logger;
-  
+
   /**
-   * Following the pattern discussed in pages 162 through 168 of 
-   * "The complete log4j manual".
+   * Following the pattern discussed in pages 162 through 168 of "The complete
+   * log4j manual".
    */
   final static String FQCN = Log4jLoggerAdapter.class.getName();
-  
-  // WARN: Log4jLoggerAdapter constructor should have only package access so that
+
+  // Does the log4j version in use recognize the TRACE level?
+  // The trace level was introduced in log4j 1.2.12.
+  final boolean traceCapable;
+
+  // WARN: Log4jLoggerAdapter constructor should have only package access so
+  // that
   // only Log4jLoggerFactory be able to create one.
   Log4jLoggerAdapter(org.apache.log4j.Logger logger) {
     this.logger = logger;
+    traceCapable = isTraceCapable();
+  }
+
+  private boolean isTraceCapable() {
+    try {
+      logger.isTraceEnabled();
+      return true;
+    } catch (NoSuchMethodError e) {
+      return false;
+    }
   }
 
   public String getName() {
-   return logger.getName();
+    return logger.getName();
   }
 
   /**
    * Is this logger instance enabled for the TRACE level?
-   *
-   * @return True if this Logger is enabled for level TRACE, false
-   * otherwise.
+   * 
+   * @return True if this Logger is enabled for level TRACE, false otherwise.
    */
   public boolean isTraceEnabled() {
-    return logger.isTraceEnabled();
+    if (traceCapable) {
+      return logger.isTraceEnabled();
+    } else {
+      return logger.isDebugEnabled();
+    }
   }
 
-
   /**
    * Log a message object at level TRACE.
-   * @param msg - the message object to be logged
+   * 
+   * @param msg -
+   *                the message object to be logged
    */
   public void trace(String msg) {
-    logger.log(FQCN, Level.TRACE, msg, null);
+    logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, msg, null);
   }
 
   /**
    * Log a message at level TRACE according to the specified format and
    * argument.
-   *
-   * <p>This form avoids superfluous object creation when the logger
-   * is disabled for level TRACE. </p>
-   *
-   * @param format the format string
-   * @param arg  the argument
+   * 
+   * <p>
+   * This form avoids superfluous object creation when the logger is disabled
+   * for level TRACE.
+   * </p>
+   * 
+   * @param format
+   *                the format string
+   * @param arg
+   *                the argument
    */
   public void trace(String format, Object arg) {
     if (logger.isTraceEnabled()) {
       String msgStr = MessageFormatter.format(format, arg);
-      logger.log(FQCN, Level.TRACE, msgStr, null);
+      logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, msgStr, null);
     }
   }
 
   /**
    * Log a message at level TRACE according to the specified format and
    * arguments.
-   *
-   * <p>This form avoids superfluous object creation when the logger
-   * is disabled for the TRACE level. </p>
-   *
-   * @param format the format string
-   * @param arg1  the first argument
-   * @param arg2  the second argument
+   * 
+   * <p>
+   * This form avoids superfluous object creation when the logger is disabled
+   * for the TRACE level.
+   * </p>
+   * 
+   * @param format
+   *                the format string
+   * @param arg1
+   *                the first argument
+   * @param arg2
+   *                the second argument
    */
   public void trace(String format, Object arg1, Object arg2) {
     if (logger.isTraceEnabled()) {
       String msgStr = MessageFormatter.format(format, arg1, arg2);
-      logger.log(FQCN, Level.TRACE, msgStr, null);
+      logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, msgStr, null);
     }
   }
-  
+
   /**
    * Log a message at level TRACE according to the specified format and
    * arguments.
-   *
-   * <p>This form avoids superfluous object creation when the logger
-   * is disabled for the TRACE level. </p>
-   *
-   * @param format the format string
-   * @param argArray an array of arguments
+   * 
+   * <p>
+   * This form avoids superfluous object creation when the logger is disabled
+   * for the TRACE level.
+   * </p>
+   * 
+   * @param format
+   *                the format string
+   * @param argArray
+   *                an array of arguments
    */
   public void trace(String format, Object[] argArray) {
     if (logger.isTraceEnabled()) {
       String msgStr = MessageFormatter.arrayFormat(format, argArray);
-      logger.log(FQCN, Level.TRACE, msgStr, null);
+      logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, msgStr, null);
     }
   }
 
   /**
-   * Log an exception (throwable) at  level TRACE with an
-   * accompanying message.
-   *
-   * @param msg the message accompanying the exception
-   * @param t the exception (throwable) to log
+   * Log an exception (throwable) at level TRACE with an accompanying message.
+   * 
+   * @param msg
+   *                the message accompanying the exception
+   * @param t
+   *                the exception (throwable) to log
    */
   public void trace(String msg, Throwable t) {
-    logger.log(FQCN, Level.TRACE, msg, t);
+    logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, msg, t);
   }
 
-  
   /**
    * Is this logger instance enabled for the DEBUG level?
-   *
-   * @return True if this Logger is enabled for level DEBUG, false
-   * otherwise.
+   * 
+   * @return True if this Logger is enabled for level DEBUG, false otherwise.
    */
   public boolean isDebugEnabled() {
     return logger.isDebugEnabled();
   }
 
-
   /**
    * Log a message object at level DEBUG.
-   * @param msg - the message object to be logged
+   * 
+   * @param msg -
+   *                the message object to be logged
    */
   public void debug(String msg) {
     logger.log(FQCN, Level.DEBUG, msg, null);
@@ -176,12 +213,16 @@
   /**
    * Log a message at level DEBUG according to the specified format and
    * argument.
-   *
-   * <p>This form avoids superfluous object creation when the logger
-   * is disabled for level DEBUG. </p>
-   *
-   * @param format the format string
-   * @param arg  the argument
+   * 
+   * <p>
+   * This form avoids superfluous object creation when the logger is disabled
+   * for level DEBUG.
+   * </p>
+   * 
+   * @param format
+   *                the format string
+   * @param arg
+   *                the argument
    */
   public void debug(String format, Object arg) {
     if (logger.isDebugEnabled()) {
@@ -193,13 +234,18 @@
   /**
    * Log a message at level DEBUG according to the specified format and
    * arguments.
-   *
-   * <p>This form avoids superfluous object creation when the logger
-   * is disabled for the DEBUG level. </p>
-   *
-   * @param format the format string
-   * @param arg1  the first argument
-   * @param arg2  the second argument
+   * 
+   * <p>
+   * This form avoids superfluous object creation when the logger is disabled
+   * for the DEBUG level.
+   * </p>
+   * 
+   * @param format
+   *                the format string
+   * @param arg1
+   *                the first argument
+   * @param arg2
+   *                the second argument
    */
   public void debug(String format, Object arg1, Object arg2) {
     if (logger.isDebugEnabled()) {
@@ -207,16 +253,20 @@
       logger.log(FQCN, Level.DEBUG, msgStr, null);
     }
   }
-  
+
   /**
    * Log a message at level DEBUG according to the specified format and
    * arguments.
-   *
-   * <p>This form avoids superfluous object creation when the logger
-   * is disabled for the DEBUG level. </p>
-   *
-   * @param format the format string
-   * @param argArray an array of arguments
+   * 
+   * <p>
+   * This form avoids superfluous object creation when the logger is disabled
+   * for the DEBUG level.
+   * </p>
+   * 
+   * @param format
+   *                the format string
+   * @param argArray
+   *                an array of arguments
    */
   public void debug(String format, Object[] argArray) {
     if (logger.isDebugEnabled()) {
@@ -226,11 +276,12 @@
   }
 
   /**
-   * Log an exception (throwable) at  level DEBUG with an
-   * accompanying message.
-   *
-   * @param msg the message accompanying the exception
-   * @param t the exception (throwable) to log
+   * Log an exception (throwable) at level DEBUG with an accompanying message.
+   * 
+   * @param msg
+   *                the message accompanying the exception
+   * @param t
+   *                the exception (throwable) to log
    */
   public void debug(String msg, Throwable t) {
     logger.log(FQCN, Level.DEBUG, msg, t);
@@ -238,9 +289,8 @@
 
   /**
    * Is this logger instance enabled for the INFO level?
-   *
-   * @return True if this Logger is enabled for the INFO level, false
-   * otherwise.
+   * 
+   * @return True if this Logger is enabled for the INFO level, false otherwise.
    */
   public boolean isInfoEnabled() {
     return logger.isInfoEnabled();
@@ -248,22 +298,26 @@
 
   /**
    * Log a message object at the INFO level.
-   *
-   * @param msg - the message object to be logged
+   * 
+   * @param msg -
+   *                the message object to be logged
    */
   public void info(String msg) {
     logger.log(FQCN, Level.INFO, msg, null);
   }
 
   /**
-   * Log a message at level INFO according to the specified format and
-   * argument.
-   *
-   * <p>This form avoids superfluous object creation when the logger
-   * is disabled for the INFO level. </p>
-   *
-   * @param format the format string
-   * @param arg  the argument
+   * Log a message at level INFO according to the specified format and argument.
+   * 
+   * <p>
+   * This form avoids superfluous object creation when the logger is disabled
+   * for the INFO level.
+   * </p>
+   * 
+   * @param format
+   *                the format string
+   * @param arg
+   *                the argument
    */
   public void info(String format, Object arg) {
     if (logger.isInfoEnabled()) {
@@ -273,15 +327,20 @@
   }
 
   /**
-   * Log a message at the INFO level according to the specified format
-   * and arguments.
-   *
-   * <p>This form avoids superfluous object creation when the logger
-   * is disabled for the INFO level. </p>
-   *
-   * @param format the format string
-   * @param arg1  the first argument
-   * @param arg2  the second argument
+   * Log a message at the INFO level according to the specified format and
+   * arguments.
+   * 
+   * <p>
+   * This form avoids superfluous object creation when the logger is disabled
+   * for the INFO level.
+   * </p>
+   * 
+   * @param format
+   *                the format string
+   * @param arg1
+   *                the first argument
+   * @param arg2
+   *                the second argument
    */
   public void info(String format, Object arg1, Object arg2) {
     if (logger.isInfoEnabled()) {
@@ -293,12 +352,16 @@
   /**
    * Log a message at level INFO according to the specified format and
    * arguments.
-   *
-   * <p>This form avoids superfluous object creation when the logger
-   * is disabled for the INFO level. </p>
-   *
-   * @param format the format string
-   * @param argArray an array of arguments
+   * 
+   * <p>
+   * This form avoids superfluous object creation when the logger is disabled
+   * for the INFO level.
+   * </p>
+   * 
+   * @param format
+   *                the format string
+   * @param argArray
+   *                an array of arguments
    */
   public void info(String format, Object[] argArray) {
     if (logger.isInfoEnabled()) {
@@ -308,11 +371,13 @@
   }
 
   /**
-   * Log an exception (throwable) at the INFO level with an
-   * accompanying message.
-   *
-   * @param msg the message accompanying the exception
-   * @param t the exception (throwable) to log
+   * Log an exception (throwable) at the INFO level with an accompanying
+   * message.
+   * 
+   * @param msg
+   *                the message accompanying the exception
+   * @param t
+   *                the exception (throwable) to log
    */
   public void info(String msg, Throwable t) {
     logger.log(FQCN, Level.INFO, msg, t);
@@ -320,32 +385,36 @@
 
   /**
    * Is this logger instance enabled for the WARN level?
-   *
-   * @return True if this Logger is enabled for the WARN level,
-   * false otherwise.
+   * 
+   * @return True if this Logger is enabled for the WARN level, false otherwise.
    */
   public boolean isWarnEnabled() {
     return logger.isEnabledFor(Level.WARN);
   }
-  
+
   /**
    * Log a message object at the WARN level.
-   *
-   * @param msg - the message object to be logged
+   * 
+   * @param msg -
+   *                the message object to be logged
    */
   public void warn(String msg) {
     logger.log(FQCN, Level.WARN, msg, null);
   }
 
   /**
-   * Log a message at the WARN level according to the specified
-   * format and argument.
-   *
-   * <p>This form avoids superfluous object creation when the logger
-   * is disabled for the WARN level. </p>
-   *
-   * @param format the format string
-   * @param arg  the argument
+   * Log a message at the WARN level according to the specified format and
+   * argument.
+   * 
+   * <p>
+   * This form avoids superfluous object creation when the logger is disabled
+   * for the WARN level.
+   * </p>
+   * 
+   * @param format
+   *                the format string
+   * @param arg
+   *                the argument
    */
   public void warn(String format, Object arg) {
     if (logger.isEnabledFor(Level.WARN)) {
@@ -355,15 +424,20 @@
   }
 
   /**
-   * Log a message at the WARN level according to the specified
-   * format and arguments.
-   *
-   * <p>This form avoids superfluous object creation when the logger
-   * is disabled for the WARN level. </p>
-   *
-   * @param format the format string
-   * @param arg1  the first argument
-   * @param arg2  the second argument
+   * Log a message at the WARN level according to the specified format and
+   * arguments.
+   * 
+   * <p>
+   * This form avoids superfluous object creation when the logger is disabled
+   * for the WARN level.
+   * </p>
+   * 
+   * @param format
+   *                the format string
+   * @param arg1
+   *                the first argument
+   * @param arg2
+   *                the second argument
    */
   public void warn(String format, Object arg1, Object arg2) {
     if (logger.isEnabledFor(Level.WARN)) {
@@ -375,12 +449,16 @@
   /**
    * Log a message at level WARN according to the specified format and
    * arguments.
-   *
-   * <p>This form avoids superfluous object creation when the logger
-   * is disabled for the WARN level. </p>
-   *
-   * @param format the format string
-   * @param argArray an array of arguments
+   * 
+   * <p>
+   * This form avoids superfluous object creation when the logger is disabled
+   * for the WARN level.
+   * </p>
+   * 
+   * @param format
+   *                the format string
+   * @param argArray
+   *                an array of arguments
    */
   public void warn(String format, Object[] argArray) {
     if (logger.isEnabledFor(Level.WARN)) {
@@ -389,13 +467,14 @@
     }
   }
 
-  
   /**
-   * Log an exception (throwable) at the WARN level with an
-   * accompanying message.
-   *
-   * @param msg the message accompanying the exception
-   * @param t the exception (throwable) to log
+   * Log an exception (throwable) at the WARN level with an accompanying
+   * message.
+   * 
+   * @param msg
+   *                the message accompanying the exception
+   * @param t
+   *                the exception (throwable) to log
    */
   public void warn(String msg, Throwable t) {
     logger.log(FQCN, Level.WARN, msg, t);
@@ -403,9 +482,8 @@
 
   /**
    * Is this logger instance enabled for level ERROR?
-   *
-   * @return True if this Logger is enabled for level ERROR, false
-   * otherwise.
+   * 
+   * @return True if this Logger is enabled for level ERROR, false otherwise.
    */
   public boolean isErrorEnabled() {
     return logger.isEnabledFor(Level.ERROR);
@@ -413,22 +491,27 @@
 
   /**
    * Log a message object at the ERROR level.
-   *
-   * @param msg - the message object to be logged
+   * 
+   * @param msg -
+   *                the message object to be logged
    */
   public void error(String msg) {
     logger.log(FQCN, Level.ERROR, msg, null);
   }
 
   /**
-   * Log a message at the ERROR level according to the specified
-   * format and argument.
-   *
-   * <p>This form avoids superfluous object creation when the logger
-   * is disabled for the ERROR level. </p>
-   *
-   * @param format the format string
-   * @param arg  the argument
+   * Log a message at the ERROR level according to the specified format and
+   * argument.
+   * 
+   * <p>
+   * This form avoids superfluous object creation when the logger is disabled
+   * for the ERROR level.
+   * </p>
+   * 
+   * @param format
+   *                the format string
+   * @param arg
+   *                the argument
    */
   public void error(String format, Object arg) {
     if (logger.isEnabledFor(Level.ERROR)) {
@@ -438,15 +521,20 @@
   }
 
   /**
-   * Log a message at the ERROR level according to the specified
-   * format and arguments.
-   *
-   * <p>This form avoids superfluous object creation when the logger
-   * is disabled for the ERROR level. </p>
-   *
-   * @param format the format string
-   * @param arg1  the first argument
-   * @param arg2  the second argument
+   * Log a message at the ERROR level according to the specified format and
+   * arguments.
+   * 
+   * <p>
+   * This form avoids superfluous object creation when the logger is disabled
+   * for the ERROR level.
+   * </p>
+   * 
+   * @param format
+   *                the format string
+   * @param arg1
+   *                the first argument
+   * @param arg2
+   *                the second argument
    */
   public void error(String format, Object arg1, Object arg2) {
     if (logger.isEnabledFor(Level.ERROR)) {
@@ -458,12 +546,16 @@
   /**
    * Log a message at level ERROR according to the specified format and
    * arguments.
-   *
-   * <p>This form avoids superfluous object creation when the logger
-   * is disabled for the ERROR level. </p>
-   *
-   * @param format the format string
-   * @param argArray an array of arguments
+   * 
+   * <p>
+   * This form avoids superfluous object creation when the logger is disabled
+   * for the ERROR level.
+   * </p>
+   * 
+   * @param format
+   *                the format string
+   * @param argArray
+   *                an array of arguments
    */
   public void error(String format, Object[] argArray) {
     if (logger.isEnabledFor(Level.ERROR)) {
@@ -472,39 +564,41 @@
     }
   }
 
-  
-  
   /**
-   * Log an exception (throwable) at the ERROR level with an
-   * accompanying message.
-   *
-   * @param msg the message accompanying the exception
-   * @param t the exception (throwable) to log
+   * Log an exception (throwable) at the ERROR level with an accompanying
+   * message.
+   * 
+   * @param msg
+   *                the message accompanying the exception
+   * @param t
+   *                the exception (throwable) to log
    */
   public void error(String msg, Throwable t) {
     logger.log(FQCN, Level.ERROR, msg, t);
   }
 
-  public void log(Marker marker, String callerFQCN, int level, String msg, Throwable t) {
+  public void log(Marker marker, String callerFQCN, int level, String msg,
+      Throwable t) {
     Level log4jLevel;
-    switch(level) {
-    case LocationAwareLogger.TRACE_INT: 
-      log4jLevel = Level.TRACE;
+    switch (level) {
+    case LocationAwareLogger.TRACE_INT:
+      log4jLevel = traceCapable ? Level.TRACE : Level.DEBUG;
       break;
-    case LocationAwareLogger.DEBUG_INT: 
+    case LocationAwareLogger.DEBUG_INT:
       log4jLevel = Level.DEBUG;
       break;
-    case LocationAwareLogger.INFO_INT: 
+    case LocationAwareLogger.INFO_INT:
       log4jLevel = Level.INFO;
       break;
-    case LocationAwareLogger.WARN_INT: 
+    case LocationAwareLogger.WARN_INT:
       log4jLevel = Level.WARN;
       break;
-    case LocationAwareLogger.ERROR_INT: 
+    case LocationAwareLogger.ERROR_INT:
       log4jLevel = Level.ERROR;
       break;
     default:
-      throw new IllegalStateException("Level number "+level+" is not recognized.");
+      throw new IllegalStateException("Level number " + level
+          + " is not recognized.");
     }
     logger.log(callerFQCN, log4jLevel, msg, t);
   }

Modified: slf4j/trunk/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
==============================================================================
--- slf4j/trunk/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticLoggerBinder.java	(original)
+++ slf4j/trunk/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticLoggerBinder.java	Tue May 27 18:23:12 2008
@@ -35,6 +35,7 @@
 import org.apache.log4j.Level;
 import org.slf4j.ILoggerFactory;
 import org.slf4j.LoggerFactory;
+import org.slf4j.helpers.Util;
 import org.slf4j.spi.LoggerFactoryBinder;
 
 /**
@@ -62,7 +63,7 @@
     try {
       Level level = Level.TRACE;
     } catch(NoSuchFieldError nsfe) {
-      throw new Error("This version of SLF4J requires log4j version 1.2.12 or later. See also http://www.slf4j.org/codes.html#log4j_version", nsfe);
+      Util.reportFailure("This version of SLF4J requires log4j version 1.2.12 or later. See also http://www.slf4j.org/codes.html#log4j_version");
     }
   }
   

Modified: slf4j/trunk/slf4j-log4j12/src/test/java/org/slf4j/InvocationTest.java
==============================================================================
--- slf4j/trunk/slf4j-log4j12/src/test/java/org/slf4j/InvocationTest.java	(original)
+++ slf4j/trunk/slf4j-log4j12/src/test/java/org/slf4j/InvocationTest.java	Tue May 27 18:23:12 2008
@@ -43,21 +43,28 @@
  */
 public class InvocationTest extends TestCase {
 
+  ListAppender listAppender = new ListAppender();
+  org.apache.log4j.Logger root;
   public InvocationTest(String arg0) {
     super(arg0);
   }
 
   protected void setUp() throws Exception {
     super.setUp();
+    root = org.apache.log4j.Logger.getRootLogger();
+    root.addAppender(listAppender);
+
   }
 
   protected void tearDown() throws Exception {
     super.tearDown();
+    root.getLoggerRepository().resetConfiguration();
   }
 
   public void test1() {
     Logger logger = LoggerFactory.getLogger("test1");
     logger.debug("Hello world.");
+    assertEquals(1, listAppender.list.size());
   }
 
   public void test2() {
@@ -67,6 +74,8 @@
     Exception e = new Exception("This is a test exception.");
     Logger logger = LoggerFactory.getLogger("test2");
 
+    logger.trace("Hello trace.");
+    
     logger.debug("Hello world 1.");
     logger.debug("Hello world {}", i1);
     logger.debug("val={} val={}", i1, i2);
@@ -81,10 +90,12 @@
     logger.error("Hello world 4.");
     logger.error("Hello world {}", new Integer(3));
     logger.error("Hello world 4.", e);
+    assertEquals(11, listAppender.list.size());
   }
 
   public void testNull() {
     Logger logger = LoggerFactory.getLogger("testNull");
+    logger.trace(null);
     logger.debug(null);
     logger.info(null);
     logger.warn(null);
@@ -95,11 +106,13 @@
     logger.info(null, e);
     logger.warn(null, e);
     logger.error(null, e);
+    assertEquals(8, listAppender.list.size());
   }
 
   public void testMarker() {
     Logger logger = LoggerFactory.getLogger("testMarker");
     Marker blue = MarkerFactory.getMarker("BLUE");
+    logger.trace(blue, "hello");
     logger.debug(blue, "hello");
     logger.info(blue, "hello");
     logger.warn(blue, "hello");
@@ -114,6 +127,7 @@
     logger.info(blue, "hello {} and {} ", "world", "universe");
     logger.warn(blue, "hello {} and {} ", "world", "universe");
     logger.error(blue, "hello {} and {} ", "world", "universe");
+    assertEquals(12, listAppender.list.size());
   }
 
   public void testMDC() {

Added: slf4j/trunk/slf4j-log4j12/src/test/java/org/slf4j/ListAppender.java
==============================================================================
--- (empty file)
+++ slf4j/trunk/slf4j-log4j12/src/test/java/org/slf4j/ListAppender.java	Tue May 27 18:23:12 2008
@@ -0,0 +1,24 @@
+package org.slf4j;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.spi.LoggingEvent;
+
+public class ListAppender extends AppenderSkeleton {
+
+  List list = new ArrayList();
+  
+  protected void append(LoggingEvent event) {
+    list.add(event);
+  }
+
+  public void close() {
+  }
+
+  public boolean requiresLayout() {
+    return false;
+  }
+
+}

Modified: slf4j/trunk/slf4j-site/src/site/pages/codes.html
==============================================================================
--- slf4j/trunk/slf4j-site/src/site/pages/codes.html	(original)
+++ slf4j/trunk/slf4j-site/src/site/pages/codes.html	Tue May 27 18:23:12 2008
@@ -125,6 +125,14 @@
     above.
     </p>
 
+    <p>However, as reported in <a
+    href="http://bugzilla.slf4j.org/show_bug.cgi?id=68">bug 68</a>, in
+    some environments it may be difficult to upgrade the log4j
+    version. To accomodate such circumstances, SLF4J's
+    <code>Log4jLoggerAdapter</code> will map the TRACE level as
+    DEBUG.</p>
+    
+
 
 </div>
 </body>

Modified: slf4j/trunk/slf4j-site/src/site/pages/news.html
==============================================================================
--- slf4j/trunk/slf4j-site/src/site/pages/news.html	(original)
+++ slf4j/trunk/slf4j-site/src/site/pages/news.html	Tue May 27 18:23:12 2008
@@ -33,11 +33,28 @@
 
   <h3>XXX, 2008 - Release of SLF4J 1.5.1</h3>
 
+  <p>Fixed <a href="http://bugzilla.slf4j.org/show_bug.cgi?id=68">bug
+  68</a> reported by Su Chuan and David Rauschenbach. SLF4J requires
+  log4j 1.2.12 or later. However, if an older version of log4j is
+  present (lacking the TRACE level), in order to avoid
+  NoSuchMethodError exceptions, the SLF4J's
+  <code>Log4jLoggerAdapter</code> will map the TRACE level as DEBUG.
+  </p>
 
   <p>The <a href="migrator.html">SLF4J Migrator</a> tool has been
   improved to support migration from JUL to SLF4J.
   </p>
 
+  <p>In <code>MarkerIgnoringBase</code> class, corrected mapping of
+  trace methods with markers to their equivalents without marker
+  data. Previously, the mapping was trace to debug. The incorrect
+  mapping affected only calls to the trace method with
+  markers. Interestingly enough, this bug was picked up by new unit
+  tests and has not been reported as a bug by our users.
+  </p>
+
+  
+
   <h3>February 26th, 2008 - Release of SLF4J 1.5.0</h3>
 
 



More information about the slf4j-dev mailing list