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 Method method = clazz.getMethod(name, parameterTypes);
054
055 if (method.isBridge()) {
056 return method;
057 }
058
059 bridge:
060 for (Method currentMethod : clazz.getMethods()) {
061 if (!currentMethod.isBridge() ||
062 !name.equals(currentMethod.getName())) {
063
064 continue;
065 }
066
067 Class<?>[] currentParameterTypes =
068 currentMethod.getParameterTypes();
069
070 if (currentParameterTypes.length != parameterTypes.length) {
071 continue;
072 }
073
074 for (int i = 0; i < currentParameterTypes.length; i++) {
075 if (!currentParameterTypes[i].isAssignableFrom(
076 parameterTypes[i])) {
077
078 continue bridge;
079 }
080 }
081
082 return currentMethod;
083 }
084
085 throw new NoSuchMethodException(
086 "No bridge method on " + clazz + " with name " + name +
087 " and parameter types " + Arrays.toString(parameterTypes));
088 }
089
090 public static Field getDeclaredField(Class<?> clazz, String name)
091 throws Exception {
092
093 Field field = clazz.getDeclaredField(name);
094
095 if (!field.isAccessible()) {
096 field.setAccessible(true);
097 }
098
099 int modifiers = field.getModifiers();
100
101 if ((modifiers & Modifier.FINAL) == Modifier.FINAL) {
102 Field modifiersField = ReflectionUtil.getDeclaredField(
103 Field.class, "modifiers");
104
105 modifiersField.setInt(field, modifiers & ~Modifier.FINAL);
106 }
107
108 return field;
109 }
110
111 public static Method getDeclaredMethod(
112 Class<?> clazz, String name, Class<?> ... parameterTypes)
113 throws Exception {
114
115 Method method = clazz.getDeclaredMethod(name, parameterTypes);
116
117 if (!method.isAccessible()) {
118 method.setAccessible(true);
119 }
120
121 return method;
122 }
123
124 public static Class<?>[] getInterfaces(Object object) {
125 return getInterfaces(object, null);
126 }
127
128 public static Class<?>[] getInterfaces(
129 Object object, ClassLoader classLoader) {
130
131 List<Class<?>> interfaceClasses = new UniqueList<Class<?>>();
132
133 Class<?> clazz = object.getClass();
134
135 _getInterfaces(interfaceClasses, clazz, classLoader);
136
137 Class<?> superClass = clazz.getSuperclass();
138
139 while (superClass != null) {
140 _getInterfaces(interfaceClasses, superClass, classLoader);
141
142 superClass = superClass.getSuperclass();
143 }
144
145 return interfaceClasses.toArray(new Class<?>[interfaceClasses.size()]);
146 }
147
148 public static Class<?>[] getParameterTypes(Object[] arguments) {
149 if (arguments == null) {
150 return null;
151 }
152
153 Class<?>[] parameterTypes = new Class<?>[arguments.length];
154
155 for (int i = 0; i < arguments.length; i++) {
156 if (arguments[i] == null) {
157 parameterTypes[i] = null;
158 }
159 else if (arguments[i] instanceof Boolean) {
160 parameterTypes[i] = Boolean.TYPE;
161 }
162 else if (arguments[i] instanceof Byte) {
163 parameterTypes[i] = Byte.TYPE;
164 }
165 else if (arguments[i] instanceof Character) {
166 parameterTypes[i] = Character.TYPE;
167 }
168 else if (arguments[i] instanceof Double) {
169 parameterTypes[i] = Double.TYPE;
170 }
171 else if (arguments[i] instanceof Float) {
172 parameterTypes[i] = Float.TYPE;
173 }
174 else if (arguments[i] instanceof Integer) {
175 parameterTypes[i] = Integer.TYPE;
176 }
177 else if (arguments[i] instanceof Long) {
178 parameterTypes[i] = Long.TYPE;
179 }
180 else if (arguments[i] instanceof Short) {
181 parameterTypes[i] = Short.TYPE;
182 }
183 else {
184 parameterTypes[i] = arguments[i].getClass();
185 }
186 }
187
188 return parameterTypes;
189 }
190
191 public static boolean isAnnotationDeclaredInClass(
192 Class<? extends Annotation> annotationClass, Class<?> clazz) {
193
194 if ((annotationClass == null) || (clazz == null)) {
195 throw new IllegalArgumentException();
196 }
197
198 Annotation[] annotations = clazz.getAnnotations();
199
200 for (Annotation annotation : annotations) {
201 if (annotationClass.equals(annotation.annotationType())) {
202 return true;
203 }
204 }
205
206 return false;
207 }
208
209 public static <T extends Enum<T>> T newEnumElement(
210 Class<T> enumClass, Class<?>[] constructorParameterTypes,
211 String name, int ordinal, Object... constructorParameters)
212 throws Exception {
213
214 Class<?>[] parameterTypes = null;
215
216 if ((constructorParameterTypes != null) &&
217 (constructorParameterTypes.length != 0)) {
218
219 parameterTypes = new Class<?>[constructorParameterTypes.length + 2];
220
221 parameterTypes[0] = String.class;
222 parameterTypes[1] = int.class;
223
224 System.arraycopy(
225 constructorParameterTypes, 0, parameterTypes, 2,
226 constructorParameterTypes.length);
227 }
228 else {
229 parameterTypes = new Class<?>[2];
230
231 parameterTypes[0] = String.class;
232 parameterTypes[1] = int.class;
233 }
234
235 Constructor<T> constructor = enumClass.getDeclaredConstructor(
236 parameterTypes);
237
238 Method acquireConstructorAccessorMethod = getDeclaredMethod(
239 Constructor.class, "acquireConstructorAccessor");
240
241 acquireConstructorAccessorMethod.invoke(constructor);
242
243 Field constructorAccessorField = getDeclaredField(
244 Constructor.class, "constructorAccessor");
245
246 Object constructorAccessor = constructorAccessorField.get(constructor);
247
248 Method newInstanceMethod = getDeclaredMethod(
249 constructorAccessor.getClass(), "newInstance", Object[].class);
250
251 Object[] parameters = null;
252
253 if ((constructorParameters != null) &&
254 (constructorParameters.length != 0)) {
255
256 parameters = new Object[constructorParameters.length + 2];
257
258 parameters[0] = name;
259 parameters[1] = ordinal;
260
261 System.arraycopy(
262 constructorParameters, 0, parameters, 2,
263 constructorParameters.length);
264 }
265 else {
266 parameters = new Object[2];
267
268 parameters[0] = name;
269 parameters[1] = ordinal;
270 }
271
272 return (T)newInstanceMethod.invoke(
273 constructorAccessor, new Object[]{parameters});
274 }
275
276 public static <T extends Enum<T>> T newEnumElement(
277 Class<T> enumClass, String name, int ordinal)
278 throws Exception {
279
280 return newEnumElement(enumClass, null, name, ordinal, (Object[])null);
281 }
282
283 private static void _getInterfaces(
284 List<Class<?>> interfaceClasses, Class<?> clazz,
285 ClassLoader classLoader) {
286
287 for (Class<?> interfaceClass : clazz.getInterfaces()) {
288 try {
289 if (classLoader != null) {
290 interfaceClasses.add(
291 classLoader.loadClass(interfaceClass.getName()));
292 }
293 else {
294 interfaceClasses.add(interfaceClass);
295 }
296 }
297 catch (ClassNotFoundException cnfe) {
298 }
299 }
300 }
301
302 }