1 |
| |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| |
8 |
| |
9 |
| |
10 |
| |
11 |
| |
12 |
| |
13 |
| |
14 |
| |
15 |
| package org.apache.tapestry.util.exception; |
16 |
| |
17 |
| import java.beans.BeanInfo; |
18 |
| import java.beans.IntrospectionException; |
19 |
| import java.beans.Introspector; |
20 |
| import java.beans.PropertyDescriptor; |
21 |
| import java.io.CharArrayWriter; |
22 |
| import java.io.IOException; |
23 |
| import java.io.LineNumberReader; |
24 |
| import java.io.PrintStream; |
25 |
| import java.io.PrintWriter; |
26 |
| import java.io.StringReader; |
27 |
| import java.lang.reflect.Method; |
28 |
| import java.util.ArrayList; |
29 |
| import java.util.List; |
30 |
| |
31 |
| |
32 |
| |
33 |
| |
34 |
| |
35 |
| |
36 |
| |
37 |
| public class ExceptionAnalyzer |
38 |
| { |
39 |
| private final List exceptionDescriptions = new ArrayList(); |
40 |
| |
41 |
| private final List propertyDescriptions = new ArrayList(); |
42 |
| |
43 |
| private final CharArrayWriter writer = new CharArrayWriter(); |
44 |
| |
45 |
| private boolean exhaustive = false; |
46 |
| |
47 |
| |
48 |
| |
49 |
| |
50 |
| |
51 |
| |
52 |
0
| public boolean isExhaustive()
|
53 |
| { |
54 |
0
| return exhaustive;
|
55 |
| } |
56 |
| |
57 |
0
| public void setExhaustive(boolean value)
|
58 |
| { |
59 |
0
| exhaustive = value;
|
60 |
| } |
61 |
| |
62 |
| |
63 |
| |
64 |
| |
65 |
| |
66 |
| |
67 |
| |
68 |
| |
69 |
| |
70 |
| |
71 |
| |
72 |
| |
73 |
| |
74 |
| |
75 |
| |
76 |
| |
77 |
| |
78 |
| |
79 |
27
| public ExceptionDescription[] analyze(Throwable exception)
|
80 |
| { |
81 |
27
| try
|
82 |
| { |
83 |
| |
84 |
27
| while (exception != null)
|
85 |
| { |
86 |
37
| exception = buildDescription(exception);
|
87 |
| } |
88 |
| |
89 |
27
| ExceptionDescription[] result = new ExceptionDescription[exceptionDescriptions.size()];
|
90 |
| |
91 |
27
| return (ExceptionDescription[]) exceptionDescriptions.toArray(result);
|
92 |
| } |
93 |
| finally |
94 |
| { |
95 |
27
| exceptionDescriptions.clear();
|
96 |
27
| propertyDescriptions.clear();
|
97 |
| |
98 |
27
| writer.reset();
|
99 |
| } |
100 |
| } |
101 |
| |
102 |
37
| protected Throwable buildDescription(Throwable exception)
|
103 |
| { |
104 |
37
| BeanInfo info;
|
105 |
37
| Class exceptionClass;
|
106 |
37
| ExceptionProperty property;
|
107 |
37
| PropertyDescriptor[] descriptors;
|
108 |
37
| PropertyDescriptor descriptor;
|
109 |
37
| Throwable next = null;
|
110 |
37
| int i;
|
111 |
37
| Object value;
|
112 |
37
| Method method;
|
113 |
37
| ExceptionProperty[] properties;
|
114 |
37
| ExceptionDescription description;
|
115 |
37
| String stringValue;
|
116 |
37
| String message;
|
117 |
37
| String[] stackTrace = null;
|
118 |
| |
119 |
37
| propertyDescriptions.clear();
|
120 |
| |
121 |
37
| message = exception.getMessage();
|
122 |
37
| exceptionClass = exception.getClass();
|
123 |
| |
124 |
| |
125 |
| |
126 |
| |
127 |
37
| try
|
128 |
| { |
129 |
37
| info = Introspector.getBeanInfo(exceptionClass, Throwable.class);
|
130 |
| } |
131 |
| catch (IntrospectionException e) |
132 |
| { |
133 |
0
| return null;
|
134 |
| } |
135 |
| |
136 |
37
| descriptors = info.getPropertyDescriptors();
|
137 |
| |
138 |
37
| for (i = 0; i < descriptors.length; i++)
|
139 |
| { |
140 |
131
| descriptor = descriptors[i];
|
141 |
| |
142 |
131
| method = descriptor.getReadMethod();
|
143 |
131
| if (method == null)
|
144 |
0
| continue;
|
145 |
| |
146 |
131
| try
|
147 |
| { |
148 |
131
| value = method.invoke(exception, null);
|
149 |
| } |
150 |
| catch (Exception e) |
151 |
| { |
152 |
0
| continue;
|
153 |
| } |
154 |
| |
155 |
131
| if (value == null)
|
156 |
64
| continue;
|
157 |
| |
158 |
| |
159 |
| |
160 |
| |
161 |
67
| if (message != null && message.equals(value))
|
162 |
0
| continue;
|
163 |
| |
164 |
| |
165 |
| |
166 |
| |
167 |
| |
168 |
| |
169 |
67
| if (value instanceof Throwable)
|
170 |
| { |
171 |
18
| if (next == null)
|
172 |
10
| next = (Throwable) value;
|
173 |
| |
174 |
18
| continue;
|
175 |
| } |
176 |
| |
177 |
49
| stringValue = value.toString().trim();
|
178 |
| |
179 |
49
| if (stringValue.length() == 0)
|
180 |
0
| continue;
|
181 |
| |
182 |
49
| property = new ExceptionProperty(descriptor.getDisplayName(), value);
|
183 |
| |
184 |
49
| propertyDescriptions.add(property);
|
185 |
| } |
186 |
| |
187 |
| |
188 |
| |
189 |
| |
190 |
37
| if (next == null || exhaustive)
|
191 |
27
| stackTrace = getStackTrace(exception);
|
192 |
| |
193 |
| |
194 |
| |
195 |
37
| properties = new ExceptionProperty[propertyDescriptions.size()];
|
196 |
| |
197 |
37
| ExceptionProperty[] propArray = (ExceptionProperty[]) propertyDescriptions
|
198 |
| .toArray(properties); |
199 |
| |
200 |
37
| description = new ExceptionDescription(exceptionClass.getName(), message, propArray,
|
201 |
| stackTrace); |
202 |
| |
203 |
37
| exceptionDescriptions.add(description);
|
204 |
| |
205 |
37
| return next;
|
206 |
| } |
207 |
| |
208 |
| |
209 |
| |
210 |
| |
211 |
| |
212 |
| |
213 |
| |
214 |
| |
215 |
| |
216 |
| |
217 |
| |
218 |
| |
219 |
| |
220 |
| |
221 |
27
| protected String[] getStackTrace(Throwable exception)
|
222 |
| { |
223 |
27
| writer.reset();
|
224 |
| |
225 |
27
| PrintWriter printWriter = new PrintWriter(writer);
|
226 |
| |
227 |
27
| exception.printStackTrace(printWriter);
|
228 |
| |
229 |
27
| printWriter.close();
|
230 |
| |
231 |
27
| String fullTrace = writer.toString();
|
232 |
| |
233 |
27
| writer.reset();
|
234 |
| |
235 |
| |
236 |
| |
237 |
27
| StringReader stringReader = new StringReader(fullTrace);
|
238 |
27
| LineNumberReader lineReader = new LineNumberReader(stringReader);
|
239 |
27
| int lineNumber = 0;
|
240 |
27
| List frames = new ArrayList();
|
241 |
| |
242 |
27
| try
|
243 |
| { |
244 |
27
| while (true)
|
245 |
| { |
246 |
1567
| String line = lineReader.readLine();
|
247 |
| |
248 |
1567
| if (line == null)
|
249 |
27
| break;
|
250 |
| |
251 |
| |
252 |
| |
253 |
1540
| if (++lineNumber == 1)
|
254 |
27
| continue;
|
255 |
| |
256 |
1513
| frames.add(stripFrame(line));
|
257 |
| } |
258 |
| |
259 |
27
| lineReader.close();
|
260 |
| } |
261 |
| catch (IOException ex) |
262 |
| { |
263 |
| |
264 |
| |
265 |
| } |
266 |
| |
267 |
27
| String result[] = new String[frames.size()];
|
268 |
| |
269 |
27
| return (String[]) frames.toArray(result);
|
270 |
| } |
271 |
| |
272 |
| private static final int SKIP_LEADING_WHITESPACE = 0; |
273 |
| |
274 |
| private static final int SKIP_T = 1; |
275 |
| |
276 |
| private static final int SKIP_OTHER_WHITESPACE = 2; |
277 |
| |
278 |
| |
279 |
| |
280 |
| |
281 |
| |
282 |
| |
283 |
1513
| private String stripFrame(String frame)
|
284 |
| { |
285 |
1513
| char array[] = frame.toCharArray();
|
286 |
| |
287 |
1513
| int i = 0;
|
288 |
1513
| int state = SKIP_LEADING_WHITESPACE;
|
289 |
1513
| boolean more = true;
|
290 |
| |
291 |
1513
| while (more)
|
292 |
| { |
293 |
| |
294 |
| |
295 |
7603
| if (i == array.length)
|
296 |
1
| return "";
|
297 |
| |
298 |
7602
| char ch = array[i];
|
299 |
| |
300 |
7602
| switch (state)
|
301 |
| { |
302 |
| |
303 |
| |
304 |
3081
| case SKIP_LEADING_WHITESPACE:
|
305 |
| |
306 |
3081
| if (Character.isWhitespace(ch))
|
307 |
| { |
308 |
1569
| i++;
|
309 |
1569
| continue;
|
310 |
| } |
311 |
| |
312 |
1512
| if (ch == 'a')
|
313 |
| { |
314 |
1507
| state = SKIP_T;
|
315 |
1507
| i++;
|
316 |
1507
| continue;
|
317 |
| } |
318 |
| |
319 |
| |
320 |
5
| more = false;
|
321 |
5
| break;
|
322 |
| |
323 |
| |
324 |
| |
325 |
1507
| case SKIP_T:
|
326 |
| |
327 |
1507
| if (ch == 't')
|
328 |
| { |
329 |
1507
| state = SKIP_OTHER_WHITESPACE;
|
330 |
1507
| i++;
|
331 |
1507
| continue;
|
332 |
| } |
333 |
| |
334 |
| |
335 |
| |
336 |
0
| i--;
|
337 |
0
| more = false;
|
338 |
0
| break;
|
339 |
| |
340 |
| |
341 |
| |
342 |
3014
| case SKIP_OTHER_WHITESPACE:
|
343 |
| |
344 |
3014
| if (Character.isWhitespace(ch))
|
345 |
| { |
346 |
1507
| i++;
|
347 |
1507
| continue;
|
348 |
| } |
349 |
| |
350 |
| |
351 |
1507
| more = false;
|
352 |
1507
| break;
|
353 |
| } |
354 |
| |
355 |
| } |
356 |
| |
357 |
| |
358 |
| |
359 |
1512
| if (i == 0)
|
360 |
1
| return frame;
|
361 |
| |
362 |
1511
| return frame.substring(i);
|
363 |
| } |
364 |
| |
365 |
| |
366 |
| |
367 |
| |
368 |
| |
369 |
3
| public void reportException(Throwable exception, PrintStream stream)
|
370 |
| { |
371 |
3
| int i;
|
372 |
3
| int j;
|
373 |
3
| ExceptionDescription[] descriptions;
|
374 |
3
| ExceptionProperty[] properties;
|
375 |
3
| String[] stackTrace;
|
376 |
3
| String message;
|
377 |
| |
378 |
3
| descriptions = analyze(exception);
|
379 |
| |
380 |
3
| for (i = 0; i < descriptions.length; i++)
|
381 |
| { |
382 |
3
| message = descriptions[i].getMessage();
|
383 |
| |
384 |
3
| if (message == null)
|
385 |
0
| stream.println(descriptions[i].getExceptionClassName());
|
386 |
| else |
387 |
3
| stream.println(descriptions[i].getExceptionClassName() + ": "
|
388 |
| + descriptions[i].getMessage()); |
389 |
| |
390 |
3
| properties = descriptions[i].getProperties();
|
391 |
| |
392 |
3
| for (j = 0; j < properties.length; j++)
|
393 |
5
| stream.println(" " + properties[j].getName() + ": " + properties[j].getValue());
|
394 |
| |
395 |
| |
396 |
| |
397 |
3
| if (i + 1 == descriptions.length)
|
398 |
| { |
399 |
3
| stackTrace = descriptions[i].getStackTrace();
|
400 |
| |
401 |
3
| for (j = 0; j < stackTrace.length; j++)
|
402 |
157
| stream.println(stackTrace[j]);
|
403 |
| } |
404 |
| else |
405 |
0
| stream.println();
|
406 |
| } |
407 |
| } |
408 |
| |
409 |
| } |