View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j;
18  
19  import org.apache.logging.log4j.status.StatusLogger;
20  import org.apache.logging.log4j.spi.LoggerContext;
21  import org.apache.logging.log4j.spi.LoggerContextFactory;
22  
23  import java.io.IOException;
24  import java.net.URL;
25  import java.util.ArrayList;
26  import java.util.Enumeration;
27  import java.util.List;
28  import java.util.Properties;
29  
30  /**
31   * The anchor point for the logging system.
32   */
33  public class LogManager {
34      /**
35       * The name of the root Logger.
36       */
37      public static final String ROOT_LOGGER_NAME = "";
38  
39      private static final String LOGGER_RESOURCE = "META-INF/log4j-provider.xml";
40      private static final String LOGGER_CONTEXT_FACTORY = "LoggerContextFactory";
41      private static final String API_VERSION = "Log4jAPIVersion";
42      private static final String[] COMPATIBLE_API_VERSIONS = {
43          "1.99.0"
44      };
45  
46      private static LoggerContextFactory factory;
47  
48      private static Logger logger = StatusLogger.getLogger();
49  
50      /**
51       * Prevent instantiation
52       */
53      protected LogManager() {
54      }
55  
56  
57      /**
58       * Scans the classpath to find all logging implementation. Currently, only one will
59       * be used but this could be extended to allow multiple implementations to be used.
60       */
61      static {
62          ClassLoader cl = findClassLoader();
63          List<LoggerContextFactory> factories = new ArrayList<LoggerContextFactory>();
64  
65          Enumeration enumResources = null;
66          try {
67              enumResources = cl.getResources(LOGGER_RESOURCE);
68          } catch (IOException e) {
69              logger.fatal("Unable to locate " + LOGGER_RESOURCE, e);
70          }
71  
72          if (enumResources != null) {
73              while (enumResources.hasMoreElements()) {
74                  Properties props = new Properties();
75                  URL url = (URL) enumResources.nextElement();
76                  try {
77                      props.loadFromXML(url.openStream());
78                  } catch (IOException ioe) {
79                      logger.error("Unable to read " + url.toString(), ioe);
80                  }
81                  if (!validVersion(props.getProperty(API_VERSION))) {
82                      continue;
83                  }
84                  String className = props.getProperty(LOGGER_CONTEXT_FACTORY);
85                  if (className != null) {
86                      try {
87                          Class clazz = cl.loadClass(className);
88                          if (LoggerContextFactory.class.isAssignableFrom(clazz)) {
89                              factories.add((LoggerContextFactory) clazz.newInstance());
90                          } else {
91                              logger.error(className + " does not implement " + LoggerContextFactory.class.getName());
92                          }
93                      } catch (ClassNotFoundException cnfe) {
94                          logger.error("Unable to locate class " + className + " specified in " + url.toString(), cnfe);
95                      } catch (IllegalAccessException iae) {
96                          logger.error("Unable to create class " + className + " specified in " + url.toString(), iae);
97                      } catch (Exception e) {
98                          logger.error("Unable to create class " + className + " specified in " + url.toString(), e);
99                          e.printStackTrace();
100                     }
101                 }
102             }
103             if (factories.size() != 1) {
104                 logger.fatal("Unable to locate a logging implementation");
105             } else {
106                 factory = factories.get(0);
107             }
108         } else {
109             logger.fatal("Unable to locate a logging implementation");
110         }
111     }
112 
113     /**
114      * Return the LoggerContextFactory.
115      * @return The LoggerContextFactory.
116      */
117     public static LoggerContextFactory getFactory() {
118         return factory;
119     }
120 
121     /**
122      * Return a Logger with the specified name.
123      *
124      * @param name The logger name.
125      * @return The Logger.
126      */
127     public static Logger getLogger(String name) {
128 
129         return factory.getContext(LogManager.class.getName(), false).getLogger(name);
130     }
131 
132     /**
133      * Return a Logger with the specified name.
134      *
135      * @param fqcn The fully qualified class name of the class that this method is a member of.
136      * @param name The logger name.
137      * @return The Logger.
138      */
139     protected static Logger getLogger(String fqcn, String name) {
140 
141         return factory.getContext(fqcn, false).getLogger(name);
142     }
143 
144     /**
145      * Returns the current LoggerContext.
146      * <p>
147      * WARNING - The LoggerContext returned by this method may not be the LoggerContext used to create a Logger
148      * for the calling class.
149      * @return  The current LoggerContext.
150      */
151     public static LoggerContext getContext() {
152         return factory.getContext(LogManager.class.getName(), true);
153     }
154 
155     /**
156      * Returns a LoggerContext.
157      *
158      * @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For
159      * example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be
160      * returned and if the caller is a class in the container's classpath then a different LoggerContext may be
161      * returned. If true then only a single LoggerContext will be returned.
162      * @return a LoggerContext.
163      */
164     public static LoggerContext getContext(boolean currentContext) {
165         return factory.getContext(LogManager.class.getName(), currentContext);
166     }
167 
168     /**
169      * Returns a LoggerContext
170      * @param fqcn The fully qualified class name of the Class that this method is a member of.
171      * @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For
172      * example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be
173      * returned and if the caller is a class in the container's classpath then a different LoggerContext may be
174      * returned. If true then only a single LoggerContext will be returned.
175      * @return a LoggerContext.
176      */
177     protected static LoggerContext getContext(String fqcn, boolean currentContext) {
178         return factory.getContext(fqcn, currentContext);
179     }
180 
181     private static ClassLoader findClassLoader() {
182         ClassLoader cl;
183         if (System.getSecurityManager() == null) {
184             cl = Thread.currentThread().getContextClassLoader();
185         } else {
186             cl = (ClassLoader) java.security.AccessController.doPrivileged(
187                 new java.security.PrivilegedAction() {
188                     public Object run() {
189                         return Thread.currentThread().getContextClassLoader();
190                     }
191                 }
192             );
193         }
194         if (cl == null) {
195             cl = LogManager.class.getClassLoader();
196         }
197 
198         return cl;
199     }
200 
201     private static boolean validVersion(String version) {
202         for (String v : COMPATIBLE_API_VERSIONS) {
203             if (version.startsWith(v)) {
204                 return true;
205             }
206         }
207         return false;
208     }
209 
210 
211 
212 }