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, "resolveName",
23 * "/net/iss/common/PrivilegeAccessor"));
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 }