root/trunk/src/java/org/jcoderz/commons/DevelopersLogFormatter.java

Revision 1360, 9.5 kB (checked in by amandel, 3 years ago)

Mini cleanup.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 *
4 * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 *    * Redistributions of source code must retain the above copyright
11 *      notice, this list of conditions and the following disclaimer.
12 *    * Redistributions in binary form must reproduce the above
13 *      copyright notice, this list of conditions and the following
14 *      disclaimer in the documentation and/or other materials
15 *      provided with the distribution.
16 *    * Neither the name of the jCoderZ.org Project nor the names of
17 *      its contributors may be used to endorse or promote products
18 *      derived from this software without specific prior written
19 *      permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33package org.jcoderz.commons;
34
35
36import java.io.PrintWriter;
37import java.io.StringWriter;
38import java.text.MessageFormat;
39import java.util.Arrays;
40import java.util.Iterator;
41import java.util.logging.Formatter;
42import java.util.logging.Level;
43import java.util.logging.LogRecord;
44
45import org.jcoderz.commons.types.Date;
46import org.jcoderz.commons.util.ArraysUtil;
47import org.jcoderz.commons.util.StringUtil;
48
49/**
50 * This type implements a Formatter to be used for logging onto
51 * the console. It tries to fulfill developers need during development
52 * as console output and is not meant to be a production system logger.
53 * It formats both standard a {@link java.util.logging.LogRecord} and
54 * instances of {@link org.jcoderz.commons.Loggable}.
55 *
56 */
57public class DevelopersLogFormatter
58      extends Formatter
59{
60   private final ThreadLocal mMessageFormatters = new ThreadLocal();
61
62   private static final String LINE_SEPARATOR
63       = System.getProperty("line.separator");
64   private static final int LOCATION_LENGTH = 30;
65
66   private static final long DUMP_TIME_DIFF = 60 * 1000;
67
68   // THREADSAVE?
69   private long mLastCall = 0;
70
71
72   /** {@inheritDoc} */
73   public String format (LogRecord record)
74   {
75      final StringBuffer sb = new StringBuffer();
76      Loggable loggable = null;
77      if (record.getParameters() != null && record.getParameters().length > 0)
78      {
79         if (record.getParameters()[0] instanceof Loggable)
80         {
81            loggable = (Loggable) record.getParameters()[0];
82         }
83      }
84
85      if (record.getMillis() - mLastCall >= DUMP_TIME_DIFF)
86      {
87          mLastCall = record.getMillis();
88          formatDumpTime(sb, record.getMillis());
89      }
90
91      if (record.getLevel() == Level.FINER)
92      {
93          if (record.getMessage() == "THROW")
94          {
95              formatThrown(sb, record);
96          }
97          else if (record.getMessage() == "ENTRY")
98          {
99              formatEntering(sb, record);
100          }
101          else if (record.getMessage() == "ENTRY {0}")
102          {
103              formatEntering(sb, record);
104          }
105          else if (record.getMessage().startsWith("ENTRY {0} {1}"))
106          {
107              formatEntering(sb, record);
108          }
109          else if (record.getMessage() == "RETURN")
110          {
111              formatExiting(sb, record);
112          }
113          else if (record.getMessage() == "RETURN {0}")
114          {
115              formatExiting(sb, record);
116          }
117          else
118          {
119              format(sb, record);
120          }
121      }
122      else
123      {
124          format(sb, record);
125      }
126      sb.append(LINE_SEPARATOR);
127
128      return sb.toString();
129   }
130
131   private void formatDumpTime (StringBuffer sb, long millis)
132   {
133       sb.append(new Date(millis).toString());
134       sb.append(LINE_SEPARATOR);
135   }
136
137   private void format (StringBuffer sb, LogRecord record)
138   {
139       formatLevelMarkerStart(sb, record.getLevel());
140       sb.append(getChar(record.getLevel()));
141       formatLocation(sb, record);
142       sb.append(": ");
143       formatMessage(sb, record);
144       if (record.getThrown() != null)
145       {
146           sb.append(LINE_SEPARATOR);
147           formatStackTrace(sb, record.getThrown());
148       }
149       formatLevelMarkerEnd(sb, record.getLevel());
150   }
151
152
153   private void formatStackTrace (StringBuffer sb, Throwable thrown)
154   {   // TODO: Refine
155       final StringWriter sw = new StringWriter();
156       final PrintWriter pw = new PrintWriter(sw);
157       thrown.printStackTrace(pw);
158       sb.append(sw.toString().trim());
159   }
160
161   private void formatMessage (StringBuffer sb, LogRecord record)
162   {
163       final Object [] parameters = record.getParameters();
164       final String msg = record.getMessage();
165       if (parameters != null && parameters.length != 0 &&
166           !StringUtil.isEmptyOrNull(msg) && msg.indexOf('{') >= 0)
167       {
168           try
169           {
170               final MessageFormat formatter = new MessageFormat(msg);
171               formatter.format(parameters, sb, null);
172           }
173           catch (IllegalArgumentException ex)
174           {
175               sb.append(ArraysUtil.toString(parameters));
176               sb.append(' ');
177               sb.append(msg);
178           }
179       }
180       else
181       {
182           sb.append(msg);
183       }
184   }
185
186
187   private static void formatEntering (StringBuffer sb, LogRecord record)
188   {
189       sb.append('>'); // Indent?
190       formatLocation(sb, record);
191       sb.append('(');
192       formatArgumentsCompact(sb, record.getParameters());
193       sb.append(')');
194   }
195
196   private static void formatExiting (StringBuffer sb, LogRecord record)
197   {
198       sb.append('<'); // Indent?
199       formatLocation(sb, record);
200       sb.append(' ');
201       formatArgumentsCompact(sb, record.getParameters());
202   }
203
204   private static void formatArgumentsCompact (StringBuffer sb,
205       Object[] parameters)
206   {
207       final Iterator i = Arrays.asList(parameters).iterator();
208       while (i.hasNext())
209       {
210           Object parameter = i.next();
211           sb.append(parameter);
212           if (i.hasNext())
213           {
214               sb.append(", ");
215           }
216       }
217   }
218
219   private static void formatThrown (StringBuffer sb, LogRecord record)
220   {
221       sb.append('!'); // Throwing!
222       formatLocation(sb, record);
223       sb.append(": ");
224       formatThrowableCompact(sb, record.getThrown());
225   }
226
227    private static void formatThrowableCompact (StringBuffer sb,
228        Throwable thrown)
229    {
230        Throwable ex = thrown;
231        sb.append(String.valueOf(ex));
232        while (ex.getCause() != null)
233        {
234            sb.append(" CAUSED BY: ");
235            sb.append(String.valueOf(ex));
236            ex = ex.getCause();
237        }
238    }
239
240    private static void formatLocation (StringBuffer sb, LogRecord record)
241    {   // TODO: Refine!!
242
243        final String className = record.getSourceClassName();
244        final StringBuffer b = new StringBuffer();
245        if (!StringUtil.isEmptyOrNull(className))
246        {
247            b.append(className);
248        }
249        else
250        {
251            b.append('?');
252        }
253        b.append('.');
254        final String methodName = record.getSourceMethodName();
255        if (!StringUtil.isEmptyOrNull(methodName))
256        {
257            b.append(methodName);
258        }
259        else
260        {
261            b.append('?');
262        }
263        while (b.length() < LOCATION_LENGTH)
264        {   // IMPROVEME
265            b.insert(0, ' ');
266        }
267        if (b.length() > LOCATION_LENGTH)
268        {
269            b.replace(0, b.length() - LOCATION_LENGTH , "");
270        }
271        sb.append(b);
272    }
273
274    private char getChar (Level level)
275    {
276        final int value = level.intValue();
277        final char result;
278        if (value <= Level.FINEST.intValue())
279        {
280            result = '.';
281        }
282        else if (value <= Level.FINER.intValue())
283        {
284            result = 'o';
285        }
286        else if (value <= Level.FINE.intValue())
287        {
288            result = 'O';
289        }
290        else if (value <= Level.CONFIG.intValue())
291        {
292            result = '#';
293        }
294        else if (value <= Level.INFO.intValue())
295        {
296            result = ' ';
297        }
298        else if (value <= Level.WARNING.intValue())
299        {
300            result = '!';
301        }
302        else if (value <= Level.SEVERE.intValue())
303        {
304            result = '*';
305        }
306        else
307        {
308            result = '|';
309        }
310        return result;
311    }
312
313    private void formatLevelMarkerStart (StringBuffer sb, Level level)
314    {
315        final int value = level.intValue();
316        if (value > Level.INFO.intValue())
317        {
318            sb.append("+----------------------------------");
319            sb.append(LINE_SEPARATOR);
320        }
321    }
322
323    private void formatLevelMarkerEnd (StringBuffer sb, Level level)
324    {
325        final int value = level.intValue();
326        if (value > Level.INFO.intValue())
327        {
328            sb.append(LINE_SEPARATOR);
329            sb.append("+----------------------------------");
330        }
331    }
332}
Note: See TracBrowser for help on using the browser.