1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
package org.mule.config; |
12 | |
|
13 | |
import org.mule.api.MuleException; |
14 | |
import org.mule.api.MuleRuntimeException; |
15 | |
import org.mule.api.config.ExceptionReader; |
16 | |
import org.mule.config.i18n.CoreMessages; |
17 | |
import org.mule.util.ClassUtils; |
18 | |
import org.mule.util.MapUtils; |
19 | |
import org.mule.util.SpiUtils; |
20 | |
import org.mule.util.StringUtils; |
21 | |
|
22 | |
import java.io.IOException; |
23 | |
import java.io.InputStream; |
24 | |
import java.util.ArrayList; |
25 | |
import java.util.HashMap; |
26 | |
import java.util.Iterator; |
27 | |
import java.util.List; |
28 | |
import java.util.Map; |
29 | |
import java.util.Properties; |
30 | |
|
31 | |
import org.apache.commons.logging.Log; |
32 | |
import org.apache.commons.logging.LogFactory; |
33 | |
|
34 | |
|
35 | |
|
36 | |
|
37 | |
|
38 | |
|
39 | |
|
40 | |
|
41 | |
|
42 | |
|
43 | |
public final class ExceptionHelper |
44 | |
{ |
45 | |
|
46 | |
|
47 | |
|
48 | |
|
49 | |
|
50 | |
public static final String ERROR_CODE_PROPERTY = "error.code.property"; |
51 | |
|
52 | |
|
53 | |
|
54 | |
|
55 | |
|
56 | |
public static final String APPLY_TO_PROPERTY = "apply.to"; |
57 | |
|
58 | |
|
59 | |
|
60 | |
|
61 | 2 | protected static final Log logger = LogFactory.getLog(ExceptionHelper.class); |
62 | |
|
63 | 2 | private static String J2SE_VERSION = ""; |
64 | |
|
65 | |
|
66 | |
private static final String J2EE_VERSION = "1.3ee"; |
67 | |
|
68 | 2 | private static Properties errorDocs = new Properties(); |
69 | 2 | private static Properties errorCodes = new Properties(); |
70 | 2 | private static Map reverseErrorCodes = null; |
71 | 2 | private static Map errorMappings = new HashMap(); |
72 | |
|
73 | 2 | private static int exceptionThreshold = 0; |
74 | 2 | private static boolean verbose = true; |
75 | |
|
76 | 2 | private static boolean initialised = false; |
77 | |
|
78 | |
|
79 | |
|
80 | |
|
81 | 2 | private static List exceptionReaders = new ArrayList(); |
82 | |
|
83 | |
|
84 | |
|
85 | |
|
86 | 2 | private static ExceptionReader defaultExceptionReader = new DefaultExceptionReader(); |
87 | |
|
88 | |
static |
89 | |
{ |
90 | 2 | initialise(); |
91 | 2 | } |
92 | |
|
93 | |
|
94 | |
private ExceptionHelper() |
95 | 0 | { |
96 | |
|
97 | 0 | } |
98 | |
|
99 | |
private static void initialise() |
100 | |
{ |
101 | |
try |
102 | |
{ |
103 | 2 | if (initialised) |
104 | |
{ |
105 | 0 | return; |
106 | |
} |
107 | |
|
108 | 2 | registerExceptionReader(new MuleExceptionReader()); |
109 | 2 | registerExceptionReader(new NamingExceptionReader()); |
110 | 2 | J2SE_VERSION = System.getProperty("java.specification.version"); |
111 | |
|
112 | 2 | String name = SpiUtils.SERVICE_ROOT + SpiUtils.EXCEPTION_SERVICE_PATH |
113 | |
+ "mule-exception-codes.properties"; |
114 | 2 | InputStream in = ExceptionHelper.class.getClassLoader().getResourceAsStream(name); |
115 | 2 | if (in == null) |
116 | |
{ |
117 | 0 | throw new IllegalArgumentException("Failed to load resource: " + name); |
118 | |
} |
119 | 2 | errorCodes.load(in); |
120 | 2 | in.close(); |
121 | |
|
122 | 2 | reverseErrorCodes = MapUtils.invertMap(errorCodes); |
123 | |
|
124 | 2 | name = SpiUtils.SERVICE_ROOT + SpiUtils.EXCEPTION_SERVICE_PATH |
125 | |
+ "mule-exception-config.properties"; |
126 | 2 | in = ExceptionHelper.class.getClassLoader().getResourceAsStream(name); |
127 | 2 | if (in == null) |
128 | |
{ |
129 | 0 | throw new IllegalArgumentException("Failed to load resource: " + name); |
130 | |
} |
131 | 2 | errorDocs.load(in); |
132 | 2 | in.close(); |
133 | |
|
134 | 2 | initialised = true; |
135 | |
} |
136 | 0 | catch (Exception e) |
137 | |
{ |
138 | 0 | throw new MuleRuntimeException(CoreMessages.failedToLoad("Exception resources"), e); |
139 | 2 | } |
140 | 2 | } |
141 | |
|
142 | |
public static int getErrorCode(Class exception) |
143 | |
{ |
144 | 172 | String code = errorCodes.getProperty(exception.getName(), "-1"); |
145 | 172 | return Integer.parseInt(code); |
146 | |
} |
147 | |
|
148 | |
public static Class getErrorClass(int code) |
149 | |
{ |
150 | 0 | String key = String.valueOf(code); |
151 | 0 | Object clazz = reverseErrorCodes.get(key); |
152 | 0 | if (clazz == null) |
153 | |
{ |
154 | 0 | return null; |
155 | |
} |
156 | 0 | else if (clazz instanceof Class) |
157 | |
{ |
158 | 0 | return (Class)clazz; |
159 | |
} |
160 | |
else |
161 | |
{ |
162 | |
try |
163 | |
{ |
164 | 0 | clazz = ClassUtils.loadClass(clazz.toString(), ExceptionHelper.class); |
165 | |
} |
166 | 0 | catch (ClassNotFoundException e) |
167 | |
{ |
168 | 0 | logger.error(e.getMessage(), e); |
169 | 0 | return null; |
170 | 0 | } |
171 | 0 | reverseErrorCodes.put(key, clazz); |
172 | 0 | return (Class)clazz; |
173 | |
} |
174 | |
} |
175 | |
|
176 | |
private static Properties getErrorMappings(String protocol) |
177 | |
{ |
178 | 0 | Object m = errorMappings.get(protocol); |
179 | 0 | if (m != null) |
180 | |
{ |
181 | 0 | if (m instanceof Properties) |
182 | |
{ |
183 | 0 | return (Properties)m; |
184 | |
} |
185 | |
else |
186 | |
{ |
187 | 0 | return null; |
188 | |
} |
189 | |
} |
190 | |
else |
191 | |
{ |
192 | 0 | String name = SpiUtils.SERVICE_ROOT + SpiUtils.EXCEPTION_SERVICE_PATH + protocol + "-exception-mappings.properties"; |
193 | 0 | InputStream in = ExceptionHelper.class.getClassLoader().getResourceAsStream(name); |
194 | 0 | if (in == null) |
195 | |
{ |
196 | 0 | errorMappings.put(protocol, "not found"); |
197 | 0 | logger.warn("Failed to load error mappings from: " + name |
198 | |
+ " This may be because there are no error code mappings for protocol: " |
199 | |
+ protocol); |
200 | 0 | return null; |
201 | |
} |
202 | |
|
203 | 0 | Properties p = new Properties(); |
204 | |
try |
205 | |
{ |
206 | 0 | p.load(in); |
207 | 0 | in.close(); |
208 | |
} |
209 | 0 | catch (IOException iox) |
210 | |
{ |
211 | 0 | throw new IllegalArgumentException("Failed to load resource: " + name); |
212 | 0 | } |
213 | |
|
214 | 0 | errorMappings.put(protocol, p); |
215 | 0 | String applyTo = p.getProperty(APPLY_TO_PROPERTY, null); |
216 | 0 | if (applyTo != null) |
217 | |
{ |
218 | 0 | String[] protocols = StringUtils.splitAndTrim(applyTo, ","); |
219 | 0 | for (int i = 0; i < protocols.length; i++) |
220 | |
{ |
221 | 0 | errorMappings.put(protocols[i], p); |
222 | |
} |
223 | |
} |
224 | 0 | return p; |
225 | |
} |
226 | |
} |
227 | |
|
228 | |
public static String getErrorCodePropertyName(String protocol) |
229 | |
{ |
230 | 0 | protocol = protocol.toLowerCase(); |
231 | 0 | Properties mappings = getErrorMappings(protocol); |
232 | 0 | if (mappings == null) |
233 | |
{ |
234 | 0 | return null; |
235 | |
} |
236 | 0 | return mappings.getProperty(ERROR_CODE_PROPERTY); |
237 | |
} |
238 | |
|
239 | |
public static String getErrorMapping(String protocol, Class exception) |
240 | |
{ |
241 | 0 | protocol = protocol.toLowerCase(); |
242 | 0 | Properties mappings = getErrorMappings(protocol); |
243 | 0 | if (mappings == null) |
244 | |
{ |
245 | 0 | logger.info("No mappings found for protocol: " + protocol); |
246 | 0 | return String.valueOf(getErrorCode(exception)); |
247 | |
} |
248 | |
|
249 | 0 | Class clazz = exception; |
250 | 0 | String code = null; |
251 | 0 | while (!clazz.equals(Object.class)) |
252 | |
{ |
253 | 0 | code = mappings.getProperty(clazz.getName()); |
254 | 0 | if (code == null) |
255 | |
{ |
256 | 0 | clazz = clazz.getSuperclass(); |
257 | |
} |
258 | |
else |
259 | |
{ |
260 | 0 | return code; |
261 | |
} |
262 | |
} |
263 | 0 | code = String.valueOf(getErrorCode(exception)); |
264 | |
|
265 | |
|
266 | 0 | return mappings.getProperty(code, code); |
267 | |
} |
268 | |
|
269 | |
public static String getJavaDocUrl(Class exception) |
270 | |
{ |
271 | 172 | return getDocUrl("javadoc.", exception.getName()); |
272 | |
} |
273 | |
|
274 | |
public static String getDocUrl(Class exception) |
275 | |
{ |
276 | 172 | return getDocUrl("doc.", exception.getName()); |
277 | |
} |
278 | |
|
279 | |
private static String getDocUrl(String prefix, String packageName) |
280 | |
{ |
281 | 344 | String key = prefix; |
282 | 344 | if (packageName.startsWith("java.") || packageName.startsWith("javax.")) |
283 | |
{ |
284 | 0 | key += J2SE_VERSION; |
285 | |
} |
286 | 344 | String url = getUrl(key, packageName); |
287 | 344 | if (url == null && (packageName.startsWith("java.") || packageName.startsWith("javax."))) |
288 | |
{ |
289 | 0 | key = prefix + J2EE_VERSION; |
290 | 0 | url = getUrl(key, packageName); |
291 | |
} |
292 | 344 | if (url != null) |
293 | |
{ |
294 | 172 | if (!url.endsWith("/")) |
295 | |
{ |
296 | 172 | url += "/"; |
297 | |
} |
298 | 172 | String s = packageName.replaceAll("[.]", "/"); |
299 | 172 | s += ".html"; |
300 | 172 | url += s; |
301 | |
} |
302 | 344 | return url; |
303 | |
} |
304 | |
|
305 | |
private static String getUrl(String key, String packageName) |
306 | |
{ |
307 | 344 | String url = null; |
308 | 344 | if (!key.endsWith(".")) |
309 | |
{ |
310 | 0 | key += "."; |
311 | |
} |
312 | 1712 | while (packageName.length() > 0) |
313 | |
{ |
314 | 1540 | url = errorDocs.getProperty(key + packageName, null); |
315 | 1540 | if (url == null) |
316 | |
{ |
317 | 1368 | int i = packageName.lastIndexOf("."); |
318 | 1368 | if (i == -1) |
319 | |
{ |
320 | 172 | packageName = ""; |
321 | |
} |
322 | |
else |
323 | |
{ |
324 | 1196 | packageName = packageName.substring(0, i); |
325 | |
} |
326 | 1368 | } |
327 | |
else |
328 | |
{ |
329 | |
break; |
330 | |
} |
331 | |
} |
332 | 344 | return url; |
333 | |
} |
334 | |
|
335 | |
public static Throwable getRootException(Throwable t) |
336 | |
{ |
337 | 6 | Throwable cause = t; |
338 | 6 | Throwable root = null; |
339 | 18 | while (cause != null) |
340 | |
{ |
341 | 12 | root = cause; |
342 | 12 | cause = getExceptionReader(cause).getCause(cause); |
343 | |
|
344 | 12 | if (t == cause) |
345 | |
{ |
346 | 0 | break; |
347 | |
} |
348 | |
} |
349 | 6 | return root; |
350 | |
} |
351 | |
|
352 | |
public static Throwable getRootParentException(Throwable t) |
353 | |
{ |
354 | 0 | Throwable cause = t; |
355 | 0 | Throwable parent = t; |
356 | 0 | while (cause != null) |
357 | |
{ |
358 | 0 | if (cause.getCause() == null) |
359 | |
{ |
360 | 0 | return parent; |
361 | |
} |
362 | 0 | parent = cause; |
363 | 0 | cause = getExceptionReader(cause).getCause(cause); |
364 | |
|
365 | 0 | if (t == cause) |
366 | |
{ |
367 | 0 | break; |
368 | |
} |
369 | |
} |
370 | 0 | return t; |
371 | |
} |
372 | |
|
373 | |
public static MuleException getRootMuleException(Throwable t) |
374 | |
{ |
375 | 22 | Throwable cause = t; |
376 | 22 | MuleException umoException = null; |
377 | 44 | while (cause != null) |
378 | |
{ |
379 | 22 | if (cause instanceof MuleException) |
380 | |
{ |
381 | 0 | umoException = (MuleException)cause; |
382 | |
} |
383 | 22 | cause = getExceptionReader(cause).getCause(cause); |
384 | |
|
385 | 22 | if (t == cause) |
386 | |
{ |
387 | 0 | break; |
388 | |
} |
389 | |
} |
390 | 22 | return umoException; |
391 | |
} |
392 | |
|
393 | |
public static List getExceptionsAsList(Throwable t) |
394 | |
{ |
395 | 0 | List exceptions = new ArrayList(); |
396 | 0 | Throwable cause = t; |
397 | 0 | while (cause != null) |
398 | |
{ |
399 | 0 | exceptions.add(0, cause); |
400 | 0 | cause = getExceptionReader(cause).getCause(cause); |
401 | |
|
402 | 0 | if (t == cause) |
403 | |
{ |
404 | 0 | break; |
405 | |
} |
406 | |
} |
407 | 0 | return exceptions; |
408 | |
} |
409 | |
|
410 | |
public static Map getExceptionInfo(Throwable t) |
411 | |
{ |
412 | 0 | Map info = new HashMap(); |
413 | 0 | Throwable cause = t; |
414 | 0 | while (cause != null) |
415 | |
{ |
416 | 0 | info.putAll(getExceptionReader(cause).getInfo(cause)); |
417 | 0 | cause = getExceptionReader(cause).getCause(cause); |
418 | |
|
419 | 0 | if (t == cause) |
420 | |
{ |
421 | 0 | break; |
422 | |
} |
423 | |
} |
424 | 0 | return info; |
425 | |
} |
426 | |
|
427 | |
public static String getExceptionStack(Throwable t) |
428 | |
{ |
429 | 0 | StringBuffer buf = new StringBuffer(); |
430 | |
|
431 | 0 | List exceptions = getExceptionsAsList(t); |
432 | |
|
433 | 0 | int i = 1; |
434 | 0 | for (Iterator iterator = exceptions.iterator(); iterator.hasNext(); i++) |
435 | |
{ |
436 | 0 | if (i > exceptionThreshold && exceptionThreshold > 0) |
437 | |
{ |
438 | 0 | buf.append("(").append(exceptions.size() - i + 1).append(" more...)"); |
439 | 0 | break; |
440 | |
} |
441 | 0 | Throwable throwable = (Throwable)iterator.next(); |
442 | 0 | ExceptionReader er = getExceptionReader(throwable); |
443 | 0 | buf.append(i).append(". ").append(er.getMessage(throwable)).append(" ("); |
444 | 0 | buf.append(throwable.getClass().getName()).append(")\n"); |
445 | 0 | if (verbose && throwable.getStackTrace().length > 0) |
446 | |
{ |
447 | 0 | StackTraceElement e = throwable.getStackTrace()[0]; |
448 | 0 | buf.append(" ") |
449 | |
.append(e.getClassName()) |
450 | |
.append(":") |
451 | |
.append(e.getLineNumber()) |
452 | |
.append(" (") |
453 | |
.append(getJavaDocUrl(throwable.getClass())) |
454 | |
.append(")\n"); |
455 | |
} |
456 | |
} |
457 | 0 | return buf.toString(); |
458 | |
} |
459 | |
|
460 | |
|
461 | |
|
462 | |
|
463 | |
|
464 | |
|
465 | |
public static void registerExceptionReader(ExceptionReader reader) |
466 | |
{ |
467 | 4 | exceptionReaders.add(reader); |
468 | 4 | } |
469 | |
|
470 | |
|
471 | |
|
472 | |
|
473 | |
|
474 | |
|
475 | |
|
476 | |
|
477 | |
public static ExceptionReader getExceptionReader(Throwable t) |
478 | |
{ |
479 | 34 | for (Iterator iterator = exceptionReaders.iterator(); iterator.hasNext();) |
480 | |
{ |
481 | 56 | ExceptionReader exceptionReader = (ExceptionReader)iterator.next(); |
482 | 56 | if (exceptionReader.getExceptionType().isInstance(t)) |
483 | |
{ |
484 | 12 | return exceptionReader; |
485 | |
} |
486 | 44 | } |
487 | 22 | return defaultExceptionReader; |
488 | |
} |
489 | |
|
490 | |
public static String writeException(Throwable t) |
491 | |
{ |
492 | 0 | ExceptionReader er = getExceptionReader(t); |
493 | 0 | StringBuffer msg = new StringBuffer(); |
494 | 0 | msg.append(er.getMessage(t)).append(". Type: ").append(t.getClass()); |
495 | 0 | return msg.toString(); |
496 | |
} |
497 | |
} |