[slf4j-dev] [GIT] SLF4J: Simple Logging Facade for Java branch, bug70, created. v1.5.11-12-g3c0ab34

added by portage for gitosis-gentoo git-noreply at pixie.qos.ch
Fri Apr 9 13:04:23 CEST 2010


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "SLF4J: Simple Logging Facade for Java".

The branch, bug70 has been created
        at  3c0ab3466b6fa6e915974c72558d64c570734700 (commit)

- Log -----------------------------------------------------------------
http://git.qos.ch/gitweb/?p=slf4j.git;a=commit;h=3c0ab3466b6fa6e915974c72558d64c570734700
http://github.com/ceki/slf4j/commit/3c0ab3466b6fa6e915974c72558d64c570734700

commit 3c0ab3466b6fa6e915974c72558d64c570734700
Author: Ceki Gulcu <ceki at qos.ch>
Date:   Fri Apr 9 13:02:20 2010 +0200

    Fixing bug 70

diff --git a/slf4j-api/src/main/java/org/slf4j/helpers/FormattingTuple.java b/slf4j-api/src/main/java/org/slf4j/helpers/FormattingTuple.java
new file mode 100644
index 0000000..c202345
--- /dev/null
+++ b/slf4j-api/src/main/java/org/slf4j/helpers/FormattingTuple.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2004-2010 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.helpers;
+
+/**
+ * Holds the results of formatting done by {@link MessageFormatter}.
+ * 
+ * @author Joern Huxhorn
+ */
+public class FormattingTuple {
+  
+  
+  static public FormattingTuple NULL = new FormattingTuple(null);
+  
+  private String message;
+  private Throwable throwable;
+
+  public FormattingTuple(String message) {
+    this(message, null);
+  }
+
+  public FormattingTuple(String message, Throwable throwable) {
+    this.message = message;
+    this.throwable = throwable;
+  }
+
+  public String getMessage() {
+    return message;
+  }
+
+  public Throwable getThrowable() {
+    return throwable;
+  }
+
+}
diff --git a/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java b/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java
index 0f38864..e1c0bdf 100644
--- a/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java
+++ b/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java
@@ -64,13 +64,16 @@ import java.util.Map;
  * character should be escaped. There is no need to escape the '}' character.
  * For example,
  * 
- * <pre>MessageFormatter.format(&quot;Set \\{} is not equal to {}.&quot;, &quot;1,2&quot;);</pre>
+ * <pre>
+ * MessageFormatter.format(&quot;Set \\{} is not equal to {}.&quot;, &quot;1,2&quot;);
+ * </pre>
  * 
  * will return the string "Set {} is not equal to 1,2.".
  * 
  * <p>
  * The escaping behavior just described can be overridden by escaping the escape
  * character '\'. Calling
+ * 
  * <pre>
  * MessageFormatter.format(&quot;File name is C:\\\\{}.&quot;, &quot;file.zip&quot;);
  * </pre>
@@ -90,9 +93,10 @@ import java.util.Map;
  * {@link #arrayFormat(String, Object[])} methods for more details.
  * 
  * @author Ceki G&uuml;lc&uuml;
+ * @author Joern Huxhorn
  */
 final public class MessageFormatter {
-  static final char DELIM_START = '{';
+  static final char DELIM_START = '{'; 
   static final char DELIM_STOP = '}';
   static final String DELIM_STR = "{}";
   private static final char ESCAPE_CHAR = '\\';
@@ -116,7 +120,7 @@ final public class MessageFormatter {
    *          The argument to be substituted in place of the formatting anchor
    * @return The formatted message
    */
-  final public static String format(String messagePattern, Object arg) {
+  final public static FormattingTuple format(String messagePattern, Object arg) {
     return arrayFormat(messagePattern, new Object[] { arg });
   }
 
@@ -143,11 +147,23 @@ final public class MessageFormatter {
    *          anchor
    * @return The formatted message
    */
-  final public static String format(final String messagePattern, Object arg1,
+  final public static FormattingTuple format(final String messagePattern, Object arg1,
       Object arg2) {
     return arrayFormat(messagePattern, new Object[] { arg1, arg2 });
   }
 
+  static final Throwable getThrowableCandidate(Object[] argArray) {
+    if (argArray == null || argArray.length == 0) {
+      return null;
+    }
+    
+    final Object lastEntry = argArray[argArray.length - 1];
+    if(lastEntry instanceof Throwable) {
+      return (Throwable) lastEntry;
+    }
+    return null;
+  }
+  
   /**
    * Same principle as the {@link #format(String, Object)} and
    * {@link #format(String, Object, Object)} methods except that any number of
@@ -160,30 +176,36 @@ final public class MessageFormatter {
    *          anchors
    * @return The formatted message
    */
-  final public static String arrayFormat(final String messagePattern,
+  final public static FormattingTuple arrayFormat(final String messagePattern,
       final Object[] argArray) {
+
+    Throwable throwableCandidate = getThrowableCandidate(argArray);
+    
     if (messagePattern == null) {
-      return null;
+      return new FormattingTuple(null, throwableCandidate);
+
     }
     if (argArray == null) {
-      return messagePattern;
+      return new FormattingTuple(messagePattern);
     }
+    
     int i = 0;
     int j;
     StringBuffer sbuf = new StringBuffer(messagePattern.length() + 50);
 
-    for (int L = 0; L < argArray.length; L++) {
+    int L;
+    for (L = 0; L < argArray.length; L++) {
 
       j = messagePattern.indexOf(DELIM_STR, i);
 
       if (j == -1) {
         // no more variables
         if (i == 0) { // this is a simple string
-          return messagePattern;
+          return  new FormattingTuple(messagePattern, throwableCandidate);
         } else { // add the tail string which contains no variables and return
           // the result.
           sbuf.append(messagePattern.substring(i, messagePattern.length()));
-          return sbuf.toString();
+          return new FormattingTuple(sbuf.toString(), throwableCandidate);;
         }
       } else {
         if (isEscapedDelimeter(messagePattern, j)) {
@@ -210,7 +232,11 @@ final public class MessageFormatter {
     }
     // append the characters following the last {} pair.
     sbuf.append(messagePattern.substring(i, messagePattern.length()));
-    return sbuf.toString();
+    if (L < argArray.length - 1) {
+      return new FormattingTuple(sbuf.toString(), throwableCandidate);
+    } else {
+      return new FormattingTuple(sbuf.toString());
+    }
   }
 
   final static boolean isEscapedDelimeter(String messagePattern,
diff --git a/slf4j-api/src/test/java/org/slf4j/helpers/MessageFormatterPerfTest.java b/slf4j-api/src/test/java/org/slf4j/helpers/MessageFormatterPerfTest.java
index 3c6f236..41e7355 100644
--- a/slf4j-api/src/test/java/org/slf4j/helpers/MessageFormatterPerfTest.java
+++ b/slf4j-api/src/test/java/org/slf4j/helpers/MessageFormatterPerfTest.java
@@ -9,7 +9,7 @@ public class MessageFormatterPerfTest extends TestCase {
   Integer i1 = new Integer(1);
   static long RUN_LENGTH = 100000;
   static long REFERENCE_BIPS = 9000;
-  
+
   public MessageFormatterPerfTest(String name) {
     super(name);
   }
@@ -23,9 +23,9 @@ public class MessageFormatterPerfTest extends TestCase {
   public void XtestJDKFormatterPerf() {
     jdkMessageFormatter(RUN_LENGTH);
     double duration = jdkMessageFormatter(RUN_LENGTH);
-    System.out.println("jdk duration = "+duration+" nanos");
+    System.out.println("jdk duration = " + duration + " nanos");
   }
-  
+
   public void testSLF4JPerf() {
     slf4jMessageFormatter(RUN_LENGTH);
     double duration = slf4jMessageFormatter(RUN_LENGTH);
@@ -34,25 +34,27 @@ public class MessageFormatterPerfTest extends TestCase {
   }
 
   public double slf4jMessageFormatter(long len) {
-    String s = ""; 
+    String s = "";
     s += ""; // keep compiler happy
     long start = System.currentTimeMillis();
     for (int i = 0; i < len; i++) {
-      s = MessageFormatter.format("This is some rather short message {} ", i1);
+      s = MessageFormatter.format("This is some rather short message {} ", i1)
+          .getMessage();
     }
     long end = System.currentTimeMillis();
-    return (1.0*end - start);
-  }  
+    return (1.0 * end - start);
+  }
+
   public double jdkMessageFormatter(long len) {
-    String s = ""; 
+    String s = "";
     s += ""; // keep compiler happy
     long start = System.currentTimeMillis();
-    Object[] oa = new Object[] {i1};
+    Object[] oa = new Object[] { i1 };
     for (int i = 0; i < len; i++) {
       s = MessageFormat.format("This is some rather short message {0}", oa);
     }
     long end = System.currentTimeMillis();
-    return (1.0*end - start);
+    return (1.0 * end - start);
   }
 
 }
diff --git a/slf4j-api/src/test/java/org/slf4j/helpers/MessageFormatterTest.java b/slf4j-api/src/test/java/org/slf4j/helpers/MessageFormatterTest.java
index 829cd0f..0d3c587 100644
--- a/slf4j-api/src/test/java/org/slf4j/helpers/MessageFormatterTest.java
+++ b/slf4j-api/src/test/java/org/slf4j/helpers/MessageFormatterTest.java
@@ -47,121 +47,128 @@ public class MessageFormatterTest extends TestCase {
   Integer[] ia0 = new Integer[] { i1, i2, i3 };
   Integer[] ia1 = new Integer[] { new Integer(10), new Integer(20),
       new Integer(30) };
-  
+
   String result;
-  
-  
+
   public void testNull() {
-    result = MessageFormatter.format(null, i1);
+    result = MessageFormatter.format(null, i1).getMessage();
     assertEquals(null, result);
   }
 
   public void testNullParam() {
-    result = MessageFormatter.format("Value is {}.", null);
+    result = MessageFormatter.format("Value is {}.", null).getMessage();
     assertEquals("Value is null.", result);
 
-    result = MessageFormatter.format("Val1 is {}, val2 is {}.", null, null);
+    result = MessageFormatter.format("Val1 is {}, val2 is {}.", null, null)
+        .getMessage();
     assertEquals("Val1 is null, val2 is null.", result);
 
-    result = MessageFormatter.format("Val1 is {}, val2 is {}.", i1, null);
+    result = MessageFormatter.format("Val1 is {}, val2 is {}.", i1, null)
+        .getMessage();
     assertEquals("Val1 is 1, val2 is null.", result);
 
-    result = MessageFormatter.format("Val1 is {}, val2 is {}.", null, i2);
+    result = MessageFormatter.format("Val1 is {}, val2 is {}.", null, i2)
+        .getMessage();
     assertEquals("Val1 is null, val2 is 2.", result);
 
     result = MessageFormatter.arrayFormat("Val1 is {}, val2 is {}, val3 is {}",
-        new Integer[] { null, null, null });
+        new Integer[] { null, null, null }).getMessage();
     assertEquals("Val1 is null, val2 is null, val3 is null", result);
 
     result = MessageFormatter.arrayFormat("Val1 is {}, val2 is {}, val3 is {}",
-        new Integer[] { null, i2, i3 });
+        new Integer[] { null, i2, i3 }).getMessage();
     assertEquals("Val1 is null, val2 is 2, val3 is 3", result);
 
     result = MessageFormatter.arrayFormat("Val1 is {}, val2 is {}, val3 is {}",
-        new Integer[] { null, null, i3 });
+        new Integer[] { null, null, i3 }).getMessage();
     assertEquals("Val1 is null, val2 is null, val3 is 3", result);
   }
 
   public void testOneParameter() {
-    result = MessageFormatter.format("Value is {}.", i3);
+    result = MessageFormatter.format("Value is {}.", i3).getMessage();
     assertEquals("Value is 3.", result);
 
-    result = MessageFormatter.format("Value is {", i3);
+    result = MessageFormatter.format("Value is {", i3).getMessage();
     assertEquals("Value is {", result);
 
-    result = MessageFormatter.format("{} is larger than 2.", i3);
+    result = MessageFormatter.format("{} is larger than 2.", i3).getMessage();
     assertEquals("3 is larger than 2.", result);
 
-    result = MessageFormatter.format("No subst", i3);
+    result = MessageFormatter.format("No subst", i3).getMessage();
     assertEquals("No subst", result);
 
-    result = MessageFormatter.format("Incorrect {subst", i3);
+    result = MessageFormatter.format("Incorrect {subst", i3).getMessage();
     assertEquals("Incorrect {subst", result);
 
-    result = MessageFormatter.format("Value is {bla} {}", i3);
+    result = MessageFormatter.format("Value is {bla} {}", i3).getMessage();
     assertEquals("Value is {bla} 3", result);
 
-    result = MessageFormatter.format("Escaped \\{} subst", i3);
+    result = MessageFormatter.format("Escaped \\{} subst", i3).getMessage();
     assertEquals("Escaped {} subst", result);
 
-    result = MessageFormatter.format("{Escaped", i3);
+    result = MessageFormatter.format("{Escaped", i3).getMessage();
     assertEquals("{Escaped", result);
 
-    result = MessageFormatter.format("\\{}Escaped", i3);
+    result = MessageFormatter.format("\\{}Escaped", i3).getMessage();
     assertEquals("{}Escaped", result);
 
-    result = MessageFormatter.format("File name is {{}}.", "App folder.zip");
+    result = MessageFormatter.format("File name is {{}}.", "App folder.zip")
+        .getMessage();
     assertEquals("File name is {App folder.zip}.", result);
 
     // escaping the escape character
     result = MessageFormatter
-        .format("File name is C:\\\\{}.", "App folder.zip");
+        .format("File name is C:\\\\{}.", "App folder.zip").getMessage();
     assertEquals("File name is C:\\App folder.zip.", result);
   }
 
   public void testTwoParameters() {
-    result = MessageFormatter.format("Value {} is smaller than {}.", i1, i2);
+    result = MessageFormatter.format("Value {} is smaller than {}.", i1, i2)
+        .getMessage();
     assertEquals("Value 1 is smaller than 2.", result);
 
-    result = MessageFormatter.format("Value {} is smaller than {}", i1, i2);
+    result = MessageFormatter.format("Value {} is smaller than {}", i1, i2)
+        .getMessage();
     assertEquals("Value 1 is smaller than 2", result);
 
-    result = MessageFormatter.format("{}{}", i1, i2);
+    result = MessageFormatter.format("{}{}", i1, i2).getMessage();
     assertEquals("12", result);
 
-    result = MessageFormatter.format("Val1={}, Val2={", i1, i2);
+    result = MessageFormatter.format("Val1={}, Val2={", i1, i2).getMessage();
     assertEquals("Val1=1, Val2={", result);
 
-    result = MessageFormatter.format("Value {} is smaller than \\{}", i1, i2);
+    result = MessageFormatter.format("Value {} is smaller than \\{}", i1, i2)
+        .getMessage();
     assertEquals("Value 1 is smaller than {}", result);
 
     result = MessageFormatter.format("Value {} is smaller than \\{} tail", i1,
-        i2);
+        i2).getMessage();
     assertEquals("Value 1 is smaller than {} tail", result);
 
-    result = MessageFormatter.format("Value {} is smaller than \\{", i1, i2);
+    result = MessageFormatter.format("Value {} is smaller than \\{", i1, i2)
+        .getMessage();
     assertEquals("Value 1 is smaller than \\{", result);
 
-    result = MessageFormatter
-        .format("Value {} is smaller than {tail", i1, i2);
+    result = MessageFormatter.format("Value {} is smaller than {tail", i1, i2)
+        .getMessage();
     assertEquals("Value 1 is smaller than {tail", result);
 
-    result = MessageFormatter.format("Value \\{} is smaller than {}", i1, i2);
+    result = MessageFormatter.format("Value \\{} is smaller than {}", i1, i2)
+        .getMessage();
     assertEquals("Value {} is smaller than 1", result);
   }
 
-  
   public void testExceptionInToString() {
     Object o = new Object() {
       public String toString() {
         throw new IllegalStateException("a");
       }
     };
-    result = MessageFormatter.format("Troublesome object {}", o);
+    result = MessageFormatter.format("Troublesome object {}", o).getMessage();
     assertEquals("Troublesome object [FAILED toString()]", result);
-    
+
   }
-  
+
   public void testNullArray() {
     String msg0 = "msg0";
     String msg1 = "msg1 {}";
@@ -170,41 +177,45 @@ public class MessageFormatterTest extends TestCase {
 
     Object[] args = null;
 
-    result = MessageFormatter.arrayFormat(msg0, args);
+    result = MessageFormatter.arrayFormat(msg0, args).getMessage();
     assertEquals(msg0, result);
 
-    result = MessageFormatter.arrayFormat(msg1, args);
+    result = MessageFormatter.arrayFormat(msg1, args).getMessage();
     assertEquals(msg1, result);
 
-    result = MessageFormatter.arrayFormat(msg2, args);
+    result = MessageFormatter.arrayFormat(msg2, args).getMessage();
     assertEquals(msg2, result);
 
-    result = MessageFormatter.arrayFormat(msg3, args);
+    result = MessageFormatter.arrayFormat(msg3, args).getMessage();
     assertEquals(msg3, result);
   }
 
   // tests the case when the parameters are supplied in a single array
   public void testArrayFormat() {
     result = MessageFormatter.arrayFormat(
-        "Value {} is smaller than {} and {}.", ia0);
+        "Value {} is smaller than {} and {}.", ia0).getMessage();
     assertEquals("Value 1 is smaller than 2 and 3.", result);
 
-    result = MessageFormatter.arrayFormat("{}{}{}", ia0);
+    result = MessageFormatter.arrayFormat("{}{}{}", ia0).getMessage();
     assertEquals("123", result);
 
-    result = MessageFormatter.arrayFormat("Value {} is smaller than {}.", ia0);
+    result = MessageFormatter.arrayFormat("Value {} is smaller than {}.", ia0)
+        .getMessage();
     assertEquals("Value 1 is smaller than 2.", result);
 
-    result = MessageFormatter.arrayFormat("Value {} is smaller than {}", ia0);
+    result = MessageFormatter.arrayFormat("Value {} is smaller than {}", ia0)
+        .getMessage();
     assertEquals("Value 1 is smaller than 2", result);
 
-    result = MessageFormatter.arrayFormat("Val={}, {, Val={}", ia0);
+    result = MessageFormatter.arrayFormat("Val={}, {, Val={}", ia0)
+        .getMessage();
     assertEquals("Val=1, {, Val=2", result);
 
-    result = MessageFormatter.arrayFormat("Val={}, {, Val={}", ia0);
+    result = MessageFormatter.arrayFormat("Val={}, {, Val={}", ia0)
+        .getMessage();
     assertEquals("Val=1, {, Val=2", result);
 
-    result = MessageFormatter.arrayFormat("Val1={}, Val2={", ia0);
+    result = MessageFormatter.arrayFormat("Val1={}, Val2={", ia0).getMessage();
     assertEquals("Val1=1, Val2={", result);
   }
 
@@ -212,58 +223,60 @@ public class MessageFormatterTest extends TestCase {
     Integer p0 = i1;
     Integer[] p1 = new Integer[] { i2, i3 };
 
-    result = MessageFormatter.format("{}{}", p0, p1);
+    result = MessageFormatter.format("{}{}", p0, p1).getMessage();
     assertEquals("1[2, 3]", result);
 
     // Integer[]
-    result = MessageFormatter.arrayFormat("{}{}", new Object[] { "a", p1 });
+    result = MessageFormatter.arrayFormat("{}{}", new Object[] { "a", p1 })
+        .getMessage();
     assertEquals("a[2, 3]", result);
 
     // byte[]
-    result = MessageFormatter.arrayFormat("{}{}", new Object[] { "a",
-        new byte[] { 1, 2 } });
+    result = MessageFormatter.arrayFormat("{}{}",
+        new Object[] { "a", new byte[] { 1, 2 } }).getMessage();
     assertEquals("a[1, 2]", result);
 
     // int[]
-    result = MessageFormatter.arrayFormat("{}{}", new Object[] { "a",
-        new int[] { 1, 2 } });
+    result = MessageFormatter.arrayFormat("{}{}",
+        new Object[] { "a", new int[] { 1, 2 } }).getMessage();
     assertEquals("a[1, 2]", result);
 
     // float[]
-    result = MessageFormatter.arrayFormat("{}{}", new Object[] { "a",
-        new float[] { 1, 2 } });
+    result = MessageFormatter.arrayFormat("{}{}",
+        new Object[] { "a", new float[] { 1, 2 } }).getMessage();
     assertEquals("a[1.0, 2.0]", result);
 
     // double[]
-    result = MessageFormatter.arrayFormat("{}{}", new Object[] { "a",
-        new double[] { 1, 2 } });
+    result = MessageFormatter.arrayFormat("{}{}",
+        new Object[] { "a", new double[] { 1, 2 } }).getMessage();
     assertEquals("a[1.0, 2.0]", result);
 
   }
 
   public void testMultiDimensionalArrayValues() {
     Integer[][] multiIntegerA = new Integer[][] { ia0, ia1 };
-    result = MessageFormatter.arrayFormat("{}{}", new Object[] { "a",
-        multiIntegerA });
+    result = MessageFormatter.arrayFormat("{}{}",
+        new Object[] { "a", multiIntegerA }).getMessage();
     assertEquals("a[[1, 2, 3], [10, 20, 30]]", result);
 
     int[][] multiIntA = new int[][] { { 1, 2 }, { 10, 20 } };
     result = MessageFormatter.arrayFormat("{}{}",
-        new Object[] { "a", multiIntA });
+        new Object[] { "a", multiIntA }).getMessage();
     assertEquals("a[[1, 2], [10, 20]]", result);
 
     float[][] multiFloatA = new float[][] { { 1, 2 }, { 10, 20 } };
-    result = MessageFormatter.arrayFormat("{}{}", new Object[] { "a",
-        multiFloatA });
+    result = MessageFormatter.arrayFormat("{}{}",
+        new Object[] { "a", multiFloatA }).getMessage();
     assertEquals("a[[1.0, 2.0], [10.0, 20.0]]", result);
 
     Object[][] multiOA = new Object[][] { ia0, ia1 };
     result = MessageFormatter
-        .arrayFormat("{}{}", new Object[] { "a", multiOA });
+        .arrayFormat("{}{}", new Object[] { "a", multiOA }).getMessage();
     assertEquals("a[[1, 2, 3], [10, 20, 30]]", result);
 
     Object[][][] _3DOA = new Object[][][] { multiOA, multiOA };
-    result = MessageFormatter.arrayFormat("{}{}", new Object[] { "a", _3DOA });
+    result = MessageFormatter.arrayFormat("{}{}", new Object[] { "a", _3DOA })
+        .getMessage();
     assertEquals("a[[[1, 2, 3], [10, 20, 30]], [[1, 2, 3], [10, 20, 30]]]",
         result);
   }
@@ -272,15 +285,16 @@ public class MessageFormatterTest extends TestCase {
     {
       Object[] cyclicA = new Object[1];
       cyclicA[0] = cyclicA;
-      assertEquals("[[...]]", MessageFormatter.arrayFormat("{}", cyclicA));
+      assertEquals("[[...]]", MessageFormatter.arrayFormat("{}", cyclicA).getMessage());
     }
     {
       Object[] a = new Object[2];
       a[0] = i1;
-      Object[] c = new Object[] {i3, a};
-      Object[] b = new Object[] {i2, c};
+      Object[] c = new Object[] { i3, a };
+      Object[] b = new Object[] { i2, c };
       a[1] = b;
-      assertEquals("1[2, [3, [1, [...]]]]", MessageFormatter.arrayFormat("{}{}", a));
+      assertEquals("1[2, [3, [1, [...]]]]", MessageFormatter.arrayFormat(
+          "{}{}", a).getMessage());
     }
   }
 }
diff --git a/slf4j-ext/src/main/java/org/slf4j/ext/LoggerWrapper.java b/slf4j-ext/src/main/java/org/slf4j/ext/LoggerWrapper.java
index 75f8e65..b9fcd9f 100644
--- a/slf4j-ext/src/main/java/org/slf4j/ext/LoggerWrapper.java
+++ b/slf4j-ext/src/main/java/org/slf4j/ext/LoggerWrapper.java
@@ -74,7 +74,8 @@ public class LoggerWrapper implements Logger {
       return;
 
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg);
+      String formattedMessage = MessageFormatter.format(format, arg)
+          .getMessage();
       ((LocationAwareLogger) logger).log(null, fqcn,
           LocationAwareLogger.TRACE_INT, formattedMessage,
           new Object[] { arg }, null);
@@ -91,7 +92,8 @@ public class LoggerWrapper implements Logger {
       return;
 
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg1, arg2);
+      String formattedMessage = MessageFormatter.format(format, arg1, arg2)
+          .getMessage();
       ((LocationAwareLogger) logger).log(null, fqcn,
           LocationAwareLogger.TRACE_INT, formattedMessage, new Object[] { arg1,
               arg2 }, null);
@@ -108,7 +110,8 @@ public class LoggerWrapper implements Logger {
       return;
 
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.arrayFormat(format, argArray);
+      String formattedMessage = MessageFormatter.arrayFormat(format, argArray)
+          .getMessage();
       ((LocationAwareLogger) logger).log(null, fqcn,
           LocationAwareLogger.TRACE_INT, formattedMessage, argArray, null);
     } else {
@@ -152,7 +155,8 @@ public class LoggerWrapper implements Logger {
     if (!logger.isTraceEnabled())
       return;
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg);
+      String formattedMessage = MessageFormatter.format(format, arg)
+          .getMessage();
       ((LocationAwareLogger) logger).log(marker, fqcn,
           LocationAwareLogger.TRACE_INT, formattedMessage,
           new Object[] { arg }, null);
@@ -168,7 +172,8 @@ public class LoggerWrapper implements Logger {
     if (!logger.isTraceEnabled())
       return;
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg1, arg2);
+      String formattedMessage = MessageFormatter.format(format, arg1, arg2)
+          .getMessage();
       ((LocationAwareLogger) logger).log(marker, fqcn,
           LocationAwareLogger.TRACE_INT, formattedMessage, new Object[] { arg1,
               arg2 }, null);
@@ -184,7 +189,8 @@ public class LoggerWrapper implements Logger {
     if (!logger.isTraceEnabled())
       return;
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.arrayFormat(format, argArray);
+      String formattedMessage = MessageFormatter.arrayFormat(format, argArray)
+          .getMessage();
       ((LocationAwareLogger) logger).log(marker, fqcn,
           LocationAwareLogger.TRACE_INT, formattedMessage, argArray, null);
     } else {
@@ -243,7 +249,8 @@ public class LoggerWrapper implements Logger {
       return;
 
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg);
+      String formattedMessage = MessageFormatter.format(format, arg)
+          .getMessage();
       ((LocationAwareLogger) logger).log(null, fqcn,
           LocationAwareLogger.DEBUG_INT, formattedMessage,
           new Object[] { arg }, null);
@@ -260,7 +267,8 @@ public class LoggerWrapper implements Logger {
       return;
 
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg1, arg2);
+      String formattedMessage = MessageFormatter.format(format, arg1, arg2)
+          .getMessage();
       ((LocationAwareLogger) logger).log(null, fqcn,
           LocationAwareLogger.DEBUG_INT, formattedMessage, new Object[] { arg1,
               arg2 }, null);
@@ -277,7 +285,8 @@ public class LoggerWrapper implements Logger {
       return;
 
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.arrayFormat(format, argArray);
+      String formattedMessage = MessageFormatter.arrayFormat(format, argArray)
+          .getMessage();
       ((LocationAwareLogger) logger).log(null, fqcn,
           LocationAwareLogger.DEBUG_INT, formattedMessage, argArray, null);
     } else {
@@ -321,7 +330,8 @@ public class LoggerWrapper implements Logger {
     if (!logger.isDebugEnabled())
       return;
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg);
+      String formattedMessage = MessageFormatter.format(format, arg)
+          .getMessage();
       ((LocationAwareLogger) logger).log(marker, fqcn,
           LocationAwareLogger.DEBUG_INT, formattedMessage,
           new Object[] { arg }, null);
@@ -337,7 +347,8 @@ public class LoggerWrapper implements Logger {
     if (!logger.isDebugEnabled())
       return;
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg1, arg2);
+      String formattedMessage = MessageFormatter.format(format, arg1, arg2)
+          .getMessage();
       ((LocationAwareLogger) logger).log(marker, fqcn,
           LocationAwareLogger.DEBUG_INT, formattedMessage, new Object[] { arg1,
               arg2 }, null);
@@ -353,7 +364,8 @@ public class LoggerWrapper implements Logger {
     if (!logger.isDebugEnabled())
       return;
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.arrayFormat(format, argArray);
+      String formattedMessage = MessageFormatter.arrayFormat(format, argArray)
+          .getMessage();
       ((LocationAwareLogger) logger).log(marker, fqcn,
           LocationAwareLogger.DEBUG_INT, formattedMessage, argArray, null);
     } else {
@@ -412,7 +424,8 @@ public class LoggerWrapper implements Logger {
       return;
 
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg);
+      String formattedMessage = MessageFormatter.format(format, arg)
+          .getMessage();
       ((LocationAwareLogger) logger).log(null, fqcn,
           LocationAwareLogger.INFO_INT, formattedMessage, new Object[] { arg },
           null);
@@ -429,7 +442,8 @@ public class LoggerWrapper implements Logger {
       return;
 
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg1, arg2);
+      String formattedMessage = MessageFormatter.format(format, arg1, arg2)
+          .getMessage();
       ((LocationAwareLogger) logger).log(null, fqcn,
           LocationAwareLogger.INFO_INT, formattedMessage, new Object[] { arg1,
               arg2 }, null);
@@ -446,7 +460,8 @@ public class LoggerWrapper implements Logger {
       return;
 
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.arrayFormat(format, argArray);
+      String formattedMessage = MessageFormatter.arrayFormat(format, argArray)
+          .getMessage();
       ((LocationAwareLogger) logger).log(null, fqcn,
           LocationAwareLogger.INFO_INT, formattedMessage, argArray, null);
     } else {
@@ -490,7 +505,8 @@ public class LoggerWrapper implements Logger {
     if (!logger.isInfoEnabled())
       return;
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg);
+      String formattedMessage = MessageFormatter.format(format, arg)
+          .getMessage();
       ((LocationAwareLogger) logger).log(marker, fqcn,
           LocationAwareLogger.INFO_INT, formattedMessage, new Object[] { arg },
           null);
@@ -506,7 +522,8 @@ public class LoggerWrapper implements Logger {
     if (!logger.isInfoEnabled())
       return;
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg1, arg2);
+      String formattedMessage = MessageFormatter.format(format, arg1, arg2)
+          .getMessage();
       ((LocationAwareLogger) logger).log(marker, fqcn,
           LocationAwareLogger.INFO_INT, formattedMessage, new Object[] { arg1,
               arg2 }, null);
@@ -522,7 +539,8 @@ public class LoggerWrapper implements Logger {
     if (!logger.isInfoEnabled())
       return;
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.arrayFormat(format, argArray);
+      String formattedMessage = MessageFormatter.arrayFormat(format, argArray)
+          .getMessage();
       ((LocationAwareLogger) logger).log(marker, fqcn,
           LocationAwareLogger.INFO_INT, formattedMessage, argArray, null);
     } else {
@@ -578,7 +596,8 @@ public class LoggerWrapper implements Logger {
       return;
 
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg);
+      String formattedMessage = MessageFormatter.format(format, arg)
+          .getMessage();
       ((LocationAwareLogger) logger).log(null, fqcn,
           LocationAwareLogger.WARN_INT, formattedMessage, new Object[] { arg },
           null);
@@ -595,7 +614,8 @@ public class LoggerWrapper implements Logger {
       return;
 
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg1, arg2);
+      String formattedMessage = MessageFormatter.format(format, arg1, arg2)
+          .getMessage();
       ((LocationAwareLogger) logger).log(null, fqcn,
           LocationAwareLogger.WARN_INT, formattedMessage, new Object[] { arg1,
               arg2 }, null);
@@ -612,7 +632,8 @@ public class LoggerWrapper implements Logger {
       return;
 
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.arrayFormat(format, argArray);
+      String formattedMessage = MessageFormatter.arrayFormat(format, argArray)
+          .getMessage();
       ((LocationAwareLogger) logger).log(null, fqcn,
           LocationAwareLogger.WARN_INT, formattedMessage, argArray, null);
     } else {
@@ -656,7 +677,8 @@ public class LoggerWrapper implements Logger {
     if (!logger.isWarnEnabled())
       return;
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg);
+      String formattedMessage = MessageFormatter.format(format, arg)
+          .getMessage();
       ((LocationAwareLogger) logger).log(marker, fqcn,
           LocationAwareLogger.WARN_INT, formattedMessage, new Object[] { arg },
           null);
@@ -672,7 +694,8 @@ public class LoggerWrapper implements Logger {
     if (!logger.isWarnEnabled())
       return;
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg1, arg2);
+      String formattedMessage = MessageFormatter.format(format, arg1, arg2)
+          .getMessage();
       ((LocationAwareLogger) logger).log(marker, fqcn,
           LocationAwareLogger.WARN_INT, formattedMessage, new Object[] { arg1,
               arg2 }, null);
@@ -688,7 +711,8 @@ public class LoggerWrapper implements Logger {
     if (!logger.isWarnEnabled())
       return;
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.arrayFormat(format, argArray);
+      String formattedMessage = MessageFormatter.arrayFormat(format, argArray)
+          .getMessage();
       ((LocationAwareLogger) logger).log(marker, fqcn,
           LocationAwareLogger.WARN_INT, formattedMessage, argArray, null);
     } else {
@@ -747,7 +771,8 @@ public class LoggerWrapper implements Logger {
       return;
 
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg);
+      String formattedMessage = MessageFormatter.format(format, arg)
+          .getMessage();
       ((LocationAwareLogger) logger).log(null, fqcn,
           LocationAwareLogger.ERROR_INT, formattedMessage,
           new Object[] { arg }, null);
@@ -764,7 +789,8 @@ public class LoggerWrapper implements Logger {
       return;
 
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg1, arg2);
+      String formattedMessage = MessageFormatter.format(format, arg1, arg2)
+          .getMessage();
       ((LocationAwareLogger) logger).log(null, fqcn,
           LocationAwareLogger.ERROR_INT, formattedMessage, new Object[] { arg1,
               arg2 }, null);
@@ -781,7 +807,8 @@ public class LoggerWrapper implements Logger {
       return;
 
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.arrayFormat(format, argArray);
+      String formattedMessage = MessageFormatter.arrayFormat(format, argArray)
+          .getMessage();
       ((LocationAwareLogger) logger).log(null, fqcn,
           LocationAwareLogger.ERROR_INT, formattedMessage, argArray, null);
     } else {
@@ -825,7 +852,8 @@ public class LoggerWrapper implements Logger {
     if (!logger.isErrorEnabled())
       return;
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg);
+      String formattedMessage = MessageFormatter.format(format, arg)
+          .getMessage();
       ((LocationAwareLogger) logger).log(marker, fqcn,
           LocationAwareLogger.ERROR_INT, formattedMessage,
           new Object[] { arg }, null);
@@ -841,7 +869,8 @@ public class LoggerWrapper implements Logger {
     if (!logger.isErrorEnabled())
       return;
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.format(format, arg1, arg2);
+      String formattedMessage = MessageFormatter.format(format, arg1, arg2)
+          .getMessage();
       ((LocationAwareLogger) logger).log(marker, fqcn,
           LocationAwareLogger.ERROR_INT, formattedMessage, new Object[] { arg1,
               arg2 }, null);
@@ -857,7 +886,8 @@ public class LoggerWrapper implements Logger {
     if (!logger.isErrorEnabled())
       return;
     if (instanceofLAL) {
-      String formattedMessage = MessageFormatter.arrayFormat(format, argArray);
+      String formattedMessage = MessageFormatter.arrayFormat(format, argArray)
+          .getMessage();
       ((LocationAwareLogger) logger).log(marker, fqcn,
           LocationAwareLogger.ERROR_INT, formattedMessage, argArray, null);
     } else {
diff --git a/slf4j-ext/src/main/java/org/slf4j/ext/XLogger.java b/slf4j-ext/src/main/java/org/slf4j/ext/XLogger.java
index 93510b0..635ef25 100644
--- a/slf4j-ext/src/main/java/org/slf4j/ext/XLogger.java
+++ b/slf4j-ext/src/main/java/org/slf4j/ext/XLogger.java
@@ -3,6 +3,7 @@ package org.slf4j.ext;
 import org.slf4j.Logger;
 import org.slf4j.Marker;
 import org.slf4j.MarkerFactory;
+import org.slf4j.helpers.FormattingTuple;
 import org.slf4j.helpers.MessageFormatter;
 import org.slf4j.spi.LocationAwareLogger;
 
@@ -98,10 +99,9 @@ public class XLogger extends LoggerWrapper implements Logger {
       } else {
         messagePattern = buildMessagePattern(argArray.length);
       }
-      String formattedMessage = MessageFormatter.arrayFormat(messagePattern,
-          argArray);
+      FormattingTuple tp = MessageFormatter.arrayFormat(messagePattern, argArray);
       ((LocationAwareLogger) logger).log(ENTRY_MARKER, FQCN,
-          LocationAwareLogger.TRACE_INT, formattedMessage, argArray, null);
+          LocationAwareLogger.TRACE_INT, tp.getMessage(), argArray, tp.getThrowable());
     }
   }
 
@@ -123,10 +123,10 @@ public class XLogger extends LoggerWrapper implements Logger {
    */
   public void exit(Object result) {
     if (instanceofLAL && logger.isTraceEnabled(ENTRY_MARKER)) {
-      String formattedMessage = MessageFormatter.format(EXIT_MESSAGE_1, result);
+      FormattingTuple tp = MessageFormatter.format(EXIT_MESSAGE_1, result);
       ((LocationAwareLogger) logger).log(EXIT_MARKER, FQCN,
-          LocationAwareLogger.TRACE_INT, formattedMessage,
-          new Object[] { result }, null);
+          LocationAwareLogger.TRACE_INT, tp.getMessage(),
+          new Object[] { result }, tp.getThrowable());
     }
   }
 
diff --git a/slf4j-ext/src/main/java/org/slf4j/instrumentation/LogTransformer.java b/slf4j-ext/src/main/java/org/slf4j/instrumentation/LogTransformer.java
index db3761f..4f2fb4e 100644
--- a/slf4j-ext/src/main/java/org/slf4j/instrumentation/LogTransformer.java
+++ b/slf4j-ext/src/main/java/org/slf4j/instrumentation/LogTransformer.java
@@ -30,272 +30,271 @@ import org.slf4j.helpers.MessageFormatter;
  */
 public class LogTransformer implements ClassFileTransformer {
 
-	/**
-	 * Builder provides a flexible way of configuring some of many options on
-	 * the parent class instead of providing many constructors.
-	 * 
-	 * {@link http 
-	 * ://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.html}
-	 * 
-	 */
-	public static class Builder {
-
-		/**
-		 * Build and return the LogTransformer corresponding to the options set
-		 * in this Builder.
-		 * 
-		 * @return
-		 */
-		public LogTransformer build() {
-			if (verbose) {
-				System.err.println("Creating LogTransformer");
-			}
-			return new LogTransformer(this);
-		}
-
-		boolean addEntryExit;
-
-		/**
-		 * Should each method log entry (with parameters) and exit (with
-		 * parameters and returnvalue)?
-		 * 
-		 * @param b
-		 *            value of flag
-		 * @return
-		 */
-		public Builder addEntryExit(boolean b) {
-			addEntryExit = b;
-			return this;
-		}
-
-		boolean addVariableAssignment;
-
-		// private Builder addVariableAssignment(boolean b) {
-		// System.err.println("cannot currently log variable assignments.");
-		// addVariableAssignment = b;
-		// return this;
-		// }
-
-		boolean verbose;
-
-		/**
-		 * Should LogTransformer be verbose in what it does? This currently list
-		 * the names of the classes being processed.
-		 * 
-		 * @param b
-		 * @return
-		 */
-		public Builder verbose(boolean b) {
-			verbose = b;
-			return this;
-		}
-
-		String[] ignore = { "org/slf4j/", "ch/qos/logback/",
-				"org/apache/log4j/" };
-
-		public Builder ignore(String[] strings) {
-			this.ignore = strings;
-			return this;
-		}
-
-		private String level = "info";
-
-		public Builder level(String level) {
-			level = level.toLowerCase();
-			if (level.equals("info") || level.equals("debug")
-					|| level.equals("trace")) {
-				this.level = level;
-			} else {
-				if (verbose) {
-					System.err.println("level not info/debug/trace : " + level);
-				}
-			}
-			return this;
-		}
-	}
-
-	private String level;
-	private String levelEnabled;
-
-	private LogTransformer(Builder builder) {
-		String s = "WARNING: javassist not available on classpath for javaagent, log statements will not be added";
-		try {
-			if (Class.forName("javassist.ClassPool") == null) {
-				System.err.println(s);
-			}
-		} catch (ClassNotFoundException e) {
-			System.err.println(s);
-		}
-
-		this.addEntryExit = builder.addEntryExit;
-		// this.addVariableAssignment = builder.addVariableAssignment;
-		this.verbose = builder.verbose;
-		this.ignore = builder.ignore;
-		this.level = builder.level;
-		this.levelEnabled = "is" + builder.level.substring(0, 1).toUpperCase()
-				+ builder.level.substring(1) + "Enabled";
-	}
-
-	private boolean addEntryExit;
-	// private boolean addVariableAssignment;
-	private boolean verbose;
-	private String[] ignore;
-
-	public byte[] transform(ClassLoader loader, String className,
-			Class<?> clazz, ProtectionDomain domain, byte[] bytes) {
-
-		try {
-			return transform0(className, clazz, domain, bytes);
-		} catch (Exception e) {
-			System.err.println("Could not instrument " + className);
-			e.printStackTrace();
-			return bytes;
-		}
-	}
-
-	/**
-	 * transform0 sees if the className starts with any of the namespaces to
-	 * ignore, if so it is returned unchanged. Otherwise it is processed by
-	 * doClass(...)
-	 * 
-	 * @param className
-	 * @param clazz
-	 * @param domain
-	 * @param bytes
-	 * @return
-	 */
-
-	private byte[] transform0(String className, Class<?> clazz,
-			ProtectionDomain domain, byte[] bytes) {
-
-		try {
-			for (int i = 0; i < ignore.length; i++) {
-				if (className.startsWith(ignore[i])) {
-					return bytes;
-				}
-			}
-			String slf4jName = "org.slf4j.LoggerFactory";
-			try {
-				if (domain != null && domain.getClassLoader() != null) {
-					domain.getClassLoader().loadClass(slf4jName);
-				} else {
-					if (verbose) {
-						System.err
-								.println("Skipping "
-										+ className
-										+ " as it doesn't have a domain or a class loader.");
-					}
-					return bytes;
-				}
-			} catch (ClassNotFoundException e) {
-				if (verbose) {
-					System.err.println("Skipping " + className
-							+ " as slf4j is not available to it");
-				}
-				return bytes;
-			}
-			if (verbose) {
-				System.err.println("Processing " + className);
-			}
-			return doClass(className, clazz, bytes);
-		} catch (Throwable e) {
-			System.out.println("e = " + e);
-			return bytes;
-		}
-	}
-
-	private String loggerName;
-
-	/**
-	 * doClass() process a single class by first creates a class description
-	 * from the byte codes. If it is a class (i.e. not an interface) the methods
-	 * defined have bodies, and a static final logger object is added with the
-	 * name of this class as an argument, and each method then gets processed
-	 * with doMethod(...) to have logger calls added.
-	 * 
-	 * @param name
-	 *            class name (slashes separate, not dots)
-	 * @param clazz
-	 * @param b
-	 * @return
-	 */
-	private byte[] doClass(String name, Class<?> clazz, byte[] b) {
-		ClassPool pool = ClassPool.getDefault();
-		CtClass cl = null;
-		try {
-			cl = pool.makeClass(new ByteArrayInputStream(b));
-			if (cl.isInterface() == false) {
-
-				loggerName = "_____log";
-
-				// We have to declare the log variable.
-
-				String pattern1 = "private static org.slf4j.Logger {};";
-				String loggerDefinition = format(pattern1, loggerName);
-				CtField field = CtField.make(loggerDefinition, cl);
-
-				// and assign it the appropriate value.
-
-				String pattern2 = "org.slf4j.LoggerFactory.getLogger({}.class);";
-				String replace = name.replace('/', '.');
-				String getLogger = format(pattern2, replace);
-
-				cl.addField(field, getLogger);
-
-				// then check every behaviour (which includes methods). We are
-				// only
-				// interested in non-empty ones, as they have code.
-				// NOTE: This will be changed, as empty methods should be
-				// instrumented too.
-
-				CtBehavior[] methods = cl.getDeclaredBehaviors();
-				for (int i = 0; i < methods.length; i++) {
-					if (methods[i].isEmpty() == false) {
-						doMethod(methods[i]);
-					}
-				}
-				b = cl.toBytecode();
-			}
-		} catch (Exception e) {
-			System.err.println("Could not instrument " + name + ", " + e);
-			e.printStackTrace(System.err);
-		} finally {
-			if (cl != null) {
-				cl.detach();
-			}
-		}
-		return b;
-	}
-
-	/**
-	 * process a single method - this means add entry/exit logging if requested.
-	 * It is only called for methods with a body.
-	 * 
-	 * @param method
-	 *            method to work on
-	 * @throws NotFoundException
-	 * @throws CannotCompileException
-	 */
-	private void doMethod(CtBehavior method) throws NotFoundException,
-			CannotCompileException {
-
-		String signature = JavassistHelper.getSignature(method);
-		String returnValue = JavassistHelper.returnValue(method);
-
-		if (addEntryExit) {
-			String messagePattern = "if ({}.{}()) {}.{}(\">> {}\");";
-			Object[] arg1 = new Object[] { loggerName, levelEnabled,
-					loggerName, level, signature };
-			String before = MessageFormatter.arrayFormat(messagePattern, arg1);
-			// System.out.println(before);
-			method.insertBefore(before);
-
-			String messagePattern2 = "if ({}.{}()) {}.{}(\"<< {}{}\");";
-			Object[] arg2 = new Object[] { loggerName, levelEnabled,
-					loggerName, level, signature, returnValue };
-			String after = MessageFormatter.arrayFormat(messagePattern2, arg2);
-			// System.out.println(after);
-			method.insertAfter(after);
-		}
-	}
+  /**
+   * Builder provides a flexible way of configuring some of many options on the
+   * parent class instead of providing many constructors.
+   * 
+   * {@link http
+   * ://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.html}
+   * 
+   */
+  public static class Builder {
+
+    /**
+     * Build and return the LogTransformer corresponding to the options set in
+     * this Builder.
+     * 
+     * @return
+     */
+    public LogTransformer build() {
+      if (verbose) {
+        System.err.println("Creating LogTransformer");
+      }
+      return new LogTransformer(this);
+    }
+
+    boolean addEntryExit;
+
+    /**
+     * Should each method log entry (with parameters) and exit (with parameters
+     * and returnvalue)?
+     * 
+     * @param b
+     *          value of flag
+     * @return
+     */
+    public Builder addEntryExit(boolean b) {
+      addEntryExit = b;
+      return this;
+    }
+
+    boolean addVariableAssignment;
+
+    // private Builder addVariableAssignment(boolean b) {
+    // System.err.println("cannot currently log variable assignments.");
+    // addVariableAssignment = b;
+    // return this;
+    // }
+
+    boolean verbose;
+
+    /**
+     * Should LogTransformer be verbose in what it does? This currently list the
+     * names of the classes being processed.
+     * 
+     * @param b
+     * @return
+     */
+    public Builder verbose(boolean b) {
+      verbose = b;
+      return this;
+    }
+
+    String[] ignore = { "org/slf4j/", "ch/qos/logback/", "org/apache/log4j/" };
+
+    public Builder ignore(String[] strings) {
+      this.ignore = strings;
+      return this;
+    }
+
+    private String level = "info";
+
+    public Builder level(String level) {
+      level = level.toLowerCase();
+      if (level.equals("info") || level.equals("debug")
+          || level.equals("trace")) {
+        this.level = level;
+      } else {
+        if (verbose) {
+          System.err.println("level not info/debug/trace : " + level);
+        }
+      }
+      return this;
+    }
+  }
+
+  private String level;
+  private String levelEnabled;
+
+  private LogTransformer(Builder builder) {
+    String s = "WARNING: javassist not available on classpath for javaagent, log statements will not be added";
+    try {
+      if (Class.forName("javassist.ClassPool") == null) {
+        System.err.println(s);
+      }
+    } catch (ClassNotFoundException e) {
+      System.err.println(s);
+    }
+
+    this.addEntryExit = builder.addEntryExit;
+    // this.addVariableAssignment = builder.addVariableAssignment;
+    this.verbose = builder.verbose;
+    this.ignore = builder.ignore;
+    this.level = builder.level;
+    this.levelEnabled = "is" + builder.level.substring(0, 1).toUpperCase()
+        + builder.level.substring(1) + "Enabled";
+  }
+
+  private boolean addEntryExit;
+  // private boolean addVariableAssignment;
+  private boolean verbose;
+  private String[] ignore;
+
+  public byte[] transform(ClassLoader loader, String className, Class<?> clazz,
+      ProtectionDomain domain, byte[] bytes) {
+
+    try {
+      return transform0(className, clazz, domain, bytes);
+    } catch (Exception e) {
+      System.err.println("Could not instrument " + className);
+      e.printStackTrace();
+      return bytes;
+    }
+  }
+
+  /**
+   * transform0 sees if the className starts with any of the namespaces to
+   * ignore, if so it is returned unchanged. Otherwise it is processed by
+   * doClass(...)
+   * 
+   * @param className
+   * @param clazz
+   * @param domain
+   * @param bytes
+   * @return
+   */
+
+  private byte[] transform0(String className, Class<?> clazz,
+      ProtectionDomain domain, byte[] bytes) {
+
+    try {
+      for (int i = 0; i < ignore.length; i++) {
+        if (className.startsWith(ignore[i])) {
+          return bytes;
+        }
+      }
+      String slf4jName = "org.slf4j.LoggerFactory";
+      try {
+        if (domain != null && domain.getClassLoader() != null) {
+          domain.getClassLoader().loadClass(slf4jName);
+        } else {
+          if (verbose) {
+            System.err.println("Skipping " + className
+                + " as it doesn't have a domain or a class loader.");
+          }
+          return bytes;
+        }
+      } catch (ClassNotFoundException e) {
+        if (verbose) {
+          System.err.println("Skipping " + className
+              + " as slf4j is not available to it");
+        }
+        return bytes;
+      }
+      if (verbose) {
+        System.err.println("Processing " + className);
+      }
+      return doClass(className, clazz, bytes);
+    } catch (Throwable e) {
+      System.out.println("e = " + e);
+      return bytes;
+    }
+  }
+
+  private String loggerName;
+
+  /**
+   * doClass() process a single class by first creates a class description from
+   * the byte codes. If it is a class (i.e. not an interface) the methods
+   * defined have bodies, and a static final logger object is added with the
+   * name of this class as an argument, and each method then gets processed with
+   * doMethod(...) to have logger calls added.
+   * 
+   * @param name
+   *          class name (slashes separate, not dots)
+   * @param clazz
+   * @param b
+   * @return
+   */
+  private byte[] doClass(String name, Class<?> clazz, byte[] b) {
+    ClassPool pool = ClassPool.getDefault();
+    CtClass cl = null;
+    try {
+      cl = pool.makeClass(new ByteArrayInputStream(b));
+      if (cl.isInterface() == false) {
+
+        loggerName = "_____log";
+
+        // We have to declare the log variable.
+
+        String pattern1 = "private static org.slf4j.Logger {};";
+        String loggerDefinition = format(pattern1, loggerName).getMessage();
+        CtField field = CtField.make(loggerDefinition, cl);
+
+        // and assign it the appropriate value.
+
+        String pattern2 = "org.slf4j.LoggerFactory.getLogger({}.class);";
+        String replace = name.replace('/', '.');
+        String getLogger = format(pattern2, replace).getMessage();
+
+        cl.addField(field, getLogger);
+
+        // then check every behaviour (which includes methods). We are
+        // only
+        // interested in non-empty ones, as they have code.
+        // NOTE: This will be changed, as empty methods should be
+        // instrumented too.
+
+        CtBehavior[] methods = cl.getDeclaredBehaviors();
+        for (int i = 0; i < methods.length; i++) {
+          if (methods[i].isEmpty() == false) {
+            doMethod(methods[i]);
+          }
+        }
+        b = cl.toBytecode();
+      }
+    } catch (Exception e) {
+      System.err.println("Could not instrument " + name + ", " + e);
+      e.printStackTrace(System.err);
+    } finally {
+      if (cl != null) {
+        cl.detach();
+      }
+    }
+    return b;
+  }
+
+  /**
+   * process a single method - this means add entry/exit logging if requested.
+   * It is only called for methods with a body.
+   * 
+   * @param method
+   *          method to work on
+   * @throws NotFoundException
+   * @throws CannotCompileException
+   */
+  private void doMethod(CtBehavior method) throws NotFoundException,
+      CannotCompileException {
+
+    String signature = JavassistHelper.getSignature(method);
+    String returnValue = JavassistHelper.returnValue(method);
+
+    if (addEntryExit) {
+      String messagePattern = "if ({}.{}()) {}.{}(\">> {}\");";
+      Object[] arg1 = new Object[] { loggerName, levelEnabled, loggerName,
+          level, signature };
+      String before = MessageFormatter.arrayFormat(messagePattern, arg1)
+          .getMessage();
+      // System.out.println(before);
+      method.insertBefore(before);
+
+      String messagePattern2 = "if ({}.{}()) {}.{}(\"<< {}{}\");";
+      Object[] arg2 = new Object[] { loggerName, levelEnabled, loggerName,
+          level, signature, returnValue };
+      String after = MessageFormatter.arrayFormat(messagePattern2, arg2)
+          .getMessage();
+      // System.out.println(after);
+      method.insertAfter(after);
+    }
+  }
 }
\ No newline at end of file
diff --git a/slf4j-jcl/src/main/java/org/slf4j/impl/JCLLoggerAdapter.java b/slf4j-jcl/src/main/java/org/slf4j/impl/JCLLoggerAdapter.java
index 9cb2a5e..31c57e0 100644
--- a/slf4j-jcl/src/main/java/org/slf4j/impl/JCLLoggerAdapter.java
+++ b/slf4j-jcl/src/main/java/org/slf4j/impl/JCLLoggerAdapter.java
@@ -27,6 +27,7 @@ package org.slf4j.impl;
 
 import org.apache.commons.logging.Log;
 import org.slf4j.Logger;
+import org.slf4j.helpers.FormattingTuple;
 import org.slf4j.helpers.MarkerIgnoringBase;
 import org.slf4j.helpers.MessageFormatter;
 
@@ -85,8 +86,8 @@ public final class JCLLoggerAdapter extends MarkerIgnoringBase {
    */
   public void trace(String format, Object arg) {
     if (log.isDebugEnabled()) {
-      String msgStr = MessageFormatter.format(format, arg);
-      log.trace(msgStr);
+      FormattingTuple ft = MessageFormatter.format(format, arg);
+      log.trace(ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -108,8 +109,8 @@ public final class JCLLoggerAdapter extends MarkerIgnoringBase {
    */
   public void trace(String format, Object arg1, Object arg2) {
     if (log.isDebugEnabled()) {
-      String msgStr = MessageFormatter.format(format, arg1, arg2);
-      log.trace(msgStr);
+      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+      log.trace(ft.getMessage(), ft.getThrowable());
     }
   }
   
@@ -128,8 +129,8 @@ public final class JCLLoggerAdapter extends MarkerIgnoringBase {
    */
   public void trace(String format, Object[] argArray) {
     if (log.isDebugEnabled()) {
-      String msgStr = MessageFormatter.arrayFormat(format, argArray);
-      log.trace(msgStr);
+      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+      log.trace(ft.getMessage(), ft.getThrowable());
     }
   }
   
@@ -183,8 +184,8 @@ public final class JCLLoggerAdapter extends MarkerIgnoringBase {
    */
   public void debug(String format, Object arg) {
     if (log.isDebugEnabled()) {
-      String msgStr = MessageFormatter.format(format, arg);
-      log.debug(msgStr);
+      FormattingTuple ft = MessageFormatter.format(format, arg);
+      log.debug(ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -206,8 +207,8 @@ public final class JCLLoggerAdapter extends MarkerIgnoringBase {
    */
   public void debug(String format, Object arg1, Object arg2) {
     if (log.isDebugEnabled()) {
-      String msgStr = MessageFormatter.format(format, arg1, arg2);
-      log.debug(msgStr);
+      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+      log.debug(ft.getMessage(), ft.getThrowable());
     }
   }
   
@@ -226,8 +227,8 @@ public final class JCLLoggerAdapter extends MarkerIgnoringBase {
    */
   public void debug(String format, Object[] argArray) {
     if (log.isDebugEnabled()) {
-      String msgStr = MessageFormatter.arrayFormat(format, argArray);
-      log.debug(msgStr);
+      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+      log.debug(ft.getMessage(), ft.getThrowable());
     }
   }
   
@@ -279,8 +280,8 @@ public final class JCLLoggerAdapter extends MarkerIgnoringBase {
 
   public void info(String format, Object arg) {
     if (log.isInfoEnabled()) {
-      String msgStr = MessageFormatter.format(format, arg);
-      log.info(msgStr);
+      FormattingTuple ft = MessageFormatter.format(format, arg);
+      log.info(ft.getMessage(), ft.getThrowable());
     }
   }
   /**
@@ -301,8 +302,9 @@ public final class JCLLoggerAdapter extends MarkerIgnoringBase {
    */
   public void info(String format, Object arg1, Object arg2) {
     if (log.isInfoEnabled()) {
-      String msgStr = MessageFormatter.format(format, arg1, arg2);
-      log.info(msgStr);
+
+      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+      log.info(ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -320,8 +322,8 @@ public final class JCLLoggerAdapter extends MarkerIgnoringBase {
    */
   public void info(String format, Object[] argArray) {
     if (log.isInfoEnabled()) {
-      String msgStr = MessageFormatter.arrayFormat(format, argArray);
-      log.info(msgStr);
+      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+      log.info(ft.getMessage(), ft.getThrowable());
     }
   }
   
@@ -373,8 +375,8 @@ public final class JCLLoggerAdapter extends MarkerIgnoringBase {
    */
   public void warn(String format, Object arg) {
     if (log.isWarnEnabled()) {
-      String msgStr = MessageFormatter.format(format, arg);
-      log.warn(msgStr);
+      FormattingTuple ft = MessageFormatter.format(format, arg);
+      log.warn(ft.getMessage(), ft.getThrowable());
     }
   }
   
@@ -396,8 +398,8 @@ public final class JCLLoggerAdapter extends MarkerIgnoringBase {
    */
   public void warn(String format, Object arg1, Object arg2) {
     if (log.isWarnEnabled()) {
-      String msgStr = MessageFormatter.format(format, arg1, arg2);
-      log.warn(msgStr);
+      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+      log.warn(ft.getMessage(), ft.getThrowable());
     }
   }
   
@@ -415,8 +417,8 @@ public final class JCLLoggerAdapter extends MarkerIgnoringBase {
    */
   public void warn(String format, Object[] argArray) {
     if (log.isWarnEnabled()) {
-      String msgStr = MessageFormatter.arrayFormat(format, argArray);
-      log.warn(msgStr);
+      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+      log.warn(ft.getMessage(), ft.getThrowable());
     }
   }
   
@@ -470,8 +472,8 @@ public final class JCLLoggerAdapter extends MarkerIgnoringBase {
    */
   public void error(String format, Object arg) {
     if (log.isErrorEnabled()) {
-      String msgStr = MessageFormatter.format(format, arg);
-      log.error(msgStr);
+      FormattingTuple ft = MessageFormatter.format(format, arg);
+      log.error(ft.getMessage(), ft.getThrowable());
     }
   }
   
@@ -493,8 +495,8 @@ public final class JCLLoggerAdapter extends MarkerIgnoringBase {
    */
   public void error(String format, Object arg1, Object arg2) {
     if (log.isErrorEnabled()) {
-      String msgStr = MessageFormatter.format(format, arg1, arg2);
-      log.error(msgStr);
+      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+      log.error(ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -512,8 +514,8 @@ public final class JCLLoggerAdapter extends MarkerIgnoringBase {
    */
   public void error(String format, Object[] argArray) {
     if (log.isErrorEnabled()) {
-      String msgStr = MessageFormatter.arrayFormat(format, argArray);
-      log.error(msgStr);
+      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+      log.error(ft.getMessage(), ft.getThrowable());
     }
   }
   
diff --git a/slf4j-jdk14/src/main/java/org/slf4j/impl/JDK14LoggerAdapter.java b/slf4j-jdk14/src/main/java/org/slf4j/impl/JDK14LoggerAdapter.java
index 55a8d5e..1c9b0cc 100644
--- a/slf4j-jdk14/src/main/java/org/slf4j/impl/JDK14LoggerAdapter.java
+++ b/slf4j-jdk14/src/main/java/org/slf4j/impl/JDK14LoggerAdapter.java
@@ -38,6 +38,7 @@ import java.util.logging.LogRecord;
 
 import org.slf4j.Logger;
 import org.slf4j.Marker;
+import org.slf4j.helpers.FormattingTuple;
 import org.slf4j.helpers.MarkerIgnoringBase;
 import org.slf4j.helpers.MessageFormatter;
 import org.slf4j.spi.LocationAwareLogger;
@@ -102,8 +103,8 @@ public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements
    */
   public void trace(String format, Object arg) {
     if (logger.isLoggable(Level.FINEST)) {
-      String msgStr = MessageFormatter.format(format, arg);
-      log(SELF, Level.FINEST, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg);
+      log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -125,8 +126,8 @@ public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements
    */
   public void trace(String format, Object arg1, Object arg2) {
     if (logger.isLoggable(Level.FINEST)) {
-      String msgStr = MessageFormatter.format(format, arg1, arg2);
-      log(SELF, Level.FINEST, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+      log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -146,8 +147,8 @@ public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements
    */
   public void trace(String format, Object[] argArray) {
     if (logger.isLoggable(Level.FINEST)) {
-      String msgStr = MessageFormatter.arrayFormat(format, argArray);
-      log(SELF, Level.FINEST, msgStr, null);
+      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+      log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -201,8 +202,8 @@ public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements
    */
   public void debug(String format, Object arg) {
     if (logger.isLoggable(Level.FINE)) {
-      String msgStr = MessageFormatter.format(format, arg);
-      log(SELF, Level.FINE, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg);
+      log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -224,8 +225,8 @@ public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements
    */
   public void debug(String format, Object arg1, Object arg2) {
     if (logger.isLoggable(Level.FINE)) {
-      String msgStr = MessageFormatter.format(format, arg1, arg2);
-      log(SELF, Level.FINE, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+      log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -245,8 +246,8 @@ public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements
    */
   public void debug(String format, Object[] argArray) {
     if (logger.isLoggable(Level.FINE)) {
-      String msgStr = MessageFormatter.arrayFormat(format, argArray);
-      log(SELF, Level.FINE, msgStr, null);
+      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+      log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -300,8 +301,8 @@ public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements
    */
   public void info(String format, Object arg) {
     if (logger.isLoggable(Level.INFO)) {
-      String msgStr = MessageFormatter.format(format, arg);
-      log(SELF, Level.INFO, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg);
+      log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -323,8 +324,8 @@ public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements
    */
   public void info(String format, Object arg1, Object arg2) {
     if (logger.isLoggable(Level.INFO)) {
-      String msgStr = MessageFormatter.format(format, arg1, arg2);
-      log(SELF, Level.INFO, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+      log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -344,8 +345,8 @@ public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements
    */
   public void info(String format, Object[] argArray) {
     if (logger.isLoggable(Level.INFO)) {
-      String msgStr = MessageFormatter.arrayFormat(format, argArray);
-      log(SELF, Level.INFO, msgStr, null);
+      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+      log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -402,8 +403,8 @@ public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements
    */
   public void warn(String format, Object arg) {
     if (logger.isLoggable(Level.WARNING)) {
-      String msgStr = MessageFormatter.format(format, arg);
-      log(SELF, Level.WARNING, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg);
+      log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -425,8 +426,8 @@ public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements
    */
   public void warn(String format, Object arg1, Object arg2) {
     if (logger.isLoggable(Level.WARNING)) {
-      String msgStr = MessageFormatter.format(format, arg1, arg2);
-      log(SELF, Level.WARNING, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+      log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -446,8 +447,8 @@ public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements
    */
   public void warn(String format, Object[] argArray) {
     if (logger.isLoggable(Level.WARNING)) {
-      String msgStr = MessageFormatter.arrayFormat(format, argArray);
-      log(SELF, Level.WARNING, msgStr, null);
+      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+      log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -503,8 +504,8 @@ public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements
    */
   public void error(String format, Object arg) {
     if (logger.isLoggable(Level.SEVERE)) {
-      String msgStr = MessageFormatter.format(format, arg);
-      log(SELF, Level.SEVERE, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg);
+      log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -526,8 +527,8 @@ public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements
    */
   public void error(String format, Object arg1, Object arg2) {
     if (logger.isLoggable(Level.SEVERE)) {
-      String msgStr = MessageFormatter.format(format, arg1, arg2);
-      log(SELF, Level.SEVERE, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+      log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -547,8 +548,8 @@ public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements
    */
   public void error(String format, Object[] argArray) {
     if (logger.isLoggable(Level.SEVERE)) {
-      String msgStr = MessageFormatter.arrayFormat(format, argArray);
-      log(SELF, Level.SEVERE, msgStr, null);
+      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+      log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable());
     }
   }
 
diff --git a/slf4j-log4j12/src/main/java/org/slf4j/impl/Log4jLoggerAdapter.java b/slf4j-log4j12/src/main/java/org/slf4j/impl/Log4jLoggerAdapter.java
index bfe6444..51cecb4 100644
--- a/slf4j-log4j12/src/main/java/org/slf4j/impl/Log4jLoggerAdapter.java
+++ b/slf4j-log4j12/src/main/java/org/slf4j/impl/Log4jLoggerAdapter.java
@@ -29,6 +29,7 @@ import java.io.Serializable;
 import org.apache.log4j.Level;
 import org.slf4j.Logger;
 import org.slf4j.Marker;
+import org.slf4j.helpers.FormattingTuple;
 import org.slf4j.helpers.MarkerIgnoringBase;
 import org.slf4j.helpers.MessageFormatter;
 import org.slf4j.spi.LocationAwareLogger;
@@ -125,8 +126,9 @@ public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
    */
   public void trace(String format, Object arg) {
     if (isTraceEnabled()) {
-      String msgStr = MessageFormatter.format(format, arg);
-      logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg);
+      logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, ft
+          .getMessage(), ft.getThrowable());
     }
   }
 
@@ -148,8 +150,9 @@ public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
    */
   public void trace(String format, Object arg1, Object arg2) {
     if (isTraceEnabled()) {
-      String msgStr = MessageFormatter.format(format, arg1, arg2);
-      logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+      logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, ft
+          .getMessage(), ft.getThrowable());
     }
   }
 
@@ -169,8 +172,9 @@ public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
    */
   public void trace(String format, Object[] argArray) {
     if (isTraceEnabled()) {
-      String msgStr = MessageFormatter.arrayFormat(format, argArray);
-      logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, msgStr, null);
+      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+      logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, ft
+          .getMessage(), ft.getThrowable());
     }
   }
 
@@ -221,8 +225,8 @@ public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
    */
   public void debug(String format, Object arg) {
     if (logger.isDebugEnabled()) {
-      String msgStr = MessageFormatter.format(format, arg);
-      logger.log(FQCN, Level.DEBUG, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg);
+      logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -244,8 +248,8 @@ public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
    */
   public void debug(String format, Object arg1, Object arg2) {
     if (logger.isDebugEnabled()) {
-      String msgStr = MessageFormatter.format(format, arg1, arg2);
-      logger.log(FQCN, Level.DEBUG, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+      logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -265,8 +269,8 @@ public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
    */
   public void debug(String format, Object[] argArray) {
     if (logger.isDebugEnabled()) {
-      String msgStr = MessageFormatter.arrayFormat(format, argArray);
-      logger.log(FQCN, Level.DEBUG, msgStr, null);
+      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+      logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -316,8 +320,8 @@ public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
    */
   public void info(String format, Object arg) {
     if (logger.isInfoEnabled()) {
-      String msgStr = MessageFormatter.format(format, arg);
-      logger.log(FQCN, Level.INFO, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg);
+      logger.log(FQCN, Level.INFO, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -339,8 +343,8 @@ public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
    */
   public void info(String format, Object arg1, Object arg2) {
     if (logger.isInfoEnabled()) {
-      String msgStr = MessageFormatter.format(format, arg1, arg2);
-      logger.log(FQCN, Level.INFO, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+      logger.log(FQCN, Level.INFO, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -360,8 +364,8 @@ public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
    */
   public void info(String format, Object[] argArray) {
     if (logger.isInfoEnabled()) {
-      String msgStr = MessageFormatter.arrayFormat(format, argArray);
-      logger.log(FQCN, Level.INFO, msgStr, null);
+      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+      logger.log(FQCN, Level.INFO, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -413,8 +417,8 @@ public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
    */
   public void warn(String format, Object arg) {
     if (logger.isEnabledFor(Level.WARN)) {
-      String msgStr = MessageFormatter.format(format, arg);
-      logger.log(FQCN, Level.WARN, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg);
+      logger.log(FQCN, Level.WARN, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -436,8 +440,8 @@ public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
    */
   public void warn(String format, Object arg1, Object arg2) {
     if (logger.isEnabledFor(Level.WARN)) {
-      String msgStr = MessageFormatter.format(format, arg1, arg2);
-      logger.log(FQCN, Level.WARN, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+      logger.log(FQCN, Level.WARN, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -457,8 +461,8 @@ public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
    */
   public void warn(String format, Object[] argArray) {
     if (logger.isEnabledFor(Level.WARN)) {
-      String msgStr = MessageFormatter.arrayFormat(format, argArray);
-      logger.log(FQCN, Level.WARN, msgStr, null);
+      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+      logger.log(FQCN, Level.WARN, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -510,8 +514,8 @@ public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
    */
   public void error(String format, Object arg) {
     if (logger.isEnabledFor(Level.ERROR)) {
-      String msgStr = MessageFormatter.format(format, arg);
-      logger.log(FQCN, Level.ERROR, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg);
+      logger.log(FQCN, Level.ERROR, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -533,8 +537,8 @@ public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
    */
   public void error(String format, Object arg1, Object arg2) {
     if (logger.isEnabledFor(Level.ERROR)) {
-      String msgStr = MessageFormatter.format(format, arg1, arg2);
-      logger.log(FQCN, Level.ERROR, msgStr, null);
+      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+      logger.log(FQCN, Level.ERROR, ft.getMessage(), ft.getThrowable());
     }
   }
 
@@ -554,8 +558,8 @@ public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
    */
   public void error(String format, Object[] argArray) {
     if (logger.isEnabledFor(Level.ERROR)) {
-      String msgStr = MessageFormatter.arrayFormat(format, argArray);
-      logger.log(FQCN, Level.ERROR, msgStr, null);
+      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+      logger.log(FQCN, Level.ERROR, ft.getMessage(), ft.getThrowable());
     }
   }
 
diff --git a/slf4j-simple/src/main/java/org/slf4j/impl/SimpleLogger.java b/slf4j-simple/src/main/java/org/slf4j/impl/SimpleLogger.java
index 810d02c..cf33b35 100644
--- a/slf4j-simple/src/main/java/org/slf4j/impl/SimpleLogger.java
+++ b/slf4j-simple/src/main/java/org/slf4j/impl/SimpleLogger.java
@@ -33,18 +33,19 @@
 
 package org.slf4j.impl;
 
+import org.slf4j.helpers.FormattingTuple;
 import org.slf4j.helpers.MarkerIgnoringBase;
 import org.slf4j.helpers.MessageFormatter;
 
 /**
- * A simple (and direct) implementation that logs messages of level
- * INFO or higher on the console (<code>System.err<code>).
- *
+ * A simple (and direct) implementation that logs messages of level INFO or
+ * higher on the console (<code>System.err<code>).
+ * 
  * <p>The 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.
@@ -58,19 +59,19 @@ import org.slf4j.helpers.MessageFormatter;
         at org.log4j.examples.Sort.main(Sort.java:64)
 467 [main] INFO  examples.Sort - Exiting main method.
 </pre>
- *
+ * 
  * @author Ceki G&uuml;lc&uuml;
  */
 public class SimpleLogger extends MarkerIgnoringBase {
-  
+
   private static final long serialVersionUID = -6560244151660620173L;
- 
+
   /**
    * Mark the time when this class gets loaded into memory.
    */
   private static long startTime = System.currentTimeMillis();
-  public static final String LINE_SEPARATOR =
-    System.getProperty("line.separator");
+  public static final String LINE_SEPARATOR = System
+      .getProperty("line.separator");
   private static String INFO_STR = "INFO";
   private static String WARN_STR = "WARN";
   private static String ERROR_STR = "ERROR";
@@ -85,6 +86,7 @@ public class SimpleLogger extends MarkerIgnoringBase {
 
   /**
    * Always returns false.
+   * 
    * @return always false
    */
   public boolean isTraceEnabled() {
@@ -92,25 +94,24 @@ public class SimpleLogger extends MarkerIgnoringBase {
   }
 
   /**
-   * A NOP implementation, as this logger is permanently disabled for
-   * the TRACE level.
+   * A NOP implementation, as this logger is permanently disabled for the TRACE
+   * level.
    */
   public void trace(String msg) {
     // NOP
   }
 
   /**
-   * A NOP implementation, as this logger is permanently disabled for
-   * the TRACE level.
+   * A NOP implementation, as this logger is permanently disabled for the TRACE
+   * level.
    */
   public void trace(String format, Object param1) {
     // NOP
   }
 
-  
   /**
-   * A NOP implementation, as this logger is permanently disabled for
-   * the TRACE level.
+   * A NOP implementation, as this logger is permanently disabled for the TRACE
+   * level.
    */
   public void trace(String format, Object param1, Object param2) {
     // NOP
@@ -119,18 +120,18 @@ public class SimpleLogger extends MarkerIgnoringBase {
   public void trace(String format, Object[] argArray) {
     // NOP
   }
-  
+
   /**
-   * A NOP implementation, as this logger is permanently disabled for
-   * the TRACE level.
+   * A NOP implementation, as this logger is permanently disabled for the TRACE
+   * level.
    */
   public void trace(String msg, Throwable t) {
     // NOP
   }
 
-  
   /**
    * Always returns false.
+   * 
    * @return always false
    */
   public boolean isDebugEnabled() {
@@ -138,25 +139,24 @@ public class SimpleLogger extends MarkerIgnoringBase {
   }
 
   /**
-   * A NOP implementation, as this logger is permanently disabled for
-   * the DEBUG level.
+   * A NOP implementation, as this logger is permanently disabled for the DEBUG
+   * level.
    */
   public void debug(String msg) {
     // NOP
   }
 
   /**
-   * A NOP implementation, as this logger is permanently disabled for
-   * the DEBUG level.
+   * A NOP implementation, as this logger is permanently disabled for the DEBUG
+   * level.
    */
   public void debug(String format, Object param1) {
     // NOP
   }
 
-  
   /**
-   * A NOP implementation, as this logger is permanently disabled for
-   * the DEBUG level.
+   * A NOP implementation, as this logger is permanently disabled for the DEBUG
+   * level.
    */
   public void debug(String format, Object param1, Object param2) {
     // NOP
@@ -165,10 +165,10 @@ public class SimpleLogger extends MarkerIgnoringBase {
   public void debug(String format, Object[] argArray) {
     // NOP
   }
-  
+
   /**
-   * A NOP implementation, as this logger is permanently disabled for
-   * the DEBUG level.
+   * A NOP implementation, as this logger is permanently disabled for the DEBUG
+   * level.
    */
   public void debug(String msg, Throwable t) {
     // NOP
@@ -177,7 +177,7 @@ public class SimpleLogger extends MarkerIgnoringBase {
   /**
    * This is our internal implementation for logging regular (non-parameterized)
    * log messages.
-   *
+   * 
    * @param level
    * @param message
    * @param t
@@ -211,18 +211,18 @@ public class SimpleLogger extends MarkerIgnoringBase {
 
   /**
    * For formatted messages, first substitute arguments and then log.
-   *
+   * 
    * @param level
    * @param format
    * @param param1
    * @param param2
    */
-  private void formatAndLog(
-    String level, String format, Object arg1, Object arg2) {
-    String message = MessageFormatter.format(format, arg1, arg2);
-    log(level, message, null);
+  private void formatAndLog(String level, String format, Object arg1,
+      Object arg2) {
+    FormattingTuple tp = MessageFormatter.format(format, arg1, arg2);
+    log(level, tp.getMessage(), tp.getThrowable());
   }
-  
+
   /**
    * For formatted messages, first substitute arguments and then log.
    * 
@@ -231,8 +231,8 @@ public class SimpleLogger extends MarkerIgnoringBase {
    * @param argArray
    */
   private void formatAndLog(String level, String format, Object[] argArray) {
-    String message = MessageFormatter.arrayFormat(format, argArray);
-    log(level, message, null);
+    FormattingTuple tp = MessageFormatter.arrayFormat(format, argArray);
+    log(level, tp.getMessage(), tp.getThrowable());
   }
 
   /**
@@ -274,7 +274,6 @@ public class SimpleLogger extends MarkerIgnoringBase {
     formatAndLog(INFO_STR, format, argArray);
   }
 
-
   /**
    * Log a message of level INFO, including an exception.
    */
@@ -288,11 +287,11 @@ public class SimpleLogger extends MarkerIgnoringBase {
   public boolean isWarnEnabled() {
     return true;
   }
-  
+
   /**
    * A simple implementation which always logs messages of level WARN according
    * to the format outlined above.
-  */
+   */
   public void warn(String msg) {
     log(WARN_STR, msg, null);
   }
@@ -367,7 +366,6 @@ public class SimpleLogger extends MarkerIgnoringBase {
     formatAndLog(ERROR_STR, format, argArray);
   }
 
-  
   /**
    * Log a message of level ERROR, including an exception.
    */

-----------------------------------------------------------------------


hooks/post-receive
-- 
SLF4J: Simple Logging Facade for Java


More information about the slf4j-dev mailing list