[slf4j-dev] [GIT] SLF4J: Simple Logging Facade for Java branch, master, updated. v1.5.11-10-gd1d27b8

added by portage for gitosis-gentoo git-noreply at pixie.qos.ch
Tue Apr 6 13:58:42 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, master has been updated
       via  d1d27b8d8748190f397b0be72c8d85722f8c5b00 (commit)
      from  a19566c1e0752a651057279e80384ef5ac37dfae (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

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

commit d1d27b8d8748190f397b0be72c8d85722f8c5b00
Author: Ceki Gulcu <ceki at qos.ch>
Date:   Tue Apr 6 13:57:15 2010 +0200

    As of SLF4J version 1.6.0, in the absence of an SLF4J binding,
    slf4j-api will default to a no-operation implementation discarding all
    log requests. Thus, instead of throwing an exception, SLF4J will emit
    a single warning message about the absence of a binding and proceed to
    discard all log requests without further protest.

diff --git a/integration/build.xml b/integration/build.xml
index d4e88a6..3c6e323 100644
--- a/integration/build.xml
+++ b/integration/build.xml
@@ -14,12 +14,18 @@
 	<echo message="test classpath:    ${test_classpath}" />
 	<echo message="plugin classpath:  ${plugin_classpath}" />
 
-	<path id="path150">
+
+	<path id="path142Binding">
 		<pathelement location="target/test-classes/" />
 		<pathelement location="../slf4j-api/target/slf4j-api-${currentVersion}.jar" />
-		<pathelement location="./lib/slf4j-simple-1.5.0.jar" />
+		<pathelement location="./lib/slf4j-simple-1.4.2.jar" />
 	</path >
 
+	<path id="path150Binding">
+		<pathelement location="target/test-classes/" />
+		<pathelement location="../slf4j-api/target/slf4j-api-${currentVersion}.jar" />
+		<pathelement location="./lib/slf4j-simple-1.5.0.jar" />
+	</path >
 
 	<path id="path1511API">
 		<pathelement location="target/test-classes/" />
@@ -33,14 +39,13 @@
 		<pathelement location="./lib/slf4j-simple-1.5.11.jar" />
 	</path >
 
-
-
-	<path id="pathIncompatible">
+  <!--<path id="pathIncompatible">
 		<pathelement location="target/test-classes/" />
 		<pathelement location="../slf4j-api/target/slf4j-api-${currentVersion}.jar" />
 		<pathelement location="./lib/slf4j-simple-INCOMPATIBLE.jar" />
 	</path >
-			
+  -->
+
 	<path id="pathCurrent">
 		<pathelement location="target/test-classes/" />
 		<pathelement location="../slf4j-api/target/slf4j-api-${currentVersion}.jar" />
@@ -101,23 +106,35 @@
 	</target>
 
 	<target name="testAll" depends="init, 
-		            testMismatch, 
-		            testPre155,
+		            testMissingSingletonMethod,
+                testMismatch, 
                 testMatch,
 		            testMultiBinding,
                 testFuture_16Series">
 	</target>
 
-	<target name="testMismatch">
 
-		<junit printsummary="yes" fork="no" haltonfailure="yes">
-			<classpath refid="pathIncompatible" />
+	<target name="testMissingSingletonMethod">
+
+    <junit printsummary="yes" fork="no" haltonfailure="yes">
+			<classpath refid="path142Binding" />
 			<formatter type="plain" />
 			<test fork="yes" todir="target/unit-reports"
-            outfile="TEST-INCOMPATIBLE" 
-            name="org.slf4j.VersionMismatchAssertionTest" />
+            outfile="TEST-142BININDING" 
+            name="org.slf4j.MissingSingletonMethodAssertionTest" />
 		</junit>
 
+    <junit printsummary="yes" fork="no" haltonfailure="yes">
+			<classpath refid="path150Binding" />
+			<formatter type="plain" />
+			<test fork="yes" todir="target/unit-reports" 
+            outfile="TEST-150BINDING" 
+            name="org.slf4j.MissingSingletonMethodAssertionTest" />
+		</junit>
+
+  </target>
+
+	<target name="testMismatch">
 
     <junit printsummary="yes" fork="no" haltonfailure="yes">
 			<classpath refid="path1511API" />
@@ -137,16 +154,6 @@
 		</junit>
 
 	</target>
-		
-	<target name="testPre155">
-		<junit printsummary="yes" fork="no" haltonfailure="yes">
-			<classpath refid="path150" />
-			<formatter type="plain" />
-			<test fork="yes" todir="target/unit-reports" 
-            outfile="TEST-testPre155" 
-            name="org.slf4j.CompatibilityAssertionTest" />
-		</junit>
-	</target>
 
 	<target name="testMatch">
 		<junit printsummary="yes" fork="no" haltonfailure="yes">
@@ -173,7 +180,7 @@
 			<classpath refid="binding1699" />
 			<formatter type="plain" />
 			<test fork="yes" todir="target/unit-reports" 
-            outfile="TEST-_binding1699" 
+            outfile="TEST-binding1699" 
             name="org.slf4j.CompatibilityAssertionTest" />
 		</junit>
 
@@ -181,7 +188,7 @@
 			<classpath refid="binding2099" />
 			<formatter type="plain" />
 			<test fork="yes" todir="target/unit-reports" 
-            outfile="TEST-_binding2099" 
+            outfile="TEST-binding2099" 
             name="org.slf4j.CompatibilityAssertionTest" />
 		</junit>
 
diff --git a/integration/lib/slf4j-simple-1.4.2.jar b/integration/lib/slf4j-simple-1.4.2.jar
new file mode 100644
index 0000000..d2e332d
Binary files /dev/null and b/integration/lib/slf4j-simple-1.4.2.jar differ
diff --git a/integration/lib/slf4j-simple-INCOMPATIBLE.jar b/integration/lib/slf4j-simple-INCOMPATIBLE.jar
deleted file mode 100644
index 0f6b680..0000000
Binary files a/integration/lib/slf4j-simple-INCOMPATIBLE.jar and /dev/null differ
diff --git a/integration/src/test/java/org/slf4j/MultiBindingAssertionTest.java b/integration/src/test/java/org/slf4j/MissingSingletonMethodAssertionTest.java
similarity index 59%
copy from integration/src/test/java/org/slf4j/MultiBindingAssertionTest.java
copy to integration/src/test/java/org/slf4j/MissingSingletonMethodAssertionTest.java
index daa81f9..cf30f9b 100644
--- a/integration/src/test/java/org/slf4j/MultiBindingAssertionTest.java
+++ b/integration/src/test/java/org/slf4j/MissingSingletonMethodAssertionTest.java
@@ -29,13 +29,13 @@ import java.util.Random;
 
 import junit.framework.TestCase;
 
-public class MultiBindingAssertionTest extends TestCase {
+public class MissingSingletonMethodAssertionTest extends TestCase {
 
   StringPrintStream sps = new StringPrintStream(System.err);
   PrintStream old = System.err;
   int diff = 1024 + new Random().nextInt(10000);
 
-  public MultiBindingAssertionTest(String name) {
+  public MissingSingletonMethodAssertionTest(String name) {
     super(name);
   }
 
@@ -50,13 +50,38 @@ public class MultiBindingAssertionTest extends TestCase {
   }
 
   public void test() throws Exception {
-    Logger logger = LoggerFactory.getLogger(this.getClass());
-    String msg = "hello world " + diff;
-    logger.info(msg);
-    assertTrue("number of lines should be greater than 4", sps.stringList
-        .size() > 4);
-    String s0 = (String) sps.stringList.get(0);
-    assertTrue(s0
-        .contains("SLF4J: Class path contains multiple SLF4J bindings."));
+    try {
+      Logger logger = LoggerFactory.getLogger(this.getClass());
+      String msg = "hello world " + diff;
+      logger.info(msg);
+      fail("NoSuchMethodError expected");
+    } catch (NoSuchMethodError e) {
+    }
+    
+    int lineCount = sps.stringList
+    .size();
+    assertTrue("number of lines should be 3 but was "+lineCount, lineCount == 3);
+
+    
+    // expected output:
+    // SLF4J: slf4j-api 1.6.x (or later) is incompatible with this binding.
+    // SLF4J: Your binding is version 1.4.x or earlier.
+    // SLF4J: Upgrade your binding to version 1.6.x. or 2.0.x
+
+    {
+      String s = (String) sps.stringList.get(0);
+      assertTrue(s
+          .contains("SLF4J: slf4j-api 1.6.x (or later) is incompatible with this binding."));
+    }
+    {
+      String s = (String) sps.stringList.get(1);
+      assertTrue(s.contains("SLF4J: Your binding is version 1.5.5 or earlier."));
+    }
+    {
+      String s = (String) sps.stringList.get(2);
+      assertTrue(s
+          .contains("SLF4J: Upgrade your binding to version 1.6.x. or 2.0.x"));
+    }
+
   }
 }
diff --git a/integration/src/test/java/org/slf4j/MultiBindingAssertionTest.java b/integration/src/test/java/org/slf4j/MultiBindingAssertionTest.java
index daa81f9..a85bfa4 100644
--- a/integration/src/test/java/org/slf4j/MultiBindingAssertionTest.java
+++ b/integration/src/test/java/org/slf4j/MultiBindingAssertionTest.java
@@ -25,6 +25,7 @@
 package org.slf4j;
 
 import java.io.PrintStream;
+import java.util.List;
 import java.util.Random;
 
 import junit.framework.TestCase;
@@ -50,13 +51,25 @@ public class MultiBindingAssertionTest extends TestCase {
   }
 
   public void test() throws Exception {
-    Logger logger = LoggerFactory.getLogger(this.getClass());
-    String msg = "hello world " + diff;
-    logger.info(msg);
-    assertTrue("number of lines should be greater than 4", sps.stringList
-        .size() > 4);
-    String s0 = (String) sps.stringList.get(0);
-    assertTrue(s0
-        .contains("SLF4J: Class path contains multiple SLF4J bindings."));
+    try {
+      Logger logger = LoggerFactory.getLogger(this.getClass());
+      String msg = "hello world " + diff;
+      logger.info(msg);
+      fail("was expecting NoSuchMethodError");
+    } catch (NoSuchMethodError e) {
+    }
+    List list = sps.stringList;
+    assertMsgContains(list, 0, "Class path contains multiple SLF4J bindings.");
+    assertMsgContains(list, 1, "Found binding in");
+    assertMsgContains(list, 2, "Found binding in");
+    assertMsgContains(list, 3, "See http://www.slf4j.org/codes.html");
+    assertMsgContains(list, 4,
+        "slf4j-api 1.6.x (or later) is incompatible with this binding");
+    assertMsgContains(list, 5, "Your binding is version 1.5.5 or earlier.");
+
+  }
+
+  void assertMsgContains(List strList, int index, String msg) {
+    assertTrue(((String) strList.get(index)).contains(msg));
   }
 }
diff --git a/log4j-over-slf4j/src/main/java/org/apache/log4j/Log4jLoggerFactory.java b/log4j-over-slf4j/src/main/java/org/apache/log4j/Log4jLoggerFactory.java
index d8d0ad7..7787dce 100644
--- a/log4j-over-slf4j/src/main/java/org/apache/log4j/Log4jLoggerFactory.java
+++ b/log4j-over-slf4j/src/main/java/org/apache/log4j/Log4jLoggerFactory.java
@@ -44,8 +44,8 @@ class Log4jLoggerFactory {
       String part2 = "See also " + LOG4J_DELEGATION_LOOP_URL
           + " for more details.";
 
-      Util.reportFailure(part1);
-      Util.reportFailure(part2);
+      Util.report(part1);
+      Util.report(part2);
             throw new IllegalStateException(part1 + part2);
     } catch (ClassNotFoundException e) {
       // this is the good case
diff --git a/slf4j-api/src/main/java/org/slf4j/LoggerFactory.java b/slf4j-api/src/main/java/org/slf4j/LoggerFactory.java
index 8df4398..7d59d13 100644
--- a/slf4j-api/src/main/java/org/slf4j/LoggerFactory.java
+++ b/slf4j-api/src/main/java/org/slf4j/LoggerFactory.java
@@ -31,6 +31,7 @@ import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.List;
 
+import org.slf4j.helpers.NOPLoggerFactory;
 import org.slf4j.helpers.SubstituteLoggerFactory;
 import org.slf4j.helpers.Util;
 import org.slf4j.impl.StaticLoggerBinder;
@@ -68,13 +69,11 @@ public final class LoggerFactory {
   static final int ONGOING_INITILIZATION = 1;
   static final int FAILED_INITILIZATION = 2;
   static final int SUCCESSFUL_INITILIZATION = 3;
-
-  static final int GET_SINGLETON_INEXISTENT = 1;
-  static final int GET_SINGLETON_EXISTS = 2;
+  static final int NOP_FALLBACK_INITILIZATION = 4;
 
   static int INITIALIZATION_STATE = UNINITIALIZED;
-  static int GET_SINGLETON_METHOD = UNINITIALIZED;
   static SubstituteLoggerFactory TEMP_FACTORY = new SubstituteLoggerFactory();
+  static NOPLoggerFactory NOP_FALLBACK_FACTORY = new NOPLoggerFactory();
 
   /**
    * It is LoggerFactory's responsibility to track version changes and manage
@@ -83,7 +82,8 @@ public final class LoggerFactory {
    * <p>
    * It is assumed that all versions in the 1.6 are mutually compatible.
    * */
-  static private final String[] API_COMPATIBILITY_LIST = new String[] { "1.6", "2.0" };
+  static private final String[] API_COMPATIBILITY_LIST = new String[] { "1.6",
+      "2.0" };
 
   // private constructor prevents instantiation
   private LoggerFactory() {
@@ -102,55 +102,70 @@ public final class LoggerFactory {
    */
   static void reset() {
     INITIALIZATION_STATE = UNINITIALIZED;
-    GET_SINGLETON_METHOD = UNINITIALIZED;
     TEMP_FACTORY = new SubstituteLoggerFactory();
   }
 
   private final static void performInitialization() {
-    bind();
-    versionSanityCheck();
     singleImplementationSanityCheck();
-
+    bind();
+    if (INITIALIZATION_STATE == SUCCESSFUL_INITILIZATION) {
+      versionSanityCheck();
+   
+    }
   }
 
   private final static void bind() {
     try {
       // the next line does the binding
-      getSingleton();
+      StaticLoggerBinder.getSingleton();
       INITIALIZATION_STATE = SUCCESSFUL_INITILIZATION;
       emitSubstituteLoggerWarning();
     } catch (NoClassDefFoundError ncde) {
-      INITIALIZATION_STATE = FAILED_INITILIZATION;
       String msg = ncde.getMessage();
       if (msg != null && msg.indexOf("org/slf4j/impl/StaticLoggerBinder") != -1) {
+        INITIALIZATION_STATE = NOP_FALLBACK_INITILIZATION;
         Util
-            .reportFailure("Failed to load class \"org.slf4j.impl.StaticLoggerBinder\".");
-        Util.reportFailure("See " + NO_STATICLOGGERBINDER_URL
+            .report("Failed to load class \"org.slf4j.impl.StaticLoggerBinder\".");
+        Util.report("Defaulting to no-operation (NOP) logger implementation");
+        Util.report("See " + NO_STATICLOGGERBINDER_URL
             + " for further details.");
-
+      } else {
+        failedBinding(ncde);
+        throw ncde;
       }
-      throw ncde;
+    } catch(java.lang.NoSuchMethodError nsme) {
+      String msg = nsme.getMessage();
+      if (msg != null && msg.indexOf("org.slf4j.impl.StaticLoggerBinder.getSingleton()") != -1) {
+        INITIALIZATION_STATE = FAILED_INITILIZATION;
+        Util.report("slf4j-api 1.6.x (or later) is incompatible with this binding.");
+        Util.report("Your binding is version 1.5.5 or earlier.");
+        Util.report("Upgrade your binding to version 1.6.x. or 2.0.x");
+      }
+      throw nsme;
     } catch (Exception e) {
-      INITIALIZATION_STATE = FAILED_INITILIZATION;
-      // we should never get here
-      Util.reportFailure("Failed to instantiate logger ["
-          + getSingleton().getLoggerFactoryClassStr() + "]", e);
+      failedBinding(e);
+      throw new IllegalStateException("Unexpected initialization failure", e);
     }
   }
 
+  static void failedBinding(Throwable t) {
+    INITIALIZATION_STATE = FAILED_INITILIZATION;
+    Util.report("Failed to instantiate SLF4J LoggerFactory", t);
+  }
+
   private final static void emitSubstituteLoggerWarning() {
     List loggerNameList = TEMP_FACTORY.getLoggerNameList();
     if (loggerNameList.size() == 0) {
       return;
     }
     Util
-        .reportFailure("The following loggers will not work becasue they were created");
+        .report("The following loggers will not work becasue they were created");
     Util
-        .reportFailure("during the default configuration phase of the underlying logging system.");
-    Util.reportFailure("See also " + SUBSTITUTE_LOGGER_URL);
+        .report("during the default configuration phase of the underlying logging system.");
+    Util.report("See also " + SUBSTITUTE_LOGGER_URL);
     for (int i = 0; i < loggerNameList.size(); i++) {
       String loggerName = (String) loggerNameList.get(i);
-      Util.reportFailure(loggerName);
+      Util.report(loggerName);
     }
   }
 
@@ -165,10 +180,10 @@ public final class LoggerFactory {
         }
       }
       if (!match) {
-        Util.reportFailure("The requested version " + requested
+        Util.report("The requested version " + requested
             + " by your slf4j binding is not compatible with "
             + Arrays.asList(API_COMPATIBILITY_LIST).toString());
-        Util.reportFailure("See " + VERSION_MISMATCH + " for further details.");
+        Util.report("See " + VERSION_MISMATCH + " for further details.");
       }
     } catch (java.lang.NoSuchFieldError nsfe) {
       // given our large user base and SLF4J's commitment to backward
@@ -177,8 +192,7 @@ public final class LoggerFactory {
       // emit compatibility warnings.
     } catch (Throwable e) {
       // we should never reach here
-      Util.reportFailure(
-          "Unexpected problem occured during version sanity check", e);
+      Util.report("Unexpected problem occured during version sanity check", e);
     }
   }
 
@@ -203,35 +217,14 @@ public final class LoggerFactory {
         implementationList.add(path);
       }
       if (implementationList.size() > 1) {
-        Util.reportFailure("Class path contains multiple SLF4J bindings.");
+        Util.report("Class path contains multiple SLF4J bindings.");
         for (int i = 0; i < implementationList.size(); i++) {
-          Util.reportFailure("Found binding in [" + implementationList.get(i)
-              + "]");
+          Util.report("Found binding in [" + implementationList.get(i) + "]");
         }
-        Util.reportFailure("See " + MULTIPLE_BINDINGS_URL
-            + " for an explanation.");
+        Util.report("See " + MULTIPLE_BINDINGS_URL + " for an explanation.");
       }
     } catch (IOException ioe) {
-      Util.reportFailure("Error getting resources from path", ioe);
-    }
-  }
-
-  private final static StaticLoggerBinder getSingleton() {
-    if (GET_SINGLETON_METHOD == GET_SINGLETON_INEXISTENT) {
-      return StaticLoggerBinder.getSingleton();
-    }
-
-    if (GET_SINGLETON_METHOD == GET_SINGLETON_EXISTS) {
-      return StaticLoggerBinder.getSingleton();
-    }
-
-    try {
-      StaticLoggerBinder singleton = StaticLoggerBinder.getSingleton();
-      GET_SINGLETON_METHOD = GET_SINGLETON_EXISTS;
-      return singleton;
-    } catch (NoSuchMethodError nsme) {
-      GET_SINGLETON_METHOD = GET_SINGLETON_INEXISTENT;
-      return StaticLoggerBinder.getSingleton();
+      Util.report("Error getting resources from path", ioe);
     }
   }
 
@@ -276,7 +269,9 @@ public final class LoggerFactory {
     }
     switch (INITIALIZATION_STATE) {
     case SUCCESSFUL_INITILIZATION:
-      return getSingleton().getLoggerFactory();
+      return StaticLoggerBinder.getSingleton().getLoggerFactory();
+    case NOP_FALLBACK_INITILIZATION:
+      return NOP_FALLBACK_FACTORY;
     case FAILED_INITILIZATION:
       throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
     case ONGOING_INITILIZATION:
diff --git a/slf4j-api/src/main/java/org/slf4j/MDC.java b/slf4j-api/src/main/java/org/slf4j/MDC.java
index f8d232d..1670061 100644
--- a/slf4j-api/src/main/java/org/slf4j/MDC.java
+++ b/slf4j-api/src/main/java/org/slf4j/MDC.java
@@ -27,6 +27,7 @@ package org.slf4j;
 import java.util.Map;
 
 import org.slf4j.helpers.BasicMDCAdapter;
+import org.slf4j.helpers.NOPMDCAdapter;
 import org.slf4j.helpers.Util;
 import org.slf4j.impl.StaticMDCBinder;
 import org.slf4j.spi.MDCAdapter;
@@ -39,13 +40,13 @@ import org.slf4j.spi.MDCAdapter;
  * If the underlying logging system offers MDC functionality, then SLF4J's MDC,
  * i.e. this class, will delegate to the underlying system's MDC. Note that at
  * this time, only two logging systems, namely log4j and logback, offer MDC
- * functionality. If the underlying system does not support MDC, e.g. java.util.logging, 
- * then SLF4J will use a {@link BasicMDCAdapter}. 
+ * functionality. If the underlying system does not support MDC, e.g.
+ * java.util.logging, then SLF4J will use a {@link BasicMDCAdapter}.
  * 
  * <p>
  * Thus, as a SLF4J user, you can take advantage of MDC in the presence of log4j
- * logback, or java.util.logging, but without forcing these systems as dependencies 
- * upon your users.
+ * logback, or java.util.logging, but without forcing these systems as
+ * dependencies upon your users.
  * 
  * <p>
  * For more information on MDC please see the <a
@@ -71,34 +72,36 @@ public class MDC {
     try {
       mdcAdapter = StaticMDCBinder.SINGLETON.getMDCA();
     } catch (NoClassDefFoundError ncde) {
+      mdcAdapter = new NOPMDCAdapter();
       String msg = ncde.getMessage();
       if (msg != null && msg.indexOf("org/slf4j/impl/StaticMDCBinder") != -1) {
+        Util.report("Failed to load class \"org.slf4j.impl.StaticMDCBinder\".");
+        Util.report("Defaulting to no-operation MDCAdapter implementation.");
         Util
-            .reportFailure("Failed to load class \"org.slf4j.impl.StaticMDCBinder\".");
-        Util.reportFailure("See " + NO_STATIC_MDC_BINDER_URL
-            + " for further details.");
-
+            .report("See " + NO_STATIC_MDC_BINDER_URL + " for further details.");
+      } else {
+        throw ncde;
       }
-      throw ncde;
     } catch (Exception e) {
       // we should never get here
-      Util.reportFailure("Could not bind with an instance of class ["
-          + StaticMDCBinder.SINGLETON.getMDCAdapterClassStr() + "]", e);
+      Util.report("MDC binding unsuccessful.", e);
     }
   }
 
   /**
-   * Put a context value (the <code>val</code> parameter) as identified with
-   * the <code>key</code> parameter into the current thread's context map.
-   * The <code>key</code> parameter cannot be null. The <code>val</code> parameter 
+   * Put a context value (the <code>val</code> parameter) as identified with the
+   * <code>key</code> parameter into the current thread's context map. The
+   * <code>key</code> parameter cannot be null. The <code>val</code> parameter
    * can be null only if the underlying implementation supports it.
    * 
    * <p>
    * This method delegates all work to the MDC of the underlying logging system.
    * 
-   * @throws IllegalArgumentException in case the "key" parameter is null
+   * @throws IllegalArgumentException
+   *           in case the "key" parameter is null
    */
-  public static void put(String key, String val) throws IllegalArgumentException {
+  public static void put(String key, String val)
+      throws IllegalArgumentException {
     if (key == null) {
       throw new IllegalArgumentException("key parameter cannot be null");
     }
@@ -110,19 +113,21 @@ public class MDC {
   }
 
   /**
-   * Get the context identified by the <code>key</code> parameter. The 
+   * Get the context identified by the <code>key</code> parameter. The
    * <code>key</code> parameter cannot be null.
    * 
-   * <p>This method delegates all work to the MDC of the underlying logging system. 
+   * <p>
+   * This method delegates all work to the MDC of the underlying logging system.
    * 
    * @return the string value identified by the <code>key</code> parameter.
-   * @throws IllegalArgumentException in case the "key" parameter is null
+   * @throws IllegalArgumentException
+   *           in case the "key" parameter is null
    */
   public static String get(String key) throws IllegalArgumentException {
     if (key == null) {
       throw new IllegalArgumentException("key parameter cannot be null");
     }
-    
+
     if (mdcAdapter == null) {
       throw new IllegalStateException("MDCAdapter cannot be null. See also "
           + NULL_MDCA_URL);
@@ -132,17 +137,18 @@ public class MDC {
 
   /**
    * Remove the the context identified by the <code>key</code> parameter using
-   * the underlying system's MDC implementation. The  <code>key</code> parameter 
-   * cannot be null. This method does nothing if there is no previous value 
+   * the underlying system's MDC implementation. The <code>key</code> parameter
+   * cannot be null. This method does nothing if there is no previous value
    * associated with <code>key</code>.
    * 
-   * @throws IllegalArgumentException in case the "key" parameter is null
+   * @throws IllegalArgumentException
+   *           in case the "key" parameter is null
    */
   public static void remove(String key) throws IllegalArgumentException {
     if (key == null) {
       throw new IllegalArgumentException("key parameter cannot be null");
     }
-    
+
     if (mdcAdapter == null) {
       throw new IllegalStateException("MDCAdapter cannot be null. See also "
           + NULL_MDCA_URL);
@@ -150,7 +156,7 @@ public class MDC {
     mdcAdapter.remove(key);
   }
 
-  /** 
+  /**
    * Clear all entries in the MDC of the underlying implementation.
    */
   public static void clear() {
@@ -160,10 +166,10 @@ public class MDC {
     }
     mdcAdapter.clear();
   }
-  
+
   /**
-   * Return a copy of the current thread's context map, with keys and 
-   * values of type String. Returned value may be null.
+   * Return a copy of the current thread's context map, with keys and values of
+   * type String. Returned value may be null.
    * 
    * @return A copy of the current thread's context map. May be null.
    * @since 1.5.1
@@ -177,11 +183,12 @@ public class MDC {
   }
 
   /**
-   * Set the current thread's context map by first clearing any existing 
-   * map and then copying the map passed as parameter. The context map passed
-   * as parameter must only contain keys and values of type String.
+   * Set the current thread's context map by first clearing any existing map and
+   * then copying the map passed as parameter. The context map passed as
+   * parameter must only contain keys and values of type String.
    * 
-   * @param contextMap must contain only keys and values of type String
+   * @param contextMap
+   *          must contain only keys and values of type String
    * @since 1.5.1
    */
   public static void setContextMap(Map contextMap) {
@@ -191,8 +198,7 @@ public class MDC {
     }
     mdcAdapter.setContextMap(contextMap);
   }
-  
-  
+
   /**
    * Returns the MDCAdapter instance currently in use.
    * 
@@ -202,6 +208,5 @@ public class MDC {
   public static MDCAdapter getMDCAdapter() {
     return mdcAdapter;
   }
-  
-  
+
 }
\ No newline at end of file
diff --git a/slf4j-api/src/main/java/org/slf4j/MarkerFactory.java b/slf4j-api/src/main/java/org/slf4j/MarkerFactory.java
index 271c4dd..3cb8cfc 100644
--- a/slf4j-api/src/main/java/org/slf4j/MarkerFactory.java
+++ b/slf4j-api/src/main/java/org/slf4j/MarkerFactory.java
@@ -24,6 +24,7 @@
 
 package org.slf4j;
 
+import org.slf4j.helpers.BasicMarkerFactory;
 import org.slf4j.helpers.Util;
 import org.slf4j.impl.StaticMarkerBinder;
 
@@ -49,10 +50,12 @@ public class MarkerFactory {
   static {
     try {
       markerFactory = StaticMarkerBinder.SINGLETON.getMarkerFactory();
+    } catch (NoClassDefFoundError e) {
+      markerFactory = new BasicMarkerFactory();
+      
     } catch (Exception e) {
       // we should never get here
-      Util.reportFailure("Could not instantiate instance of class ["
-          + StaticMarkerBinder.SINGLETON.getMarkerFactoryClassStr() + "]", e);
+      Util.report("Unexpected failure while binding MarkerFactory", e);
     }
   }
 
diff --git a/slf4j-nop/src/main/java/org/slf4j/impl/NOPLoggerFactory.java b/slf4j-api/src/main/java/org/slf4j/helpers/NOPLoggerFactory.java
similarity index 98%
rename from slf4j-nop/src/main/java/org/slf4j/impl/NOPLoggerFactory.java
rename to slf4j-api/src/main/java/org/slf4j/helpers/NOPLoggerFactory.java
index c63331c..cff1a47 100644
--- a/slf4j-nop/src/main/java/org/slf4j/impl/NOPLoggerFactory.java
+++ b/slf4j-api/src/main/java/org/slf4j/helpers/NOPLoggerFactory.java
@@ -31,7 +31,7 @@
  *
  */
 
-package org.slf4j.impl;
+package org.slf4j.helpers;
 
 import org.slf4j.ILoggerFactory;
 import org.slf4j.Logger;
diff --git a/slf4j-api/src/main/java/org/slf4j/helpers/NOPMakerAdapter.java b/slf4j-api/src/main/java/org/slf4j/helpers/NOPMDCAdapter.java
similarity index 92%
rename from slf4j-api/src/main/java/org/slf4j/helpers/NOPMakerAdapter.java
rename to slf4j-api/src/main/java/org/slf4j/helpers/NOPMDCAdapter.java
index ab85753..b995cba 100644
--- a/slf4j-api/src/main/java/org/slf4j/helpers/NOPMakerAdapter.java
+++ b/slf4j-api/src/main/java/org/slf4j/helpers/NOPMDCAdapter.java
@@ -13,7 +13,7 @@ import org.slf4j.spi.MDCAdapter;
  * 
  * @since 1.4.1
  */
-public class NOPMakerAdapter implements MDCAdapter {
+public class NOPMDCAdapter implements MDCAdapter {
 
   public void clear() {
   }
diff --git a/slf4j-api/src/main/java/org/slf4j/helpers/Util.java b/slf4j-api/src/main/java/org/slf4j/helpers/Util.java
index 1ce0f97..1af1224 100644
--- a/slf4j-api/src/main/java/org/slf4j/helpers/Util.java
+++ b/slf4j-api/src/main/java/org/slf4j/helpers/Util.java
@@ -33,13 +33,13 @@ package org.slf4j.helpers;
  */
 public class Util {
     
-  static final public void reportFailure(String msg, Throwable t) {
+  static final public void report(String msg, Throwable t) {
     System.err.println(msg);
     System.err.println("Reported exception:");
     t.printStackTrace();
   }
   
-  static final public void reportFailure(String msg) {
+  static final public void report(String msg) {
     System.err.println("SLF4J: " +msg);
   }
 }
diff --git a/slf4j-api/src/test/java/org/slf4j/NoBindingTest.java b/slf4j-api/src/test/java/org/slf4j/NoBindingTest.java
index e906513..89136e8 100644
--- a/slf4j-api/src/test/java/org/slf4j/NoBindingTest.java
+++ b/slf4j-api/src/test/java/org/slf4j/NoBindingTest.java
@@ -1,25 +1,50 @@
+/*
+ * 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;
 
+import java.util.Random;
+
+import org.slf4j.helpers.BasicMarker;
+import org.slf4j.helpers.NOPLogger;
+
 import junit.framework.TestCase;
 
 public class NoBindingTest extends TestCase {
 
+  int diff = new Random().nextInt(10000);
+  
   public void testLogger() {
-    try {
-      Logger logger = LoggerFactory.getLogger(NoBindingTest.class);
-      logger.debug("hello");
-      fail("slf4j-api does not ship with a binding");
-    } catch (NoClassDefFoundError e) {
-
-    }
+    Logger logger = LoggerFactory.getLogger(NoBindingTest.class);
+    logger.debug("hello"+diff);
+    assertTrue(logger instanceof NOPLogger);
   }
 
   public void testMDC() {
-    try {
-      MDC.put("k", "v");
-      fail("slf4j-api does not ship with a binding");
-    } catch (NoClassDefFoundError e) {
+    MDC.put("k"+diff, "v");
+    assertNull(MDC.get("k"));
+  }
 
-    }
+  public void testMarker() {
+    Marker m = MarkerFactory.getMarker("a"+diff);
+    assertTrue(m instanceof BasicMarker);
   }
 }
diff --git a/slf4j-jcl/src/main/java/org/slf4j/impl/JCLLoggerFactory.java b/slf4j-jcl/src/main/java/org/slf4j/impl/JCLLoggerFactory.java
index c3ce664..17a5f63 100644
--- a/slf4j-jcl/src/main/java/org/slf4j/impl/JCLLoggerFactory.java
+++ b/slf4j-jcl/src/main/java/org/slf4j/impl/JCLLoggerFactory.java
@@ -59,8 +59,8 @@ public class JCLLoggerFactory implements ILoggerFactory {
       String part2 = "See also " + JCL_DELEGATION_LOOP_URL
           + " for more details.";
 
-      Util.reportFailure(part1);
-      Util.reportFailure(part2);
+      Util.report(part1);
+      Util.report(part2);
       throw new IllegalStateException(part1 + part2);
     } catch (ClassNotFoundException e) {
       // this is the good case
diff --git a/slf4j-jcl/src/main/java/org/slf4j/impl/StaticMDCBinder.java b/slf4j-jcl/src/main/java/org/slf4j/impl/StaticMDCBinder.java
index 0b9fb17..9630a24 100644
--- a/slf4j-jcl/src/main/java/org/slf4j/impl/StaticMDCBinder.java
+++ b/slf4j-jcl/src/main/java/org/slf4j/impl/StaticMDCBinder.java
@@ -1,11 +1,11 @@
 package org.slf4j.impl;
 
-import org.slf4j.helpers.NOPMakerAdapter;
+import org.slf4j.helpers.NOPMDCAdapter;
 import org.slf4j.spi.MDCAdapter;
 
 
 /**
- * This implementation is bound to {@link NOPMakerAdapter}.
+ * This implementation is bound to {@link NOPMDCAdapter}.
  *
  * @author Ceki G&uuml;lc&uuml;
  */
@@ -25,10 +25,10 @@ public class StaticMDCBinder {
    * {@link StaticMDCBinder}.
    */
   public MDCAdapter getMDCA() {
-     return new NOPMakerAdapter();
+     return new NOPMDCAdapter();
   }
   
   public String  getMDCAdapterClassStr() {
-    return NOPMakerAdapter.class.getName();
+    return NOPMDCAdapter.class.getName();
   }
 }
diff --git a/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
index 37487de..8b6af97 100644
--- a/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
+++ b/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
@@ -83,7 +83,7 @@ public class StaticLoggerBinder implements LoggerFactoryBinder {
       Level level = Level.TRACE;
     } catch (NoSuchFieldError 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");
+          .report("This version of SLF4J requires log4j version 1.2.12 or later. See also http://www.slf4j.org/codes.html#log4j_version");
     }
   }
 
diff --git a/slf4j-nop/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/slf4j-nop/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
index ef15ec3..779ad1c 100644
--- a/slf4j-nop/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
+++ b/slf4j-nop/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
@@ -35,6 +35,7 @@ package org.slf4j.impl;
 
 import org.slf4j.ILoggerFactory;
 import org.slf4j.LoggerFactory;
+import org.slf4j.helpers.NOPLoggerFactory;
 import org.slf4j.spi.LoggerFactoryBinder;
 
 /**
diff --git a/slf4j-nop/src/main/java/org/slf4j/impl/StaticMDCBinder.java b/slf4j-nop/src/main/java/org/slf4j/impl/StaticMDCBinder.java
index 0b9fb17..9630a24 100644
--- a/slf4j-nop/src/main/java/org/slf4j/impl/StaticMDCBinder.java
+++ b/slf4j-nop/src/main/java/org/slf4j/impl/StaticMDCBinder.java
@@ -1,11 +1,11 @@
 package org.slf4j.impl;
 
-import org.slf4j.helpers.NOPMakerAdapter;
+import org.slf4j.helpers.NOPMDCAdapter;
 import org.slf4j.spi.MDCAdapter;
 
 
 /**
- * This implementation is bound to {@link NOPMakerAdapter}.
+ * This implementation is bound to {@link NOPMDCAdapter}.
  *
  * @author Ceki G&uuml;lc&uuml;
  */
@@ -25,10 +25,10 @@ public class StaticMDCBinder {
    * {@link StaticMDCBinder}.
    */
   public MDCAdapter getMDCA() {
-     return new NOPMakerAdapter();
+     return new NOPMDCAdapter();
   }
   
   public String  getMDCAdapterClassStr() {
-    return NOPMakerAdapter.class.getName();
+    return NOPMDCAdapter.class.getName();
   }
 }
diff --git a/slf4j-simple/src/main/java/org/slf4j/impl/StaticMDCBinder.java b/slf4j-simple/src/main/java/org/slf4j/impl/StaticMDCBinder.java
index a06185e..e4abdbe 100644
--- a/slf4j-simple/src/main/java/org/slf4j/impl/StaticMDCBinder.java
+++ b/slf4j-simple/src/main/java/org/slf4j/impl/StaticMDCBinder.java
@@ -24,12 +24,12 @@
 
 package org.slf4j.impl;
 
-import org.slf4j.helpers.NOPMakerAdapter;
+import org.slf4j.helpers.NOPMDCAdapter;
 import org.slf4j.spi.MDCAdapter;
 
 
 /**
- * This implementation is bound to {@link NOPMakerAdapter}.
+ * This implementation is bound to {@link NOPMDCAdapter}.
  *
  * @author Ceki G&uuml;lc&uuml;
  */
@@ -49,10 +49,10 @@ public class StaticMDCBinder {
    * {@link StaticMDCBinder}.
    */
   public MDCAdapter getMDCA() {
-     return new NOPMakerAdapter();
+     return new NOPMDCAdapter();
   }
   
   public String  getMDCAdapterClassStr() {
-    return NOPMakerAdapter.class.getName();
+    return NOPMDCAdapter.class.getName();
   }
 }
diff --git a/slf4j-site/src/site/pages/codes.html b/slf4j-site/src/site/pages/codes.html
index f5d7ed2..ff2281c 100644
--- a/slf4j-site/src/site/pages/codes.html
+++ b/slf4j-site/src/site/pages/codes.html
@@ -103,6 +103,10 @@
     problem.
     </p>
 
+    <p>As of SLF4J version 1.6, in the absence of a binding, SLF4J
+    will default to a no-operation (NOP) logger implementation.
+    </p>
+
     <p>You can download SLF4J bindings from the project <a
     href="http://www.slf4j.org/download.html">download page</a>. </p>
 
diff --git a/slf4j-site/src/site/pages/faq.html b/slf4j-site/src/site/pages/faq.html
index aad3d9f..84881c6 100644
--- a/slf4j-site/src/site/pages/faq.html
+++ b/slf4j-site/src/site/pages/faq.html
@@ -531,8 +531,8 @@ org.slf4j.impl.StaticLoggerBinder.SINGLETON from class org.slf4j.LoggerFactory
       to wrap SLF4J and link with it only if it is already present on
       the classpath, making SLF4J an optional dependency of Wombat. In
       addition to solving the dependency problem, the wrapper will
-      isolate Wombat from SLF4J;s API ensuring that logging in Wombat
-      is future-proof.
+      isolate Wombat from SLF4J's API ensuring that logging in Wombat
+      is future-proof. 
       </p>
 
       <p>On the other hand, any SLF4J-wrapper by definition depends on
@@ -542,7 +542,17 @@ org.slf4j.impl.StaticLoggerBinder.SINGLETON from class org.slf4j.LoggerFactory
       migrate to the new API as code that used SLF4J directly. Thus,
       the wrapper is not likely to future-proof your code, but to make
       it heavier by adding an additional indirection on top SLF4J
-      which is an indirection in itself.
+      which is an indirection in itself. It's actually a lot worse
+      than that. Wrappers will need to depend on certain internal
+      SLF4J interfaces which change from time to time, typical on each
+      major series, contrary to the client-facing API which never
+      changes. Thus, wrappers are usually dependent on the major
+      version they were compiled with. A wrapper compiled against
+      SLF4J version 1.5.x will not work with SLF4J 1.6 whereas client
+      code using <code>org.slf4j.Logger</code>,
+      <code>LoggerFactory</code>, <code>MarkerFactory</code>,
+      <code>org.slf4j.Marker</code>, and <code>MDC</code> will work
+      fine with any SLF4J version from version 1.0 and onwards.
       </p>
 
       <p>It is reasonable to assume that in most projects Wombat will
@@ -573,7 +583,8 @@ org.slf4j.impl.StaticLoggerBinder.SINGLETON from class org.slf4j.LoggerFactory
       <p>For the above reasons, developers of frameworks should resist
       the temptation to write their own logging wrapper. Not only is
       it a waste of time of the developer, it will actually make life
-      more difficult for the users of said frameworks.
+      more difficult for the users of said frameworks and make logging
+      code paradoxically more vulnerable to change.
       </p>
     </dd>
 
@@ -616,6 +627,11 @@ org.slf4j.impl.StaticLoggerBinder.SINGLETON from class org.slf4j.LoggerFactory
       any SLF4J-binding or any underlying logging system.
       </p>
       
+      <p>Note that as of SLF4J version 1.6, in the absence of an SLF4J
+      binding, slf4j-api will default to a no-operation
+      implementation.
+      </p>
+
       <hr/>
       
     </dd>
diff --git a/slf4j-site/src/site/pages/news.html b/slf4j-site/src/site/pages/news.html
index 0385121..7ff7bab 100644
--- a/slf4j-site/src/site/pages/news.html
+++ b/slf4j-site/src/site/pages/news.html
@@ -32,7 +32,15 @@
    <p>It is expected that <em>all</em> SLF4J releases in the 1.6.x and
    2.0.x series will be mutually compatible. Note that the 2.0.x
    series is expected to require JDK 1.5 or later.
-    </p>
+   </p>
+
+   <p>Note that as of SLF4J version 1.6.0, in the absence of an SLF4J
+   binding, slf4j-api will default to a no-operation implementation
+   discarding all log requests. Thus, instead of throwing an
+   exception, SLF4J will emit a single warning message about the
+   absence of a binding and proceed to discard all log requests
+   without further protest.
+   </p>
 
    <p>Fixed <a
    href="http://bugzilla.slf4j.org/show_bug.cgi?id=150">bug 150</a> by

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

Summary of changes:
 integration/build.xml                              |   57 ++++++-----
 ...f4j-simple-1.5.0.jar => slf4j-simple-1.4.2.jar} |  Bin 7477 -> 7470 bytes
 integration/lib/slf4j-simple-INCOMPATIBLE.jar      |  Bin 7478 -> 0 bytes
 ...va => MissingSingletonMethodAssertionTest.java} |   45 +++++++--
 .../java/org/slf4j/MultiBindingAssertionTest.java  |   29 ++++--
 .../java/org/apache/log4j/Log4jLoggerFactory.java  |    4 +-
 .../src/main/java/org/slf4j/LoggerFactory.java     |  101 +++++++++----------
 slf4j-api/src/main/java/org/slf4j/MDC.java         |   77 ++++++++-------
 .../src/main/java/org/slf4j/MarkerFactory.java     |    7 +-
 .../java/org/slf4j/helpers}/NOPLoggerFactory.java  |    2 +-
 .../{NOPMakerAdapter.java => NOPMDCAdapter.java}   |    2 +-
 .../src/main/java/org/slf4j/helpers/Util.java      |    4 +-
 .../src/test/java/org/slf4j/NoBindingTest.java     |   49 +++++++---
 .../main/java/org/slf4j/impl/JCLLoggerFactory.java |    4 +-
 .../main/java/org/slf4j/impl/StaticMDCBinder.java  |    8 +-
 .../java/org/slf4j/impl/StaticLoggerBinder.java    |    2 +-
 .../java/org/slf4j/impl/StaticLoggerBinder.java    |    1 +
 .../main/java/org/slf4j/impl/StaticMDCBinder.java  |    8 +-
 .../main/java/org/slf4j/impl/StaticMDCBinder.java  |    8 +-
 slf4j-site/src/site/pages/codes.html               |    4 +
 slf4j-site/src/site/pages/faq.html                 |   24 ++++-
 slf4j-site/src/site/pages/news.html                |   10 ++-
 22 files changed, 274 insertions(+), 172 deletions(-)
 copy integration/lib/{slf4j-simple-1.5.0.jar => slf4j-simple-1.4.2.jar} (54%)
 delete mode 100644 integration/lib/slf4j-simple-INCOMPATIBLE.jar
 copy integration/src/test/java/org/slf4j/{MultiBindingAssertionTest.java => MissingSingletonMethodAssertionTest.java} (59%)
 rename {slf4j-nop/src/main/java/org/slf4j/impl => slf4j-api/src/main/java/org/slf4j/helpers}/NOPLoggerFactory.java (98%)
 rename slf4j-api/src/main/java/org/slf4j/helpers/{NOPMakerAdapter.java => NOPMDCAdapter.java} (92%)


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


More information about the slf4j-dev mailing list