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