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 Object newInstanceOf(final String className) throws ClassNotFoundException, IllegalAccessException,
139 InstantiationException, NoSuchMethodException, InvocationTargetException {
140 final Class<?> clazz = loadClass(className);
141 try {
142 return clazz.getConstructor().newInstance();
143 } catch (final NoSuchMethodException ignored) {
144
145 return 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 private static boolean isIgnoreTccl() {
171
172 if (ignoreTCCL == null) {
173 final String ignoreTccl = PropertiesUtil.getProperties().getStringProperty(IGNORE_TCCL_PROPERTY, null);
174 ignoreTCCL = ignoreTccl != null && !"false".equalsIgnoreCase(ignoreTccl.trim());
175 }
176 return ignoreTCCL;
177 }
178
179
180
181
182
183
184
185
186 public static Collection<URL> findResources(final String resource) {
187 final Collection<UrlResource> urlResources = findUrlResources(resource);
188 final Collection<URL> resources = new LinkedHashSet<>(urlResources.size());
189 for (final UrlResource urlResource : urlResources) {
190 resources.add(urlResource.getUrl());
191 }
192 return resources;
193 }
194
195 static Collection<UrlResource> findUrlResources(final String resource) {
196 final ClassLoader[] candidates = {getThreadContextClassLoader(), LoaderUtil.class.getClassLoader(),
197 GET_CLASS_LOADER_DISABLED ? null : ClassLoader.getSystemClassLoader()};
198 final Collection<UrlResource> resources = new LinkedHashSet<>();
199 for (final ClassLoader cl : candidates) {
200 if (cl != null) {
201 try {
202 final Enumeration<URL> resourceEnum = cl.getResources(resource);
203 while (resourceEnum.hasMoreElements()) {
204 resources.add(new UrlResource(cl, resourceEnum.nextElement()));
205 }
206 } catch (final IOException e) {
207 e.printStackTrace();
208 }
209 }
210 }
211 return resources;
212 }
213
214
215
216
217 static class UrlResource {
218 private final ClassLoader classLoader;
219 private final URL url;
220
221 public UrlResource(final ClassLoader classLoader, final URL url) {
222 this.classLoader = classLoader;
223 this.url = url;
224 }
225
226 public ClassLoader getClassLoader() {
227 return classLoader;
228 }
229
230 public URL getUrl() {
231 return url;
232 }
233
234 @Override
235 public boolean equals(final Object o) {
236 if (this == o) {
237 return true;
238 }
239 if (o == null || getClass() != o.getClass()) {
240 return false;
241 }
242
243 final UrlResource that = (UrlResource) o;
244
245 if (classLoader != null ? !classLoader.equals(that.classLoader) : that.classLoader != null) {
246 return false;
247 }
248 if (url != null ? !url.equals(that.url) : that.url != null) {
249 return false;
250 }
251
252 return true;
253 }
254
255 @Override
256 public int hashCode() {
257 return Objects.hashCode(classLoader) + Objects.hashCode(url);
258 }
259 }
260 }