View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2011, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.classic.util;
15  
16  import java.io.File;
17  import java.io.IOException;
18  import java.net.MalformedURLException;
19  import java.net.URL;
20  import java.util.List;
21  
22  import ch.qos.logback.classic.BasicConfigurator;
23  import ch.qos.logback.classic.LoggerContext;
24  import ch.qos.logback.classic.gaffer.GafferUtil;
25  import ch.qos.logback.classic.joran.JoranConfigurator;
26  import ch.qos.logback.core.joran.spi.JoranException;
27  import ch.qos.logback.core.status.ErrorStatus;
28  import ch.qos.logback.core.status.InfoStatus;
29  import ch.qos.logback.core.status.StatusManager;
30  import ch.qos.logback.core.status.WarnStatus;
31  import ch.qos.logback.core.util.Loader;
32  import ch.qos.logback.core.util.OptionHelper;
33  
34  // contributors
35  // Ted Graham, Matt Fowles, see also http://jira.qos.ch/browse/LBCORE-32
36  
37  /**
38   * This class contains logback's logic for automatic configuration
39   *
40   * @author Ceki Gulcu
41   */
42  public class ContextInitializer {
43  
44    final public static String GROOVY_AUTOCONFIG_FILE = "logback.groovy";
45    final public static String AUTOCONFIG_FILE = "logback.xml";
46    final public static String TEST_AUTOCONFIG_FILE = "logback-test.xml";
47    final public static String CONFIG_FILE_PROPERTY = "logback.configurationFile";
48    final public static String STATUS_LISTENER_CLASS = "logback.statusListenerClass";
49    final public static String SYSOUT = "SYSOUT";
50  
51    final LoggerContext loggerContext;
52  
53    public ContextInitializer(LoggerContext loggerContext) {
54      this.loggerContext = loggerContext;
55    }
56  
57    public void configureByResource(URL url) throws JoranException {
58      if (url == null) {
59        throw new IllegalArgumentException("URL argument cannot be null");
60      }
61      if (url.toString().endsWith("groovy")) {
62        if (EnvUtil.isGroovyAvailable()) {
63          // avoid directly referring to GafferConfigurator so as to avoid
64          // loading  groovy.lang.GroovyObject . See also http://jira.qos.ch/browse/LBCLASSIC-214
65          GafferUtil.runGafferConfiguratorOn(loggerContext, this, url);
66        } else {
67          StatusManager sm = loggerContext.getStatusManager();
68          sm.add(new ErrorStatus("Groovy classes are not available on the class path. ABORTING INITIALIZATION.",
69                  loggerContext));
70        }
71      }
72      if (url.toString().endsWith("xml")) {
73        JoranConfigurator configurator = new JoranConfigurator();
74        configurator.setContext(loggerContext);
75        configurator.doConfigure(url);
76      }
77    }
78  
79    void joranConfigureByResource(URL url) throws JoranException {
80      JoranConfigurator configurator = new JoranConfigurator();
81      configurator.setContext(loggerContext);
82      configurator.doConfigure(url);
83    }
84  
85    private URL findConfigFileURLFromSystemProperties(ClassLoader classLoader, boolean updateStatus) {
86      String logbackConfigFile = OptionHelper.getSystemProperty(CONFIG_FILE_PROPERTY);
87      if (logbackConfigFile != null) {
88        URL result = null;
89        try {
90          result = new URL(logbackConfigFile);
91          return result;
92        } catch (MalformedURLException e) {
93          // so, resource is not a URL:
94          // attempt to get the resource from the class path
95          result = Loader.getResource(logbackConfigFile, classLoader);
96          if (result != null) {
97            return result;
98          }
99          File f = new File(logbackConfigFile);
100         if (f.exists() && f.isFile()) {
101           try {
102             result = f.toURI().toURL();
103             return result;
104           } catch (MalformedURLException e1) {
105           }
106         }
107       } finally {
108         if (updateStatus) {
109           statusOnResourceSearch(logbackConfigFile, classLoader, result);
110         }
111       }
112     }
113     return null;
114   }
115 
116   public URL findURLOfDefaultConfigurationFile(boolean updateStatus) {
117     ClassLoader myClassLoader = Loader.getClassLoaderOfObject(this);
118     URL url = findConfigFileURLFromSystemProperties(myClassLoader, updateStatus);
119     if (url != null) {
120       return url;
121     }
122 
123     url = getResource(GROOVY_AUTOCONFIG_FILE, myClassLoader, updateStatus);
124     if (url != null) {
125       return url;
126     }
127 
128     url = getResource(TEST_AUTOCONFIG_FILE, myClassLoader, updateStatus);
129     if (url != null) {
130       return url;
131     }
132 
133     return getResource(AUTOCONFIG_FILE, myClassLoader, updateStatus);
134   }
135 
136   private URL getResource(String filename, ClassLoader myClassLoader, boolean updateStatus) {
137     URL url = Loader.getResource(filename, myClassLoader);
138     if (updateStatus) {
139       statusOnResourceSearch(filename, myClassLoader, url);
140     }
141     return url;
142   }
143 
144   public void autoConfig() throws JoranException {
145     StatusListenerConfigHelper.installIfAsked(loggerContext);
146     URL url = findURLOfDefaultConfigurationFile(true);
147     if (url != null) {
148       configureByResource(url);
149     } else {
150       BasicConfigurator.configure(loggerContext);
151     }
152   }
153 
154   private void multiplicityWarning(String resourceName, ClassLoader classLoader) {
155     List<URL> urlList = null;
156     StatusManager sm = loggerContext.getStatusManager();
157     try {
158       urlList = Loader.getResourceOccurenceCount(resourceName, classLoader);
159     } catch (IOException e) {
160       sm.add(new ErrorStatus("Failed to get url list for resource [" + resourceName + "]",
161               loggerContext, e));
162     }
163     if (urlList != null && urlList.size() > 1) {
164       sm.add(new WarnStatus("Resource [" + resourceName + "] occurs multiple times on the classpath.",
165               loggerContext));
166       for (URL url : urlList) {
167         sm.add(new WarnStatus("Resource [" + resourceName + "] occurs at [" + url.toString() + "]",
168                 loggerContext));
169       }
170     }
171   }
172 
173   private void statusOnResourceSearch(String resourceName, ClassLoader classLoader, URL url) {
174     StatusManager sm = loggerContext.getStatusManager();
175     if (url == null) {
176       sm.add(new InfoStatus("Could NOT find resource [" + resourceName + "]",
177               loggerContext));
178     } else {
179       sm.add(new InfoStatus("Found resource [" + resourceName + "] at [" + url.toString() + "]",
180               loggerContext));
181       multiplicityWarning(resourceName, classLoader);
182     }
183   }
184 
185 }