001: package junitx.ddtunit.util;
002:
003: import java.lang.reflect.Field;
004: import java.lang.reflect.InvocationTargetException;
005: import java.lang.reflect.Method;
006:
007: /**
008: * a.k.a. The "ObjectMolester"
009: * <p>
010: *
011: * This class is used to access a method or field of an object no matter what
012: * the access modifier of the method or field. The syntax for accessing fields
013: * and methods is out of the ordinary because this class uses reflection to peel
014: * away protection.
015: * <p>
016: *
017: * Here is an example of using this to access a private member.
018: * <code>resolveName</code> is a private method of <code>Class</code>.
019: *
020: * <pre>
021: * Class c = Class.class;
022: * System.out.println(PrivilegedAccessor.invokeMethod(c, "resolveName",
023: * "/net/iss/common/PrivilegeAccessor"));
024: * </pre>
025: *
026: * @author Charlie Hubbard (chubbard@iss.net)
027: * @author Prashant Dhokte (pdhokte@iss.net)
028: * @created 1. November 2002
029: */
030: public class PrivilegedAccessor {
031: /**
032: * Gets the value of the named field and returns it as an object.
033: *
034: * @param instance
035: * the object instance
036: * @param fieldName
037: * the name of the field
038: * @return an object representing the value of the field
039: * @exception IllegalAccessException
040: * Description of the Exception
041: * @exception NoSuchFieldException
042: * Description of the Exception
043: */
044: public static Object getFieldValue(Object instance, String fieldName)
045: throws IllegalAccessException, NoSuchFieldException {
046: Field field = getField(instance.getClass(), fieldName);
047: field.setAccessible(true);
048:
049: return field.get(instance);
050: }
051:
052: /**
053: * Set the value of the named field and returns it as an object.
054: *
055: * @param instance
056: * the object instance
057: * @param fieldName
058: * the name of the field
059: * @param value
060: * The new value value
061: * @exception IllegalAccessException
062: * Description of the Exception
063: * @exception NoSuchFieldException
064: * Description of the Exception
065: */
066: public static void setFieldValue(Object instance, String fieldName,
067: Object value) throws IllegalAccessException,
068: NoSuchFieldException {
069: Field field = getField(instance.getClass(), fieldName);
070: field.setAccessible(true);
071: String fieldType = field.getType().getName();
072: // if value != null check type
073: if (value == null) {
074: field.set(instance, value);
075: } else {
076: String valueType = value.getClass().getName();
077: if (fieldType.equals(valueType)
078: || (!fieldType.startsWith("[") && !valueType
079: .startsWith("["))) {
080: field.set(instance, value);
081: } else {
082: // try to transform to primitive array
083: Object valueArray = ClassAnalyser
084: .createPrimitiveArray(value);
085: System.err.println("error on setfieldValue "
086: + valueType + " to " + fieldType);
087: field.set(instance, valueArray);
088: }
089: }
090: }
091:
092: /**
093: * Calls a method on the given object instance with the given argument.
094: *
095: * @param instance
096: * the object instance
097: * @param methodName
098: * the name of the method to invoke
099: * @param arg
100: * the argument to pass to the method
101: * @return Description of the Return Value
102: * @exception NoSuchMethodException
103: * Description of the Exception
104: * @exception IllegalAccessException
105: * Description of the Exception
106: * @exception InvocationTargetException
107: * Description of the Exception
108: * @see PrivilegedAccessor#invokeMethod(Object,String,Object[])
109: */
110: public static Object invokeMethod(Object instance,
111: String methodName, Object arg)
112: throws NoSuchMethodException, IllegalAccessException,
113: InvocationTargetException {
114: Object[] args = new Object[1];
115: args[0] = arg;
116:
117: return invokeMethod(instance, methodName, args);
118: }
119:
120: /**
121: * Calls a method on the given object instance with the given arguments.
122: *
123: * @param instance
124: * the object instance
125: * @param methodName
126: * the name of the method to invoke
127: * @param args
128: * an array of objects to pass as arguments
129: * @return Description of the Return Value
130: * @exception NoSuchMethodException
131: * Description of the Exception
132: * @exception IllegalAccessException
133: * Description of the Exception
134: * @exception InvocationTargetException
135: * Description of the Exception
136: * @see PrivilegedAccessor#invokeMethod(Object,String,Object)
137: */
138: public static Object invokeMethod(Object instance,
139: String methodName, Object[] args)
140: throws NoSuchMethodException, IllegalAccessException,
141: InvocationTargetException {
142: Class[] classTypes = null;
143:
144: if (args != null) {
145: classTypes = new Class[args.length];
146:
147: for (int i = 0; i < args.length; i++) {
148: if (args[i] != null) {
149: classTypes[i] = args[i].getClass();
150: }
151: }
152: }
153:
154: return getMethod(instance, methodName, classTypes).invoke(
155: instance, args);
156: }
157:
158: /**
159: * @param instance
160: * the object instance
161: * @param methodName
162: * the
163: * @param classTypes
164: * Description of the Parameter
165: * @return The method value
166: * @exception NoSuchMethodException
167: * Description of the Exception
168: */
169: public static Method getMethod(Object instance, String methodName,
170: Class[] classTypes) throws NoSuchMethodException {
171: Method accessMethod = getMethod(instance.getClass(),
172: methodName, classTypes);
173: accessMethod.setAccessible(true);
174:
175: return accessMethod;
176: }
177:
178: /**
179: * Return the named field from the given class.
180: *
181: * @param thisClass
182: * Description of the Parameter
183: * @param fieldName
184: * Description of the Parameter
185: * @return The field value
186: * @exception NoSuchFieldException
187: * Description of the Exception
188: */
189: private static Field getField(Class this Class, String fieldName)
190: throws NoSuchFieldException {
191: if (this Class == null) {
192: throw new NoSuchFieldException("Invalid class field : "
193: + fieldName);
194: }
195:
196: Field[] fields = this Class.getDeclaredFields();
197: Field selField = null;
198: boolean found = false;
199:
200: for (int i = 0; i < fields.length; i++) {
201: selField = fields[i];
202:
203: if (selField.getName().compareTo(fieldName) == 0) {
204: found = true;
205:
206: break;
207: } else {
208: selField = null;
209: }
210: }
211:
212: if (!found) {
213: return getField(this Class.getSuperclass(), fieldName);
214: } else if (selField != null) {
215: return selField;
216: } else {
217: throw new NoSuchFieldException("Invalid field : "
218: + fieldName + " for class " + this Class.getName());
219: }
220: }
221:
222: /**
223: * Return the named method with a method signature matching classTypes from
224: * the given class.
225: *
226: * @param thisClass
227: * Description of the Parameter
228: * @param methodName
229: * Description of the Parameter
230: * @param classTypes
231: * Description of the Parameter
232: * @return The method value
233: * @exception NoSuchMethodException
234: * Description of the Exception
235: */
236: private static Method getMethod(Class this Class, String methodName,
237: Class[] classTypes) throws NoSuchMethodException {
238: if (this Class == null) {
239: throw new NoSuchMethodException("Invalid method : "
240: + methodName);
241: }
242: Method clazzMethod;
243: try {
244: clazzMethod = this Class.getDeclaredMethod(methodName,
245: classTypes);
246: } catch (NoSuchMethodException e) {
247: clazzMethod = getMethod(thisClass.getSuperclass(),
248: methodName, classTypes);
249: }
250: return clazzMethod;
251: }
252: }
|