Home » SLF4J-1.5.8 » org » slf4j » [javadoc | source]

    1   /*
    2    * Copyright (c) 2004-2008 QOS.ch
    3    * All rights reserved.
    4    * 
    5    * Permission is hereby granted, free  of charge, to any person obtaining
    6    * a  copy  of this  software  and  associated  documentation files  (the
    7    * "Software"), to  deal in  the Software without  restriction, including
    8    * without limitation  the rights to  use, copy, modify,  merge, publish,
    9    * distribute,  sublicense, and/or sell  copies of  the Software,  and to
   10    * permit persons to whom the Software  is furnished to do so, subject to
   11    * the following conditions:
   12    * 
   13    * The  above  copyright  notice  and  this permission  notice  shall  be
   14    * included in all copies or substantial portions of the Software.
   15    * 
   16    * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
   17    * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
   18    * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
   19    * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
   20    * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
   21    * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
   22    * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   23    */
   24   
   25   package org.slf4j;
   26   
   27   import java.io.File;
   28   import java.io.IOException;
   29   import java.net.URL;
   30   import java.util.ArrayList;
   31   import java.util.Arrays;
   32   import java.util.Enumeration;
   33   import java.util.List;
   34   
   35   import org.slf4j.helpers.SubstituteLoggerFactory;
   36   import org.slf4j.helpers.Util;
   37   import org.slf4j.impl.StaticLoggerBinder;
   38   
   39   /**
   40    * The <code>LoggerFactory</code> is a utility class producing Loggers for
   41    * various logging APIs, most notably for log4j, logback and JDK 1.4 logging.
   42    * Other implementations such as {@link org.slf4j.impl.NOPLogger NOPLogger} and
   43    * {@link org.slf4j.impl.SimpleLogger SimpleLogger} are also supported.
   44    * 
   45    * <p>
   46    * <code>LoggerFactory</code> is essentially a wrapper around an
   47    * {@link ILoggerFactory} instance bound with <code>LoggerFactory</code> at
   48    * compile time.
   49    * 
   50    * <p>
   51    * Please note that all methods in <code>LoggerFactory</code> are static.
   52    * 
   53    * @author Ceki G&uuml;lc&uuml;
   54    * @author Robert Elliot
   55    */
   56   public final class LoggerFactory {
   57   
   58     static final String NO_STATICLOGGERBINDER_URL = "http://www.slf4j.org/codes.html#StaticLoggerBinder";
   59     static final String MULTIPLE_BINDINGS_URL = "http://www.slf4j.org/codes.html#multiple_bindings";
   60     static final String NULL_LF_URL = "http://www.slf4j.org/codes.html#null_LF";
   61     static final String VERSION_MISMATCH = "http://www.slf4j.org/codes.html#version_mismatch";
   62     static final String SUBSTITUTE_LOGGER_URL = "http://www.slf4j.org/codes.html#substituteLogger";
   63   
   64     static final String UNSUCCESSFUL_INIT_URL = "http://www.slf4j.org/codes.html#unsuccessfulInit";
   65     static final String UNSUCCESSFUL_INIT_MSG = "org.slf4j.LoggerFactory could not be successfully initialized. See also "
   66         + UNSUCCESSFUL_INIT_URL;
   67   
   68     static final int UNINITIALIZED = 0;
   69     static final int ONGOING_INITILIZATION = 1;
   70     static final int FAILED_INITILIZATION = 2;
   71     static final int SUCCESSFUL_INITILIZATION = 3;
   72   
   73     static final int GET_SINGLETON_INEXISTENT = 1;
   74     static final int GET_SINGLETON_EXISTS = 2;
   75   
   76     static int INITIALIZATION_STATE = UNINITIALIZED;
   77     static int GET_SINGLETON_METHOD = UNINITIALIZED;
   78     static SubstituteLoggerFactory TEMP_FACTORY = new SubstituteLoggerFactory();
   79   
   80     /**
   81      * It is our responsibility to track version changes and manage the
   82      * compatibility list.
   83      * 
   84      * <p>
   85      */
   86     static private final String[] API_COMPATIBILITY_LIST = new String[] {
   87         "1.5.5", "1.5.6", "1.5.7", "1.5.8" };
   88   
   89     // private constructor prevents instantiation
   90     private LoggerFactory() {
   91     }
   92   
   93     /**
   94      * Force LoggerFactory to consider itself uninitialized.
   95      * 
   96      * <p>
   97      * This method is intended to be called by classes (in the same package) for
   98      * testing purposes. This method is internal. It can be modified, renamed or
   99      * removed at any time without notice.
  100      * 
  101      * <p>
  102      * You are strongly discouraged from calling this method in production code.
  103      */
  104     static void reset() {
  105       INITIALIZATION_STATE = UNINITIALIZED;
  106       GET_SINGLETON_METHOD = UNINITIALIZED;
  107       TEMP_FACTORY = new SubstituteLoggerFactory();
  108     }
  109   
  110     private final static void performInitialization() {
  111       bind();
  112       versionSanityCheck();
  113       singleImplementationSanityCheck();
  114   
  115     }
  116   
  117     private final static void bind() {
  118       try {
  119         // the next line does the binding
  120         getSingleton();
  121         INITIALIZATION_STATE = SUCCESSFUL_INITILIZATION;
  122         emitSubstitureLoggerWarning();
  123       } catch (NoClassDefFoundError ncde) {
  124         INITIALIZATION_STATE = FAILED_INITILIZATION;
  125         String msg = ncde.getMessage();
  126         if (msg != null && msg.indexOf("org/slf4j/impl/StaticLoggerBinder") != -1) {
  127           Util
  128               .reportFailure("Failed to load class \"org.slf4j.impl.StaticLoggerBinder\".");
  129           Util.reportFailure("See " + NO_STATICLOGGERBINDER_URL
  130               + " for further details.");
  131   
  132         }
  133         throw ncde;
  134       } catch (Exception e) {
  135         INITIALIZATION_STATE = FAILED_INITILIZATION;
  136         // we should never get here
  137         Util.reportFailure("Failed to instantiate logger ["
  138             + getSingleton().getLoggerFactoryClassStr() + "]", e);
  139       }
  140     }
  141   
  142     private final static void emitSubstitureLoggerWarning() {
  143       List loggerNameList = TEMP_FACTORY.getLoggerNameList();
  144       if (loggerNameList.size() == 0) {
  145         return;
  146       }
  147       Util
  148           .reportFailure("The following loggers will not work becasue they were created");
  149       Util
  150           .reportFailure("during the default configuration phase of the underlying logging system.");
  151       Util.reportFailure("See also " + SUBSTITUTE_LOGGER_URL);
  152       for (int i = 0; i < loggerNameList.size(); i++) {
  153         String loggerName = (String) loggerNameList.get(i);
  154         Util.reportFailure(loggerName);
  155       }
  156     }
  157   
  158     private final static void versionSanityCheck() {
  159       try {
  160         String requested = StaticLoggerBinder.REQUESTED_API_VERSION;
  161   
  162         boolean match = false;
  163         for (int i = 0; i < API_COMPATIBILITY_LIST.length; i++) {
  164           if (API_COMPATIBILITY_LIST[i].equals(requested)) {
  165             match = true;
  166           }
  167         }
  168         if (!match) {
  169           Util.reportFailure("The requested version " + requested
  170               + " by your slf4j binding is not compatible with "
  171               + Arrays.asList(API_COMPATIBILITY_LIST).toString());
  172           Util.reportFailure("See " + VERSION_MISMATCH + " for further details.");
  173         }
  174       } catch (java.lang.NoSuchFieldError nsfe) {
  175         // given our large user base and SLF4J's commitment to backward
  176         // compatibility, we cannot cry here. Only for implementations
  177         // which willingly declare a REQUESTED_API_VERSION field do we
  178         // emit compatibility warnings.
  179       } catch (Throwable e) {
  180         // we should never reach here
  181         Util.reportFailure(
  182             "Unexpected problem occured during version sanity check", e);
  183       }
  184     }
  185   
  186     // We need to use the name of the StaticLoggerBinder class, we can't reference
  187     // the class itseld.
  188     private static String STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class";
  189   
  190     private static void singleImplementationSanityCheck() {
  191       try {
  192         Enumeration paths = LoggerFactory.class.getClassLoader().getResources(
  193             STATIC_LOGGER_BINDER_PATH);
  194         List implementationList = new ArrayList();
  195         while (paths.hasMoreElements()) {
  196           URL path = (URL) paths.nextElement();
  197           implementationList.add(path);
  198         }
  199         if (implementationList.size() > 1) {
  200           Util
  201               .reportFailure("Class path contains multiple SLF4J bindings.");
  202           for(int i = 0; i < implementationList.size(); i++) {
  203             Util.reportFailure("Found binding in ["+implementationList.get(i)+"]");
  204           }
  205           Util.reportFailure("See " + MULTIPLE_BINDINGS_URL
  206               + " for an explanation.");
  207         }
  208       } catch (IOException ioe) {
  209         Util.reportFailure("Error getting resources from path", ioe);
  210       }
  211     }
  212   
  213     private final static StaticLoggerBinder getSingleton() {
  214       if (GET_SINGLETON_METHOD == GET_SINGLETON_INEXISTENT) {
  215         return StaticLoggerBinder.SINGLETON;
  216       }
  217   
  218       if (GET_SINGLETON_METHOD == GET_SINGLETON_EXISTS) {
  219         return StaticLoggerBinder.getSingleton();
  220       }
  221   
  222       try {
  223         StaticLoggerBinder singleton = StaticLoggerBinder.getSingleton();
  224         GET_SINGLETON_METHOD = GET_SINGLETON_EXISTS;
  225         return singleton;
  226       } catch (NoSuchMethodError nsme) {
  227         GET_SINGLETON_METHOD = GET_SINGLETON_INEXISTENT;
  228         return StaticLoggerBinder.SINGLETON;
  229       }
  230   
  231     }
  232   
  233     /**
  234      * Return a logger named according to the name parameter using the statically
  235      * bound {@link ILoggerFactory} instance.
  236      * 
  237      * @param name
  238      *                The name of the logger.
  239      * @return logger
  240      */
  241     public static Logger getLogger(String name) {
  242       ILoggerFactory iLoggerFactory = getILoggerFactory();
  243       return iLoggerFactory.getLogger(name);
  244     }
  245   
  246     /**
  247      * Return a logger named corresponding to the class passed as parameter, using
  248      * the statically bound {@link ILoggerFactory} instance.
  249      * 
  250      * @param clazz
  251      *                the returned logger will be named after clazz
  252      * @return logger
  253      */
  254     public static Logger getLogger(Class clazz) {
  255       return getLogger(clazz.getName());
  256     }
  257   
  258     /**
  259      * Return the {@link ILoggerFactory} instance in use.
  260      * 
  261      * <p>
  262      * ILoggerFactory instance is bound with this class at compile time.
  263      * 
  264      * @return the ILoggerFactory instance in use
  265      */
  266     public static ILoggerFactory getILoggerFactory() {
  267       if (INITIALIZATION_STATE == UNINITIALIZED) {
  268         INITIALIZATION_STATE = ONGOING_INITILIZATION;
  269         performInitialization();
  270   
  271       }
  272       switch (INITIALIZATION_STATE) {
  273       case SUCCESSFUL_INITILIZATION:
  274         return getSingleton().getLoggerFactory();
  275       case FAILED_INITILIZATION:
  276         throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
  277       case ONGOING_INITILIZATION:
  278         // support re-entrant behavior.
  279         // See also http://bugzilla.slf4j.org/show_bug.cgi?id=106
  280         return TEMP_FACTORY;
  281       }
  282       throw new IllegalStateException("Unreachable code");
  283     }
  284   }

Home » SLF4J-1.5.8 » org » slf4j » [javadoc | source]