View Javadoc

1   // ========================================================================
2   // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses.
12  // ========================================================================
13  
14  package org.eclipse.jetty.util.log;
15  
16  import java.io.IOException;
17  import java.io.InputStream;
18  import java.lang.reflect.Method;
19  import java.net.URL;
20  import java.security.AccessController;
21  import java.security.PrivilegedAction;
22  import java.util.Enumeration;
23  import java.util.Properties;
24  
25  import org.eclipse.jetty.util.IO;
26  import org.eclipse.jetty.util.Loader;
27  
28  /**
29   * Logging.
30   * This class provides a static logging interface.  If an instance of the
31   * org.slf4j.Logger class is found on the classpath, the static log methods
32   * are directed to a slf4j logger for "org.eclipse.log".   Otherwise the logs
33   * are directed to stderr.
34   * <p>
35   * The "org.eclipse.jetty.util.log.class" system property can be used
36   * to select a specific logging implementation.
37   * <p>
38   * If the system property org.eclipse.jetty.util.log.IGNORED is set,
39   * then ignored exceptions are logged in detail.
40   *
41   * @see StdErrLog
42   * @see Slf4jLog
43   */
44  public class Log
45  {
46      public final static String EXCEPTION= "EXCEPTION ";
47      public final static String IGNORED= "IGNORED ";
48  
49      /**
50       * Logging Configuration Properties
51       */
52      protected static Properties __props;
53      /**
54       * The {@link Logger} implementation class name
55       */
56      public static String __logClass;
57      /**
58       * Legacy flag indicating if {@link Log#ignore(Throwable)} methods produce any output in the {@link Logger}s
59       */
60      public static boolean __ignored;
61  
62      static
63      {
64          /* Instantiate a default configuration properties (empty)
65           */
66          __props = new Properties();
67  
68          AccessController.doPrivileged(new PrivilegedAction<Object>()
69          {
70              public Object run()
71              {
72                  /* First see if the jetty-logging.properties object exists in the classpath.
73                   * This is an optional feature used by embedded mode use, and test cases to allow for early
74                   * configuration of the Log class in situations where access to the System.properties are
75                   * either too late or just impossible.
76                   */
77                  URL testProps = Log.class.getClassLoader().getResource("jetty-logging.properties");
78                  if (testProps != null)
79                  {
80                      InputStream in = null;
81                      try
82                      {
83                          in = testProps.openStream();
84                          __props.load(in);
85                      }
86                      catch (IOException e)
87                      {
88                          System.err.println("Unable to load " + testProps);
89                          e.printStackTrace(System.err);
90                      }
91                      finally
92                      {
93                          IO.close(in);
94                      }
95                  }
96  
97                  /* Now load the System.properties as-is into the __props, these values will override
98                   * any key conflicts in __props.
99                   */
100                 @SuppressWarnings("unchecked")
101                 Enumeration<String> systemKeyEnum = (Enumeration<String>)System.getProperties().propertyNames();
102                 while (systemKeyEnum.hasMoreElements())
103                 {
104                     String key = systemKeyEnum.nextElement();
105                     __props.setProperty(key,System.getProperty(key));
106                 }
107 
108                 /* Now use the configuration properties to configure the Log statics
109                  */
110                 __logClass = __props.getProperty("org.eclipse.jetty.util.log.class","org.eclipse.jetty.util.log.Slf4jLog");
111                 __ignored = Boolean.parseBoolean(__props.getProperty("org.eclipse.jetty.util.log.IGNORED","false"));
112                 return null;
113             }
114         });
115     }
116 
117     private static Logger LOG;
118     private static boolean __initialized;
119 
120     public static boolean initialized()
121     {
122         if (LOG != null)
123         {
124             return true;
125         }
126 
127         synchronized (Log.class)
128         {
129             if (__initialized)
130             {
131                 return LOG != null;
132             }
133             __initialized = true;
134         }
135 
136         try
137         {
138             Class<?> log_class = Loader.loadClass(Log.class, __logClass);
139             if (LOG == null || !LOG.getClass().equals(log_class))
140             {
141                 LOG = (Logger)log_class.newInstance();
142                 LOG.debug("Logging to {} via {}", LOG, log_class.getName());
143             }
144         }
145         catch(Throwable e)
146         {
147             // Unable to load specified Logger implementation, default to standard logging.
148             initStandardLogging(e);
149         }
150 
151         return LOG != null;
152     }
153 
154     private static void initStandardLogging(Throwable e)
155     {
156         Class<?> log_class;
157         if(e != null && __ignored)
158         {
159             e.printStackTrace();
160         }
161 
162         if (LOG == null)
163         {
164             log_class = StdErrLog.class;
165             LOG = new StdErrLog();
166             LOG.debug("Logging to {} via {}", LOG, log_class.getName());
167         }
168     }
169 
170     public static void setLog(Logger log)
171     {
172         Log.LOG = log;
173     }
174 
175     /**
176      * @deprecated anonymous logging is deprecated, use a named {@link Logger} obtained from {@link #getLogger(String)}
177      */
178     @Deprecated
179     public static Logger getLog()
180     {
181         initialized();
182         return LOG;
183     }
184 
185     /**
186      * Get the root logger.
187      * @return the root logger
188      */
189     public static Logger getRootLogger() {
190         initialized();
191         return LOG;
192     }
193 
194     static boolean isIgnored()
195     {
196         return __ignored;
197     }
198 
199     /**
200      * Set Log to parent Logger.
201      * <p>
202      * If there is a different Log class available from a parent classloader,
203      * call {@link #getLogger(String)} on it and construct a {@link LoggerLog} instance
204      * as this Log's Logger, so that logging is delegated to the parent Log.
205      * <p>
206      * This should be used if a webapp is using Log, but wishes the logging to be
207      * directed to the containers log.
208      * <p>
209      * If there is not parent Log, then this call is equivalent to<pre>
210      *   Log.setLog(Log.getLogger(name));
211      * </pre>
212      * @param name Logger name
213      */
214     public static void setLogToParent(String name)
215     {
216         ClassLoader loader = Log.class.getClassLoader();
217         if (loader.getParent()!=null)
218         {
219             try
220             {
221                 Class<?> uberlog = loader.getParent().loadClass("org.eclipse.jetty.util.log.Log");
222                 Method getLogger = uberlog.getMethod("getLogger", new Class[]{String.class});
223                 Object logger = getLogger.invoke(null,name);
224                 setLog(new LoggerLog(logger));
225             }
226             catch (Exception e)
227             {
228                 e.printStackTrace();
229             }
230         }
231         else
232         {
233             setLog(getLogger(name));
234         }
235     }
236 
237     /**
238      * @deprecated anonymous logging is deprecated, use a named {@link Logger} obtained from {@link #getLogger(String)}
239      */
240     @Deprecated
241     public static void debug(Throwable th)
242     {
243         if (!isDebugEnabled())
244             return;
245         LOG.debug(EXCEPTION, th);
246     }
247 
248     /**
249      * @deprecated anonymous logging is deprecated, use a named {@link Logger} obtained from {@link #getLogger(String)}
250      */
251     @Deprecated
252     public static void debug(String msg)
253     {
254         if (!initialized())
255             return;
256         LOG.debug(msg);
257     }
258 
259     /**
260      * @deprecated anonymous logging is deprecated, use a named {@link Logger} obtained from {@link #getLogger(String)}
261      */
262     @Deprecated
263     public static void debug(String msg, Object arg)
264     {
265         if (!initialized())
266             return;
267         LOG.debug(msg, arg);
268     }
269 
270     /**
271      * @deprecated anonymous logging is deprecated, use a named {@link Logger} obtained from {@link #getLogger(String)}
272      */
273     @Deprecated
274     public static void debug(String msg, Object arg0, Object arg1)
275     {
276         if (!initialized())
277             return;
278         LOG.debug(msg, arg0, arg1);
279     }
280 
281     /**
282      * Ignore an exception unless trace is enabled.
283      * This works around the problem that log4j does not support the trace level.
284      * @param thrown the Throwable to ignore
285      */
286     /**
287      * @deprecated anonymous logging is deprecated, use a named {@link Logger} obtained from {@link #getLogger(String)}
288      */
289     @Deprecated
290     public static void ignore(Throwable thrown)
291     {
292         if (!initialized())
293             return;
294         LOG.ignore(thrown);
295     }
296 
297     /**
298      * @deprecated anonymous logging is deprecated, use a named {@link Logger} obtained from {@link #getLogger(String)}
299      */
300     @Deprecated
301     public static void info(String msg)
302     {
303         if (!initialized())
304             return;
305         LOG.info(msg);
306     }
307 
308     /**
309      * @deprecated anonymous logging is deprecated, use a named {@link Logger} obtained from {@link #getLogger(String)}
310      */
311     @Deprecated
312     public static void info(String msg, Object arg)
313     {
314         if (!initialized())
315             return;
316         LOG.info(msg, arg);
317     }
318 
319     /**
320      * @deprecated anonymous logging is deprecated, use a named {@link Logger} obtained from {@link #getLogger(String)}
321      */
322     @Deprecated
323     public static void info(String msg, Object arg0, Object arg1)
324     {
325         if (!initialized())
326             return;
327         LOG.info(msg, arg0, arg1);
328     }
329 
330     /**
331      * @deprecated anonymous logging is deprecated, use a named {@link Logger} obtained from {@link #getLogger(String)}
332      */
333     @Deprecated
334     public static boolean isDebugEnabled()
335     {
336         if (!initialized())
337             return false;
338         return LOG.isDebugEnabled();
339     }
340 
341     /**
342      * @deprecated anonymous logging is deprecated, use a named {@link Logger} obtained from {@link #getLogger(String)}
343      */
344     @Deprecated
345     public static void warn(String msg)
346     {
347         if (!initialized())
348             return;
349         LOG.warn(msg);
350     }
351 
352     /**
353      * @deprecated anonymous logging is deprecated, use a named {@link Logger} obtained from {@link #getLogger(String)}
354      */
355     @Deprecated
356     public static void warn(String msg, Object arg)
357     {
358         if (!initialized())
359             return;
360         LOG.warn(msg, arg);
361     }
362 
363     /**
364      * @deprecated anonymous logging is deprecated, use a named {@link Logger} obtained from {@link #getLogger(String)}
365      */
366     @Deprecated
367     public static void warn(String msg, Object arg0, Object arg1)
368     {
369         if (!initialized())
370             return;
371         LOG.warn(msg, arg0, arg1);
372     }
373 
374     /**
375      * @deprecated anonymous logging is deprecated, use a named {@link Logger} obtained from {@link #getLogger(String)}
376      */
377     @Deprecated
378     public static void warn(String msg, Throwable th)
379     {
380         if (!initialized())
381             return;
382         LOG.warn(msg, th);
383     }
384 
385     /**
386      * @deprecated anonymous logging is deprecated, use a named {@link Logger} obtained from {@link #getLogger(String)}
387      */
388     @Deprecated
389     public static void warn(Throwable th)
390     {
391         if (!initialized())
392             return;
393         LOG.warn(EXCEPTION, th);
394     }
395 
396     /**
397      * Obtain a named Logger based on the fully qualified class name.
398      *
399      * @param clazz
400      *            the class to base the Logger name off of
401      * @return the Logger with the given name
402      */
403     public static Logger getLogger(Class<?> clazz)
404     {
405         return getLogger(clazz.getName());
406     }
407 
408     /**
409      * Obtain a named Logger or the default Logger if null is passed.
410      * @param name the Logger name
411      * @return the Logger with the given name
412      */
413     public static Logger getLogger(String name)
414     {
415         if (!initialized())
416             return null;
417 
418         return name == null ? LOG : LOG.getLogger(name);
419     }
420 }