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

Revision 1011, 8.2 kB (checked in by amandel, 4 years ago)

Aligned svn keyword settings.

  • 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.nio.CharBuffer;
37import java.text.Format;
38import java.text.ParseException;
39import java.util.ArrayList;
40import java.util.List;
41import java.util.logging.LogRecord;
42
43import org.jcoderz.commons.Loggable;
44import org.jcoderz.commons.util.StringUtil;
45
46/**
47 * This class is used for formatting the stack trace of a Throwable or for
48 * parsing one line of stack trace.
49 *
50 */
51public final class StackTraceFormat
52      extends ContinuationLineFormat
53{
54   /** The number of fields added to the basic continuation line format.
55     * The cause field is added.
56     */
57   private static final int NUMBER_OF_ADDITIONAL_PARAMETERS = 1;
58
59   private static final int TEXT_INDEX = NUMBER_OF_PARAMETERS;
60
61   /** The fields added to the basic format. Parameter name and parameter value
62    * list are added.
63    */
64   private static final String ADDITIONAL_LOGLINE_FORMAT_PATTERN
65        = " {" + TEXT_INDEX + "}";
66
67   private static final String CAUSED_BY_CLAUSE = "Caused by: ";
68   private static final String AT_CLAUSE = "  at ";
69
70   /**
71    * Creates a new instance of this and initializes the message format.
72    */
73   public StackTraceFormat ()
74   {
75      super(LogLineFormat.STACKTRACE_MESSAGE, ADDITIONAL_LOGLINE_FORMAT_PATTERN,
76            NUMBER_OF_ADDITIONAL_PARAMETERS);
77      setFormats(getFormatList(null, true));
78   }
79
80   /**
81    * Gets the formats as array for formatting a stack trace line.
82    *
83    * @param options The display options specifying which fields to display.
84    * Will be ignored and ,ight be null if <code>ignoreOptions == true</code>.
85    * @param ignoreOptions flag whether to ignore the supplied options and
86    * return the formats for all fields.
87    *
88    * @return array filled with formats for each selected field. Might be empty
89    * array, never null.
90    */
91   static Format[] getFormatList (
92         final DisplayOptions options,
93         final boolean ignoreOptions)
94   {
95      final List formatList = new ArrayList();
96      if (ignoreOptions || options.displayThreadId())
97      {
98         // thread id
99         formatList.add(getThreadIdFormat());
100      }
101      if (ignoreOptions || options.displayTrackingNumber())
102      {
103         // sequence of tracking id
104         formatList.add(getTrackingNumberFormat());
105      }
106      formatList.add(new AsItIsFormat("\r\n"));
107      return (Format[]) formatList.toArray(EMPTY_FORMATTERS);
108   }
109
110   /**
111    * Formats a Throwable.
112    * Append a line feed after the data has been formatted into the
113    * StringBuffer.
114    *
115    * @param sb The StringBuffer where to append the formatted data.
116    * @param record The LogRecord to format, if <code>loggable</code> is not
117    * null, this is unused and might be null.
118    * @param loggable The Loggable to format, might be null, but then
119    * <code>record</code> must not be null.
120    * @param trackingIdSequence The sequence of contributing tracking ids.
121    * @param thrown The Throwable to format.
122    * @param parameter The Throwable containing <code>thrown</code> as cause.
123    * Might be null, if no such. Must be instance of Throwable if not null.
124    */
125   public void format (
126         final StringBuffer sb,
127         final LogRecord record,
128         final Loggable loggable,
129         final List trackingIdSequence,
130         final Throwable thrown,
131         final Object parameter)
132   {
133      if ((parameter != null) && ! (parameter instanceof Throwable))
134      {
135         throw new IllegalArgumentException(
136               "Parameter must be null or a Throwable, but is: " + parameter);
137      }
138      final Throwable parentThrown = (Throwable) parameter;
139
140      appendThrown(sb, record, loggable, trackingIdSequence, thrown,
141            parentThrown == null);
142      appendStackTrace(sb, record, loggable, trackingIdSequence, thrown,
143            parentThrown);
144   }
145
146   /**
147    * Parses one line of log data and sets the data in the supplied
148    * LogFileEntry.
149    *
150    * @param sb The StringBuffer containing the log line to parse from the
151    * current position to the end.
152    * @param entry The LogFileEntry which gets the data being parsed.
153    *
154    * @throws ParseException if an error occurs parsing the log line.
155    */
156   public void parse (StringBuffer sb, LogFileEntry entry)
157         throws ParseException
158   {
159      try
160      {
161         parse(sb);
162         entry.addToStackTrace(
163               StackTraceElementParser.parse(CharBuffer.wrap(getText())));
164      }
165      catch (ParseException pex)
166      {
167         // just rethrow
168         throw pex;
169      }
170      catch (Exception ex)
171      {
172         final ParseException pex = new ParseException(
173               "Got an error parsing " + sb, 0);
174         pex.initCause(ex);
175         throw pex;
176      }
177   }
178
179   private void appendThrown (
180         final StringBuffer sb,
181         final LogRecord record,
182         final Loggable loggable,
183         final List trackingIdSequence,
184         final Throwable thrown,
185         final boolean topLevel)
186   {
187      final StringBuffer text = new StringBuffer();
188      if (! topLevel)
189      {
190         text.append(CAUSED_BY_CLAUSE);
191      }
192      text.append(thrown.toString());
193      setText(text.toString());
194      basicFormat(sb, record, loggable, trackingIdSequence);
195   }
196
197   private void appendStackTrace (
198         final StringBuffer sb,
199         final LogRecord record,
200         final Loggable loggable,
201         final List trackingIdSequence,
202         final Throwable thrown,
203         final Throwable outerTrace)
204   {
205      // Compute number of frames in common between this and caused
206      final StackTraceElement[] trace = thrown.getStackTrace();
207      final int framesInCommon;
208      int uniqueFrames = trace.length - 1;
209      if (outerTrace != null)
210      {
211         final StackTraceElement[] causedTrace = outerTrace.getStackTrace();
212         int n = causedTrace.length - 1;
213         while (uniqueFrames >= 0 && n >= 0
214               && trace[uniqueFrames].equals(causedTrace[n]))
215         {
216            uniqueFrames--; n--;
217         }
218         framesInCommon = trace.length - 1 - uniqueFrames;
219      }
220      else
221      {
222         framesInCommon = 0;
223      }
224
225      for (int i = 0; i <= uniqueFrames; ++i)
226      {
227
228//         sb.append(Constants.LINE_SEPARATOR);
229
230         setText(AT_CLAUSE + trace[i].toString());
231
232         basicFormat(sb, record, loggable, trackingIdSequence);
233      }
234      if (framesInCommon != 0)
235      {
236//         sb.append(Constants.LINE_SEPARATOR);
237         setText("..." + framesInCommon + " more");
238         basicFormat(sb, record, loggable, trackingIdSequence);
239//         format(sb);
240      }
241   }
242
243   private void setText (final String text)
244   {
245      setParameter(TEXT_INDEX, text);
246   }
247
248   private String getText ()
249   {
250      return (String) getParameter(TEXT_INDEX);
251   }
252}
Note: See TracBrowser for help on using the browser.