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.security.AccessControlException;
17  
18  import org.eclipse.jetty.util.DateCache;
19  
20  /**
21   * StdErr Logging. This implementation of the Logging facade sends all logs to
22   * StdErr with minimal formatting.
23   * <p>
24   * If the system property "org.eclipse.jetty.util.log.DEBUG" is set, then debug
25   * logs are printed if stderr is being used. For named debuggers, the system 
26   * property name+".DEBUG" is checked. If it is not not set, then 
27   * "org.eclipse.jetty.util.log.DEBUG" is used as the default.
28   * <p>
29   * If the system property "org.eclipse.jetty.util.log.SOURCE" is set, then the
30   * source method/file of a log is logged. For named debuggers, the system 
31   * property name+".SOURCE" is checked. If it is not not set, then 
32   * "org.eclipse.jetty.util.log.SOURCE" is used as the default.
33   * 
34   */
35  public class StdErrLog implements Logger
36  {
37      private static DateCache _dateCache;
38  
39      private final static boolean __debug = Boolean.parseBoolean(
40              System.getProperty("org.eclipse.jetty.util.log.DEBUG",
41                      System.getProperty("org.eclipse.jetty.util.log.stderr.DEBUG", "false")));
42      private final static boolean __source = Boolean.parseBoolean(
43              System.getProperty("org.eclipse.jetty.util.log.SOURCE",
44                      System.getProperty("org.eclipse.jetty.util.log.stderr.SOURCE", "false")));
45  
46      static
47      {
48          try
49          {
50              _dateCache = new DateCache("yyyy-MM-dd HH:mm:ss");
51          }
52          catch (Exception x)
53          {
54              x.printStackTrace();
55          }
56      }
57  
58      private boolean _debug = __debug;
59      private boolean _source = __source;
60      private final String _name;
61      private boolean _hideStacks = false;
62  
63      public StdErrLog()
64      {
65          this(null);
66      }
67  
68      public StdErrLog(String name)
69      {
70          this._name = name == null ? "" : name;
71  
72          try
73          {
74              _debug = Boolean.parseBoolean(System.getProperty(_name + ".DEBUG", Boolean.toString(_debug)));
75          }
76          catch (AccessControlException ace)
77          {
78              _debug = __debug;
79          }
80          
81          try
82          {
83              _source = Boolean.parseBoolean(System.getProperty(_name + ".SOURCE", Boolean.toString(_source)));
84          }
85          catch (AccessControlException ace)
86          {
87              _source = __source;
88          }
89      }
90  
91      public String getName()
92      {
93          return _name;
94      }
95  
96      public boolean isHideStacks()
97      {
98          return _hideStacks;
99      }
100 
101     public void setHideStacks(boolean hideStacks)
102     {
103         _hideStacks = hideStacks;
104     }
105 
106     /* ------------------------------------------------------------ */
107     /** Is the source of a log, logged
108      * @return true if the class, method, file and line number of a log is logged.
109      */
110     public boolean isSource()
111     {
112         return _source;
113     }
114 
115     /* ------------------------------------------------------------ */
116     /** Set if a log source is logged.
117      * @param source true if the class, method, file and line number of a log is logged.
118      */
119     public void setSource(boolean source)
120     {
121         _source = source;
122     }
123 
124     public void warn(String msg, Object... args)
125     {
126         StringBuilder buffer = new StringBuilder(64);
127         format(buffer, ":WARN:", msg, args);
128         System.err.println(buffer);
129     }
130 
131     public void warn(Throwable thrown)
132     {
133         warn("", thrown);
134     }
135 
136     public void warn(String msg, Throwable thrown)
137     {
138         StringBuilder buffer = new StringBuilder(64);
139         format(buffer, ":WARN:", msg, thrown);
140         System.err.println(buffer);
141     }
142 
143     public void info(String msg, Object... args)
144     {
145         StringBuilder buffer = new StringBuilder(64);
146         format(buffer, ":INFO:", msg, args);
147         System.err.println(buffer);
148     }
149 
150     public void info(Throwable thrown)
151     {
152         info("", thrown);
153     }
154 
155     public void info(String msg, Throwable thrown)
156     {
157         StringBuilder buffer = new StringBuilder(64);
158         format(buffer, ":INFO:", msg, thrown);
159         System.err.println(buffer);
160     }
161 
162     public boolean isDebugEnabled()
163     {
164         return _debug;
165     }
166 
167     public void setDebugEnabled(boolean enabled)
168     {
169         _debug = enabled;
170     }
171 
172     public void debug(String msg, Object... args)
173     {
174         if (!_debug)
175             return;
176         StringBuilder buffer = new StringBuilder(64);
177         format(buffer, ":DBUG:", msg, args);
178         System.err.println(buffer);
179     }
180 
181     public void debug(Throwable thrown)
182     {
183         debug("", thrown);
184     }
185 
186     public void debug(String msg, Throwable thrown)
187     {
188         if (!_debug)
189             return;
190         StringBuilder buffer = new StringBuilder(64);
191         format(buffer, ":DBUG:", msg, thrown);
192         System.err.println(buffer);
193     }
194 
195     private void format(StringBuilder buffer, String level, String msg, Object... args)
196     {
197         String d = _dateCache.now();
198         int ms = _dateCache.lastMs();
199         tag(buffer, d, ms, level);
200         format(buffer, msg, args);
201     }
202 
203     private void format(StringBuilder buffer, String level, String msg, Throwable thrown)
204     {
205         format(buffer, level, msg);
206         if (isHideStacks())
207             format(buffer, String.valueOf(thrown));
208         else
209             format(buffer, thrown);
210     }
211 
212     private void tag(StringBuilder buffer, String d, int ms, String tag)
213     {
214         buffer.setLength(0);
215         buffer.append(d);
216         if (ms > 99)
217             buffer.append('.');
218         else if (ms > 9)
219             buffer.append(".0");
220         else
221             buffer.append(".00");
222         buffer.append(ms).append(tag).append(_name).append(':');
223         if (_source)
224         {
225             Throwable source = new Throwable();
226             StackTraceElement[] frames =  source.getStackTrace();
227             for (int i=0;i<frames.length;i++)
228             {
229                 final StackTraceElement frame = frames[i];
230                 String clazz = frame.getClassName();
231                 if (clazz.equals(StdErrLog.class.getName())|| clazz.equals(Log.class.getName()))
232                     continue;
233                 if (clazz.startsWith("org.eclipse.jetty."))
234                     buffer.append("o.e.j.").append(clazz,18,clazz.length());
235                 else
236                     buffer.append(clazz);
237                 buffer.append('#').append(frame.getMethodName());
238                 if (frame.getFileName()!=null)
239                     buffer.append('(').append(frame.getFileName()).append(':').append(frame.getLineNumber()).append(')');
240                 buffer.append(':');
241                 break;
242             }
243         }
244     }
245 
246     private void format(StringBuilder builder, String msg, Object... args)
247     {
248         msg = String.valueOf(msg); // Avoids NPE
249         String braces = "{}";
250         int start = 0;
251         for (Object arg : args)
252         {
253             int bracesIndex = msg.indexOf(braces, start);
254             if (bracesIndex < 0)
255             {
256                 escape(builder, msg.substring(start));
257                 builder.append(" ");
258                 builder.append(arg);
259                 start = msg.length();
260             }
261             else
262             {
263                 escape(builder, msg.substring(start, bracesIndex));
264                 builder.append(String.valueOf(arg));
265                 start = bracesIndex + braces.length();
266             }
267         }
268         escape(builder, msg.substring(start));
269     }
270 
271     private void escape(StringBuilder builder, String string)
272     {
273         for (int i = 0; i < string.length(); ++i)
274         {
275             char c = string.charAt(i);
276             if (Character.isISOControl(c))
277             {
278                 if (c == '\n')
279                     builder.append('|');
280                 else if (c == '\r')
281                     builder.append('<');
282                 else
283                     builder.append('?');
284             }
285             else
286                 builder.append(c);
287         }
288     }
289 
290     private void format(StringBuilder buffer, Throwable thrown)
291     {
292         if (thrown == null)
293         {
294             buffer.append("null");
295         }
296         else
297         {
298             buffer.append('\n');
299             format(buffer, thrown.toString());
300             StackTraceElement[] elements = thrown.getStackTrace();
301             for (int i = 0; elements != null && i < elements.length; i++)
302             {
303                 buffer.append("\n\tat ");
304                 format(buffer, elements[i].toString());
305             }
306             
307             Throwable cause = thrown.getCause();
308             if (cause!=null && cause!=thrown)
309             {
310                 buffer.append("\nCaused by: ");
311                 format(buffer,cause);
312             }
313         }
314     }
315 
316     public Logger getLogger(String name)
317     {
318         if ((name == null && this._name == null) || (name != null && name.equals(this._name)))
319             return this;
320         return new StdErrLog(_name == null || _name.length() == 0?name:_name + "." + name);
321     }
322 
323     @Override
324     public String toString()
325     {
326         return "StdErrLog:" + _name + ":DEBUG=" + _debug;
327     }
328 
329     public void ignore(Throwable ignored)
330     {
331         if (Log.isIgnored())
332         {
333             warn(Log.IGNORED, ignored);
334         }
335     }
336 }