import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Utility class for reflect purpose.
*/
public final class ReflectHelper {
/**
* Empty private constructor for util class.
*/
private ReflectHelper() {
// Empty private constructor for util class.
}
/** Constant meaning accessor type setter. */
public static final String SETTER = "set";
/** Constant meaning accessor type getter. */
public static final String GETTER = "get";
/** Constant meaning accessor type getter for boolean. */
public static final String BOOLEAN_GETTER = "is";
/**
* Instantiate a Class using its name.
* @param className The class name.
* @param arguments The arguments to be passed to constructor.
* @param types The types of arguments.
* @return The instance
* @throws ClassNotFoundException Thrown if you try to instanciate a class that does not exist.
* @throws NoSuchMethodException Thrown if you try to retreive a method that does not exist.
* @throws InvocationTargetException Can occure during invocation
* @throws IllegalAccessException Thrown while trying to access illagaly the instance
* @throws InstantiationException Any other case
*/
public static Object newInstance(final String className, final Object[] arguments, final Class[] types) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
// Retrieve class to be load
Class clazz = Class.forName(className);
// R??cup??ration du constructeur correspondant ????????? la liste des parametres donn??e
Constructor constructor = clazz.getConstructor(types);
// Cr??ation d'une instance avec le constructeur r??cup??r??s
return constructor.newInstance(arguments);
}
/**
* Instantiate a Class using its name.
* @param className The class name.
* @param arguments The parameters to be passed to constructor.
* @return The instance
* @throws ClassNotFoundException Thrown if you try to instanciate a class that does not exist.
* @throws NoSuchMethodException Thrown if you try to retreive a method that does not exist.
* @throws InvocationTargetException Can occure during invocation
* @throws IllegalAccessException Thrown while trying to access illagaly the instance
* @throws InstantiationException Any other case
*/
public static Object newInstance(final String className, final Object[] arguments) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
// Construct the types array
Class[] types = new Class[arguments.length];
for (int i = 0; i <= arguments.length; ++i) {
types[i] = arguments[i].getClass();
}
// Instantiate class
return newInstance(className, arguments, types);
}
/**
* Instantiate a Class using its name.
* @param className The class name
* @return The instance
* @throws ClassNotFoundException Thrown if you try to instanciate a class that does not exist.
* @throws InstantiationException Any other case
* @throws NoSuchMethodException Thrown if you try to retreive a method that does not exist.
* @throws InvocationTargetException Can occure during invocation
* @throws IllegalAccessException Thrown while trying to access illagaly the instance
*/
public static Object newInstance(final String className) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
return newInstance(className, new Object[] {});
}
/**
* Invoke a methods (<code>methodName</code>) from an <code>object</code> with <code>arguments</code> of <code>types</code>.
* @param object The object from which you want to invoke a methods.
* @param methodName The method name to invoke.
* @param arguments The arguments to pass to the methods.
* @param types The types of arguments.
* @return the result of the invoked method.
* @throws NoSuchMethodException Thrown if you try to retreive a method that does not exist.
* @throws InvocationTargetException Can occure during invocation
* @throws IllegalAccessException Thrown while trying to access illagaly the instance
*/
public static Object invokeMethod(final Object object, final String methodName, final Object[] arguments, final Class[] types) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
try {
// If simple getter is not found ... try boolean one
return getMethod(object.getClass(), methodName, types).invoke(object, arguments);
} catch (NoSuchMethodException ex) {
NoSuchMethodException thrown = new NoSuchMethodException(formatInvokeGetterException(ex, object, methodName, arguments));
thrown.setStackTrace(ex.getStackTrace());
throw thrown;
} catch (InvocationTargetException ex) {
throw new InvocationTargetException(ex.getTargetException(), formatInvokeGetterException(ex.getTargetException(), object, methodName, arguments));
} catch (IllegalAccessException ex) {
IllegalAccessException thrown = new IllegalAccessException(formatInvokeGetterException(ex, object, methodName, arguments));
thrown.setStackTrace(ex.getStackTrace());
throw thrown;
}
}
/**
* Invoke a methods (<code>methodName</code>) from an <code>object</code> with <code>arguments</code> of <code>types</code>.
* @param object The object from which you want to invoke a methods.
* @param method The method to invoke.
* @param arguments The arguments to pass to the methods.
* @return the result of the invoked method.
* @throws InvocationTargetException Can occure during invocation
* @throws IllegalAccessException Thrown while trying to access illagaly the instance
*/
public static Object invokeMethod(final Object object, final Method method, final Object[] arguments) throws IllegalAccessException, InvocationTargetException {
return method.invoke(object, arguments);
}
/**
* Invoke a methods (<code>methodName</code>) from an <code>object</code> with <code>arguments</code> of <code>types</code>.
* @param clazz The <code>clazz</code> on which to retreive the method.
* @param methodName The method name to invoke.
* @param arguments The arguments to pass to the methods.
* @param types The types of arguments.
* @return the result of the invoked method.
* @throws NoSuchMethodException Thrown if you try to retreive a method that does not exist.
* @throws InvocationTargetException Can occure during invocation
* @throws IllegalAccessException Thrown while trying to access illagaly the instance
*/
public static Object invokeStaticMethod(final Class clazz, final String methodName, final Object[] arguments, final Class[] types) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
return getMethod(clazz, methodName, types).invoke(null, arguments);
}
/**
* Invoke a methods (<code>methodName</code>) from an <code>object</code> with <code>arguments</code>.
* @param object The object from which you want to invoke a methods.
* @param methodName The method name to invoke.
* @param arguments The arguments to pass to the methods.
* @return the result of the invoked method.
* @throws NoSuchMethodException Thrown if you try to retreive a method that does not exist.
* @throws InvocationTargetException Can occure during invocation
* @throws IllegalAccessException Thrown while trying to access illagaly the instance
*/
public static Object invokeMethod(final Object object, final String methodName, final Object[] arguments) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
// Construct the types array
Class[] types = new Class[arguments.length];
for (int i = 0; i < arguments.length; ++i) {
types[i] = arguments[i].getClass();
}
return invokeMethod(object, methodName, arguments, types);
}
/**
* This method invoke the setter according to the <code>fieldName</code> on the <code>toFill</code> object with as argument.
* <code>valueToSet</code> of type <code>valueToSetType</code>
* @param toFill the object to fill.
* @param fieldName the field name.
* @param valueToSet the value to set.
* @param valueToSetType the type of the value to set.
* @throws NoSuchMethodException Thrown if you try to retreive a method that does not exist.
* @throws InvocationTargetException Can occure during invocation
* @throws IllegalAccessException Thrown while trying to access illagaly the instance
*/
public static void invokeSetter(final Object toFill, final String fieldName, final Object valueToSet, final Class valueToSetType) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
invokeMethod(toFill, computeAccessorMethodName(SETTER, fieldName), new Object[] {valueToSet}, new Class[] {valueToSetType});
}
/**
* This method invoke the getter according to the <code>fieldName</code> on the <code>toFill</code> object with as argument.
* <code>valueToSet</code> of type <code>valueToSetType</code>
* @param bean the JavaBean object.
* @param fieldName the field name.
* @return The value returned by the getter.
* @throws NoSuchMethodException Thrown if you try to retreive a method that does not exist.
* @throws InvocationTargetException Can occure during invocation
* @throws IllegalAccessException Thrown while trying to access illagaly the instance
*/
public static Object invokeGetter(final Object bean, final String fieldName) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
String field = fieldName;
Object instance = bean;
while (field.indexOf('[') > -1) {
// Invoke getter to retreive the child element
instance = invokeGetter(instance, field.substring(0, field.indexOf('[')));
// If result is null no need to continue
if (instance == null) {
return null;
}
// Re route field name to retreive the field of the child instance
int index = Integer.parseInt(field.substring(field.indexOf('[') + 1, field.indexOf(']')));
instance = Array.get(instance, index);
field = field.substring(field.indexOf(']') + 1);
}
// In the case that you want to retrieve in one time the field of a child object
while (field.indexOf('.') > 0) {
// Invoke getter to retreive the child element
instance = invokeGetter(instance, field.substring(0, field.indexOf('.')));
// If result is null no need to continue
if (instance == null) {
return null;
}
// Re route field name to retreive the field of the child instance
field = field.substring(field.indexOf('.') + 1);
}
if (field.length() == 0) {
return instance;
}
try {
return invokeMethod(instance, computeAccessorMethodName(GETTER, field), new Object[] {});
} catch (NoSuchMethodException noSuchMethod) {
String accessor = computeAccessorMethodName(BOOLEAN_GETTER, field);
try {
// If simple getter is not found ... try boolean one
return invokeMethod(instance, accessor, new Object[] {});
} catch (NoSuchMethodException ex) {
// If it's still not found or return an error ... than throw the original error.
throw noSuchMethod;
}
}
}
/**
* Format a more detailed message when an exception occured during invocation.
* @param ex The exception
* @param object The object on which the given method is invoked
* @param method The invoked method
* @param arguments The method arguments
* @return The detailed message
*/
private static String formatInvokeGetterException(final Throwable ex, final Object object, final String method, final Object[] arguments) {
String message = ex.getMessage();
if (message == null) {
message = "";
} else {
message += " - ";
}
String args = "";
for (int i = 0; i < arguments.length; ++i) {
args += arguments[i].getClass().getName();
// Concat each element
args += arguments[i];
// Add separator if necessary
if ((i < arguments.length - 1)) {
args += ", ";
}
}
return message + "Error occured while tyring to invoke " + object.getClass().getName() + "." + method + "(" + args + ") method.";
}
/**
* Get the field (<code>filedName</code>) value of an <code>object</code>.
* @param object The <code>object</code> on which to retreive the field value.
* @param fieldName The <code>fieldName</code> to retreive.
* @return The value of the field.
* @throws NoSuchFieldException Thrown if you try to retreive a field that does not exist.
* @throws InvocationTargetException Can occure during invocation
* @throws IllegalAccessException Thrown while trying to access illagaly the instance
*/
public static Object getFieldValue(final Object object, final String fieldName) throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
try {
return getField(object.getClass(), fieldName).get(object);
} catch (NoSuchFieldException ex) {
try {
return invokeGetter(object, fieldName);
} catch (NoSuchMethodException x) {
throw ex;
}
}
}
/**
* Get the field (<code>filedName</code>) of a class (<code>clazz</code>).
* @param clazz The <code>clazz</code> on which to retreive the field.
* @param fieldName The <code>fieldName</code> to retreive.
* @return The Field object of the given class.
* @throws NoSuchFieldException Thrown if you try to retreive a field that does not exist.
*/
public static Field getField(final Class clazz, final String fieldName) throws NoSuchFieldException {
try {
Field f = clazz.getDeclaredField(fieldName);
f.setAccessible(true);
return f;
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchFieldException e) {
if (clazz == Object.class) {
throw e;
}
// Get the one from parent super class recursivly
return getField(clazz.getSuperclass(), fieldName);
}
}
/**
* Return all declared fields of a class (and all its super class).
* @see {@link Class#getDeclaredFields()}
* @param clazz The class on which to retreive the fields.
* @return All the fields.
*/
public static List getDeclaredFields(final Class clazz) {
List fields = new ArrayList();
Class current = clazz;
while (!current.getName().equals(Object.class.getName())) {
fields.addAll(Arrays.asList(current.getDeclaredFields()));
current = current.getSuperclass();
}
return fields;
}
/**
* Return all getter of a class (but not the ones from parent).
* @param clazz The class on which to retreive the getters.
* @return All the methods.
*/
public static List getGetters(final Class clazz) {
List getters = new ArrayList();
if (clazz != null) {
Method[] methods = clazz.getMethods();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getDeclaringClass().equals(clazz)) {
if ((methods[i].getName().startsWith(GETTER) || methods[i].getName().startsWith(BOOLEAN_GETTER)) && methods[i].getParameterTypes().length == 0) {
getters.add(methods[i]);
}
}
}
}
return getters;
}
/**
* Return all getter of a class (even parent's ones).
* @param clazz The class on which to retreive the getters.
* @return All the methods.
*/
public static List getGettersRecursivly(final Class clazz) {
List getters = new ArrayList();
if (clazz != null) {
Class current = clazz;
while (!current.getName().equals(Object.class.getName())) {
Method[] methods = current.getMethods();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getDeclaringClass().equals(current)) {
if ((methods[i].getName().startsWith(GETTER) || methods[i].getName().startsWith(BOOLEAN_GETTER)) && methods[i].getParameterTypes().length == 0) {
getters.add(methods[i]);
}
}
}
current = current.getSuperclass();
}
}
return getters;
}
/**
* Return all getter of a class (but not the ones from parent).
* @param clazz The class on which to retreive the getters.
* @return All the methods.
*/
public static List getSetters(final Class clazz) {
List getters = new ArrayList();
if (clazz != null) {
Method[] methods = clazz.getMethods();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getDeclaringClass().equals(clazz)) {
if (methods[i].getName().startsWith(SETTER) && methods[i].getName().length() > SETTER.length() && methods[i].getParameterTypes().length == 1) {
getters.add(methods[i]);
}
}
}
}
return getters;
}
/**
* Return all getter of a class (even parent's ones).
* @param clazz The class on which to retreive the getters.
* @return All the methods.
*/
public static List getSettersRecursivly(final Class clazz) {
List getters = new ArrayList();
if (clazz != null) {
Class current = clazz;
while (!current.getName().equals(Object.class.getName())) {
Method[] methods = current.getMethods();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getDeclaringClass().equals(current)) {
if (methods[i].getName().startsWith(SETTER) && methods[i].getName().length() > SETTER.length() && methods[i].getParameterTypes().length == 1) {
getters.add(methods[i]);
}
}
}
current = current.getSuperclass();
}
}
return getters;
}
/**
* Retreive the method (<code>methodName</code>) of a class (<code>clazz</code>) using parameters <code>types</code>.
* @param clazz The <code>clazz</code> on which to retreive the method.
* @param methodName The method name to retreive.
* @param types The types of the method's arguments.
* @return A Method objec.
* @throws NoSuchMethodException Thrown if you try to retreive a method that does not exist.
*/
public static Method getMethod(final Class clazz, final String methodName, final Class[] types) throws NoSuchMethodException {
try {
Method m = clazz.getDeclaredMethod(methodName, types);
m.setAccessible(true);
return m;
} catch (NoSuchMethodException x) {
try {
if (clazz == Object.class) {
throw x;
}
return getMethod(clazz.getSuperclass(), methodName, types);
} catch (Exception ex) {
throw x;
}
}
}
/**
* This method compute the accessor method name according to the <code>accessorType</code> and <code>fieldName</code>.
* @param accessorType the accessor type.
* @param fieldName the field name.
* @return the accessor method name.
* @throw IllegalArgumentException If the arguments type is not valid.
*/
private static String computeAccessorMethodName(final String accessorType, final String fieldName) {
if (!accessorType.equals(SETTER) && !accessorType.equals(GETTER) && !accessorType.equals(BOOLEAN_GETTER)) {
throw new IllegalArgumentException("Accessor Type : " + accessorType + " isn't correct");
}
if (null == fieldName || "".equals(fieldName)) {
throw new IllegalArgumentException("fieldName migth not be null or empty");
}
return accessorType + fieldName.replaceFirst("" + fieldName.charAt(0), ("" + fieldName.charAt(0)).toUpperCase());
}
/**
* If you want to map a getter/setter with its fied name.
* Use this method to convert getter or setter into fieldname
* @param method The method to be converted
* @return The field name or method name if the method is neither a getter neither a setter
*/
public static String getFieldName(final Method method) {
String prefix = null;
if (method.getName().startsWith(GETTER)) {
prefix = GETTER;
} else if (method.getName().startsWith(SETTER)) {
prefix = SETTER;
} else if (method.getName().startsWith(BOOLEAN_GETTER)) {
prefix = BOOLEAN_GETTER;
} else {
return method.getName();
}
if (method.getName().length() == prefix.length()) {
return method.getName();
}
return ("" + method.getName().charAt(prefix.length())).toLowerCase() + method.getName().substring(prefix.length() + 1);
}
}
Java