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