[slf4j-dev] svn commit: r1238 - in slf4j/trunk: jul-to-slf4j/src/main/java/org/slf4j/bridge slf4j-api/src/main/java/org/slf4j slf4j-api/src/main/java/org/slf4j/helpers slf4j-api/src/main/java/org/slf4j/impl slf4j-jcl/src/main/java/org/slf4j/impl slf4j-jdk14/src/main/java/org/slf4j/impl slf4j-log4j12/src/main/java/org/slf4j/impl slf4j-log4j12/src/test/java/org/slf4j/impl slf4j-log4j12/src/test/resources slf4j-nop/src/main/java/org/slf4j/impl slf4j-simple/src/main/java/org/slf4j/impl

ceki at slf4j.org ceki at slf4j.org
Thu Nov 20 11:00:27 CET 2008


Author: ceki
Date: Thu Nov 20 11:00:27 2008
New Revision: 1238

Added:
   slf4j/trunk/slf4j-log4j12/src/test/java/org/slf4j/impl/RecursiveAppender.java
   slf4j/trunk/slf4j-log4j12/src/test/java/org/slf4j/impl/RecursiveInitializationTest.java
   slf4j/trunk/slf4j-log4j12/src/test/resources/
   slf4j/trunk/slf4j-log4j12/src/test/resources/recursiveInit.properties
Modified:
   slf4j/trunk/jul-to-slf4j/src/main/java/org/slf4j/bridge/SLF4JBridgeHandler.java
   slf4j/trunk/slf4j-api/src/main/java/org/slf4j/LoggerFactory.java
   slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/SubstituteLoggerFactory.java
   slf4j/trunk/slf4j-api/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
   slf4j/trunk/slf4j-jcl/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
   slf4j/trunk/slf4j-jdk14/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
   slf4j/trunk/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
   slf4j/trunk/slf4j-nop/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
   slf4j/trunk/slf4j-simple/src/main/java/org/slf4j/impl/StaticLoggerBinder.java

Log:

An attempt at fixing bug 113 [1] and indirectly LBCORE-51 [2]. Instead
of caching StaticLoggerBinder singleton, we retrieve afresh each
time. This agrees well with native implementations with context
selectors, e.g. logback. Unfortunately, the code in LoggerFactory is
no longer dumb and totally obvious. 

[1] http://bugzilla.slf4j.org/show_bug.cgi?id=113
[2] http://jira.qos.ch/browse/LBCORE-51


Modified: slf4j/trunk/jul-to-slf4j/src/main/java/org/slf4j/bridge/SLF4JBridgeHandler.java
==============================================================================
--- slf4j/trunk/jul-to-slf4j/src/main/java/org/slf4j/bridge/SLF4JBridgeHandler.java	(original)
+++ slf4j/trunk/jul-to-slf4j/src/main/java/org/slf4j/bridge/SLF4JBridgeHandler.java	Thu Nov 20 11:00:27 2008
@@ -118,6 +118,13 @@
    *                 LoggingPermission("control").
    */
   public static void uninstall() throws SecurityException, IOException {
+    java.util.logging.Logger rootLogger = LogManager.getLogManager().getLogger("");
+    Handler[] handlers = rootLogger.getHandlers();
+    for(int i = 0; i < handlers.length; i++) {
+      if(handlers[i] instanceof SLF4JBridgeHandler) {
+        rootLogger.removeHandler(handlers[i]);
+      }
+    }
     LogManager.getLogManager().readConfiguration();
   }
 

Modified: slf4j/trunk/slf4j-api/src/main/java/org/slf4j/LoggerFactory.java
==============================================================================
--- slf4j/trunk/slf4j-api/src/main/java/org/slf4j/LoggerFactory.java	(original)
+++ slf4j/trunk/slf4j-api/src/main/java/org/slf4j/LoggerFactory.java	Thu Nov 20 11:00:27 2008
@@ -24,7 +24,6 @@
 
 package org.slf4j;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
@@ -50,40 +49,71 @@
  */
 public final class LoggerFactory {
 
-  static ILoggerFactory loggerFactory;
-
   static final String NO_STATICLOGGERBINDER_URL = "http://www.slf4j.org/codes.html#StaticLoggerBinder";
   static final String NULL_LF_URL = "http://www.slf4j.org/codes.html#null_LF";
   static final String VERSION_MISMATCH = "http://www.slf4j.org/codes.html#version_mismatch";
   static final String SUBSTITUTE_LOGGER_URL = "http://www.slf4j.org/codes.html#substituteLogger";
 
+  static final String UNSUCCESSFUL_INIT_URL = "http://www.slf4j.org/codes.html#unsuccessfulInit";
+  static final String UNSUCCESSFUL_INIT_MSG = "org.slf4j.LoggerFactory could not be successfully initialized. See also "
+      + UNSUCCESSFUL_INIT_URL;
+
+  static final int UNINITIALIZED = 0;
+  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 int INITIALIZATION_STATE = UNINITIALIZED;
+  static int GET_SINGLETON_METHOD = UNINITIALIZED;
+  static SubstituteLoggerFactory TEMP_FACTORY = new SubstituteLoggerFactory();
+
   /**
-   * It is out responsibility to track version changes and manage the
+   * It is our responsibility to track version changes and manage the
    * compatibility list.
    * 
    * <p>
    */
-  static private final String[] API_COMPATIBILITY_LIST = new String[] { "1.5.5", "1.5.6" };
+  static private final String[] API_COMPATIBILITY_LIST = new String[] {
+      "1.5.5", "1.5.6" };
 
   // private constructor prevents instantiation
   private LoggerFactory() {
   }
 
-  static {
-    staticInitialize();
+  /**
+   * Force LoggerFactory to consider itself uninitialized.
+   * 
+   * <p>
+   * This method is intended to be called by classes (in the same package) for
+   * testing purposes. This method is internal. It can be modified, renamed or
+   * removed at any time without notice. 
+   * 
+   * You are strongly discouraged from calling this method in production code.
+   */
+  static void reset() {
+    INITIALIZATION_STATE = UNINITIALIZED;
+    GET_SINGLETON_METHOD = UNINITIALIZED;
+    TEMP_FACTORY = new SubstituteLoggerFactory();
+  }
+
+  private final static void performInitialization() {
+    bind();
     versionSanityCheck();
   }
 
-  private final static void staticInitialize() {
+  private final static void bind() {
     try {
-      // support re-entrant behavior.
-      // See also http://bugzilla.slf4j.org/show_bug.cgi?id=106
-      List loggerNameList = new ArrayList();
-      loggerFactory = new SubstituteLoggerFactory(loggerNameList);
-      loggerFactory = StaticLoggerBinder.SINGLETON.getLoggerFactory();
-      emitSubstitureLoggerWarning(loggerNameList);
+      // the next line does the binding
+      getSingleton();
+      INITIALIZATION_STATE = SUCCESSFUL_INITILIZATION;
+      emitSubstitureLoggerWarning();
     } catch (NoClassDefFoundError ncde) {
-      loggerFactory = null; // undo SubstituteLoggerFactory assignment
+      INITIALIZATION_STATE = FAILED_INITILIZATION;
       String msg = ncde.getMessage();
       if (msg != null && msg.indexOf("org/slf4j/impl/StaticLoggerBinder") != -1) {
         Util
@@ -94,14 +124,15 @@
       }
       throw ncde;
     } catch (Exception e) {
-      loggerFactory = null; // undo SubstituteLoggerFactory assignment
+      INITIALIZATION_STATE = FAILED_INITILIZATION;
       // we should never get here
       Util.reportFailure("Failed to instantiate logger ["
-          + StaticLoggerBinder.SINGLETON.getLoggerFactoryClassStr() + "]", e);
+          + getSingleton().getLoggerFactoryClassStr() + "]", e);
     }
   }
 
-  private final static void emitSubstitureLoggerWarning(List loggerNameList) {
+  private final static void emitSubstitureLoggerWarning() {
+    List loggerNameList = TEMP_FACTORY.getLoggerNameList();
     if (loggerNameList.size() == 0) {
       return;
     }
@@ -133,10 +164,10 @@
         Util.reportFailure("See " + VERSION_MISMATCH + " for further details.");
       }
     } catch (java.lang.NoSuchFieldError nsfe) {
-      // given our large user base anbd SLF4J's commitment to backward
-      // compatibility, we cannot cry
-      // here. Only for implementations which willingly declare a
-      // REQUESTED_API_VERSION field do we emit compatibility warnings.
+      // given our large user base and SLF4J's commitment to backward
+      // compatibility, we cannot cry here. Only for implementations
+      // which willingly declare a REQUESTED_API_VERSION field do we
+      // emit compatibility warnings.
     } catch (Throwable e) {
       // we should never reach here
       Util.reportFailure(
@@ -144,6 +175,27 @@
     }
   }
 
+  
+  private final static StaticLoggerBinder getSingleton() {
+    if(GET_SINGLETON_METHOD == GET_SINGLETON_INEXISTENT) {
+      return StaticLoggerBinder.SINGLETON;
+    }
+    
+    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.SINGLETON;
+    }
+    
+    
+  }
   /**
    * Return a logger named according to the name parameter using the statically
    * bound {@link ILoggerFactory} instance.
@@ -153,12 +205,8 @@
    * @return logger
    */
   public static Logger getLogger(String name) {
-    if (loggerFactory == null) {
-      throw new IllegalStateException(
-          "Logging factory implementation cannot be null. See also "
-              + NULL_LF_URL);
-    }
-    return loggerFactory.getLogger(name);
+    ILoggerFactory iLoggerFactory = getILoggerFactory();
+    return iLoggerFactory.getLogger(name);
   }
 
   /**
@@ -170,12 +218,7 @@
    * @return logger
    */
   public static Logger getLogger(Class clazz) {
-    if (loggerFactory == null) {
-      throw new IllegalStateException(
-          "Logging factory implementation cannot be null. See also "
-              + NULL_LF_URL);
-    }
-    return loggerFactory.getLogger(clazz.getName());
+    return getLogger(clazz.getName());
   }
 
   /**
@@ -187,6 +230,21 @@
    * @return the ILoggerFactory instance in use
    */
   public static ILoggerFactory getILoggerFactory() {
-    return loggerFactory;
+    if (INITIALIZATION_STATE == UNINITIALIZED) {
+      INITIALIZATION_STATE = ONGOING_INITILIZATION;
+      performInitialization();
+
+    }
+    switch (INITIALIZATION_STATE) {
+    case SUCCESSFUL_INITILIZATION:
+      return getSingleton().getLoggerFactory();
+    case FAILED_INITILIZATION:
+      throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
+    case ONGOING_INITILIZATION:
+      // support re-entrant behavior.
+      // See also http://bugzilla.slf4j.org/show_bug.cgi?id=106
+      return TEMP_FACTORY;
+    }
+    throw new IllegalStateException("Unreachable code");
   }
 }

Modified: slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/SubstituteLoggerFactory.java
==============================================================================
--- slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/SubstituteLoggerFactory.java	(original)
+++ slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/SubstituteLoggerFactory.java	Thu Nov 20 11:00:27 2008
@@ -33,35 +33,35 @@
 
 package org.slf4j.helpers;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.slf4j.ILoggerFactory;
 import org.slf4j.Logger;
 
-
 /**
  * SubstituteLoggerFactory is an trivial implementation of {@link
- * ILoggerFactory} which always returns the unique instance of
- * NOPLogger.
+ * ILoggerFactory} which always returns the unique instance of NOPLogger.
  * 
- * <p>It used as a temporary substitute for the real ILoggerFactory
- * during its auto-configuration which may re-enter LoggerFactory
- * to obtain logger instances. See also  
- * http://bugzilla.slf4j.org/show_bug.cgi?id=106
+ * <p>
+ * It used as a temporary substitute for the real ILoggerFactory during its
+ * auto-configuration which may re-enter LoggerFactory to obtain logger
+ * instances. See also http://bugzilla.slf4j.org/show_bug.cgi?id=106
  * 
  * @author Ceki G&uuml;lc&uuml;
  */
 public class SubstituteLoggerFactory implements ILoggerFactory {
-  
+
   // keep a record of requested logger names
-  final List loggerNameList;
-  
-  public SubstituteLoggerFactory(List loggerNameList) {
-    this.loggerNameList = loggerNameList;
-  }
-  
+  final List loggerNameList = new ArrayList();
+
   public Logger getLogger(String name) {
     loggerNameList.add(name);
     return NOPLogger.NOP_LOGGER;
   }
+
+  public List getLoggerNameList() {
+    return loggerNameList;
+  }
+
 }

Modified: slf4j/trunk/slf4j-api/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
==============================================================================
--- slf4j/trunk/slf4j-api/src/main/java/org/slf4j/impl/StaticLoggerBinder.java	(original)
+++ slf4j/trunk/slf4j-api/src/main/java/org/slf4j/impl/StaticLoggerBinder.java	Thu Nov 20 11:00:27 2008
@@ -36,14 +36,27 @@
  * 
  * @author Ceki G&uuml;lc&uuml;
  */
-public class StaticLoggerBinder { 
-
+public class StaticLoggerBinder {
+ 
   /**
    * The unique instance of this class.
+   * 
+   * @deprecated Please use the {@link #getSingleton()} method instead of
+   *             accessing this field directly. In future versions, this field
+   *             will become private.
    */
   public static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
   
   /**
+   * Return the singleton of this class.
+   * 
+   * @return the StaticLoggerBinder singleton
+   */
+  public static final StaticLoggerBinder getSingleton() {
+    return SINGLETON;
+  }
+  
+  /**
    * Declare the version of the SLF4J API this implementation is compiled against. 
    * The value of this field is usually modified with each release. 
    */

Modified: slf4j/trunk/slf4j-jcl/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
==============================================================================
--- slf4j/trunk/slf4j-jcl/src/main/java/org/slf4j/impl/StaticLoggerBinder.java	(original)
+++ slf4j/trunk/slf4j-jcl/src/main/java/org/slf4j/impl/StaticLoggerBinder.java	Thu Nov 20 11:00:27 2008
@@ -48,9 +48,18 @@
   /**
    * The unique instance of this class.
    */
-  public static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
+  private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
 
   /**
+   * Return the singleton of this class.
+   * 
+   * @return the StaticLoggerBinder singleton
+   */
+  public static final StaticLoggerBinder getSingleton() {
+    return SINGLETON;
+  }
+  
+  /**
    * Version tag used to check compatibility. The value of this field is
    * modified with each release. 
    */ 

Modified: slf4j/trunk/slf4j-jdk14/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
==============================================================================
--- slf4j/trunk/slf4j-jdk14/src/main/java/org/slf4j/impl/StaticLoggerBinder.java	(original)
+++ slf4j/trunk/slf4j-jdk14/src/main/java/org/slf4j/impl/StaticLoggerBinder.java	Thu Nov 20 11:00:27 2008
@@ -47,8 +47,19 @@
 
   /**
    * The unique instance of this class.
+   * 
    */
-  public static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
+  private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
+  
+  /**
+   * Return the singleton of this class.
+   * 
+   * @return the StaticLoggerBinder singleton
+   */
+  public static final StaticLoggerBinder getSingleton() {
+    return SINGLETON;
+  }
+
   
   /**
    * Declare the version of the SLF4J API this implementation is compiled against. 

Modified: slf4j/trunk/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
==============================================================================
--- slf4j/trunk/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticLoggerBinder.java	(original)
+++ slf4j/trunk/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticLoggerBinder.java	Thu Nov 20 11:00:27 2008
@@ -39,8 +39,8 @@
 import org.slf4j.spi.LoggerFactoryBinder;
 
 /**
- * The binding of {@link LoggerFactory} class with an actual instance of 
- * {@link ILoggerFactory} is performed using information returned by this class. 
+ * The binding of {@link LoggerFactory} class with an actual instance of
+ * {@link ILoggerFactory} is performed using information returned by this class.
  * 
  * @author Ceki G&uuml;lc&uuml;
  */
@@ -48,37 +48,50 @@
 
   /**
    * The unique instance of this class.
+   * 
    */
-  public static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
-  
+  private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
+
+  /**
+   * Return the singleton of this class.
+   * 
+   * @return the StaticLoggerBinder singleton
+   */
+  public static final StaticLoggerBinder getSingleton() {
+    return SINGLETON;
+  }
+
   /**
-   * Declare the version of the SLF4J API this implementation is compiled against. 
-   * The value of this field is usually modified with each release. 
+   * Declare the version of the SLF4J API this implementation is compiled
+   * against. The value of this field is usually modified with each release.
    */
   // to avoid constant folding by the compiler, this field must *not* be final
-  public static String REQUESTED_API_VERSION = "1.5.6";  // !final
-  
-  private static final String loggerFactoryClassStr = Log4jLoggerFactory.class.getName();
+  public static String REQUESTED_API_VERSION = "1.5.6"; // !final
+
+  private static final String loggerFactoryClassStr = Log4jLoggerFactory.class
+      .getName();
 
-  /** The ILoggerFactory instance returned by the {@link #getLoggerFactory} method
-   * should always be the same object
+  /**
+   * The ILoggerFactory instance returned by the {@link #getLoggerFactory}
+   * method should always be the same object
    */
   private final ILoggerFactory loggerFactory;
-  
+
   private StaticLoggerBinder() {
     loggerFactory = new Log4jLoggerFactory();
     try {
       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");
+    } 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");
     }
   }
-  
+
   public ILoggerFactory getLoggerFactory() {
     return loggerFactory;
   }
-  
+
   public String getLoggerFactoryClassStr() {
     return loggerFactoryClassStr;
-  }   
+  }
 }

Added: slf4j/trunk/slf4j-log4j12/src/test/java/org/slf4j/impl/RecursiveAppender.java
==============================================================================
--- (empty file)
+++ slf4j/trunk/slf4j-log4j12/src/test/java/org/slf4j/impl/RecursiveAppender.java	Thu Nov 20 11:00:27 2008
@@ -0,0 +1,30 @@
+package org.slf4j.impl;
+
+import java.util.Random;
+
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.spi.LoggingEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RecursiveAppender extends AppenderSkeleton {
+
+  int diff = new Random().nextInt();
+  
+  public RecursiveAppender() {
+    System.out.println("in RecursiveAppender constructor");
+    Logger logger = LoggerFactory.getLogger("RecursiveAppender"+diff);
+    System.out.println("logger class="+logger.getClass().getName());
+    logger.info("Calling a logger in the constructor");
+  }
+  
+  protected void append(LoggingEvent arg0) {
+  }
+
+  public void close() {
+  }
+
+  public boolean requiresLayout() {
+    return false;
+  }
+}

Added: slf4j/trunk/slf4j-log4j12/src/test/java/org/slf4j/impl/RecursiveInitializationTest.java
==============================================================================
--- (empty file)
+++ slf4j/trunk/slf4j-log4j12/src/test/java/org/slf4j/impl/RecursiveInitializationTest.java	Thu Nov 20 11:00:27 2008
@@ -0,0 +1,33 @@
+package org.slf4j.impl;
+
+import java.util.Random;
+
+import junit.framework.TestCase;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RecursiveInitializationTest extends TestCase {
+
+  // value of LogManager.DEFAULT_CONFIGURATION_KEY;
+  static String CONFIG_FILE_KEY = "log4j.configuration";
+
+  int diff = new Random().nextInt(10000);
+  
+  protected void setUp() throws Exception {
+    System.setProperty(CONFIG_FILE_KEY, "recursiveInit.properties");
+    super.setUp();
+  }
+
+  protected void tearDown() throws Exception {
+    System.clearProperty(CONFIG_FILE_KEY);
+    super.tearDown();
+  }
+
+  public void testLog4j() {
+    Logger logger = LoggerFactory.getLogger("x"+diff);
+    System.out.println("logger class="+logger.getClass().getName());
+    logger.info("hello");
+  }
+
+}

Added: slf4j/trunk/slf4j-log4j12/src/test/resources/recursiveInit.properties
==============================================================================
--- (empty file)
+++ slf4j/trunk/slf4j-log4j12/src/test/resources/recursiveInit.properties	Thu Nov 20 11:00:27 2008
@@ -0,0 +1,8 @@
+log4j.debug=true
+log4j.rootLogger=DEBUG, RECURSIVE
+
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=%d [%t] %c - %m%n
+
+log4j.appender.RECURSIVE=org.slf4j.impl.RecursiveAppender
\ No newline at end of file

Modified: slf4j/trunk/slf4j-nop/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
==============================================================================
--- slf4j/trunk/slf4j-nop/src/main/java/org/slf4j/impl/StaticLoggerBinder.java	(original)
+++ slf4j/trunk/slf4j-nop/src/main/java/org/slf4j/impl/StaticLoggerBinder.java	Thu Nov 20 11:00:27 2008
@@ -47,8 +47,19 @@
 
   /**
    * The unique instance of this class.
+   * 
    */
-  public static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
+  private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
+
+  /**
+   * Return the singleton of this class.
+   * 
+   * @return the StaticLoggerBinder singleton
+   */
+  public static final StaticLoggerBinder getSingleton() {
+    return SINGLETON;
+  }
+
   
   /**
    * Declare the version of the SLF4J API this implementation is compiled against. 

Modified: slf4j/trunk/slf4j-simple/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
==============================================================================
--- slf4j/trunk/slf4j-simple/src/main/java/org/slf4j/impl/StaticLoggerBinder.java	(original)
+++ slf4j/trunk/slf4j-simple/src/main/java/org/slf4j/impl/StaticLoggerBinder.java	Thu Nov 20 11:00:27 2008
@@ -29,8 +29,8 @@
 import org.slf4j.spi.LoggerFactoryBinder;
 
 /**
- * The binding of {@link LoggerFactory} class with an actual instance of 
- * {@link ILoggerFactory} is performed using information returned by this class. 
+ * The binding of {@link LoggerFactory} class with an actual instance of
+ * {@link ILoggerFactory} is performed using information returned by this class.
  * 
  * 
  * @author Ceki G&uuml;lc&uuml;
@@ -39,20 +39,32 @@
 
   /**
    * The unique instance of this class.
+   * 
    */
-  public static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
+  private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
   
   /**
-   * Declare the version of the SLF4J API this implementation is compiled against. 
-   * The value of this field is usually modified with each release. 
+   * Return the singleton of this class.
+   * 
+   * @return the StaticLoggerBinder singleton
+   */
+  public static final StaticLoggerBinder getSingleton() {
+    return SINGLETON;
+  }
+
+  
+  /**
+   * Declare the version of the SLF4J API this implementation is compiled
+   * against. The value of this field is usually modified with each release.
    */
   // to avoid constant folding by the compiler, this field must *not* be final
   public static String REQUESTED_API_VERSION = "1.5.6";  // !final
   
   private static final String loggerFactoryClassStr = SimpleLoggerFactory.class.getName();
 
-  /** The ILoggerFactory instance returned by the {@link #getLoggerFactory} method
-   * should always be the same object
+  /**
+   * The ILoggerFactory instance returned by the {@link #getLoggerFactory}
+   * method should always be the same object
    */
   private final ILoggerFactory loggerFactory;
   



More information about the slf4j-dev mailing list