001
014
015 package com.liferay.portal.kernel.util;
016
017 import java.lang.annotation.Annotation;
018 import java.lang.reflect.Constructor;
019 import java.lang.reflect.Field;
020 import java.lang.reflect.Method;
021 import java.lang.reflect.Modifier;
022
023 import java.util.Arrays;
024 import java.util.List;
025
026
031 public class ReflectionUtil {
032
033 public static Class<?> getAnnotationDeclaringClass(
034 Class<? extends Annotation> annotationClass, Class<?> clazz) {
035
036 if ((clazz == null) || clazz.equals(Object.class)) {
037 return null;
038 }
039
040 if (isAnnotationDeclaredInClass(annotationClass, clazz)) {
041 return clazz;
042 }
043 else {
044 return getAnnotationDeclaringClass(
045 annotationClass, clazz.getSuperclass());
046 }
047 }
048
049 public static Method getBridgeMethod(
050 Class<?> clazz, String name, Class<?> ... parameterTypes)
051 throws Exception {
052
053 return getBridgeMethod(true, clazz, name, parameterTypes);
054 }
055
056 public static Method getDeclaredBridgeMethod(
057 Class<?> clazz, String name, Class<?> ... parameterTypes)
058 throws Exception {
059
060 return getBridgeMethod(false, clazz, name, parameterTypes);
061 }
062
063 public static Field getDeclaredField(Class<?> clazz, String name)
064 throws Exception {
065
066 Field field = clazz.getDeclaredField(name);
067
068 if (!field.isAccessible()) {
069 field.setAccessible(true);
070 }
071
072 int modifiers = field.getModifiers();
073
074 if ((modifiers & Modifier.FINAL) == Modifier.FINAL) {
075 Field modifiersField = ReflectionUtil.getDeclaredField(
076 Field.class, "modifiers");
077
078 modifiersField.setInt(field, modifiers & ~Modifier.FINAL);
079 }
080
081 return field;
082 }
083
084 public static Method getDeclaredMethod(
085 Class<?> clazz, String name, Class<?> ... parameterTypes)
086 throws Exception {
087
088 Method method = clazz.getDeclaredMethod(name, parameterTypes);
089
090 if (!method.isAccessible()) {
091 method.setAccessible(true);
092 }
093
094 return method;
095 }
096
097 public static Class<?>[] getInterfaces(Object object) {
098 return getInterfaces(object, null);
099 }
100
101 public static Class<?>[] getInterfaces(
102 Object object, ClassLoader classLoader) {
103
104 List<Class<?>> interfaceClasses = new UniqueList<Class<?>>();
105
106 Class<?> clazz = object.getClass();
107
108 _getInterfaces(interfaceClasses, clazz, classLoader);
109
110 Class<?> superClass = clazz.getSuperclass();
111
112 while (superClass != null) {
113 _getInterfaces(interfaceClasses, superClass, classLoader);
114
115 superClass = superClass.getSuperclass();
116 }
117
118 return interfaceClasses.toArray(new Class<?>[interfaceClasses.size()]);
119 }
120
121 public static Class<?>[] getParameterTypes(Object[] arguments) {
122 if (arguments == null) {
123 return null;
124 }
125
126 Class<?>[] parameterTypes = new Class<?>[arguments.length];
127
128 for (int i = 0; i < arguments.length; i++) {
129 if (arguments[i] == null) {
130 parameterTypes[i] = null;
131 }
132 else if (arguments[i] instanceof Boolean) {
133 parameterTypes[i] = Boolean.TYPE;
134 }
135 else if (arguments[i] instanceof Byte) {
136 parameterTypes[i] = Byte.TYPE;
137 }
138 else if (arguments[i] instanceof Character) {
139 parameterTypes[i] = Character.TYPE;
140 }
141 else if (arguments[i] instanceof Double) {
142 parameterTypes[i] = Double.TYPE;
143 }
144 else if (arguments[i] instanceof Float) {
145 parameterTypes[i] = Float.TYPE;
146 }
147 else if (arguments[i] instanceof Integer) {
148 parameterTypes[i] = Integer.TYPE;
149 }
150 else if (arguments[i] instanceof Long) {
151 parameterTypes[i] = Long.TYPE;
152 }
153 else if (arguments[i] instanceof Short) {
154 parameterTypes[i] = Short.TYPE;
155 }
156 else {
157 parameterTypes[i] = arguments[i].getClass();
158 }
159 }
160
161 return parameterTypes;
162 }
163
164 public static boolean isAnnotationDeclaredInClass(
165 Class<? extends Annotation> annotationClass, Class<?> clazz) {
166
167 if ((annotationClass == null) || (clazz == null)) {
168 throw new IllegalArgumentException();
169 }
170
171 Annotation[] annotations = clazz.getAnnotations();
172
173 for (Annotation annotation : annotations) {
174 if (annotationClass.equals(annotation.annotationType())) {
175 return true;
176 }
177 }
178
179 return false;
180 }
181
182 public static <T extends Enum<T>> T newEnumElement(
183 Class<T> enumClass, Class<?>[] constructorParameterTypes,
184 String name, int ordinal, Object... constructorParameters)
185 throws Exception {
186
187 Class<?>[] parameterTypes = null;
188
189 if ((constructorParameterTypes != null) &&
190 (constructorParameterTypes.length != 0)) {
191
192 parameterTypes = new Class<?>[constructorParameterTypes.length + 2];
193
194 parameterTypes[0] = String.class;
195 parameterTypes[1] = int.class;
196
197 System.arraycopy(
198 constructorParameterTypes, 0, parameterTypes, 2,
199 constructorParameterTypes.length);
200 }
201 else {
202 parameterTypes = new Class<?>[2];
203
204 parameterTypes[0] = String.class;
205 parameterTypes[1] = int.class;
206 }
207
208 Constructor<T> constructor = enumClass.getDeclaredConstructor(
209 parameterTypes);
210
211 Method acquireConstructorAccessorMethod = getDeclaredMethod(
212 Constructor.class, "acquireConstructorAccessor");
213
214 acquireConstructorAccessorMethod.invoke(constructor);
215
216 Field constructorAccessorField = getDeclaredField(
217 Constructor.class, "constructorAccessor");
218
219 Object constructorAccessor = constructorAccessorField.get(constructor);
220
221 Method newInstanceMethod = getDeclaredMethod(
222 constructorAccessor.getClass(), "newInstance", Object[].class);
223
224 Object[] parameters = null;
225
226 if ((constructorParameters != null) &&
227 (constructorParameters.length != 0)) {
228
229 parameters = new Object[constructorParameters.length + 2];
230
231 parameters[0] = name;
232 parameters[1] = ordinal;
233
234 System.arraycopy(
235 constructorParameters, 0, parameters, 2,
236 constructorParameters.length);
237 }
238 else {
239 parameters = new Object[2];
240
241 parameters[0] = name;
242 parameters[1] = ordinal;
243 }
244
245 return (T)newInstanceMethod.invoke(
246 constructorAccessor, new Object[] {parameters});
247 }
248
249 public static <T extends Enum<T>> T newEnumElement(
250 Class<T> enumClass, String name, int ordinal)
251 throws Exception {
252
253 return newEnumElement(enumClass, null, name, ordinal, (Object[])null);
254 }
255
256 public static <T> T throwException(Throwable throwable) {
257 return ReflectionUtil.<T, RuntimeException>_doThrowException(throwable);
258 }
259
260 public static Field unfinalField(Field field) throws Exception {
261 int modifiers = field.getModifiers();
262
263 if ((modifiers & Modifier.FINAL) == Modifier.FINAL) {
264 Field modifiersField = getDeclaredField(Field.class, "modifiers");
265
266 modifiersField.setInt(field, modifiers & ~Modifier.FINAL);
267 }
268
269 return field;
270 }
271
272 protected static Method getBridgeMethod(
273 boolean publicMethod, Class<?> clazz, String name,
274 Class<?> ... parameterTypes)
275 throws Exception {
276
277 Method method = null;
278
279 if (publicMethod) {
280 method = clazz.getMethod(name, parameterTypes);
281 }
282 else {
283 method = clazz.getDeclaredMethod(name, parameterTypes);
284 }
285
286 if (method.isBridge()) {
287 return method;
288 }
289
290 Method[] methods = null;
291
292 if (publicMethod) {
293 methods = clazz.getMethods();
294 }
295 else {
296 methods = clazz.getDeclaredMethods();
297 }
298
299 bridge:
300 for (Method currentMethod : methods) {
301 if (!currentMethod.isBridge() ||
302 !name.equals(currentMethod.getName())) {
303
304 continue;
305 }
306
307 Class<?>[] currentParameterTypes =
308 currentMethod.getParameterTypes();
309
310 if (currentParameterTypes.length != parameterTypes.length) {
311 continue;
312 }
313
314 for (int i = 0; i < currentParameterTypes.length; i++) {
315 if (!currentParameterTypes[i].isAssignableFrom(
316 parameterTypes[i])) {
317
318 continue bridge;
319 }
320 }
321
322 return currentMethod;
323 }
324
325 throw new NoSuchMethodException(
326 "No bridge method on " + clazz + " with name " + name +
327 " and parameter types " + Arrays.toString(parameterTypes));
328 }
329
330 @SuppressWarnings("unchecked")
331 private static <T, E extends Throwable> T _doThrowException(
332 Throwable throwable)
333 throws E {
334
335 throw (E)throwable;
336 }
337
338 private static void _getInterfaces(
339 List<Class<?>> interfaceClasses, Class<?> clazz,
340 ClassLoader classLoader) {
341
342 for (Class<?> interfaceClass : clazz.getInterfaces()) {
343 try {
344 if (classLoader != null) {
345 interfaceClasses.add(
346 classLoader.loadClass(interfaceClass.getName()));
347 }
348 else {
349 interfaceClasses.add(interfaceClass);
350 }
351 }
352 catch (ClassNotFoundException cnfe) {
353 }
354 }
355 }
356
357 }