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

Revision 1535, 14.2 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.text.Format;
37import java.text.MessageFormat;
38import java.text.ParseException;
39import java.util.HashMap;
40import java.util.List;
41import java.util.Map;
42import java.util.logging.LogRecord;
43
44import org.jcoderz.commons.Loggable;
45
46/**
47 * This is the base class for various log line formats. It gives the defined
48 * types of log lines and a common interface for formatting and parsing
49 * different types of log lines.
50 *
51 */
52public abstract class LogLineFormat
53{
54   /** Used for standard LogRecord logs. */
55   public static final LogLineType TRACE_MESSAGE = new LogLineType('T');
56
57   /** Used for standard LogRecord logs carrying a Throwable. */
58   public static final LogLineType EXCEPTION_MESSAGE
59         = new LogLineType('F');
60   /** Used for Loggable logs. */
61   public static final LogLineType LOG_MESSAGE
62         = new LogLineType('M');
63   /** Used for Loggable logs carrying a Throwable or being derived from a
64    * Throwable. */
65   public static final LogLineType ERROR_MESSAGE
66         = new LogLineType('E');
67
68   /** Used for nested loggables. */
69   public static final LogLineType NESTED_MESSAGE
70         = new LogLineType('N');
71   /** Used for stack trace elements of logged Throwables. */
72   public static final LogLineType STACKTRACE_MESSAGE
73         = new LogLineType('S');
74
75   /** Used for logging parameters as name and value list. */
76   public static final LogLineType PARAMETER_LINE
77         = new LogLineType('P');
78
79   protected static final Format [] EMPTY_FORMATTERS = new Format[0];
80
81   /** Index for source class name within String array as it is returned by
82    * {@linkplain #getLogSource(String)}. */
83   protected static final int SOURCECLASS_INDEX = 0;
84
85   /** Index for source method name within String array as it is returned by
86    * {@linkplain #getLogSource(String)}. */
87   protected static final int SOURCEMETHOD_INDEX = 1;
88
89
90   /* length of fixed length fields */
91   private static final int NODEID_LENGTH = 15;
92   private static final int INSTANCEID_LENGTH = 10;
93   private static final int THREADID_LENGTH = 5;
94   private static final int LOGGERLEVEL_LENGTH = 8;
95   private static final int TRACKINGID_LENGTH = 8;
96   private static final int SYMBOL_LENGTH = 8;
97   private static final int BUSINESS_IMPACT_LENGTH = 9;
98   private static final int CATEGORY_LENGTH = 9;
99
100   private static final int NUMBER_OF_SOURCE_ELEMENTS = 2;
101
102   private final LogLineType mLogLineType;
103
104   private Object [] mLineItems;
105
106   private final MessageFormat mMessageFormat;
107
108   /**
109    * This helper class is used as type safe enumeration for all defined
110    * log line types.
111    *
112    */
113   public static final class LogLineType
114         implements Comparable
115   {
116      private static int sOrdinal = 0;
117      private static final Map TYPE_CODE_MAPPING = new HashMap();
118
119      private final int mOrdinal;
120
121      private final char mTypeSpecifier;
122
123      /**
124       * Creates a new instance of this.
125       *
126       * @param typeSpecifier The code of this.
127       */
128      private LogLineType (final char typeSpecifier)
129      {
130         mTypeSpecifier = typeSpecifier;
131         mOrdinal = sOrdinal++;
132         TYPE_CODE_MAPPING.put(new Character(mTypeSpecifier), this);
133      }
134
135      /**
136       * Gets the code of this.
137       *
138       * @return the code of this.
139       */
140      public char getTypeSpecifier ()
141      {
142         return mTypeSpecifier;
143      }
144
145      /**
146       * Compares this to the supplied object.
147       *
148       * @param o The object to compare with this.
149       *
150       * @return result of compare as defined for {@link Comparable}.
151       *
152       * @see java.lang.Comparable#compareTo(java.lang.Object)
153       */
154      public int compareTo (Object o)
155      {
156         return mOrdinal - ((LogLineType) o).mOrdinal;
157      }
158   }
159
160   /**
161    * Creates and initializes a new instance of this.
162    *
163    * @param type The type of this.
164    *
165    * @param format The MessageFormat used for formatting and parsing a log line
166    * of this type.
167    *
168    * @param numberOfArguments The number of arguments for the supplied message
169    * format.
170    */
171   protected LogLineFormat (
172         final LogLineType type,
173         final MessageFormat format,
174         final int numberOfArguments)
175   {
176      mLogLineType = type;
177      mMessageFormat = format;
178      mLineItems = new Object[numberOfArguments];
179   }
180
181   /**
182    * The common interface for all log line formatters. Not all parameters might
183    * be used for implementations of this.
184    * Common for all implementation is that they append a line feed after the
185    * data has been formatted into the StringBuffer.
186    *
187    * @param sb The StringBuffer where to append the formatted data.
188    * @param record THe LogRecord to format.
189    * @param loggable The Loggable to format.
190    * @param trackingIdSequence The sequence of contributing tracking ids.
191    * @param thrown The Throwable to format.
192    * @param parameter An additional parameter, which might be required for
193    * an implementation of this.
194    */
195   public abstract void format (
196         final StringBuffer sb,
197         final LogRecord record,
198         final Loggable loggable,
199         final List trackingIdSequence,
200         final Throwable thrown,
201         final Object parameter);
202
203   /**
204    * The common interface for all log line formatters. A log line is parsed
205    * and the data being retrieved is set within the supplied LogFileEntry.
206    *
207    * @param sb The StringBuffer containing the log line to parse from the
208    * current position to the end.
209    * @param entry The LogFileEntry which gets the data being parsed.
210    *
211    * @throws ParseException if an error occurs parsing the log line.
212    */
213   public abstract void parse (
214         final StringBuffer sb,
215         final LogFileEntry entry)
216         throws ParseException;
217
218   /**
219    * Gets the LogLineType matching the supplied code.
220    *
221    * @param code The code for the LogLineType to return.
222    *
223    * @return LogLineType with code matching <code>code</code>.
224    *
225    * @throws IllegalArgumentException if no such LogLineType.
226    */
227   public static LogLineType getLogLineType (final char code)
228       throws IllegalArgumentException
229   {
230      final LogLineType rc = (LogLineType) LogLineType.TYPE_CODE_MAPPING
231            .get(new Character(code));
232      if (rc == null)
233      {
234         throw new IllegalArgumentException("There is no LogLineType with "
235               + "code " + code);
236      }
237      return rc;
238   }
239
240
241   /**
242    * Sets the contributing formats for the encapsulated MessageFormat.
243    *
244    * @param formats The formats to set.
245    */
246   protected final void setFormats (Format[] formats)
247   {
248      mMessageFormat.setFormats(formats);
249   }
250
251   /**
252    * Sets a parameter at the specified position to be used when formatting.
253    *
254    * @param index The index at which to set the parameter. It must hold true
255    * <code>0 <= index < num parameters</code> with num parameter being the
256    * number set when creating this.
257    * @param obj The object to set at the supplied position.
258    */
259   protected final void setParameter (final int index, final Object obj)
260   {
261      mLineItems[index] = obj;
262   }
263
264   /**
265    * Gets the parameter at the specified position.
266    *
267    * @param index The index from which to get the parameter. It must hold true
268    * <code>0 <= index < num parameters</code> with num parameter being the
269    * number set when creating this.
270    *
271    * @return The object at the supplied position.
272    */
273   protected final Object getParameter (final int index)
274   {
275      return mLineItems[index];
276   }
277
278   /**
279    * Formats all parameters set so far into the supplied StringBuffer using the
280    * encapsulated MessageFormat.
281    *
282    * @param sb The StringBuffer into which to format the data.
283    */
284   protected final void format (final StringBuffer sb)
285   {
286      mMessageFormat.format(mLineItems, sb, null);
287   }
288
289   /**
290    * Parses the supplied StringBuffer from beginning to end with the
291    * encapsulated MessageFormat. The parsed objects can be accessed by
292    * calling {@linkplain #getParameter(int)} with the appropriate index.
293    *
294    * @param sb The StringBuffer from which to parse the parameter values.
295    *
296    * @throws ParseException if an error occurs parsing the string.
297    */
298   protected final void parse (final StringBuffer sb)
299         throws ParseException
300   {
301      mLineItems = mMessageFormat.parse(sb.toString());
302   }
303
304   /**
305    * Gets the format to use for formatting a thread id element.
306    *
307    * @return Format for formatting the thread id.
308    */
309   protected static final Format getThreadIdFormat ()
310   {
311      return new FixLengthFormat(
312            THREADID_LENGTH, FixLengthFormat.LEFT_PADDING);
313   }
314
315   /**
316    * Gets the format to use for formatting a timestamp element.
317    *
318    * @return Format for formatting the timestamp.
319    */
320   protected static final Format getTimestampFormat ()
321   {
322      return new TimestampFormat();
323   }
324
325   /**
326    * Gets the format to use for formatting a node id element.
327    *
328    * @return Format for formatting the node id.
329    */
330   protected static final Format getNodeIdFormat ()
331   {
332      return new FixLengthFormat(
333            NODEID_LENGTH, FixLengthFormat.LEFT_PADDING);
334   }
335
336   /**
337    * Gets the format to use for formatting an instance id element.
338    *
339    * @return Format for formatting the instance id.
340    */
341   protected static final Format getInstanceIdFormat ()
342   {
343      return new FixLengthFormat(
344            INSTANCEID_LENGTH, FixLengthFormat.RIGHT_PADDING);
345   }
346
347   /**
348    * Gets the format to use for formatting the logger /severity level element.
349    *
350    * @return Format for formatting the logger level.
351    */
352   protected static final Format getLoggerLevelFormat ()
353   {
354      return new FixLengthFormat(
355            LOGGERLEVEL_LENGTH, FixLengthFormat.RIGHT_PADDING);
356   }
357
358   /**
359    * Gets the format to use for formatting a symbol id element.
360    *
361    * @return Format for formatting the message symbol.
362    */
363   protected static final Format getMessageSymbolFormat ()
364   {
365      return new FixLengthFormat(
366            SYMBOL_LENGTH, FixLengthFormat.RIGHT_PADDING);
367   }
368
369   /**
370    * Gets the format to use for formatting the business impact element.
371    *
372    * @return Format for formatting the business impact.
373    */
374   protected static final Format getBusinessImpactFormat ()
375   {
376      return new FixLengthFormat(
377            BUSINESS_IMPACT_LENGTH, FixLengthFormat.RIGHT_PADDING);
378   }
379
380   /**
381    * Gets the format to use for formatting the category element.
382    *
383    * @return Format for formatting the category.
384    */
385   protected static final Format getCategoryFormat ()
386   {
387      return new FixLengthFormat(
388            CATEGORY_LENGTH, FixLengthFormat.RIGHT_PADDING);
389   }
390
391   /**
392    * Gets the format to use for formatting the thread name element.
393    *
394    * @return Format for formatting the category.
395    */
396   protected static final Format getThreadNameFormat ()
397   {
398      return new FixLengthFormat(
399            CATEGORY_LENGTH, FixLengthFormat.LEFT_CUT_RIGHT_PADDING);
400   }
401
402   /**
403    * Gets the format to use for formatting the tracking numbers
404    *
405    * @return Format for formatting the tracking numbers.
406    */
407   protected static final Format getTrackingNumberFormat ()
408   {
409      return new CollectionFormat(new FixLengthFormat(
410            TRACKINGID_LENGTH, FixLengthFormat.LEFT_PADDING, '0'),
411            null, null, ">-");
412   }
413
414   /**
415    * Gets the source class name and source method name where the Log record was
416    * logged from the supplied string.
417    * Use {@linkplain #SOURCECLASS_INDEX} and {@linkplain #SOURCEMETHOD_INDEX}
418    * for accessing the appropriate values in the string array being returned.
419    *
420    * @param source the log source in format classname.methodname
421    *
422    * @return String array with source class name as first and source method
423    * name as second parameter.
424    */
425   protected final String [] getLogSource (final String source)
426   {
427      int afterMethodName = source.lastIndexOf('(');
428      // if the loggable has not yet filled stack trace the source does not
429      // contain the '()' part, thus we will take the whole string length.
430      if (afterMethodName == -1)
431      {
432         afterMethodName = source.length() - 1;
433      }
434      final int beforeMethodName = source.lastIndexOf('.', afterMethodName);
435      final String[] splittedSource = new String[NUMBER_OF_SOURCE_ELEMENTS];
436      splittedSource[SOURCECLASS_INDEX]
437                     = source.substring(0, beforeMethodName);
438      if (beforeMethodName + 1 < source.length())
439      {
440          splittedSource[SOURCEMETHOD_INDEX]
441                            = source.substring(beforeMethodName + 1);
442      }
443      else
444      {
445          splittedSource[SOURCEMETHOD_INDEX] = "";
446      }
447      return splittedSource;
448   }
449}
Note: See TracBrowser for help on using the browser.