1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.util;
18
19
20 import java.io.InputStream;
21 import java.lang.reflect.InvocationTargetException;
22 import java.lang.reflect.ReflectPermission;
23 import java.net.URL;
24
25 import org.apache.logging.log4j.Logger;
26 import org.apache.logging.log4j.status.StatusLogger;
27 import org.apache.logging.log4j.util.LoaderUtil;
28 import org.apache.logging.log4j.util.PropertiesUtil;
29
30
31
32
33 public final class Loader {
34
35 private static boolean ignoreTCL = false;
36
37 private static final Logger LOGGER = StatusLogger.getLogger();
38
39 private static final String TSTR = "Caught Exception while in Loader.getResource. This may be innocuous.";
40
41 static {
42 final String ignoreTCLProp = PropertiesUtil.getProperties().getStringProperty("log4j.ignoreTCL", null);
43 if (ignoreTCLProp != null) {
44 ignoreTCL = OptionConverter.toBoolean(ignoreTCLProp, true);
45 }
46 final SecurityManager sm = System.getSecurityManager();
47 if (sm != null) {
48 sm.checkPermission(new RuntimePermission("getStackTrace"));
49 sm.checkPermission(new ReflectPermission("suppressAccessChecks"));
50 }
51 }
52
53
54
55
56
57 public static ClassLoader getClassLoader() {
58
59 return getClassLoader(Loader.class, null);
60 }
61
62
63
64
65
66
67
68 public static ClassLoader getThreadContextClassLoader() {
69 return LoaderUtil.getThreadContextClassLoader();
70 }
71
72
73 public static ClassLoader getClassLoader(final Class<?> class1, final Class<?> class2) {
74
75 ClassLoader threadContextClassLoader = null;
76 try {
77 threadContextClassLoader = getTcl();
78 } catch (final Exception ex) {
79 LOGGER.warn("Caught exception locating thread ClassLoader {}", ex.getMessage());
80 }
81 final ClassLoader loader1 = class1 == null ? null : class1.getClassLoader();
82 final ClassLoader loader2 = class2 == null ? null : class2.getClassLoader();
83
84 if (isChild(threadContextClassLoader, loader1)) {
85 return isChild(threadContextClassLoader, loader2) ? threadContextClassLoader : loader2;
86 }
87 return isChild(loader1, loader2) ? loader1 : loader2;
88 }
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 public static URL getResource(final String resource, final ClassLoader defaultLoader) {
113 try {
114 ClassLoader classLoader = getTcl();
115 if (classLoader != null) {
116 LOGGER.trace("Trying to find [{}] using context class loader {}.", resource, classLoader);
117 final URL url = classLoader.getResource(resource);
118 if (url != null) {
119 return url;
120 }
121 }
122
123
124 classLoader = Loader.class.getClassLoader();
125 if (classLoader != null) {
126 LOGGER.trace("Trying to find [{}] using {} class loader.", resource, classLoader);
127 final URL url = classLoader.getResource(resource);
128 if (url != null) {
129 return url;
130 }
131 }
132
133 if (defaultLoader != null) {
134 LOGGER.trace("Trying to find [{}] using {} class loader.", resource, defaultLoader);
135 final URL url = defaultLoader.getResource(resource);
136 if (url != null) {
137 return url;
138 }
139 }
140 } catch (final Throwable t) {
141
142
143
144 LOGGER.warn(TSTR, t);
145 }
146
147
148
149
150
151 LOGGER.trace("Trying to find [{}] using ClassLoader.getSystemResource().", resource);
152 return ClassLoader.getSystemResource(resource);
153 }
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177 public static InputStream getResourceAsStream(final String resource, final ClassLoader defaultLoader) {
178 try {
179 ClassLoader classLoader = getTcl();
180 InputStream is;
181 if (classLoader != null) {
182 LOGGER.trace("Trying to find [{}] using context class loader {}.", resource, classLoader);
183 is = classLoader.getResourceAsStream(resource);
184 if (is != null) {
185 return is;
186 }
187 }
188
189
190 classLoader = Loader.class.getClassLoader();
191 if (classLoader != null) {
192 LOGGER.trace("Trying to find [{}] using {} class loader.", resource, classLoader);
193 is = classLoader.getResourceAsStream(resource);
194 if (is != null) {
195 return is;
196 }
197 }
198
199
200 if (defaultLoader != null) {
201 LOGGER.trace("Trying to find [{}] using {} class loader.", resource, defaultLoader);
202 is = defaultLoader.getResourceAsStream(resource);
203 if (is != null) {
204 return is;
205 }
206 }
207 } catch (final Throwable t) {
208
209
210
211 LOGGER.warn(TSTR, t);
212 }
213
214
215
216
217
218 LOGGER.trace("Trying to find [{}] using ClassLoader.getSystemResource().", resource);
219 return ClassLoader.getSystemResourceAsStream(resource);
220 }
221
222 private static ClassLoader getTcl() {
223 return LoaderUtil.getThreadContextClassLoader();
224 }
225
226
227
228
229
230
231
232
233
234 private static boolean isChild(final ClassLoader loader1, final ClassLoader loader2) {
235 if (loader1 != null && loader2 != null) {
236 ClassLoader parent = loader1.getParent();
237 while (parent != null && parent != loader2) {
238 parent = parent.getParent();
239 }
240
241 return parent != null;
242 }
243 return loader1 != null;
244 }
245
246
247
248
249
250
251
252
253
254
255 public static Class<?> loadClass(final String className) throws ClassNotFoundException {
256
257 if (ignoreTCL) {
258 LOGGER.trace("Ignoring TCCL. Trying Class.forName({}).", className);
259 return loadClassWithDefaultClassLoader(className);
260 }
261 try {
262 LOGGER.trace("Trying TCCL for class {}.", className);
263
264 return Class.forName(className, true, getTcl());
265 } catch (final Throwable e) {
266 LOGGER.trace("TCCL didn't work for class {}: {}.", className, e.toString());
267 return loadClassWithDefaultClassLoader(className);
268 }
269 }
270
271 private static Class<?> loadClassWithDefaultClassLoader(final String className) throws ClassNotFoundException {
272 return Class.forName(className);
273 }
274
275
276
277
278
279
280
281
282
283 public static Class<?> initializeClass(final String className, final ClassLoader loader)
284 throws ClassNotFoundException {
285 return Class.forName(className, true, loader);
286 }
287
288
289
290
291
292
293
294
295
296 public static Class<?> loadSystemClass(final String className) throws ClassNotFoundException {
297 try {
298 return Class.forName(className, true, ClassLoader.getSystemClassLoader());
299 } catch (final Throwable t) {
300 LOGGER.trace("Couldn't use SystemClassLoader. Trying Class.forName({}).", className, t);
301 return Class.forName(className);
302 }
303 }
304
305
306
307
308
309
310
311
312
313
314
315
316 public static Object newInstanceOf(final String className)
317 throws ClassNotFoundException,
318 IllegalAccessException,
319 InstantiationException,
320 NoSuchMethodException,
321 InvocationTargetException {
322 final Class<?> clazz = loadClass(className);
323 try {
324 return clazz.getConstructor().newInstance();
325 } catch (final NoSuchMethodException e) {
326
327
328 return clazz.newInstance();
329 }
330 }
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346 public static <T> T newCheckedInstanceOf(final String className, final Class<T> clazz)
347 throws ClassNotFoundException,
348 NoSuchMethodException,
349 IllegalAccessException,
350 InvocationTargetException,
351 InstantiationException {
352 return clazz.cast(newInstanceOf(className));
353 }
354
355
356
357
358
359
360
361 public static boolean isClassAvailable(final String className) {
362 try {
363 final Class<?> clazz = loadClass(className);
364 return clazz != null;
365 } catch (final ClassNotFoundException e) {
366 return false;
367 } catch (final Throwable e) {
368 LOGGER.trace("Unknown error checking for existence of class [{}].", className, e);
369 return false;
370 }
371 }
372
373 private Loader() {
374 }
375 }