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  import java.lang.reflect.Method;
16  import java.security.AccessController;
17  import java.security.PrivilegedAction;
18  
19  import org.eclipse.jetty.util.Loader;
20  
21  
22  
23  /*-----------------------------------------------------------------------*/
24  /** Logging.
25   * This class provides a static logging interface.  If an instance of the 
26   * org.slf4j.Logger class is found on the classpath, the static log methods
27   * are directed to a slf4j logger for "org.eclipse.log".   Otherwise the logs
28   * are directed to stderr.
29   * <p>
30   * The "org.eclipse.jetty.util.log.class" system property can be used
31   * to select a specific logging implementation.
32   * <p>
33   * If the system property org.eclipse.jetty.util.log.IGNORED is set, 
34   * then ignored exceptions are logged in detail.
35   * 
36   * @see StdErrLog
37   * @see Slf4jLog
38   */
39  public class Log 
40  {    
41      private static final String[] __nestedEx =
42          {"getTargetException","getTargetError","getException","getRootCause"};
43      /*-------------------------------------------------------------------*/
44      private static final Class[] __noArgs=new Class[0];
45      public final static String EXCEPTION= "EXCEPTION ";
46      public final static String IGNORED= "IGNORED";
47      public final static String IGNORED_FMT= "IGNORED: {}";
48      public final static String NOT_IMPLEMENTED= "NOT IMPLEMENTED ";
49      
50      public static String __logClass;
51      public static boolean __ignored;
52      
53      static
54      {
55          AccessController.doPrivileged(new PrivilegedAction<Boolean>() 
56              {
57                  public Boolean run() 
58                  { 
59                      __logClass = System.getProperty("org.eclipse.jetty.util.log.class","org.eclipse.jetty.util.log.Slf4jLog"); 
60                      __ignored = Boolean.parseBoolean(System.getProperty("org.eclipse.jetty.util.log.IGNORED","false")); 
61                      return true; 
62                  }
63              });
64      }
65         
66      private static Logger __log;
67      private static boolean _initialized;
68      
69      public static boolean initialized()
70      {
71          if (__log!=null)
72              return true;
73          
74          synchronized (Log.class)
75          {
76              if (_initialized)
77                  return __log!=null;
78              _initialized=true;
79          }
80          
81          Class log_class=null;
82          try
83          {
84              log_class=Loader.loadClass(Log.class, __logClass);
85              if (__log==null || !__log.getClass().equals(log_class))
86              {
87                  __log=(Logger) log_class.newInstance();
88                  __log.info("Logging to {} via {}",__log,log_class.getName());
89              }
90          }
91          catch(NoClassDefFoundError e)
92          {
93              initStandardLogging(e);
94          }
95          catch(Exception e)
96          {
97              initStandardLogging(e);
98          }
99  
100         return __log!=null;
101     }
102 
103     private static void initStandardLogging(Throwable e) 
104     {
105         Class log_class;
106         if(e != null && __ignored)
107             e.printStackTrace();
108         if (__log==null)
109         {
110             log_class= StdErrLog.class;
111             __log=new StdErrLog();
112             __log.info("Logging to {} via {}",__log,log_class.getName());
113         }
114     }
115 
116     public static void setLog(Logger log)
117     {
118         Log.__log=log;
119     }
120     
121     public static Logger getLog()
122     {
123         initialized();
124         return __log;
125     }
126 
127     
128     /**
129      * Set Log to parent Logger.
130      * <p>
131      * If there is a different Log class available from a parent classloader,
132      * call {@link #getLogger(String)} on it and construct a {@link LoggerLog} instance
133      * as this Log's Logger, so that logging is delegated to the parent Log.
134      * <p>
135      * This should be used if a webapp is using Log, but wishes the logging to be 
136      * directed to the containers log.
137      * <p>
138      * If there is not parent Log, then this call is equivalent to<pre>
139      *   Log.setLog(Log.getLogger(name));
140      * </pre> 
141      * @param name Logger name
142      */
143     public static void setLogToParent(String name)
144     {
145         ClassLoader loader = Log.class.getClassLoader();
146         if (loader.getParent()!=null)
147         {
148             try
149             {
150                 Class<?> uberlog = loader.getParent().loadClass("org.eclipse.jetty.util.log.Log");
151                 Method getLogger=uberlog.getMethod("getLogger",new Class[]{String.class});
152                 Object logger = getLogger.invoke(null,name);
153                 setLog(new LoggerLog(logger));
154                 return;
155             }
156             catch (Exception e)
157             {
158                 e.printStackTrace();
159             }     
160         }
161             
162         setLog(getLogger(name));
163     }
164     
165     public static void debug(Throwable th)
166     {        
167         if (!isDebugEnabled())
168             return;
169         __log.debug(EXCEPTION,th);
170         unwind(th);
171     }
172 
173     public static void debug(String msg)
174     {
175         if (!initialized())
176             return;
177         
178         __log.debug(msg,null,null);
179     }
180     
181     public static void debug(String msg,Object arg)
182     {
183         if (!initialized())
184             return;
185         __log.debug(msg,arg,null);
186     }
187     
188     public static void debug(String msg,Object arg0, Object arg1)
189     {
190         if (!initialized())
191             return;
192         __log.debug(msg,arg0,arg1);
193     }
194     
195     /* ------------------------------------------------------------ */
196     /**
197      * Ignore an exception unless trace is enabled.
198      * This works around the problem that log4j does not support the trace level.
199      */
200     public static void ignore(Throwable th)
201     {
202         if (!initialized())
203             return;
204         if (__ignored)
205         {
206             __log.warn(IGNORED,th);
207             unwind(th);
208         }
209     }
210     
211     public static void info(String msg)
212     {
213         if (!initialized())
214             return;
215         __log.info(msg,null,null);
216     }
217     
218     public static void info(String msg,Object arg)
219     {
220         if (!initialized())
221             return;
222         __log.info(msg,arg,null);
223     }
224     
225     public static void info(String msg,Object arg0, Object arg1)
226     {
227         if (!initialized())
228             return;
229         __log.info(msg,arg0,arg1);
230     }
231     
232     public static boolean isDebugEnabled()
233     {
234         if (!initialized())
235             return false;
236         return __log.isDebugEnabled();
237     }
238     
239     public static void warn(String msg)
240     {
241         if (!initialized())
242             return;
243         __log.warn(msg,null,null);
244     }
245     
246     public static void warn(String msg,Object arg)
247     {
248         if (!initialized())
249             return;
250         __log.warn(msg,arg,null);        
251     }
252     
253     public static void warn(String msg,Object arg0, Object arg1)
254     {
255         if (!initialized())
256             return;
257         __log.warn(msg,arg0,arg1);        
258     }
259     
260     public static void warn(String msg, Throwable th)
261     {
262         if (!initialized())
263             return;
264         __log.warn(msg,th);
265         unwind(th);
266     }
267 
268     public static void warn(Throwable th)
269     {
270         if (!initialized())
271             return;
272         __log.warn(EXCEPTION,th);
273         unwind(th);
274     }
275 
276     /** Obtain a named Logger.
277      * Obtain a named Logger or the default Logger if null is passed.
278      */
279     public static Logger getLogger(String name)
280     {
281         if (!initialized())
282             return null;
283         
284         if (name==null)
285           return __log;
286         return __log.getLogger(name);
287     }
288 
289     private static void unwind(Throwable th)
290     {
291         if (th==null)
292             return;
293         for (int i=0;i<__nestedEx.length;i++)
294         {
295             try
296             {
297                 Method get_target = th.getClass().getMethod(__nestedEx[i],__noArgs);
298                 Throwable th2=(Throwable)get_target.invoke(th,(Object[])null);
299                 if (th2!=null && th2!=th)
300                     warn("Nested in "+th+":",th2);
301             }
302             catch(Exception ignore){}
303         }
304     }
305     
306 
307 }
308