View Javadoc

1   package junitx.ddtunit.util;
2   
3   import java.lang.reflect.Field;
4   import java.lang.reflect.InvocationTargetException;
5   import java.lang.reflect.Method;
6   
7   /**
8    * a.k.a. The "ObjectMolester"
9    * <p>
10   * 
11   * This class is used to access a method or field of an object no matter what
12   * the access modifier of the method or field. The syntax for accessing fields
13   * and methods is out of the ordinary because this class uses reflection to peel
14   * away protection.
15   * <p>
16   * 
17   * Here is an example of using this to access a private member.
18   * <code>resolveName</code> is a private method of <code>Class</code>.
19   * 
20   * <pre>
21   * Class c = Class.class;
22   * System.out.println(PrivilegedAccessor.invokeMethod(c, &quot;resolveName&quot;,
23   * 		&quot;/net/iss/common/PrivilegeAccessor&quot;));
24   * </pre>
25   * 
26   * @author Charlie Hubbard (chubbard@iss.net)
27   * @author Prashant Dhokte (pdhokte@iss.net)
28   * @created 1. November 2002
29   */
30  public class PrivilegedAccessor {
31  	/**
32  	 * Gets the value of the named field and returns it as an object.
33  	 * 
34  	 * @param instance
35  	 *            the object instance
36  	 * @param fieldName
37  	 *            the name of the field
38  	 * @return an object representing the value of the field
39  	 * @exception IllegalAccessException
40  	 *                Description of the Exception
41  	 * @exception NoSuchFieldException
42  	 *                Description of the Exception
43  	 */
44  	public static Object getFieldValue(Object instance, String fieldName)
45  			throws IllegalAccessException, NoSuchFieldException {
46  		Field field = getField(instance.getClass(), fieldName);
47  		field.setAccessible(true);
48  
49  		return field.get(instance);
50  	}
51  
52  	/**
53  	 * Set the value of the named field and returns it as an object.
54  	 * 
55  	 * @param instance
56  	 *            the object instance
57  	 * @param fieldName
58  	 *            the name of the field
59  	 * @param value
60  	 *            The new value value
61  	 * @exception IllegalAccessException
62  	 *                Description of the Exception
63  	 * @exception NoSuchFieldException
64  	 *                Description of the Exception
65  	 */
66  	public static void setFieldValue(Object instance, String fieldName,
67  			Object value) throws IllegalAccessException, NoSuchFieldException {
68  		Field field = getField(instance.getClass(), fieldName);
69  		field.setAccessible(true);
70  		String fieldType = field.getType().getName();
71  		// if value != null check type
72  		if (value == null) {
73  			field.set(instance, value);
74  		} else {
75  			String valueType = value.getClass().getName();
76  			if (fieldType.equals(valueType)
77  					|| (!fieldType.startsWith("[") && !valueType
78  							.startsWith("["))) {
79  				field.set(instance, value);
80  			} else {
81  				// try to transform to primitive array
82  				Object valueArray = ClassAnalyser.createPrimitiveArray(value);
83  				field.set(instance, valueArray);
84  			}
85  		}
86  	}
87  
88  	/**
89  	 * Calls a method on the given object instance with the given argument.
90  	 * 
91  	 * @param instance
92  	 *            the object instance
93  	 * @param methodName
94  	 *            the name of the method to invoke
95  	 * @param arg
96  	 *            the argument to pass to the method
97  	 * @return Description of the Return Value
98  	 * @exception NoSuchMethodException
99  	 *                Description of the Exception
100 	 * @exception IllegalAccessException
101 	 *                Description of the Exception
102 	 * @exception InvocationTargetException
103 	 *                Description of the Exception
104 	 * @see PrivilegedAccessor#invokeMethod(Object,String,Object[])
105 	 */
106 	public static Object invokeMethod(Object instance, String methodName,
107 			Object arg) throws NoSuchMethodException, IllegalAccessException,
108 			InvocationTargetException {
109 		Object[] args = new Object[1];
110 		args[0] = arg;
111 
112 		return invokeMethod(instance, methodName, args);
113 	}
114 
115 	/**
116 	 * Calls a method on the given object instance with the given arguments.
117 	 * 
118 	 * @param instance
119 	 *            the object instance
120 	 * @param methodName
121 	 *            the name of the method to invoke
122 	 * @param args
123 	 *            an array of objects to pass as arguments
124 	 * @return Description of the Return Value
125 	 * @exception NoSuchMethodException
126 	 *                Description of the Exception
127 	 * @exception IllegalAccessException
128 	 *                Description of the Exception
129 	 * @exception InvocationTargetException
130 	 *                Description of the Exception
131 	 * @see PrivilegedAccessor#invokeMethod(Object,String,Object)
132 	 */
133 	public static Object invokeMethod(Object instance, String methodName,
134 			Object[] args) throws NoSuchMethodException,
135 			IllegalAccessException, InvocationTargetException {
136 		Class[] classTypes = null;
137 
138 		if (args != null) {
139 			classTypes = new Class[args.length];
140 
141 			for (int i = 0; i < args.length; i++) {
142 				if (args[i] != null) {
143 					classTypes[i] = args[i].getClass();
144 				}
145 			}
146 		}
147 
148 		return getMethod(instance, methodName, classTypes).invoke(instance,
149 				args);
150 	}
151 
152 	/**
153 	 * @param instance
154 	 *            the object instance
155 	 * @param methodName
156 	 *            the
157 	 * @param classTypes
158 	 *            Description of the Parameter
159 	 * @return The method value
160 	 * @exception NoSuchMethodException
161 	 *                Description of the Exception
162 	 */
163 	public static Method getMethod(Object instance, String methodName,
164 			Class[] classTypes) throws NoSuchMethodException {
165 		Method accessMethod = getMethod(instance.getClass(), methodName,
166 				classTypes);
167 		accessMethod.setAccessible(true);
168 
169 		return accessMethod;
170 	}
171 
172 	/**
173 	 * Return the named field from the given class.
174 	 * 
175 	 * @param thisClass
176 	 *            Description of the Parameter
177 	 * @param fieldName
178 	 *            Description of the Parameter
179 	 * @return The field value
180 	 * @exception NoSuchFieldException
181 	 *                Description of the Exception
182 	 */
183 	private static Field getField(Class thisClass, String fieldName)
184 			throws NoSuchFieldException {
185 		if (thisClass == null) {
186 			throw new NoSuchFieldException("Invalid class field : " + fieldName);
187 		}
188 
189 		Field[] fields = thisClass.getDeclaredFields();
190 		Field selField = null;
191 		boolean found = false;
192 
193 		for (int i = 0; i < fields.length; i++) {
194 			selField = fields[i];
195 
196 			if (selField.getName().compareTo(fieldName) == 0) {
197 				found = true;
198 
199 				break;
200 			} else {
201 				selField = null;
202 			}
203 		}
204 
205 		if (!found) {
206 			return getField(thisClass.getSuperclass(), fieldName);
207 		} else if (selField != null) {
208 			return selField;
209 		} else {
210 			throw new NoSuchFieldException("Invalid field : " + fieldName
211 					+ " for class " + thisClass.getName());
212 		}
213 	}
214 
215 	/**
216 	 * Return the named method with a method signature matching classTypes from
217 	 * the given class.
218 	 * 
219 	 * @param thisClass
220 	 *            Description of the Parameter
221 	 * @param methodName
222 	 *            Description of the Parameter
223 	 * @param classTypes
224 	 *            Description of the Parameter
225 	 * @return The method value
226 	 * @exception NoSuchMethodException
227 	 *                Description of the Exception
228 	 */
229 	private static Method getMethod(Class thisClass, String methodName,
230 			Class[] classTypes) throws NoSuchMethodException {
231 		if (thisClass == null) {
232 			throw new NoSuchMethodException("Invalid method : " + methodName);
233 		}
234 		Method clazzMethod;
235 		try {
236 			clazzMethod = thisClass.getDeclaredMethod(methodName, classTypes);
237 		} catch (NoSuchMethodException e) {
238 			clazzMethod = getMethod(thisClass.getSuperclass(), methodName,
239 					classTypes);
240 		}
241 		return clazzMethod;
242 	}
243 }