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

Revision 1011, 9.4 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
35import java.nio.CharBuffer;
36import java.text.ParseException;
37import java.util.regex.Matcher;
38import java.util.regex.Pattern;
39
40/**
41 * This helper class is used to parse a CharBuffer containing data of one
42 * line of a StackTrace.
43 * A Stacktrace line is one of:
44 * <ul>
45 * <li><code>at packagename.classname.methodname(</code>...<code>)</code>
46 * <li><code>Caused by: </code>...
47 * <li><code>...</code> nn <code>more</code>
48 * <li><code>exception message</code>
49 * </ul>
50 *
51 */
52public final class StackTraceElementParser
53{
54   private static final Pattern FULL_LOCATION_PATTERN = Pattern.compile(
55         "^\\s*at\\s+[^\\s\\.]([^\\s\\(]+\\.)*[^\\s\\(]+\\(.*\\)\\s*$");
56   private static final Pattern LOCATION_PATTERN = Pattern.compile(
57         "^\\s*at\\s+");
58   private static final Pattern CLASS_PATTERN = Pattern.compile(
59         "([^\\s\\(]+\\.)*");
60   private static final Pattern METHOD_PATTERN = Pattern.compile(
61         "[^\\s\\(]+\\s*\\(");
62   private static final Pattern LINE_PATTERN = Pattern.compile(
63         "[^\\d\\)]+");
64
65   private static final Pattern FULL_CAUSE_PATTERN = Pattern.compile(
66         "^\\s*Caused by\\:\\s*.*$");
67   private static final Pattern CAUSE_PATTERN = Pattern.compile(
68         "^\\s*Caused by\\:\\s*");
69
70   private static final Pattern FULL_MORE_PATTERN = Pattern.compile(
71         "^\\s*\\.+\\s*\\d+\\s+more\\s*$");
72   private static final Pattern MORE_PATTERN = Pattern.compile(
73         "^\\s*\\.+\\s*");
74
75   private static final Pattern FULL_EXCEPTION_TEXT_PATTERN = Pattern.compile(
76         "^\\s*.*$");
77   private static final Pattern EXCEPTION_TEXT_PATTERN = Pattern.compile(
78         "^\\s*");
79
80   /**
81    * Hide the default constructor.
82    */
83   private StackTraceElementParser ()
84   {
85      // nop
86   }
87
88   /**
89    * Parses the supplied buffer for the parameters of a stacktrace element and
90    * returns the information as StackTraceInfo.
91    *
92    * @param buffer The buffer containing data of one stack trace line.
93    *
94    * @return A new instance of StackTraceInfo containing the information of the
95    * parsed line.
96    *
97    * @throws ParseException if an error occurs.
98    */
99   public static StackTraceInfo parse (final CharBuffer buffer)
100         throws ParseException
101   {
102      StackTraceInfo rc = null;
103      StackTraceInfo stInfo = null;
104
105      if ((stInfo = parseLocation(buffer)) != null)
106      {
107         rc = stInfo;
108      }
109      else if ((stInfo = parseCause(buffer)) != null)
110      {
111         rc = stInfo;
112      }
113      else if ((stInfo = parseMore(buffer)) != null)
114      {
115         rc = stInfo;
116      }
117      else if ((stInfo = parseMore(buffer)) != null)
118      {
119         rc = stInfo;
120      }
121      else if ((stInfo = parseExceptionText(buffer)) != null)
122      {
123         rc = stInfo;
124      }
125      else
126      {
127         throw new ParseException(
128               "Buffer does not match any of the defined patterns: "
129               + buffer, buffer.position());
130      }
131      return rc;
132   }
133
134   private static StackTraceInfo parseLocation (final CharBuffer buffer)
135         throws ParseException
136   {
137      StackTraceInfo rc = null;
138
139      Matcher matcher = FULL_LOCATION_PATTERN.matcher(buffer);
140
141      if (matcher.matches())
142      {
143         final int savePos = buffer.position();
144
145         matcher = LOCATION_PATTERN.matcher(buffer);
146         if (! matcher.lookingAt())
147         {
148            throw new ParseException("Cannot parse correctly: " + buffer,
149                  buffer.position());
150         }
151         int pos = matcher.end();
152         buffer.position(buffer.position() + pos);
153         matcher = CLASS_PATTERN.matcher(buffer);
154         if (! matcher.lookingAt())
155         {
156            throw new ParseException("Cannot parse correctly: " + buffer,
157                  buffer.position());
158         }
159         pos = matcher.end();
160         final CharBuffer classname = buffer.asReadOnlyBuffer();
161         classname.limit(classname.position() + pos - 1);
162
163         buffer.position(buffer.position() + pos);
164         matcher = METHOD_PATTERN.matcher(buffer);
165         if (! matcher.lookingAt())
166         {
167            throw new ParseException("Cannot parse correctly: " + buffer,
168                  buffer.position());
169         }
170         pos = matcher.end();
171         final CharBuffer methodname = buffer.asReadOnlyBuffer();
172         methodname.limit(methodname.position() + pos - 1);
173         int line = -1;
174         matcher = LINE_PATTERN.matcher(buffer);
175         // this time there need not to be a match
176         if (matcher.lookingAt())
177         {
178            pos = matcher.end();
179            buffer.position(buffer.position() + pos);
180            boolean digit = false;
181            int i = 0;
182            while (Character.isDigit(buffer.charAt(i)))
183            {
184               ++i;
185               digit = true;
186            }
187            if (digit)
188            {
189               line = Integer.parseInt(buffer.subSequence(0, i).toString());
190            }
191         }
192         buffer.position(savePos);
193         rc = new StackTraceInfo(
194               buffer.asReadOnlyBuffer(), classname, methodname, line);
195      }
196      return rc;
197   }
198
199   private static StackTraceInfo parseCause (final CharBuffer buffer)
200         throws ParseException
201   {
202      StackTraceInfo rc = null;
203      Matcher matcher = FULL_CAUSE_PATTERN.matcher(buffer);
204      if (matcher.matches())
205      {
206         final int savePos = buffer.position();
207         matcher = CAUSE_PATTERN.matcher(buffer);
208         if (! matcher.lookingAt())
209         {
210            throw new ParseException("Cannot parse a caused-by correctly: "
211                  + buffer, buffer.position());
212         }
213         final int pos = matcher.end();
214         buffer.position(buffer.position() + pos);
215         final CharBuffer cause = buffer.asReadOnlyBuffer();
216         buffer.position(savePos);
217         rc = new StackTraceInfo(buffer.asReadOnlyBuffer(), cause, true);
218      }
219      return rc;
220   }
221
222   private static StackTraceInfo parseExceptionText (final CharBuffer buffer)
223         throws ParseException
224   {
225      StackTraceInfo rc = null;
226      Matcher matcher = FULL_EXCEPTION_TEXT_PATTERN.matcher(buffer);
227      if (matcher.matches())
228      {
229         final int savePos = buffer.position();
230         matcher = EXCEPTION_TEXT_PATTERN.matcher(buffer);
231         if (! matcher.lookingAt())
232         {
233            throw new ParseException(
234                  "Cannot parse an exception text correctly: " + buffer,
235                  buffer.position());
236         }
237         final int pos = matcher.end();
238         buffer.position(buffer.position() + pos);
239         final CharBuffer exceptionText = buffer.asReadOnlyBuffer();
240         buffer.position(savePos);
241         rc = new StackTraceInfo(
242               buffer.asReadOnlyBuffer(), exceptionText, false);
243      }
244      return rc;
245   }
246
247   private static StackTraceInfo parseMore (final CharBuffer buffer)
248         throws ParseException
249   {
250      StackTraceInfo rc = null;
251      Matcher matcher = FULL_MORE_PATTERN.matcher(buffer);
252      if (matcher.matches())
253      {
254         final int savePos = buffer.position();
255         matcher = MORE_PATTERN.matcher(buffer);
256         if (! matcher.lookingAt())
257         {
258            throw new ParseException("Cannot parse a more-line correctly: "
259                  + buffer, buffer.position());
260         }
261         final int pos = matcher.end();
262         buffer.position(buffer.position() + pos);
263         boolean digit = false;
264         int i = 0;
265         while (Character.isDigit(buffer.charAt(i)))
266         {
267            ++i;
268            digit = true;
269         }
270         if (! digit)
271         {
272            throw new ParseException("Number of more lines is missing: "
273                  + buffer, buffer.position());
274         }
275         final int moreLines = Integer.parseInt(
276               buffer.subSequence(0, i).toString());
277         buffer.position(savePos);
278         rc = new StackTraceInfo(buffer.asReadOnlyBuffer(), moreLines);
279      }
280      return rc;
281   }
282}
Note: See TracBrowser for help on using the browser.