View Javadoc

1   /**
2    * Logback: the generic, reliable, fast and flexible logging framework.
3    * 
4    * Copyright (C) 1999-2006, QOS.ch
5    * 
6    * This library is free software, you can redistribute it and/or modify it under
7    * the terms of the GNU Lesser General Public License as published by the Free
8    * Software Foundation.
9    */
10  package org.slf4j.impl;
11  
12  import java.lang.reflect.Constructor;
13  import java.lang.reflect.InvocationTargetException;
14  
15  import org.slf4j.ILoggerFactory;
16  import org.slf4j.LoggerFactory;
17  import org.slf4j.helpers.Util;
18  import org.slf4j.spi.LoggerFactoryBinder;
19  
20  import ch.qos.logback.classic.ClassicGlobal;
21  import ch.qos.logback.classic.LoggerContext;
22  import ch.qos.logback.classic.selector.ContextJNDISelector;
23  import ch.qos.logback.classic.selector.ContextSelector;
24  import ch.qos.logback.classic.selector.DefaultContextSelector;
25  import ch.qos.logback.classic.util.ContextInitializer;
26  import ch.qos.logback.core.CoreConstants;
27  import ch.qos.logback.core.joran.spi.JoranException;
28  import ch.qos.logback.core.util.Loader;
29  import ch.qos.logback.core.util.OptionHelper;
30  import ch.qos.logback.core.util.StatusPrinter;
31  
32  /**
33   * 
34   * The binding of {@link LoggerFactory} class with an actual instance of
35   * {@link ILoggerFactory} is performed using information returned by this class.
36   * 
37   * @author <a href="http://www.qos.ch/log4j/">Ceki G&uuml;lc&uuml;</a>
38   */
39  public class StaticLoggerBinder implements LoggerFactoryBinder {
40  
41    /**
42     * Declare the version of the SLF4J API this implementation is compiled
43     * against. The value of this field is usually modified with each release.
44     */
45    // to avoid constant folding by the compiler, this field must *not* be final
46    public static String REQUESTED_API_VERSION = "1.5.6"; // !final
47  
48    final static String NULL_CS_URL = CoreConstants.CODES_URL + "#null_CS";
49  
50    /**
51     * The unique instance of this class.
52     */
53    private static StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
54  
55    static {
56      SINGLETON.init();
57    }
58  
59    private boolean initialized = false;
60    private LoggerContext defaultLoggerContext = new LoggerContext();
61    private ContextSelector contextSelector;
62  
63    private StaticLoggerBinder() {
64      defaultLoggerContext.setName(CoreConstants.DEFAULT_CONTEXT_NAME);
65    }
66  
67    public static StaticLoggerBinder getSingleton() {
68      return SINGLETON;
69    }
70  
71    /**
72     * Package access for testing purposes.
73     */
74    static void reset() {
75      SINGLETON = new StaticLoggerBinder();
76      SINGLETON.init();
77    }
78  
79    /**
80     * Package access for testing purposes.
81     */
82    void init() {
83      try {
84        try {
85          new ContextInitializer(defaultLoggerContext).autoConfig();
86        } catch (JoranException je) {
87          Util.reportFailure("Failed to auto configure default logger context",
88              je);
89        }
90        StatusPrinter.printInCaseOfErrorsOrWarnings(defaultLoggerContext);
91  
92        // See if a special context selector is needed
93        String contextSelectorStr = OptionHelper
94            .getSystemProperty(ClassicGlobal.LOGBACK_CONTEXT_SELECTOR);
95        if (contextSelectorStr == null) {
96          contextSelector = new DefaultContextSelector(defaultLoggerContext);
97        } else if (contextSelectorStr.equals("JNDI")) {
98          // if jndi is specified, let's use the appropriate class
99          contextSelector = new ContextJNDISelector(defaultLoggerContext);
100       } else {
101         contextSelector = dynamicalContextSelector(defaultLoggerContext,
102             contextSelectorStr);
103       }
104       initialized = true;
105     } catch (Throwable t) {
106       // we should never get here
107       Util.reportFailure("Failed to instantiate ["
108           + LoggerContext.class.getName() + "]", t);
109     }
110   }
111 
112   /**
113    * Intantiate the context selector class designated by the user. The selector
114    * must have a constructor taking a LoggerContext instance as an argument.
115    * 
116    * @param defaultLoggerContext
117    * @param contextSelectorStr
118    * @return an instance of the designated context selector class
119    * @throws ClassNotFoundException
120    * @throws SecurityException
121    * @throws NoSuchMethodException
122    * @throws IllegalArgumentException
123    * @throws InstantiationException
124    * @throws IllegalAccessException
125    * @throws InvocationTargetException
126    */
127   static ContextSelector dynamicalContextSelector(
128       LoggerContext defaultLoggerContext, String contextSelectorStr)
129       throws ClassNotFoundException, SecurityException, NoSuchMethodException,
130       IllegalArgumentException, InstantiationException, IllegalAccessException,
131       InvocationTargetException {
132     Class<?> contextSelectorClass = Loader.loadClass(contextSelectorStr);
133     Constructor cons = contextSelectorClass
134         .getConstructor(new Class[] { LoggerContext.class });
135     return (ContextSelector) cons.newInstance(defaultLoggerContext);
136   }
137 
138   public ILoggerFactory getLoggerFactory() {
139     if (!initialized) {
140       return defaultLoggerContext;
141     }
142 
143     if (contextSelector == null) {
144       throw new IllegalStateException(
145           "contextSelector cannot be null. See also " + NULL_CS_URL);
146     }
147     return contextSelector.getLoggerContext();
148   }
149 
150   public String getLoggerFactoryClassStr() {
151     return contextSelector.getClass().getName();
152   }
153 
154   /**
155    * Return the {@link ContextSelector} instance in use.
156    * 
157    * @return the ContextSelector instance in use
158    */
159   public ContextSelector getContextSelector() {
160     return contextSelector;
161   }
162 
163 }