1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.log4j;
18
19 import org.apache.log4j.spi.ThrowableRenderer;
20
21 import java.io.File;
22 import java.lang.reflect.Method;
23 import java.net.URL;
24 import java.security.CodeSource;
25 import java.util.HashMap;
26 import java.util.Map;
27
28
29
30
31
32
33
34
35 public final class EnhancedThrowableRenderer implements ThrowableRenderer {
36
37
38
39 private Method getStackTraceMethod;
40
41
42
43 private Method getClassNameMethod;
44
45
46
47
48
49 public EnhancedThrowableRenderer() {
50 try {
51 Class[] noArgs = null;
52 getStackTraceMethod = Throwable.class.getMethod("getStackTrace", noArgs);
53 Class ste = Class.forName("java.lang.StackTraceElement");
54 getClassNameMethod = ste.getMethod("getClassName", noArgs);
55 } catch(Exception ex) {
56 }
57 }
58
59
60
61
62 public String[] doRender(final Throwable throwable) {
63 if (getStackTraceMethod != null) {
64 try {
65 Object[] noArgs = null;
66 Object[] elements = (Object[]) getStackTraceMethod.invoke(throwable, noArgs);
67 String[] lines = new String[elements.length + 1];
68 lines[0] = throwable.toString();
69 Map classMap = new HashMap();
70 for(int i = 0; i < elements.length; i++) {
71 lines[i+1] = formatElement(elements[i], classMap);
72 }
73 return lines;
74 } catch(Exception ex) {
75 }
76 }
77 return DefaultThrowableRenderer.render(throwable);
78 }
79
80
81
82
83
84
85
86 private String formatElement(final Object element, final Map classMap) {
87 StringBuffer buf = new StringBuffer("\tat ");
88 buf.append(element);
89 try {
90 String className = getClassNameMethod.invoke(element, (Object[]) null).toString();
91 Object classDetails = classMap.get(className);
92 if (classDetails != null) {
93 buf.append(classDetails);
94 } else {
95 Class cls = findClass(className);
96 int detailStart = buf.length();
97 buf.append('[');
98 try {
99 CodeSource source = cls.getProtectionDomain().getCodeSource();
100 if (source != null) {
101 URL locationURL = source.getLocation();
102 if (locationURL != null) {
103
104
105
106 if ("file".equals(locationURL.getProtocol())) {
107 String path = locationURL.getPath();
108 if (path != null) {
109
110
111
112 int lastSlash = path.lastIndexOf('/');
113 int lastBack = path.lastIndexOf(File.separatorChar);
114 if (lastBack > lastSlash) {
115 lastSlash = lastBack;
116 }
117
118
119
120
121 if (lastSlash <= 0 || lastSlash == path.length() - 1) {
122 buf.append(locationURL);
123 } else {
124 buf.append(path.substring(lastSlash + 1));
125 }
126 }
127 } else {
128 buf.append(locationURL);
129 }
130 }
131 }
132 } catch(SecurityException ex) {
133 }
134 buf.append(':');
135 Package pkg = cls.getPackage();
136 if (pkg != null) {
137 String implVersion = pkg.getImplementationVersion();
138 if (implVersion != null) {
139 buf.append(implVersion);
140 }
141 }
142 buf.append(']');
143 classMap.put(className, buf.substring(detailStart));
144 }
145 } catch(Exception ex) {
146 }
147 return buf.toString();
148 }
149
150
151
152
153
154
155
156 private Class findClass(final String className) throws ClassNotFoundException {
157 try {
158 return Thread.currentThread().getContextClassLoader().loadClass(className);
159 } catch (ClassNotFoundException e) {
160 try {
161 return Class.forName(className);
162 } catch (ClassNotFoundException e1) {
163 return getClass().getClassLoader().loadClass(className);
164 }
165 }
166 }
167
168 }