View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.util.log;
20  
21  import java.net.URL;
22  import java.security.AccessController;
23  import java.security.PrivilegedAction;
24  import java.util.logging.Level;
25  import java.util.logging.LogManager;
26  import java.util.logging.LogRecord;
27  
28  import org.eclipse.jetty.util.Loader;
29  
30  /**
31   * <p>
32   * Implementation of Jetty {@link Logger} based on {@link java.util.logging.Logger}.
33   * </p>
34   *
35   * <p>
36   * You can also set the logger level using <a href="http://docs.oracle.com/javase/8/docs/api/java/util/logging/package-summary.html">
37   * standard java.util.logging configuration</a>.
38   * </p>
39   * 
40   * Configuration Properties:
41   * <dl>
42   *   <dt>${name|hierarchy}.LEVEL=(ALL|DEBUG|INFO|WARN|OFF)</dt>
43   *   <dd>
44   *   Sets the level that the Logger should log at.<br>
45   *   Names can be a package name, or a fully qualified class name.<br>
46   *   Default: The default from the java.util.logging mechanism/configuration
47   *   <br>
48   *   <dt>org.eclipse.jetty.util.log.javautil.PROPERTIES=&lt;property-resource-name&gt;</dt>
49   *   <dd>If set, it is used as a classpath resource name to find a java.util.logging 
50   *   property file.
51   *   <br>
52   *   Default: null
53   *   </dd>
54   *   <dt>org.eclipse.jetty.util.log.javautil.SOURCE=(true|false)</dt>
55   *   <dd>Set the LogRecord source class and method for JavaUtilLog.<br>
56   *   Default: true
57   *   </dd>
58   *   <dt>org.eclipse.jetty.util.log.SOURCE=(true|false)</dt>
59   *   <dd>Set the LogRecord source class and method for all Loggers.<br>
60   *   Default: depends on Logger class
61   *   </dd>
62   * </dl>
63   */
64  public class JavaUtilLog extends AbstractLogger
65  {
66      private final static String THIS_CLASS= JavaUtilLog.class.getName();
67      private final static boolean __source = 
68              Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.SOURCE",
69              Log.__props.getProperty("org.eclipse.jetty.util.log.javautil.SOURCE","true")));
70      
71      private static boolean _initialized=false;
72      
73      private Level configuredLevel;
74      private java.util.logging.Logger _logger;
75  
76      public JavaUtilLog()
77      {
78          this("org.eclipse.jetty.util.log.javautil");
79      }
80  
81      public JavaUtilLog(String name)
82      {
83          synchronized (JavaUtilLog.class)
84          {
85              if (!_initialized)
86              {
87                  _initialized=true;
88  
89                  final String properties=Log.__props.getProperty("org.eclipse.jetty.util.log.javautil.PROPERTIES",null);
90                  if (properties!=null)
91                  {
92                      AccessController.doPrivileged(new PrivilegedAction<Object>()
93                      {
94                          public Object run()
95                          {
96                              try
97                              {
98                                  URL props = Loader.getResource(JavaUtilLog.class,properties);
99                                  if (props != null)
100                                     LogManager.getLogManager().readConfiguration(props.openStream());
101                             }
102                             catch(Throwable e)
103                             {
104                                 System.err.println("[WARN] Error loading logging config: " + properties);
105                                 e.printStackTrace(System.err);
106                             }
107                             
108                             return null;
109                         }
110                     });
111                 }
112             }
113         }
114         
115         _logger = java.util.logging.Logger.getLogger(name);
116         
117         switch(lookupLoggingLevel(Log.__props,name))
118         {
119             case LEVEL_ALL:
120                 _logger.setLevel(Level.ALL);
121                 break;
122             case LEVEL_DEBUG:
123                 _logger.setLevel(Level.FINE);
124                 break;
125             case LEVEL_INFO:
126                 _logger.setLevel(Level.INFO);
127                 break;
128             case LEVEL_WARN:
129                 _logger.setLevel(Level.WARNING);
130                 break;
131             case LEVEL_OFF:
132                 _logger.setLevel(Level.OFF);
133                 break;
134             case LEVEL_DEFAULT:
135             default:
136                 break;
137         }
138         
139         configuredLevel = _logger.getLevel();
140     }
141 
142     public String getName()
143     {
144         return _logger.getName();
145     }
146 
147     protected void log(Level level,String msg,Throwable thrown)
148     {
149         LogRecord record = new LogRecord(level,msg);
150         if (thrown!=null)
151             record.setThrown(thrown);
152         record.setLoggerName(_logger.getName());
153         if (__source)
154         {
155             StackTraceElement[] stack = new Throwable().getStackTrace();
156             for (int i=0;i<stack.length;i++)
157             {
158                 StackTraceElement e=stack[i];
159                 if (!e.getClassName().equals(THIS_CLASS))
160                 {
161                     record.setSourceClassName(e.getClassName());
162                     record.setSourceMethodName(e.getMethodName());
163                     break;
164                 }
165             }
166         }
167         _logger.log(record);
168     }
169     
170     public void warn(String msg, Object... args)
171     {
172         if (_logger.isLoggable(Level.WARNING))
173             log(Level.WARNING,format(msg,args),null);
174     }
175 
176     public void warn(Throwable thrown)
177     {
178         if (_logger.isLoggable(Level.WARNING))
179             log(Level.WARNING,"",thrown);
180     }
181 
182     public void warn(String msg, Throwable thrown)
183     {
184         if (_logger.isLoggable(Level.WARNING))
185             log(Level.WARNING,msg,thrown);
186     }
187 
188     public void info(String msg, Object... args)
189     {
190         if (_logger.isLoggable(Level.INFO))
191             log(Level.INFO, format(msg, args),null);
192     }
193 
194     public void info(Throwable thrown)
195     {
196         if (_logger.isLoggable(Level.INFO))
197             log(Level.INFO, "",thrown);
198     }
199 
200     public void info(String msg, Throwable thrown)
201     {
202         if (_logger.isLoggable(Level.INFO))
203             log(Level.INFO,msg,thrown);
204     }
205 
206     public boolean isDebugEnabled()
207     {
208         return _logger.isLoggable(Level.FINE);
209     }
210 
211     public void setDebugEnabled(boolean enabled)
212     {
213         if (enabled)
214         {
215             configuredLevel = _logger.getLevel();
216             _logger.setLevel(Level.FINE);
217         }
218         else
219         {
220             _logger.setLevel(configuredLevel);
221         }
222     }
223 
224     public void debug(String msg, Object... args)
225     {
226         if (_logger.isLoggable(Level.FINE))
227             log(Level.FINE,format(msg, args),null);
228     }
229 
230     public void debug(String msg, long arg)
231     {
232         if (_logger.isLoggable(Level.FINE))
233             log(Level.FINE,format(msg, arg),null);
234     }
235 
236     public void debug(Throwable thrown)
237     {
238         if (_logger.isLoggable(Level.FINE))
239             log(Level.FINE,"",thrown);
240     }
241 
242     public void debug(String msg, Throwable thrown)
243     {
244         if (_logger.isLoggable(Level.FINE))
245             log(Level.FINE,msg,thrown);
246     }
247 
248     /**
249      * Create a Child Logger of this Logger.
250      */
251     protected Logger newLogger(String fullname)
252     {
253         return new JavaUtilLog(fullname);
254     }
255 
256     public void ignore(Throwable ignored)
257     {
258         if (_logger.isLoggable(Level.ALL))
259             log(Level.WARNING,Log.IGNORED,ignored);
260     }
261 
262     private String format(String msg, Object... args)
263     {
264         msg = String.valueOf(msg); // Avoids NPE
265         String braces = "{}";
266         StringBuilder builder = new StringBuilder();
267         int start = 0;
268         for (Object arg : args)
269         {
270             int bracesIndex = msg.indexOf(braces, start);
271             if (bracesIndex < 0)
272             {
273                 builder.append(msg.substring(start));
274                 builder.append(" ");
275                 builder.append(arg);
276                 start = msg.length();
277             }
278             else
279             {
280                 builder.append(msg.substring(start, bracesIndex));
281                 builder.append(String.valueOf(arg));
282                 start = bracesIndex + braces.length();
283             }
284         }
285         builder.append(msg.substring(start));
286         return builder.toString();
287     }
288 }