package com.tddinaction.patterns.test; import java.lang.reflect.*; /** * a.k.a. The "ObjectMolester" * <p> * This class is used to access a method or field of an object no matter what * the access modifier of the method or field. The syntax for accessing fields * and methods is out of the ordinary because this class uses reflection to peel * away protection. * <p> * Here is an example of using this to access a private member. * <code>resolveName</code> is a private method of <code>Class</code>. * * <pre> * Class c = Class.class; * System.out.println(PrivilegedAccessor.invokeMethod(c, "resolveName", * "/net/iss/common/PrivilegeAccessor")); * </pre> * * @author Charlie Hubbard (chubbard@iss.net) * @author Prashant Dhokte (pdhokte@iss.net) */ public class PrivilegedAccessor { /** * Gets the value of the named field and returns it as an object. * * @param instance * the object instance * @param fieldName * the name of the field * @return an object representing the value of the field */ public static Object getValue(Object instance, String fieldName) throws IllegalAccessException, NoSuchFieldException { Field field = getField(instance.getClass(), fieldName); field.setAccessible(true); return field.get(instance); } /** * Calls a method on the given object instance with the given argument. * * @param instance * the object instance * @param methodName * the name of the method to invoke * @param arg * the argument to pass to the method * @see PrivilegedAccessor#invokeMethod(Object,String,Object[]) */ public static Object invokeMethod(Object instance, String methodName, Object arg) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Object[] args = new Object[1]; args[0] = arg; return invokeMethod(instance, methodName, args); } /** * Calls a method on the given object instance with the given arguments. * * @param instance * the object instance * @param methodName * the name of the method to invoke * @param args * an array of objects to pass as arguments * @see PrivilegedAccessor#invokeMethod(Object,String,Object) */ public static Object invokeMethod(Object instance, String methodName, Object[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Class[] classTypes = null; if (args != null) { classTypes = new Class[args.length]; for (int i = 0; i < args.length; i++) { if (args[i] != null) classTypes[i] = args[i].getClass(); } } return getMethod(instance, methodName, classTypes).invoke( instance, args); } /** * * @param instance * the object instance * @param methodName * the */ public static Method getMethod(Object instance, String methodName, Class[] classTypes) throws NoSuchMethodException { Method accessMethod = getMethod(instance.getClass(), methodName, classTypes); accessMethod.setAccessible(true); return accessMethod; } /** * Return the named field from the given class. */ private static Field getField(Class thisClass, String fieldName) throws NoSuchFieldException { if (thisClass == null) throw new NoSuchFieldException("Invalid field : " + fieldName); try { return thisClass.getDeclaredField(fieldName); } catch (NoSuchFieldException e) { return getField(thisClass.getSuperclass(), fieldName); } } /** * Return the named method with a method signature matching classTypes from * the given class. */ private static Method getMethod(Class thisClass, String methodName, Class[] classTypes) throws NoSuchMethodException { if (thisClass == null) throw new NoSuchMethodException("Invalid method : " + methodName); try { return thisClass .getDeclaredMethod(methodName, classTypes); } catch (NoSuchMethodException e) { return getMethod(thisClass.getSuperclass(), methodName, classTypes); } } }