1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.util;
18
19 import java.io.IOException;
20 import java.lang.reflect.InvocationTargetException;
21 import java.net.URL;
22 import java.security.AccessController;
23 import java.security.PrivilegedAction;
24 import java.util.Collection;
25 import java.util.Enumeration;
26 import java.util.LinkedHashSet;
27 import java.util.Objects;
28
29
30
31
32
33
34
35
36
37 public final class LoaderUtil {
38
39
40
41
42
43
44 public static final String IGNORE_TCCL_PROPERTY = "log4j.ignoreTCL";
45
46 private static final SecurityManager SECURITY_MANAGER = System.getSecurityManager();
47
48
49
50 private static Boolean ignoreTCCL;
51
52 private static final boolean GET_CLASS_LOADER_DISABLED;
53
54 private static final PrivilegedAction<ClassLoader> TCCL_GETTER = new ThreadContextClassLoaderGetter();
55
56 static {
57 if (SECURITY_MANAGER != null) {
58 boolean getClassLoaderDisabled;
59 try {
60 SECURITY_MANAGER.checkPermission(new RuntimePermission("getClassLoader"));
61 getClassLoaderDisabled = false;
62 } catch (final SecurityException ignored) {
63 getClassLoaderDisabled = true;
64 }
65 GET_CLASS_LOADER_DISABLED = getClassLoaderDisabled;
66 } else {
67 GET_CLASS_LOADER_DISABLED = false;
68 }
69 }
70
71 private LoaderUtil() {
72 }
73
74
75
76
77
78
79
80
81
82 public static ClassLoader getThreadContextClassLoader() {
83 if (GET_CLASS_LOADER_DISABLED) {
84
85
86 return LoaderUtil.class.getClassLoader();
87 }
88 return SECURITY_MANAGER == null ? TCCL_GETTER.run() : AccessController.doPrivileged(TCCL_GETTER);
89 }
90
91
92
93
94 private static class ThreadContextClassLoaderGetter implements PrivilegedAction<ClassLoader> {
95 @Override
96 public ClassLoader run() {
97 final ClassLoader cl = Thread.currentThread().getContextClassLoader();
98 if (cl != null) {
99 return cl;
100 }
101 final ClassLoader ccl = LoaderUtil.class.getClassLoader();
102 return ccl == null && !GET_CLASS_LOADER_DISABLED ? ClassLoader.getSystemClassLoader() : ccl;
103 }
104 }
105
106
107
108
109
110
111
112
113 public static boolean isClassAvailable(final String className) {
114 try {
115 final Class<?> clazz = loadClass(className);
116 return clazz != null;
117 } catch (final ClassNotFoundException e) {
118 return false;
119 } catch (final Throwable e) {
120 LowLevelLogUtil.logException("Unknown error checking for existence of class: " + className, e);
121 return false;
122 }
123 }
124
125
126
127
128
129
130
131
132
133
134 public static Class<?> loadClass(final String className) throws ClassNotFoundException {
135 if (isIgnoreTccl()) {
136 return Class.forName(className);
137 }
138 try {
139 return getThreadContextClassLoader().loadClass(className);
140 } catch (final Throwable ignored) {
141 return Class.forName(className);
142 }
143 }
144
145
146
147
148
149
150
151
152
153
154
155 public static <T> T newInstanceOf(final Class<T> clazz)
156 throws InstantiationException, IllegalAccessException, InvocationTargetException {
157 try {
158 return clazz.getConstructor().newInstance();
159 } catch (final NoSuchMethodException ignored) {
160
161 return clazz.newInstance();
162 }
163 }
164
165
166
167
168
169
170
171
172
173
174
175
176
177 @SuppressWarnings("unchecked")
178 public static <T> T newInstanceOf(final String className) throws ClassNotFoundException, IllegalAccessException,
179 InstantiationException, NoSuchMethodException, InvocationTargetException {
180 return newInstanceOf((Class<T>) loadClass(className));
181 }
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198 public static <T> T newCheckedInstanceOf(final String className, final Class<T> clazz)
199 throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException,
200 IllegalAccessException {
201 return clazz.cast(newInstanceOf(className));
202 }
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219 public static <T> T newCheckedInstanceOfProperty(final String propertyName, final Class<T> clazz)
220 throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException,
221 IllegalAccessException {
222 final String className = PropertiesUtil.getProperties().getStringProperty(propertyName);
223 if (className == null) {
224 return null;
225 }
226 return newCheckedInstanceOf(className, clazz);
227 }
228
229 private static boolean isIgnoreTccl() {
230
231 if (ignoreTCCL == null) {
232 final String ignoreTccl = PropertiesUtil.getProperties().getStringProperty(IGNORE_TCCL_PROPERTY, null);
233 ignoreTCCL = ignoreTccl != null && !"false".equalsIgnoreCase(ignoreTccl.trim());
234 }
235 return ignoreTCCL;
236 }
237
238
239
240
241
242
243
244
245 public static Collection<URL> findResources(final String resource) {
246 final Collection<UrlResource> urlResources = findUrlResources(resource);
247 final Collection<URL> resources = new LinkedHashSet<>(urlResources.size());
248 for (final UrlResource urlResource : urlResources) {
249 resources.add(urlResource.getUrl());
250 }
251 return resources;
252 }
253
254 static Collection<UrlResource> findUrlResources(final String resource) {
255 final ClassLoader[] candidates = {getThreadContextClassLoader(), LoaderUtil.class.getClassLoader(),
256 GET_CLASS_LOADER_DISABLED ? null : ClassLoader.getSystemClassLoader()};
257 final Collection<UrlResource> resources = new LinkedHashSet<>();
258 for (final ClassLoader cl : candidates) {
259 if (cl != null) {
260 try {
261 final Enumeration<URL> resourceEnum = cl.getResources(resource);
262 while (resourceEnum.hasMoreElements()) {
263 resources.add(new UrlResource(cl, resourceEnum.nextElement()));
264 }
265 } catch (final IOException e) {
266 LowLevelLogUtil.logException(e);
267 }
268 }
269 }
270 return resources;
271 }
272
273
274
275
276 static class UrlResource {
277 private final ClassLoader classLoader;
278 private final URL url;
279
280 UrlResource(final ClassLoader classLoader, final URL url) {
281 this.classLoader = classLoader;
282 this.url = url;
283 }
284
285 public ClassLoader getClassLoader() {
286 return classLoader;
287 }
288
289 public URL getUrl() {
290 return url;
291 }
292
293 @Override
294 public boolean equals(final Object o) {
295 if (this == o) {
296 return true;
297 }
298 if (o == null || getClass() != o.getClass()) {
299 return false;
300 }
301
302 final UrlResource that = (UrlResource) o;
303
304 if (classLoader != null ? !classLoader.equals(that.classLoader) : that.classLoader != null) {
305 return false;
306 }
307 if (url != null ? !url.equals(that.url) : that.url != null) {
308 return false;
309 }
310
311 return true;
312 }
313
314 @Override
315 public int hashCode() {
316 return Objects.hashCode(classLoader) + Objects.hashCode(url);
317 }
318 }
319 }