/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.kernel.test; import com.liferay.portal.kernel.util.ReflectionUtil; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; /** * @author Shuyang Zhou */ public class ReflectionTestUtil { public static <T> T getAndSetFieldValue( Class<?> clazz, String fieldName, T newValue) { Field field = getField(clazz, fieldName); try { T t = (T)field.get(null); field.set(null, newValue); return t; } catch (Exception e) { return ReflectionUtil.throwException(e); } } public static <T> T getAndSetFieldValue( Object instance, String fieldName, T newValue) { Field field = getField(instance.getClass(), fieldName); try { T t = (T)field.get(instance); field.set(instance, newValue); return t; } catch (Exception e) { return ReflectionUtil.throwException(e); } } public static Method getBridgeMethod( Class<?> clazz, String methodName, Class<?>... parameterTypes) { Method method = getMethod(clazz, methodName, parameterTypes); if (method.isBridge()) { return method; } Method bridgeMethod = _findBridgeMethod(clazz.getMethods(), method); if (bridgeMethod != null) { return bridgeMethod; } while (clazz != null) { bridgeMethod = _findBridgeMethod( clazz.getDeclaredMethods(), method); if (bridgeMethod != null) { return bridgeMethod; } clazz = clazz.getSuperclass(); } return ReflectionUtil.throwException( new NoSuchMethodException( "No bridge method on " + clazz + " with name " + methodName + " and parameter types " + Arrays.toString(parameterTypes))); } public static Field getField(Class<?> clazz, String fieldName) { try { Field field = clazz.getField(fieldName); field.setAccessible(true); ReflectionUtil.unfinalField(field); return field; } catch (NoSuchFieldException nsfe) { } catch (Exception e) { return ReflectionUtil.throwException(e); } while (clazz != null) { try { Field field = clazz.getDeclaredField(fieldName); field.setAccessible(true); ReflectionUtil.unfinalField(field); return field; } catch (NoSuchFieldException nsfe) { clazz = clazz.getSuperclass(); } catch (Exception e) { return ReflectionUtil.throwException(e); } } return ReflectionUtil.throwException( new NoSuchFieldException( "No field on " + clazz + " with name " + fieldName)); } public static <T> T getFieldValue(Class<?> clazz, String fieldName) { Field field = getField(clazz, fieldName); try { return (T)field.get(null); } catch (Exception e) { return ReflectionUtil.throwException(e); } } public static <T> T getFieldValue(Object instance, String fieldName) { Field field = getField(instance.getClass(), fieldName); try { return (T)field.get(instance); } catch (Exception e) { return ReflectionUtil.throwException(e); } } public static Method getMethod( Class<?> clazz, String methodName, Class<?>... parameterTypes) { try { Method method = clazz.getMethod(methodName, parameterTypes); method.setAccessible(true); return method; } catch (NoSuchMethodException nsme) { } while (clazz != null) { try { Method method = clazz.getDeclaredMethod( methodName, parameterTypes); method.setAccessible(true); return method; } catch (NoSuchMethodException nsme) { clazz = clazz.getSuperclass(); } } return ReflectionUtil.throwException( new NoSuchMethodException( "No method on " + clazz + " with name " + methodName + " and parameter types " + Arrays.toString(parameterTypes))); } public static <T> T invoke( Class<?> clazz, String methodName, Class<?>[] parameterTypes, Object... parameters) { Method method = getMethod(clazz, methodName, parameterTypes); try { return (T)method.invoke(null, parameters); } catch (InvocationTargetException ite) { return ReflectionUtil.throwException(ite.getCause()); } catch (Exception e) { return ReflectionUtil.throwException(e); } } public static <T> T invoke( Object instance, String methodName, Class<?>[] parameterTypes, Object... parameters) { Method method = getMethod( instance.getClass(), methodName, parameterTypes); try { return (T)method.invoke(instance, parameters); } catch (InvocationTargetException ite) { return ReflectionUtil.throwException(ite.getCause()); } catch (Exception e) { return ReflectionUtil.throwException(e); } } public static <T> T invokeBridge( Object instance, String methodName, Class<?>[] parameterTypes, Object... parameters) { Method method = getBridgeMethod( instance.getClass(), methodName, parameterTypes); try { return (T)method.invoke(instance, parameters); } catch (InvocationTargetException ite) { return ReflectionUtil.throwException(ite.getCause()); } catch (Exception e) { return ReflectionUtil.throwException(e); } } public static <T extends Enum<T>> T newEnumElement( Class<T> enumClass, Class<?>[] constructorParameterTypes, String name, int ordinal, Object... constructorParameters) { Class<?>[] parameterTypes = null; if ((constructorParameterTypes != null) && (constructorParameterTypes.length != 0)) { parameterTypes = new Class<?>[constructorParameterTypes.length + 2]; parameterTypes[0] = String.class; parameterTypes[1] = int.class; System.arraycopy( constructorParameterTypes, 0, parameterTypes, 2, constructorParameterTypes.length); } else { parameterTypes = new Class<?>[2]; parameterTypes[0] = String.class; parameterTypes[1] = int.class; } try { Constructor<T> constructor = enumClass.getDeclaredConstructor( parameterTypes); Method acquireConstructorAccessorMethod = ReflectionUtil.getDeclaredMethod( Constructor.class, "acquireConstructorAccessor"); acquireConstructorAccessorMethod.invoke(constructor); Field constructorAccessorField = ReflectionUtil.getDeclaredField( Constructor.class, "constructorAccessor"); Object constructorAccessor = constructorAccessorField.get( constructor); Method newInstanceMethod = ReflectionUtil.getDeclaredMethod( constructorAccessor.getClass(), "newInstance", Object[].class); Object[] parameters = null; if ((constructorParameters != null) && (constructorParameters.length != 0)) { parameters = new Object[constructorParameters.length + 2]; parameters[0] = name; parameters[1] = ordinal; System.arraycopy( constructorParameters, 0, parameters, 2, constructorParameters.length); } else { parameters = new Object[2]; parameters[0] = name; parameters[1] = ordinal; } return (T)newInstanceMethod.invoke( constructorAccessor, new Object[] {parameters}); } catch (Exception e) { return ReflectionUtil.throwException(e); } } public static <T extends Enum<T>> T newEnumElement( Class<T> enumClass, String name, int ordinal) { return newEnumElement(enumClass, null, name, ordinal, (Object[])null); } public static void setFieldValue( Class<?> clazz, String fieldName, Object value) { Field field = getField(clazz, fieldName); try { field.set(null, value); } catch (Exception e) { ReflectionUtil.throwException(e); } } public static void setFieldValue( Object instance, String fieldName, Object value) { Field field = getField(instance.getClass(), fieldName); try { field.set(instance, value); } catch (Exception e) { ReflectionUtil.throwException(e); } } private static Method _findBridgeMethod(Method[] methods, Method method) { String name = method.getName(); Class<?>[] parameterTypes = method.getParameterTypes(); bridge: for (Method currentMethod : methods) { if (!currentMethod.isBridge() || !name.equals(currentMethod.getName())) { continue; } Class<?>[] currentParameterTypes = currentMethod.getParameterTypes(); if (currentParameterTypes.length != parameterTypes.length) { continue; } for (int i = 0; i < currentParameterTypes.length; i++) { if (!currentParameterTypes[i].isAssignableFrom( parameterTypes[i])) { continue bridge; } } currentMethod.setAccessible(true); return currentMethod; } return null; } }