1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.shiro.util;
20
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import java.io.InputStream;
25 import java.lang.annotation.Annotation;
26 import java.lang.reflect.Constructor;
27 import java.lang.reflect.Method;
28 import java.util.ArrayList;
29 import java.util.List;
30
31
32
33
34
35
36
37
38 public class ClassUtils {
39
40
41
42
43
44
45 private static final Logger log = LoggerFactory.getLogger(ClassUtils.class);
46
47
48
49
50 private static final ClassLoaderAccessor THREAD_CL_ACCESSOR = new ExceptionIgnoringAccessor() {
51 @Override
52 protected ClassLoader doGetClassLoader() throws Throwable {
53 return Thread.currentThread().getContextClassLoader();
54 }
55 };
56
57
58
59
60 private static final ClassLoaderAccessor CLASS_CL_ACCESSOR = new ExceptionIgnoringAccessor() {
61 @Override
62 protected ClassLoader doGetClassLoader() throws Throwable {
63 return ClassUtils.class.getClassLoader();
64 }
65 };
66
67
68
69
70 private static final ClassLoaderAccessor SYSTEM_CL_ACCESSOR = new ExceptionIgnoringAccessor() {
71 @Override
72 protected ClassLoader doGetClassLoader() throws Throwable {
73 return ClassLoader.getSystemClassLoader();
74 }
75 };
76
77
78
79
80
81
82
83
84
85
86
87
88
89 public static InputStream getResourceAsStream(String name) {
90
91 InputStream is = THREAD_CL_ACCESSOR.getResourceStream(name);
92
93 if (is == null) {
94 if (log.isTraceEnabled()) {
95 log.trace("Resource [" + name + "] was not found via the thread context ClassLoader. Trying the " +
96 "current ClassLoader...");
97 }
98 is = CLASS_CL_ACCESSOR.getResourceStream(name);
99 }
100
101 if (is == null) {
102 if (log.isTraceEnabled()) {
103 log.trace("Resource [" + name + "] was not found via the current class loader. Trying the " +
104 "system/application ClassLoader...");
105 }
106 is = SYSTEM_CL_ACCESSOR.getResourceStream(name);
107 }
108
109 if (is == null && log.isTraceEnabled()) {
110 log.trace("Resource [" + name + "] was not found via the thread context, current, or " +
111 "system/application ClassLoaders. All heuristics have been exhausted. Returning null.");
112 }
113
114 return is;
115 }
116
117
118
119
120
121
122
123
124
125
126
127
128
129 public static Class forName(String fqcn) throws UnknownClassException {
130
131 Class clazz = THREAD_CL_ACCESSOR.loadClass(fqcn);
132
133 if (clazz == null) {
134 if (log.isTraceEnabled()) {
135 log.trace("Unable to load class named [" + fqcn +
136 "] from the thread context ClassLoader. Trying the current ClassLoader...");
137 }
138 clazz = CLASS_CL_ACCESSOR.loadClass(fqcn);
139 }
140
141 if (clazz == null) {
142 if (log.isTraceEnabled()) {
143 log.trace("Unable to load class named [" + fqcn + "] from the current ClassLoader. " +
144 "Trying the system/application ClassLoader...");
145 }
146 clazz = SYSTEM_CL_ACCESSOR.loadClass(fqcn);
147 }
148
149 if (clazz == null) {
150 String msg = "Unable to load class named [" + fqcn + "] from the thread context, current, or " +
151 "system/application ClassLoaders. All heuristics have been exhausted. Class could not be found.";
152 throw new UnknownClassException(msg);
153 }
154
155 return clazz;
156 }
157
158 public static boolean isAvailable(String fullyQualifiedClassName) {
159 try {
160 forName(fullyQualifiedClassName);
161 return true;
162 } catch (UnknownClassException e) {
163 return false;
164 }
165 }
166
167 public static Object newInstance(String fqcn) {
168 return newInstance(forName(fqcn));
169 }
170
171 public static Object newInstance(String fqcn, Object... args) {
172 return newInstance(forName(fqcn), args);
173 }
174
175 public static Object newInstance(Class clazz) {
176 if (clazz == null) {
177 String msg = "Class method parameter cannot be null.";
178 throw new IllegalArgumentException(msg);
179 }
180 try {
181 return clazz.newInstance();
182 } catch (Exception e) {
183 throw new InstantiationException("Unable to instantiate class [" + clazz.getName() + "]", e);
184 }
185 }
186
187 public static Object newInstance(Class clazz, Object... args) {
188 Class[] argTypes = new Class[args.length];
189 for (int i = 0; i < args.length; i++) {
190 argTypes[i] = args[i].getClass();
191 }
192 Constructor ctor = getConstructor(clazz, argTypes);
193 return instantiate(ctor, args);
194 }
195
196 public static Constructor getConstructor(Class clazz, Class... argTypes) {
197 try {
198 return clazz.getConstructor(argTypes);
199 } catch (NoSuchMethodException e) {
200 throw new IllegalStateException(e);
201 }
202
203 }
204
205 public static Object instantiate(Constructor ctor, Object... args) {
206 try {
207 return ctor.newInstance(args);
208 } catch (Exception e) {
209 String msg = "Unable to instantiate Permission instance with constructor [" + ctor + "]";
210 throw new InstantiationException(msg, e);
211 }
212 }
213
214
215
216
217
218
219
220
221 public static List<Method> getAnnotatedMethods(final Class<?> type, final Class<? extends Annotation> annotation) {
222 final List<Method> methods = new ArrayList<Method>();
223 Class<?> clazz = type;
224 while (!Object.class.equals(clazz)) {
225 Method[] currentClassMethods = clazz.getDeclaredMethods();
226 for (final Method method : currentClassMethods) {
227 if (annotation == null || method.isAnnotationPresent(annotation)) {
228 methods.add(method);
229 }
230 }
231
232 clazz = clazz.getSuperclass();
233 }
234 return methods;
235 }
236
237
238
239
240 private static interface ClassLoaderAccessor {
241 Class loadClass(String fqcn);
242 InputStream getResourceStream(String name);
243 }
244
245
246
247
248 private static abstract class ExceptionIgnoringAccessor implements ClassLoaderAccessor {
249
250 public Class loadClass(String fqcn) {
251 Class clazz = null;
252 ClassLoader cl = getClassLoader();
253 if (cl != null) {
254 try {
255 clazz = cl.loadClass(fqcn);
256 } catch (ClassNotFoundException e) {
257 if (log.isTraceEnabled()) {
258 log.trace("Unable to load clazz named [" + fqcn + "] from class loader [" + cl + "]");
259 }
260 }
261 }
262 return clazz;
263 }
264
265 public InputStream getResourceStream(String name) {
266 InputStream is = null;
267 ClassLoader cl = getClassLoader();
268 if (cl != null) {
269 is = cl.getResourceAsStream(name);
270 }
271 return is;
272 }
273
274 protected final ClassLoader getClassLoader() {
275 try {
276 return doGetClassLoader();
277 } catch (Throwable t) {
278 if (log.isDebugEnabled()) {
279 log.debug("Unable to acquire ClassLoader.", t);
280 }
281 }
282 return null;
283 }
284
285 protected abstract ClassLoader doGetClassLoader() throws Throwable;
286 }
287 }