1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.classic.spi;
15
16 import java.net.URL;
17 import java.security.CodeSource;
18 import java.util.HashMap;
19
20
21
22
23
24
25
26
27
28
29 public class PackagingDataCalculator {
30
31 final static StackTraceElementProxy[] STEP_ARRAY_TEMPLATE = new StackTraceElementProxy[0];
32
33 HashMap<String, ClassPackagingData> cache = new HashMap<String, ClassPackagingData>();
34
35 private static boolean GET_CALLER_CLASS_METHOD_AVAILABLE = false;
36
37
38 static {
39
40
41
42
43
44 try {
45
46
47 } catch (NoClassDefFoundError e) {
48 } catch (NoSuchMethodError e) {
49 } catch (UnsupportedOperationException e) {
50 } catch (Throwable e) {
51 System.err.println("Unexpected exception");
52 e.printStackTrace();
53 }
54 }
55
56 public void calculate(IThrowableProxy tp) {
57 while (tp != null) {
58 populateFrames(tp.getStackTraceElementProxyArray());
59 IThrowableProxy[] suppressed = tp.getSuppressed();
60 if (suppressed != null) {
61 for (IThrowableProxy current : suppressed) {
62 populateFrames(current.getStackTraceElementProxyArray());
63 }
64 }
65 tp = tp.getCause();
66 }
67 }
68
69 @SuppressWarnings("unused")
70 void populateFrames(StackTraceElementProxy[] stepArray) {
71
72
73 final Throwable t = new Throwable("local stack reference");
74 final StackTraceElement[] localSTEArray = t.getStackTrace();
75 final int commonFrames = STEUtil.findNumberOfCommonFrames(localSTEArray, stepArray);
76 final int localFirstCommon = localSTEArray.length - commonFrames;
77 final int stepFirstCommon = stepArray.length - commonFrames;
78
79 ClassLoader lastExactClassLoader = null;
80 ClassLoader firsExactClassLoader = null;
81
82 int missfireCount = 0;
83 for (int i = 0; i < commonFrames; i++) {
84 Class<?> callerClass = null;
85 if (GET_CALLER_CLASS_METHOD_AVAILABLE) {
86
87
88 }
89 StackTraceElementProxy step = stepArray[stepFirstCommon + i];
90 String stepClassname = step.ste.getClassName();
91
92 if (callerClass != null && stepClassname.equals(callerClass.getName())) {
93
94 lastExactClassLoader = callerClass.getClassLoader();
95 if (firsExactClassLoader == null) {
96 firsExactClassLoader = lastExactClassLoader;
97 }
98 ClassPackagingData pi = calculateByExactType(callerClass);
99 step.setClassPackagingData(pi);
100 } else {
101 missfireCount++;
102 ClassPackagingData pi = computeBySTEP(step, lastExactClassLoader);
103 step.setClassPackagingData(pi);
104 }
105 }
106 populateUncommonFrames(commonFrames, stepArray, firsExactClassLoader);
107 }
108
109 void populateUncommonFrames(int commonFrames, StackTraceElementProxy[] stepArray,
110 ClassLoader firstExactClassLoader) {
111 int uncommonFrames = stepArray.length - commonFrames;
112 for (int i = 0; i < uncommonFrames; i++) {
113 StackTraceElementProxy step = stepArray[i];
114 ClassPackagingData pi = computeBySTEP(step, firstExactClassLoader);
115 step.setClassPackagingData(pi);
116 }
117 }
118
119 private ClassPackagingData calculateByExactType(Class<?> type) {
120 String className = type.getName();
121 ClassPackagingData cpd = cache.get(className);
122 if (cpd != null) {
123 return cpd;
124 }
125 String version = getImplementationVersion(type);
126 String codeLocation = getCodeLocation(type);
127 cpd = new ClassPackagingData(codeLocation, version);
128 cache.put(className, cpd);
129 return cpd;
130 }
131
132 private ClassPackagingData computeBySTEP(StackTraceElementProxy step, ClassLoader lastExactClassLoader) {
133 String className = step.ste.getClassName();
134 ClassPackagingData cpd = cache.get(className);
135 if (cpd != null) {
136 return cpd;
137 }
138 Class<?> type = bestEffortLoadClass(lastExactClassLoader, className);
139 String version = getImplementationVersion(type);
140 String codeLocation = getCodeLocation(type);
141 cpd = new ClassPackagingData(codeLocation, version, false);
142 cache.put(className, cpd);
143 return cpd;
144 }
145
146 String getImplementationVersion(Class<?> type) {
147 if (type == null) {
148 return "na";
149 }
150 Package aPackage = type.getPackage();
151 if (aPackage != null) {
152 String v = aPackage.getImplementationVersion();
153 if (v == null) {
154 return "na";
155 } else {
156 return v;
157 }
158 }
159 return "na";
160
161 }
162
163 String getCodeLocation(Class<?> type) {
164 try {
165 if (type != null) {
166
167 CodeSource codeSource = type.getProtectionDomain().getCodeSource();
168 if (codeSource != null) {
169 URL resource = codeSource.getLocation();
170 if (resource != null) {
171 String locationStr = resource.toString();
172
173 String result = getCodeLocation(locationStr, '/');
174 if (result != null) {
175 return result;
176 }
177 return getCodeLocation(locationStr, '\\');
178 }
179 }
180 }
181 } catch (Exception e) {
182
183 }
184 return "na";
185 }
186
187 private String getCodeLocation(String locationStr, char separator) {
188 int idx = locationStr.lastIndexOf(separator);
189 if (isFolder(idx, locationStr)) {
190 idx = locationStr.lastIndexOf(separator, idx - 1);
191 return locationStr.substring(idx + 1);
192 } else if (idx > 0) {
193 return locationStr.substring(idx + 1);
194 }
195 return null;
196 }
197
198 private boolean isFolder(int idx, String text) {
199 return (idx != -1 && idx + 1 == text.length());
200 }
201
202 private Class<?> loadClass(ClassLoader cl, String className) {
203 if (cl == null) {
204 return null;
205 }
206 try {
207 return cl.loadClass(className);
208 } catch (ClassNotFoundException e1) {
209 return null;
210 } catch (NoClassDefFoundError e1) {
211 return null;
212 } catch (Exception e) {
213 e.printStackTrace();
214 return null;
215 }
216
217 }
218
219
220
221
222
223
224 private Class<?> bestEffortLoadClass(ClassLoader lastGuaranteedClassLoader, String className) {
225 Class<?> result = loadClass(lastGuaranteedClassLoader, className);
226 if (result != null) {
227 return result;
228 }
229 ClassLoader tccl = Thread.currentThread().getContextClassLoader();
230 if (tccl != lastGuaranteedClassLoader) {
231 result = loadClass(tccl, className);
232 }
233 if (result != null) {
234 return result;
235 }
236
237 try {
238 return Class.forName(className);
239 } catch (ClassNotFoundException e1) {
240 return null;
241 } catch (NoClassDefFoundError e1) {
242 return null;
243 } catch (Exception e) {
244 e.printStackTrace();
245 return null;
246 }
247 }
248
249 }