001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.test;
016    
017    import com.liferay.portal.kernel.util.ReflectionUtil;
018    
019    import java.lang.reflect.Constructor;
020    import java.lang.reflect.Field;
021    import java.lang.reflect.InvocationTargetException;
022    import java.lang.reflect.Method;
023    
024    import java.util.Arrays;
025    
026    /**
027     * @author Shuyang Zhou
028     */
029    public class ReflectionTestUtil {
030    
031            public static Method getBridgeMethod(
032                    Class<?> clazz, String methodName, Class<?>... parameterTypes) {
033    
034                    Method method = getMethod(clazz, methodName, parameterTypes);
035    
036                    if (method.isBridge()) {
037                            return method;
038                    }
039    
040                    Method bridgeMethod = _findBridgeMethod(clazz.getMethods(), method);
041    
042                    if (bridgeMethod != null) {
043                            return bridgeMethod;
044                    }
045    
046                    while (clazz != null) {
047                            bridgeMethod = _findBridgeMethod(
048                                    clazz.getDeclaredMethods(), method);
049    
050                            if (bridgeMethod != null) {
051                                    return bridgeMethod;
052                            }
053    
054                            clazz = clazz.getSuperclass();
055                    }
056    
057                    return ReflectionUtil.throwException(
058                            new NoSuchMethodException(
059                                    "No bridge method on " + clazz + " with name " + methodName +
060                                            " and parameter types " + Arrays.toString(parameterTypes)));
061            }
062    
063            public static Field getField(Class<?> clazz, String fieldName) {
064                    try {
065                            Field field = clazz.getField(fieldName);
066    
067                            field.setAccessible(true);
068    
069                            ReflectionUtil.unfinalField(field);
070    
071                            return field;
072                    }
073                    catch (NoSuchFieldException nsfe) {
074                    }
075                    catch (Exception e) {
076                            return ReflectionUtil.throwException(e);
077                    }
078    
079                    while (clazz != null) {
080                            try {
081                                    Field field = clazz.getDeclaredField(fieldName);
082    
083                                    field.setAccessible(true);
084    
085                                    ReflectionUtil.unfinalField(field);
086    
087                                    return field;
088                            }
089                            catch (NoSuchFieldException nsfe) {
090                                    clazz = clazz.getSuperclass();
091                            }
092                            catch (Exception e) {
093                                    return ReflectionUtil.throwException(e);
094                            }
095                    }
096    
097                    return ReflectionUtil.throwException(
098                            new NoSuchFieldException(
099                                    "No field on " + clazz + " with name " + fieldName));
100            }
101    
102            public static <T> T getFieldValue(Class<?> clazz, String fieldName) {
103                    Field field = getField(clazz, fieldName);
104    
105                    try {
106                            return (T)field.get(null);
107                    }
108                    catch (Exception e) {
109                            return ReflectionUtil.throwException(e);
110                    }
111            }
112    
113            public static <T> T getFieldValue(Object instance, String fieldName) {
114                    Field field = getField(instance.getClass(), fieldName);
115    
116                    try {
117                            return (T)field.get(instance);
118                    }
119                    catch (Exception e) {
120                            return ReflectionUtil.throwException(e);
121                    }
122            }
123    
124            public static Method getMethod(
125                    Class<?> clazz, String methodName, Class<?>... parameterTypes) {
126    
127                    try {
128                            Method method = clazz.getMethod(methodName, parameterTypes);
129    
130                            method.setAccessible(true);
131    
132                            return method;
133                    }
134                    catch (NoSuchMethodException nsme) {
135                    }
136    
137                    while (clazz != null) {
138                            try {
139                                    Method method = clazz.getDeclaredMethod(
140                                            methodName, parameterTypes);
141    
142                                    method.setAccessible(true);
143    
144                                    return method;
145                            }
146                            catch (NoSuchMethodException nsme) {
147                                    clazz = clazz.getSuperclass();
148                            }
149                    }
150    
151                    return ReflectionUtil.throwException(
152                            new NoSuchMethodException(
153                                    "No method on " + clazz + " with name " + methodName +
154                                            " and parameter types " + Arrays.toString(parameterTypes)));
155            }
156    
157            public static <T> T invoke(
158                    Class<?> clazz, String methodName, Class<?>[] parameterTypes,
159                    Object... parameters) {
160    
161                    Method method = getMethod(clazz, methodName, parameterTypes);
162    
163                    try {
164                            return (T)method.invoke(null, parameters);
165                    }
166                    catch (InvocationTargetException ite) {
167                            return ReflectionUtil.throwException(ite.getCause());
168                    }
169                    catch (Exception e) {
170                            return ReflectionUtil.throwException(e);
171                    }
172            }
173    
174            public static <T> T invoke(
175                    Object instance, String methodName, Class<?>[] parameterTypes,
176                    Object... parameters) {
177    
178                    Method method = getMethod(
179                            instance.getClass(), methodName, parameterTypes);
180    
181                    try {
182                            return (T)method.invoke(instance, parameters);
183                    }
184                    catch (InvocationTargetException ite) {
185                            return ReflectionUtil.throwException(ite.getCause());
186                    }
187                    catch (Exception e) {
188                            return ReflectionUtil.throwException(e);
189                    }
190            }
191    
192            public static <T> T invokeBridge(
193                    Object instance, String methodName, Class<?>[] parameterTypes,
194                    Object... parameters) {
195    
196                    Method method = getBridgeMethod(
197                            instance.getClass(), methodName, parameterTypes);
198    
199                    try {
200                            return (T)method.invoke(instance, parameters);
201                    }
202                    catch (InvocationTargetException ite) {
203                            return ReflectionUtil.throwException(ite.getCause());
204                    }
205                    catch (Exception e) {
206                            return ReflectionUtil.throwException(e);
207                    }
208            }
209    
210            public static <T extends Enum<T>> T newEnumElement(
211                    Class<T> enumClass, Class<?>[] constructorParameterTypes, String name,
212                    int ordinal, Object... constructorParameters) {
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                    try {
236                            Constructor<T> constructor = enumClass.getDeclaredConstructor(
237                                    parameterTypes);
238    
239                            Method acquireConstructorAccessorMethod =
240                                    ReflectionUtil.getDeclaredMethod(
241                                            Constructor.class, "acquireConstructorAccessor");
242    
243                            acquireConstructorAccessorMethod.invoke(constructor);
244    
245                            Field constructorAccessorField = ReflectionUtil.getDeclaredField(
246                                    Constructor.class, "constructorAccessor");
247    
248                            Object constructorAccessor = constructorAccessorField.get(
249                                    constructor);
250    
251                            Method newInstanceMethod = ReflectionUtil.getDeclaredMethod(
252                                    constructorAccessor.getClass(), "newInstance", Object[].class);
253    
254                            Object[] parameters = null;
255    
256                            if ((constructorParameters != null) &&
257                                    (constructorParameters.length != 0)) {
258    
259                                    parameters = new Object[constructorParameters.length + 2];
260    
261                                    parameters[0] = name;
262                                    parameters[1] = ordinal;
263    
264                                    System.arraycopy(
265                                            constructorParameters, 0, parameters, 2,
266                                            constructorParameters.length);
267                            }
268                            else {
269                                    parameters = new Object[2];
270    
271                                    parameters[0] = name;
272                                    parameters[1] = ordinal;
273                            }
274    
275                            return (T)newInstanceMethod.invoke(
276                                    constructorAccessor, new Object[] {parameters});
277                    }
278                    catch (Exception e) {
279                            return ReflectionUtil.throwException(e);
280                    }
281            }
282    
283            public static <T extends Enum<T>> T newEnumElement(
284                    Class<T> enumClass, String name, int ordinal) {
285    
286                    return newEnumElement(enumClass, null, name, ordinal, (Object[])null);
287            }
288    
289            public static void setFieldValue(
290                    Class<?> clazz, String fieldName, Object value) {
291    
292                    Field field = getField(clazz, fieldName);
293    
294                    try {
295                            field.set(null, value);
296                    }
297                    catch (Exception e) {
298                            ReflectionUtil.throwException(e);
299                    }
300            }
301    
302            public static void setFieldValue(
303                    Object instance, String fieldName, Object value) {
304    
305                    Field field = getField(instance.getClass(), fieldName);
306    
307                    try {
308                            field.set(instance, value);
309                    }
310                    catch (Exception e) {
311                            ReflectionUtil.throwException(e);
312                    }
313            }
314    
315            private static Method _findBridgeMethod(Method[] methods, Method method) {
316                    String name = method.getName();
317                    Class<?>[] parameterTypes = method.getParameterTypes();
318    
319                    bridge:
320                    for (Method currentMethod : methods) {
321                            if (!currentMethod.isBridge() ||
322                                    !name.equals(currentMethod.getName())) {
323    
324                                    continue;
325                            }
326    
327                            Class<?>[] currentParameterTypes =
328                                    currentMethod.getParameterTypes();
329    
330                            if (currentParameterTypes.length != parameterTypes.length) {
331                                    continue;
332                            }
333    
334                            for (int i = 0; i < currentParameterTypes.length; i++) {
335                                    if (!currentParameterTypes[i].isAssignableFrom(
336                                                    parameterTypes[i])) {
337    
338                                            continue bridge;
339                                    }
340                            }
341    
342                            currentMethod.setAccessible(true);
343    
344                            return currentMethod;
345                    }
346    
347                    return null;
348            }
349    
350    }