root/trunk/src/java/org/jcoderz/commons/logging/BasicPrinter.java

Revision 1535, 18.0 kB (checked in by amandel, 3 years ago)

Take care not to add multiple "()" to output of source method.

  • 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.logging;
34
35
36import java.io.PrintWriter;
37import java.text.Format;
38import java.text.MessageFormat;
39import java.util.ArrayList;
40import java.util.Arrays;
41import java.util.Iterator;
42import java.util.List;
43import java.util.Set;
44
45import org.jcoderz.commons.util.Assert;
46
47/**
48 * This printer prints the log information as lines of text and uses the display
49 * options for selecting the fields to display.
50 * The format is similar to the log file format.
51 *
52 */
53public class BasicPrinter
54      extends LogPrinter
55{
56   private static final String SOURCE_TAG = "_LOGGED_AT_";
57   private static final String SOLUTION_TAG = "_SOLUTION_";
58   private static final String SYMBOL_TAG = "_SYMBOL_";
59
60   private static final String FIRST_MSG_ITEM = "{0}";
61
62   private MessageFormat mStackTraceFormat = null;
63   private MessageFormat mTraceLineFormat = null;
64   private MessageFormat mLogMessageFormat = null;
65   private MessageFormat mParameterLineFormat = null;
66   private MessageFormat mNestedLineFormat = null;
67
68   private Object[] mStackTraceData = null;
69   private Object[] mTraceLineData = null;
70   private Object[] mLogMessageData = null;
71   private Object[] mParameterLineData = null;
72   private Object[] mNestedLineData = null;
73
74   private final StringBuffer mBuffer = new StringBuffer();
75
76   /** {@inheritDoc} */
77   public void setDisplayOptions (DisplayOptions options)
78   {
79      super.setDisplayOptions(options);
80      setStackTraceFormat();
81      setTraceLineFormat();
82      setLogMessageFormat();
83      setParameterLineFormat();
84      setNestedLineFormat();
85   }
86
87   /** {@inheritDoc} */
88   public void print (
89         final PrintWriter printer,
90         final LogItem entry)
91   {
92      LogItem currentEntry = entry;
93
94      Assert.notNull(printer, "Printer");
95      Assert.notNull(entry, "entry");
96      Assert.notNull(entry.getType(), "entry.getType()");
97      final List trackingIds = new ArrayList();
98      while (currentEntry != null)
99      {
100         printEntry(printer, currentEntry, trackingIds);
101         currentEntry = currentEntry.getNestedItem();
102         if (currentEntry != null)
103         {
104            printNesting(printer, currentEntry, trackingIds);
105         }
106      }
107      currentEntry = entry;
108      trackingIds.clear();
109      while (currentEntry != null)
110      {
111         if (displayStackTrace(currentEntry))
112         {
113            printStackTrace(printer, currentEntry, trackingIds);
114         }
115         currentEntry = currentEntry.getNestedItem();
116      }
117   }
118
119   /**
120    * @param printer
121    * @param currentEntry
122    * @param trackingIds
123    */
124   private void printEntry (
125         final PrintWriter printer,
126         final LogItem entry,
127         final List trackingIds)
128   {
129      if (! entry.isExceptionItem())
130      {
131         addTrackingNumber(trackingIds, entry.getTrackingNumber());
132         final LogLineFormat.LogLineType type
133               = LogLineFormat.getLogLineType(entry.getType().charAt(0));
134         if ((type == LogLineFormat.TRACE_MESSAGE)
135               || (type == LogLineFormat.EXCEPTION_MESSAGE))
136         {
137            printTraceLine(printer, entry, trackingIds);
138         }
139         else if ((type == LogLineFormat.LOG_MESSAGE)
140               || (type == LogLineFormat.ERROR_MESSAGE))
141         {
142            printMessageLine(printer, entry, trackingIds);
143            printParameters(printer, entry, trackingIds);
144         }
145      }
146   }
147
148   private void setStackTraceFormat ()
149   {
150      final Format[] formats = StackTraceFormat.getFormatList(
151            getDisplayOptions(), false);
152
153      mStackTraceData = new Object[formats.length];
154
155      final StringBuffer pattern = new StringBuffer(FIRST_MSG_ITEM);
156      for (int i = 1; i < formats.length; ++i)
157      {
158         pattern.append(" {").append(i).append('}');
159      }
160      mStackTraceFormat = new MessageFormat(pattern.toString());
161      mStackTraceFormat.setFormats(formats);
162   }
163
164   private void setTraceLineFormat ()
165   {
166      final Format[] formats = TraceLineFormat.getFormatList(
167            getDisplayOptions(), false);
168      mTraceLineData = new Object[formats.length];
169
170      final StringBuffer pattern = new StringBuffer(FIRST_MSG_ITEM);
171      for (int i = 1; i < formats.length; ++i)
172      {
173         pattern.append(" {").append(i).append('}');
174      }
175      mTraceLineFormat = new MessageFormat(pattern.toString());
176      mTraceLineFormat.setFormats(formats);
177   }
178
179   private void setLogMessageFormat ()
180   {
181      final Format[] formats = MessageLineFormat.getFormatList(
182            getDisplayOptions(), false);
183      mLogMessageData = new Object[formats.length];
184
185      final StringBuffer pattern = new StringBuffer(FIRST_MSG_ITEM);
186      for (int i = 1; i < formats.length; ++i)
187      {
188         pattern.append(" {").append(i).append('}');
189      }
190      mLogMessageFormat = new MessageFormat(pattern.toString());
191      mLogMessageFormat.setFormats(formats);
192   }
193
194   private void setParameterLineFormat ()
195   {
196      final Format[] formats = ParameterLineFormat.getFormatList(
197            getDisplayOptions(), false);
198
199      mParameterLineData = new Object[formats.length];
200
201      final StringBuffer pattern = new StringBuffer(FIRST_MSG_ITEM);
202      int i;
203      for (i = 1; i < formats.length - 1; ++i)
204      {
205         pattern.append(" {").append(i).append('}');
206      }
207      pattern.append(": \t{").append(i).append('}');
208      mParameterLineFormat = new MessageFormat(pattern.toString());
209      mParameterLineFormat.setFormats(formats);
210   }
211
212   private void setNestedLineFormat ()
213   {
214      final Format[] formats = NestedLineFormat.getFormatList(
215            getDisplayOptions(), false);
216      mNestedLineData = new Object[formats.length];
217
218      final StringBuffer pattern = new StringBuffer();
219      int i = 0;
220      for (i = 0; i < formats.length - 1; ++i)
221      {
222         pattern.append('{').append(i).append("} ");
223      }
224      pattern.append("Caused by: {").append(i).append('}');
225      mNestedLineFormat = new MessageFormat(pattern.toString());
226      mNestedLineFormat.setFormats(formats);
227   }
228
229   private void printTraceLine (
230         final PrintWriter writer,
231         final LogItem entry,
232         final List trackingIds)
233   {
234      int i = 0;
235      i = setTimeStamp(i, mTraceLineData, entry);
236      i = setNodeId(i, mTraceLineData, entry);
237      i = setInstanceId(i, mTraceLineData, entry);
238      i = setThreadId(i, mTraceLineData, entry);
239      i = setLoggerLevel(i, mTraceLineData, entry);
240      i = setSymbolId(i, mTraceLineData, entry);
241      i = setBusinessImpact(i, mTraceLineData, entry);
242      i = setThreadName(i, mTraceLineData, entry);
243      i = setCategory(i, mTraceLineData, entry);
244      i = setTrackingNumber(i, mTraceLineData, trackingIds);
245      i = setSource(i, mTraceLineData, entry);
246      i = setMessage(i, mTraceLineData, entry);
247      mBuffer.setLength(0);
248      mTraceLineFormat.format(mTraceLineData, mBuffer, null);
249      writer.println(mBuffer);
250   }
251
252   private void printMessageLine (
253         final PrintWriter writer,
254         final LogItem entry,
255         final List trackingIds)
256   {
257      int i = 0;
258      i = setTimeStamp(i, mLogMessageData, entry);
259      i = setNodeId(i, mLogMessageData, entry);
260      i = setInstanceId(i, mLogMessageData, entry);
261      i = setThreadId(i, mLogMessageData, entry);
262      i = setLoggerLevel(i, mLogMessageData, entry);
263      i = setSymbolId(i, mLogMessageData, entry);
264      i = setBusinessImpact(i, mLogMessageData, entry);
265      i = setThreadName(i, mTraceLineData, entry);
266      i = setCategory(i, mLogMessageData, entry);
267      i = setTrackingNumber(i, mLogMessageData, trackingIds);
268      i = setMessage(i, mLogMessageData, entry);
269      mBuffer.setLength(0);
270      mLogMessageFormat.format(mLogMessageData, mBuffer, null);
271      writer.println(mBuffer);
272   }
273
274   private void printParameterLine (
275         final PrintWriter writer,
276         final LogItem entry,
277         final List trackingIds,
278         final String parameterName,
279         final List parameterValues)
280   {
281      int i = 0;
282      i = setThreadId(i, mParameterLineData, entry);
283      i = setTrackingNumber(i, mParameterLineData, trackingIds);
284
285      mParameterLineData[i++] = parameterName;
286      mParameterLineData[i++] = parameterValues;
287
288      mBuffer.setLength(0);
289      mParameterLineFormat.format(mParameterLineData, mBuffer, null);
290      writer.println(mBuffer);
291   }
292
293   private void printStackTraceLine (
294         final PrintWriter writer,
295         final LogItem entry,
296         final List trackingIds,
297         final StackTraceInfo stacktraceLine)
298   {
299      int i = 0;
300      i = setThreadId(i, mStackTraceData, entry);
301      i = setTrackingNumber(i, mStackTraceData, trackingIds);
302
303      mStackTraceData[i++] = stacktraceLine.toString();
304
305      mBuffer.setLength(0);
306      mStackTraceFormat.format(mStackTraceData, mBuffer, null);
307      writer.println(mBuffer);
308   }
309
310   private void printNesting (
311         final PrintWriter writer,
312         final LogItem entry,
313         final List trackingIds)
314   {
315      int i = 0;
316      i = setThreadId(i, mNestedLineData, entry);
317      i = setTrackingNumber(i, mNestedLineData, trackingIds);
318      i = setMessage(i, mNestedLineData, entry);
319
320      mBuffer.setLength(0);
321      mNestedLineFormat.format(mNestedLineData, mBuffer, null);
322      writer.println(mBuffer);
323   }
324
325   private void printParameters (
326         final PrintWriter writer,
327         final LogItem entry,
328         final List trackingIds)
329   {
330      final StringBuffer source = getPrintableSource(
331            entry.getSourceClass(), entry.getSourceMethod());
332      if (source != null)
333      {
334         printParameterLine(
335               writer, entry, trackingIds, SOURCE_TAG, Arrays.asList(
336                     new String[]{source.toString()}));
337      }
338      if (getDisplayOptions().displaySymbol())
339      {
340         printParameterLine(
341               writer, entry, trackingIds, SYMBOL_TAG, Arrays.asList(
342                     new String[]{entry.getSymbol()}));
343      }
344      if (getDisplayOptions().displaySolution())
345      {
346         printParameterLine(
347               writer, entry, trackingIds, SOLUTION_TAG, Arrays.asList(
348                     new String[]{entry.getSolution()}));
349      }
350      if (getDisplayOptions().displayParameters())
351      {
352         final Set names = entry.getParameterNames();
353         for (final Iterator nameIter = names.iterator(); nameIter.hasNext(); )
354         {
355            final String name = (String) nameIter.next();
356            printParameterLine(writer, entry, trackingIds,
357                  name, entry.getParameterValues(name));
358         }
359      }
360   }
361
362   private void printStackTrace (
363         final PrintWriter writer,
364         final LogItem entry,
365         final List trackingIds)
366   {
367      for (final Iterator iter = entry.getStackTraceLines().iterator();
368            iter.hasNext(); )
369      {
370         final StackTraceInfo info = (StackTraceInfo) iter.next();
371         if (! info.isMoreLine())
372         {
373            printStackTraceLine(writer, entry, trackingIds, info);
374         }
375         else
376         {
377            printMoreStackTrace(writer, entry, trackingIds, info);
378         }
379      }
380   }
381
382   private void printMoreStackTrace (
383         final PrintWriter writer,
384         final LogItem entry,
385         final List trackingIds,
386         final StackTraceInfo info)
387   {
388      final LogItem stackTraceEntry = getEntryForMoreStackTrace(entry, info);
389      if (stackTraceEntry == null)
390      {
391         throw new IllegalStateException("Did not find correct stack trace to "
392               + "display for " + entry);
393      }
394      else if (entry == stackTraceEntry)
395      {
396         printStackTraceLine(writer, entry, trackingIds, info);
397      }
398      else
399      {
400         printStackTrace(writer, stackTraceEntry, trackingIds);
401      }
402   }
403
404   private int setTimeStamp (
405         final int i,
406         final Object[] data,
407         final LogItem entry)
408   {
409      int rc = i;
410      if (getDisplayOptions().displayTimestamp())
411      {
412         data[rc++] = entry.getTimestamp();
413      }
414      return rc;
415   }
416
417   private int setNodeId (
418         final int i,
419         final Object[] data,
420         final LogItem entry)
421   {
422      int rc = i;
423      if (getDisplayOptions().displayNodeId())
424      {
425         data[rc++] = entry.getNodeId();
426      }
427      return rc;
428   }
429
430   private int setInstanceId (
431         final int i,
432         final Object[] data,
433         final LogItem entry)
434   {
435      int rc = i;
436      if (getDisplayOptions().displayInstanceId())
437      {
438         data[rc++] = entry.getInstanceId();
439      }
440      return rc;
441   }
442
443   private int setThreadId (
444         final int i,
445         final Object[] data,
446         final LogItem entry)
447   {
448      int rc = i;
449      if (getDisplayOptions().displayThreadId())
450      {
451         data[rc++] = String.valueOf(entry.getThreadId());
452      }
453      return rc;
454   }
455
456   private int setLoggerLevel (
457         final int i,
458         final Object[] data,
459         final LogItem entry)
460   {
461      int rc = i;
462      if (getDisplayOptions().displayLoggerLevel())
463      {
464         data[rc++] = entry.getLoggerLevel().toString();
465      }
466      return rc;
467   }
468
469   private int setSymbolId (
470         final int i,
471         final Object[] data,
472         final LogItem entry)
473   {
474      int rc = i;
475      if (getDisplayOptions().displaySymbolId())
476      {
477         data[rc++] = entry.getSymbolId();
478      }
479      return rc;
480   }
481
482   private int setBusinessImpact (
483         final int i,
484         final Object[] data,
485         final LogItem entry)
486   {
487      int rc = i;
488      if (getDisplayOptions().displayBusinessImpact())
489      {
490         data[rc++] = entry.getBusinessImpact().toString();
491      }
492      return rc;
493   }
494
495   private int setCategory (
496         final int i,
497         final Object[] data,
498         final LogItem entry)
499   {
500      int rc = i;
501      if (getDisplayOptions().displayCategory())
502      {
503         data[rc++] = entry.getCategory().toString();
504      }
505      return rc;
506   }
507
508   private int setThreadName (
509       final int i,
510       final Object[] data,
511       final LogItem entry)
512 {
513    int rc = i;
514    if (getDisplayOptions().displayThreadName())
515    {
516       data[rc++] = entry.getThreadName();
517    }
518    return rc;
519 }
520
521   private int setTrackingNumber (
522         final int i,
523         final Object[] data,
524         final List trackingNumbers)
525   {
526      int rc = i;
527      if (getDisplayOptions().displayTrackingNumber())
528      {
529         data[rc++] = trackingNumbers;
530      }
531      return rc;
532   }
533
534   private int setSource (
535         final int i,
536         final Object[] data,
537         final LogItem entry)
538   {
539      int rc = i;
540      final StringBuffer source
541         = getPrintableSource(entry.getSourceClass(), entry.getSourceMethod());
542      if (source != null)
543      {
544         data[rc++] = source.toString();
545      }
546      return rc;
547   }
548
549   /**
550    * Gets source class and method appended within one string buffer according
551    * to the display options currently set.
552    *
553    * @param sourceClass The name of the source class.
554    * @param sourceMethod The name of the source method.
555    *
556    * @return null if none of source class or method is to display;
557    * StringBuffer containing the displayable parts of source class name
558    * and source method name, else
559    */
560   private StringBuffer getPrintableSource (
561         final String sourceClass,
562         final String sourceMethod)
563   {
564      StringBuffer rc = null;
565      final StringBuffer source = new StringBuffer();
566
567      if (getDisplayOptions().displaySourceClass())
568      {
569         rc = source.append(sourceClass);
570      }
571      if (getDisplayOptions().displaySourceMethod())
572      {
573         if (getDisplayOptions().displaySourceClass())
574         {
575            rc = source.append('.');
576         }
577         source.append(sourceMethod);
578         if (sourceMethod.indexOf('(') < 0)
579         {
580            rc = source.append("()");
581         }
582      }
583      return rc;
584   }
585
586   private int setMessage (
587         final int i,
588         final Object[] data,
589         final LogItem entry)
590   {
591      int rc = i;
592      data[rc++] = entry.getMessage();
593      return rc;
594   }
595
596   /**
597    * Adds the new tracking number as new tracking id to the sequence of
598    * tracking ids, if it is not already included as last element.
599    *
600    * @param trackingIds The list storing the sequence of tracking ids.
601    * @param newId The number to add to the sequence.
602    */
603   private void addTrackingNumber (
604         final List trackingIds,
605         final String newId)
606   {
607      if (! trackingIds.isEmpty())
608      {
609         if (! trackingIds.get(trackingIds.size() - 1).equals(newId))
610         {
611            trackingIds.add(newId);
612         }
613      }
614      else
615      {
616         trackingIds.add(newId);
617      }
618   }
619}
Note: See TracBrowser for help on using the browser.