View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, 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.Set;
21  
22  import ch.qos.logback.classic.BasicConfigurator;
23  import ch.qos.logback.classic.ClassicConstants;
24  import ch.qos.logback.classic.LoggerContext;
25  import ch.qos.logback.classic.joran.JoranConfigurator;
26  import ch.qos.logback.classic.spi.Configurator;
27  import ch.qos.logback.core.LogbackException;
28  import ch.qos.logback.core.joran.spi.JoranException;
29  import ch.qos.logback.core.status.ErrorStatus;
30  import ch.qos.logback.core.status.InfoStatus;
31  import ch.qos.logback.core.status.StatusManager;
32  import ch.qos.logback.core.status.WarnStatus;
33  import ch.qos.logback.core.util.Loader;
34  import ch.qos.logback.core.util.OptionHelper;
35  import ch.qos.logback.core.util.StatusListenerConfigHelper;
36  
37  // contributors
38  // Ted Graham, Matt Fowles, see also http://jira.qos.ch/browse/LBCORE-32
39  
40  /**
41   * This class contains logback's logic for automatic configuration
42   *
43   * @author Ceki Gulcu
44   */
45  public class ContextInitializer {
46  
47      final public static String GROOVY_AUTOCONFIG_FILE = "logback.groovy";
48      final public static String AUTOCONFIG_FILE = "logback.xml";
49      final public static String TEST_AUTOCONFIG_FILE = "logback-test.xml";
50      /**
51       * @deprecated Please use ClassicConstants.CONFIG_FILE_PROPERTY instead
52       */
53      final public static String CONFIG_FILE_PROPERTY = ClassicConstants.CONFIG_FILE_PROPERTY;
54  
55      final LoggerContext loggerContext;
56  
57      public ContextInitializer(LoggerContext loggerContext) {
58          this.loggerContext = loggerContext;
59      }
60  
61      public void configureByResource(URL url) throws JoranException {
62          if (url == null) {
63              throw new IllegalArgumentException("URL argument cannot be null");
64          }
65          final String urlString = url.toString();
66          if (urlString.endsWith("groovy")) {
67              if (EnvUtil.isGroovyAvailable()) {
68                  // avoid directly referring to GafferConfigurator so as to avoid
69                  // loading groovy.lang.GroovyObject . See also http://jira.qos.ch/browse/LBCLASSIC-214
70                  //GafferUtil.runGafferConfiguratorOn(loggerContext, this, url);
71  
72                  StatusManager sm = loggerContext.getStatusManager();
73                  sm.add(new ErrorStatus("Groovy configuration disabled due to Java 9 compilation issues.", loggerContext));
74                  
75              } else {
76                  StatusManager sm = loggerContext.getStatusManager();
77                  sm.add(new ErrorStatus("Groovy classes are not available on the class path. ABORTING INITIALIZATION.", loggerContext));
78              }
79          } else if (urlString.endsWith("xml")) {
80              JoranConfigurator configurator = new JoranConfigurator();
81              configurator.setContext(loggerContext);
82              configurator.doConfigure(url);
83          } else {
84              throw new LogbackException("Unexpected filename extension of file [" + url.toString() + "]. Should be either .groovy or .xml");
85          }
86      }
87  
88      void joranConfigureByResource(URL url) throws JoranException {
89          JoranConfigurator configurator = new JoranConfigurator();
90          configurator.setContext(loggerContext);
91          configurator.doConfigure(url);
92      }
93  
94      private URL findConfigFileURLFromSystemProperties(ClassLoader classLoader, boolean updateStatus) {
95          String logbackConfigFile = OptionHelper.getSystemProperty(CONFIG_FILE_PROPERTY);
96          if (logbackConfigFile != null) {
97              URL result = null;
98              try {
99                  result = new URL(logbackConfigFile);
100                 return result;
101             } catch (MalformedURLException e) {
102                 // so, resource is not a URL:
103                 // attempt to get the resource from the class path
104                 result = Loader.getResource(logbackConfigFile, classLoader);
105                 if (result != null) {
106                     return result;
107                 }
108                 File f = new File(logbackConfigFile);
109                 if (f.exists() && f.isFile()) {
110                     try {
111                         result = f.toURI().toURL();
112                         return result;
113                     } catch (MalformedURLException e1) {
114                     }
115                 }
116             } finally {
117                 if (updateStatus) {
118                     statusOnResourceSearch(logbackConfigFile, classLoader, result);
119                 }
120             }
121         }
122         return null;
123     }
124 
125     public URL findURLOfDefaultConfigurationFile(boolean updateStatus) {
126         ClassLoader myClassLoader = Loader.getClassLoaderOfObject(this);
127         URL url = findConfigFileURLFromSystemProperties(myClassLoader, updateStatus);
128         if (url != null) {
129             return url;
130         }
131 
132         url = getResource(TEST_AUTOCONFIG_FILE, myClassLoader, updateStatus);
133         if (url != null) {
134             return url;
135         }
136 
137         url = getResource(GROOVY_AUTOCONFIG_FILE, myClassLoader, updateStatus);
138         if (url != null) {
139             return url;
140         }
141 
142         return getResource(AUTOCONFIG_FILE, myClassLoader, updateStatus);
143     }
144 
145     private URL getResource(String filename, ClassLoader myClassLoader, boolean updateStatus) {
146         URL url = Loader.getResource(filename, myClassLoader);
147         if (updateStatus) {
148             statusOnResourceSearch(filename, myClassLoader, url);
149         }
150         return url;
151     }
152 
153     public void autoConfig() throws JoranException {
154         StatusListenerConfigHelper.installIfAsked(loggerContext);
155         URL url = findURLOfDefaultConfigurationFile(true);
156         if (url != null) {
157             configureByResource(url);
158         } else {
159             Configurator c = EnvUtil.loadFromServiceLoader(Configurator.class);
160             if (c != null) {
161                 try {
162                     c.setContext(loggerContext);
163                     c.configure(loggerContext);
164                 } catch (Exception e) {
165                     throw new LogbackException(String.format("Failed to initialize Configurator: %s using ServiceLoader", c != null ? c.getClass()
166                                     .getCanonicalName() : "null"), e);
167                 }
168             } else {
169                 BasicConfigurator basicConfigurator = new BasicConfigurator();
170                 basicConfigurator.setContext(loggerContext);
171                 basicConfigurator.configure(loggerContext);
172             }
173         }
174     }
175 
176     private void statusOnResourceSearch(String resourceName, ClassLoader classLoader, URL url) {
177         StatusManager sm = loggerContext.getStatusManager();
178         if (url == null) {
179             sm.add(new InfoStatus("Could NOT find resource [" + resourceName + "]", loggerContext));
180         } else {
181             sm.add(new InfoStatus("Found resource [" + resourceName + "] at [" + url.toString() + "]", loggerContext));
182             multiplicityWarning(resourceName, classLoader);
183         }
184     }
185 
186     private void multiplicityWarning(String resourceName, ClassLoader classLoader) {
187         Set<URL> urlSet = null;
188         StatusManager sm = loggerContext.getStatusManager();
189         try {
190             urlSet = Loader.getResources(resourceName, classLoader);
191         } catch (IOException e) {
192             sm.add(new ErrorStatus("Failed to get url list for resource [" + resourceName + "]", loggerContext, e));
193         }
194         if (urlSet != null && urlSet.size() > 1) {
195             sm.add(new WarnStatus("Resource [" + resourceName + "] occurs multiple times on the classpath.", loggerContext));
196             for (URL url : urlSet) {
197                 sm.add(new WarnStatus("Resource [" + resourceName + "] occurs at [" + url.toString() + "]", loggerContext));
198             }
199         }
200     }
201 }