1   package ch.qos.logback.classic.util;
2   
3   import ch.qos.logback.classic.ClassicConstants;
4   import ch.qos.logback.classic.LoggerContext;
5   import ch.qos.logback.classic.joran.JoranConfigurator;
6   import ch.qos.logback.classic.spi.ConfiguratorRank;
7   import ch.qos.logback.core.Context;
8   import ch.qos.logback.core.LogbackException;
9   import ch.qos.logback.core.joran.spi.JoranException;
10  import ch.qos.logback.classic.spi.Configurator;
11  import ch.qos.logback.core.spi.ContextAwareBase;
12  import ch.qos.logback.core.status.InfoStatus;
13  import ch.qos.logback.core.status.StatusManager;
14  import ch.qos.logback.core.util.Loader;
15  import ch.qos.logback.core.util.OptionHelper;
16  
17  import java.io.File;
18  import java.io.IOException;
19  import java.net.MalformedURLException;
20  import java.net.URL;
21  import java.util.Set;
22  
23  /**
24   * @since 1.3.0-beta1
25   */
26  // Note that DefaultJoranConfigurator is invoked via reflection
27  @ConfiguratorRank(value = ConfiguratorRank.NOMINAL)
28  public class DefaultJoranConfigurator extends ContextAwareBase implements Configurator {
29  
30      @Override
31      public ExecutionStatus configure(LoggerContext context) {
32          URL url = performMultiStepConfigurationFileSearch(true);
33          if (url != null) {
34              try {
35                  configureByResource(url);
36              } catch (JoranException e) {
37                  e.printStackTrace();
38              }
39              // You tried and that counts Mary.
40              return ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY;
41          } else {
42              return ExecutionStatus.INVOKE_NEXT_IF_ANY;
43          }
44      }
45  
46      private URL performMultiStepConfigurationFileSearch(boolean updateStatus) {
47          ClassLoader myClassLoader = Loader.getClassLoaderOfObject(this);
48          URL url = findConfigFileURLFromSystemProperties(myClassLoader, updateStatus);
49          if (url != null) {
50              return url;
51          }
52  
53          url = getResource(ClassicConstants.TEST_AUTOCONFIG_FILE, myClassLoader, updateStatus);
54          if (url != null) {
55              return url;
56          }
57  
58          return getResource(ClassicConstants.AUTOCONFIG_FILE, myClassLoader, updateStatus);
59      }
60      public void configureByResource(URL url) throws JoranException {
61          if (url == null) {
62              throw new IllegalArgumentException("URL argument cannot be null");
63          }
64          final String urlString = url.toString();
65          if (urlString.endsWith("xml")) {
66              JoranConfigurator configurator = new JoranConfigurator();
67              configurator.setContext(context);
68              configurator.doConfigure(url);
69          } else {
70              throw new LogbackException(
71                      "Unexpected filename extension of file [" + url.toString() + "]. Should be .xml");
72          }
73      }
74  
75  
76      /**
77       * Perform multi-search for configuration file
78       * @param updateStatus
79       * @return
80       *
81       * @deprecated  with no replacement
82       */
83      public URL findURLOfDefaultConfigurationFile(boolean updateStatus) {
84          return performMultiStepConfigurationFileSearch(updateStatus);
85      }
86  
87      private URL findConfigFileURLFromSystemProperties(ClassLoader classLoader, boolean updateStatus) {
88          String logbackConfigFile = OptionHelper.getSystemProperty(ClassicConstants.CONFIG_FILE_PROPERTY);
89          if (logbackConfigFile != null) {
90              URL result = null;
91              try {
92                  result = new URL(logbackConfigFile);
93                  return result;
94              } catch (MalformedURLException e) {
95                  // so, resource is not a URL:
96                  // attempt to get the resource from the class path
97                  result = Loader.getResource(logbackConfigFile, classLoader);
98                  if (result != null) {
99                      return result;
100                 }
101                 // if the above fails, try to find as a file
102                 File f = new File(logbackConfigFile);
103                 if (f.exists() && f.isFile()) {
104                     try {
105                         result = f.toURI().toURL();
106                         return result;
107                     } catch (MalformedURLException e1) {
108                     }
109                 }
110             } finally {
111                 if (updateStatus) {
112                     statusOnResourceSearch(logbackConfigFile, classLoader, result);
113                 }
114             }
115         }
116         return null;
117     }
118 
119     private URL getResource(String filename, ClassLoader myClassLoader, boolean updateStatus) {
120         URL url = Loader.getResource(filename, myClassLoader);
121         if (updateStatus) {
122             statusOnResourceSearch(filename, myClassLoader, url);
123         }
124         return url;
125     }
126 
127     private void statusOnResourceSearch(String resourceName, ClassLoader classLoader, URL url) {
128         StatusManager sm = context.getStatusManager();
129         if (url == null) {
130             sm.add(new InfoStatus("Could NOT find resource [" + resourceName + "]", context));
131         } else {
132             sm.add(new InfoStatus("Found resource [" + resourceName + "] at [" + url.toString() + "]", context));
133             multiplicityWarning(resourceName, classLoader);
134         }
135     }
136 
137     private void multiplicityWarning(String resourceName, ClassLoader classLoader) {
138         Set<URL> urlSet = null;
139         try {
140             urlSet = Loader.getResources(resourceName, classLoader);
141         } catch (IOException e) {
142             addError("Failed to get url list for resource [" + resourceName + "]", e);
143         }
144         if (urlSet != null && urlSet.size() > 1) {
145             addWarn("Resource [" + resourceName + "] occurs multiple times on the classpath.");
146             for (URL url : urlSet) {
147                 addWarn("Resource [" + resourceName + "] occurs at [" + url.toString() + "]");
148             }
149         }
150     }
151 }