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
114
115 public static Class<?> loadClass(final String className) throws ClassNotFoundException {
116 if (isIgnoreTccl()) {
117 return Class.forName(className);
118 }
119 try {
120 return getThreadContextClassLoader().loadClass(className);
121 } catch (final Throwable ignored) {
122 return Class.forName(className);
123 }
124 }
125
126
127
128
129
130
131
132
133
134
135
136
137
138 public static <T> T newInstanceOf(final String className) throws ClassNotFoundException, IllegalAccessException,
139 InstantiationException, NoSuchMethodException, InvocationTargetException {
140 final Class<?> clazz = loadClass(className);
141 try {
142 return (T) clazz.getConstructor().newInstance();
143 } catch (final NoSuchMethodException ignored) {
144
145 return (T) clazz.newInstance();
146 }
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 public static <T> T newCheckedInstanceOf(final String className, final Class<T> clazz)
165 throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException,
166 IllegalAccessException {
167 return clazz.cast(newInstanceOf(className));
168 }
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185 public static <T> T newCheckedInstanceOfProperty(final String propertyName, final Class<T> clazz)
186 throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException,
187 IllegalAccessException {
188 final String className = PropertiesUtil.getProperties().getStringProperty(propertyName);
189 if (className == null) {
190 return null;
191 }
192 return newCheckedInstanceOf(className, clazz);
193 }
194
195 private static boolean isIgnoreTccl() {
196
197 if (ignoreTCCL == null) {
198 final String ignoreTccl = PropertiesUtil.getProperties().getStringProperty(IGNORE_TCCL_PROPERTY, null);
199 ignoreTCCL = ignoreTccl != null && !"false".equalsIgnoreCase(ignoreTccl.trim());
200 }
201 return ignoreTCCL;
202 }
203
204
205
206
207
208
209
210
211 public static Collection<URL> findResources(final String resource) {
212 final Collection<UrlResource> urlResources = findUrlResources(resource);
213 final Collection<URL> resources = new LinkedHashSet<>(urlResources.size());
214 for (final UrlResource urlResource : urlResources) {
215 resources.add(urlResource.getUrl());
216 }
217 return resources;
218 }
219
220 static Collection<UrlResource> findUrlResources(final String resource) {
221 final ClassLoader[] candidates = {getThreadContextClassLoader(), LoaderUtil.class.getClassLoader(),
222 GET_CLASS_LOADER_DISABLED ? null : ClassLoader.getSystemClassLoader()};
223 final Collection<UrlResource> resources = new LinkedHashSet<>();
224 for (final ClassLoader cl : candidates) {
225 if (cl != null) {
226 try {
227 final Enumeration<URL> resourceEnum = cl.getResources(resource);
228 while (resourceEnum.hasMoreElements()) {
229 resources.add(new UrlResource(cl, resourceEnum.nextElement()));
230 }
231 } catch (final IOException e) {
232 LowLevelLogUtil.logException(e);
233 }
234 }
235 }
236 return resources;
237 }
238
239
240
241
242 static class UrlResource {
243 private final ClassLoader classLoader;
244 private final URL url;
245
246 UrlResource(final ClassLoader classLoader, final URL url) {
247 this.classLoader = classLoader;
248 this.url = url;
249 }
250
251 public ClassLoader getClassLoader() {
252 return classLoader;
253 }
254
255 public URL getUrl() {
256 return url;
257 }
258
259 @Override
260 public boolean equals(final Object o) {
261 if (this == o) {
262 return true;
263 }
264 if (o == null || getClass() != o.getClass()) {
265 return false;
266 }
267
268 final UrlResource that = (UrlResource) o;
269
270 if (classLoader != null ? !classLoader.equals(that.classLoader) : that.classLoader != null) {
271 return false;
272 }
273 if (url != null ? !url.equals(that.url) : that.url != null) {
274 return false;
275 }
276
277 return true;
278 }
279
280 @Override
281 public int hashCode() {
282 return Objects.hashCode(classLoader) + Objects.hashCode(url);
283 }
284 }
285 }