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 static com.liferay.portal.kernel.util.ReflectionUtil.getDeclaredField;
018    import static com.liferay.portal.kernel.util.ReflectionUtil.getDeclaredMethod;
019    
020    import com.liferay.portal.kernel.util.ReflectionUtil;
021    
022    import java.lang.reflect.Constructor;
023    import java.lang.reflect.Field;
024    import java.lang.reflect.Method;
025    
026    import java.util.Arrays;
027    
028    /**
029     * @author Shuyang Zhou
030     */
031    public class ReflectionTestUtil {
032    
033            public static Method getBridgeMethod(
034                    Class<?> clazz, String methodName, Class<?>... parameterTypes) {
035    
036                    Method method = getMethod(clazz, methodName, parameterTypes);
037    
038                    if (method.isBridge()) {
039                            return method;
040                    }
041    
042                    Method bridgeMethod = _findBridgeMethod(clazz.getMethods(), method);
043    
044                    if (bridgeMethod != null) {
045                            return bridgeMethod;
046                    }
047    
048                    while (clazz != null) {
049                            bridgeMethod = _findBridgeMethod(
050                                    clazz.getDeclaredMethods(), method);
051    
052                            if (bridgeMethod != null) {
053                                    return bridgeMethod;
054                            }
055    
056                            clazz =  clazz.getSuperclass();
057                    }
058    
059                    return ReflectionUtil.throwException(
060                            new NoSuchMethodException(
061                                    "No bridge method on " + clazz + " with name " + methodName +
062                                            " and parameter types " + Arrays.toString(parameterTypes)));
063            }
064    
065            public static Field getField(Class<?> clazz, String fieldName) {
066                    try {
067                            Field field = clazz.getField(fieldName);
068    
069                            field.setAccessible(true);
070    
071                            ReflectionUtil.unfinalField(field);
072    
073                            return field;
074                    }
075                    catch (NoSuchFieldException nsfe) {
076                    }
077                    catch (Exception e) {
078                            return ReflectionUtil.throwException(e);
079                    }
080    
081                    while (clazz != null) {
082                            try {
083                                    Field field = clazz.getDeclaredField(fieldName);
084    
085                                    field.setAccessible(true);
086    
087                                    ReflectionUtil.unfinalField(field);
088    
089                                    return field;
090                            }
091                            catch (NoSuchFieldException nsfe) {
092                                    clazz = clazz.getSuperclass();
093                            }
094                            catch (Exception e) {
095                                    return ReflectionUtil.throwException(e);
096                            }
097                    }
098    
099                    return ReflectionUtil.throwException(
100                            new NoSuchFieldException(
101                                    "No field on " + clazz + " with name " + fieldName));
102            }
103    
104            public static <T> T getFieldValue(Class<?> clazz, String fieldName) {
105                    Field field = getField(clazz, fieldName);
106    
107                    try {
108                            return (T)field.get(null);
109                    }
110                    catch (Exception e) {
111                            return ReflectionUtil.throwException(e);
112                    }
113            }
114    
115            public static <T> T getFieldValue(Object instance, String fieldName) {
116                    Field field = getField(instance.getClass(), fieldName);
117    
118                    try {
119                            return (T)field.get(instance);
120                    }
121                    catch (Exception e) {
122                            return ReflectionUtil.throwException(e);
123                    }
124            }
125    
126            public static Method getMethod(
127                    Class<?> clazz, String methodName, Class<?>... parameterTypes) {
128    
129                    try {
130                            Method method = clazz.getMethod(methodName, parameterTypes);
131    
132                            method.setAccessible(true);
133    
134                            return method;
135                    }
136                    catch (NoSuchMethodException nsme) {
137                    }
138    
139                    while (clazz != null) {
140                            try {
141                                    Method method = clazz.getDeclaredMethod(
142                                            methodName, parameterTypes);
143    
144                                    method.setAccessible(true);
145    
146                                    return method;
147                            }
148                            catch (NoSuchMethodException nsme) {
149                                    clazz = clazz.getSuperclass();
150                            }
151                    }
152    
153                    return ReflectionUtil.throwException(
154                            new NoSuchMethodException(
155                                    "No method on " + clazz + " with name " + methodName +
156                                            " and parameter types " + Arrays.toString(parameterTypes)));
157            }
158    
159            public static <T> T invoke(
160                    Class<?> clazz, String methodName, Class<?>[] parameterTypes,
161                    Object... parameters) {
162    
163                    Method method = getMethod(clazz, methodName, parameterTypes);
164    
165                    try {
166                            return (T)method.invoke(null, parameters);
167                    }
168                    catch (Exception e) {
169                            return ReflectionUtil.throwException(e);
170                    }
171            }
172    
173            public static <T> T invoke(
174                    Object instance, String methodName, Class<?>[] parameterTypes,
175                    Object... parameters) {
176    
177                    Method method = getMethod(
178                            instance.getClass(), methodName, parameterTypes);
179    
180                    try {
181                            return (T)method.invoke(instance, parameters);
182                    }
183                    catch (Exception e) {
184                            return ReflectionUtil.throwException(e);
185                    }
186            }
187    
188            public static <T> T invokeBridge(
189                    Object instance, String methodName, Class<?>[] parameterTypes,
190                    Object... parameters) {
191    
192                    Method method = getBridgeMethod(
193                            instance.getClass(), methodName, parameterTypes);
194    
195                    try {
196                            return (T)method.invoke(instance, parameters);
197                    }
198                    catch (Exception e) {
199                            return ReflectionUtil.throwException(e);
200                    }
201            }
202    
203            public static <T extends Enum<T>> T newEnumElement(
204                    Class<T> enumClass, Class<?>[] constructorParameterTypes, String name,
205                    int ordinal, Object... constructorParameters) {
206    
207                    Class<?>[] parameterTypes = null;
208    
209                    if ((constructorParameterTypes != null) &&
210                            (constructorParameterTypes.length != 0)) {
211    
212                            parameterTypes = new Class<?>[constructorParameterTypes.length + 2];
213    
214                            parameterTypes[0] = String.class;
215                            parameterTypes[1] = int.class;
216    
217                            System.arraycopy(
218                                    constructorParameterTypes, 0, parameterTypes, 2,
219                                    constructorParameterTypes.length);
220                    }
221                    else {
222                            parameterTypes = new Class<?>[2];
223    
224                            parameterTypes[0] = String.class;
225                            parameterTypes[1] = int.class;
226                    }
227    
228                    try {
229                            Constructor<T> constructor = enumClass.getDeclaredConstructor(
230                                    parameterTypes);
231    
232                            Method acquireConstructorAccessorMethod = getDeclaredMethod(
233                                    Constructor.class, "acquireConstructorAccessor");
234    
235                            acquireConstructorAccessorMethod.invoke(constructor);
236    
237                            Field constructorAccessorField = getDeclaredField(
238                                    Constructor.class, "constructorAccessor");
239    
240                            Object constructorAccessor = constructorAccessorField.get(
241                                    constructor);
242    
243                            Method newInstanceMethod = getDeclaredMethod(
244                                    constructorAccessor.getClass(), "newInstance", Object[].class);
245    
246                            Object[] parameters = null;
247    
248                            if ((constructorParameters != null) &&
249                                    (constructorParameters.length != 0)) {
250    
251                                    parameters = new Object[constructorParameters.length + 2];
252    
253                                    parameters[0] = name;
254                                    parameters[1] = ordinal;
255    
256                                    System.arraycopy(
257                                            constructorParameters, 0, parameters, 2,
258                                            constructorParameters.length);
259                            }
260                            else {
261                                    parameters = new Object[2];
262    
263                                    parameters[0] = name;
264                                    parameters[1] = ordinal;
265                            }
266    
267                            return (T)newInstanceMethod.invoke(
268                                    constructorAccessor, new Object[] {parameters});
269                    }
270                    catch (Exception e) {
271                            return ReflectionUtil.throwException(e);
272                    }
273            }
274    
275            public static <T extends Enum<T>> T newEnumElement(
276                    Class<T> enumClass, String name, int ordinal) {
277    
278                    return newEnumElement(enumClass, null, name, ordinal, (Object[])null);
279            }
280    
281            public static void setFieldValue(
282                    Class<?> clazz, String fieldName, Object value) {
283    
284                    Field field = getField(clazz, fieldName);
285    
286                    try {
287                            field.set(null, value);
288                    }
289                    catch (Exception e) {
290                            ReflectionUtil.throwException(e);
291                    }
292            }
293    
294            public static void setFieldValue(
295                    Object instance, String fieldName, Object value) {
296    
297                    Field field = getField(instance.getClass(), fieldName);
298    
299                    try {
300                            field.set(instance, value);
301                    }
302                    catch (Exception e) {
303                            ReflectionUtil.throwException(e);
304                    }
305            }
306    
307            private static Method _findBridgeMethod(Method[] methods, Method method) {
308                    String name = method.getName();
309                    Class<?>[] parameterTypes = method.getParameterTypes();
310    
311                    bridge:
312                    for (Method currentMethod : methods) {
313                            if (!currentMethod.isBridge() ||
314                                    !name.equals(currentMethod.getName())) {
315    
316                                    continue;
317                            }
318    
319                            Class<?>[] currentParameterTypes =
320                                    currentMethod.getParameterTypes();
321    
322                            if (currentParameterTypes.length != parameterTypes.length) {
323                                    continue;
324                            }
325    
326                            for (int i = 0; i < currentParameterTypes.length; i++) {
327                                    if (!currentParameterTypes[i].isAssignableFrom(
328                                                    parameterTypes[i])) {
329    
330                                            continue bridge;
331                                    }
332                            }
333    
334                            currentMethod.setAccessible(true);
335    
336                            return currentMethod;
337                    }
338    
339                    return null;
340            }
341    
342    }