1 /* 2 * Copyright (c) 2006 JMockit developers 3 * This file is subject to the terms of the MIT license (see LICENSE.txt). 4 */ 5 package mockit; 6 7 import edu.umd.cs.findbugs.annotations.NonNull; 8 import edu.umd.cs.findbugs.annotations.Nullable; 9 10 import mockit.internal.reflection.FieldReflection; 11 import mockit.internal.reflection.MethodReflection; 12 import mockit.internal.util.ClassLoad; 13 14 /** 15 * Provides utility methods that enable access to ("de-encapsulate") otherwise non-accessible fields. 16 * 17 * @see #getField(Object, String) 18 * @see #setField(Object, String, Object) 19 */ 20 public final class Deencapsulation { 21 private Deencapsulation() { 22 } 23 24 /** 25 * Gets the value of a non-accessible (eg <code>private</code>) field from a given object. 26 * 27 * @param <T> 28 * interface or class type to which the returned value should be assignable 29 * @param objectWithField 30 * the instance from which to get the field value 31 * @param fieldName 32 * the name of the field to get 33 * 34 * @return the field 35 * 36 * @throws IllegalArgumentException 37 * if the desired field is not found 38 * 39 * @see #getField(Object, Class) 40 * @see #getField(Class, String) 41 * @see #setField(Object, String, Object) 42 */ 43 @Nullable 44 public static <T> T getField(@NonNull Object objectWithField, @NonNull String fieldName) { 45 return FieldReflection.getField(objectWithField.getClass(), fieldName, objectWithField); 46 } 47 48 /** 49 * Gets the value of a non-accessible (eg <code>private</code>) field from a given object, <em>assuming</em> there 50 * is only one field declared in the class of the given object whose type can receive values of the specified field 51 * type. 52 * 53 * @param <T> 54 * the generic type 55 * @param objectWithField 56 * the instance from which to get the field value 57 * @param fieldType 58 * the declared type of the field, or a sub-type of the declared field type 59 * 60 * @return the field 61 * 62 * @throws IllegalArgumentException 63 * if either the desired field is not found, or more than one is 64 * 65 * @see #getField(Object, String) 66 * @see #getField(Class, String) 67 * @see #setField(Object, Object) 68 */ 69 @Nullable 70 public static <T> T getField(@NonNull Object objectWithField, @NonNull Class<T> fieldType) { 71 return FieldReflection.getField(objectWithField.getClass(), fieldType, objectWithField); 72 } 73 74 /** 75 * Gets the value of a non-accessible static field defined in a given class. 76 * 77 * @param <T> 78 * interface or class type to which the returned value should be assignable 79 * @param classWithStaticField 80 * the class from which to get the field value 81 * @param fieldName 82 * the name of the static field to get 83 * 84 * @return the field 85 * 86 * @throws IllegalArgumentException 87 * if the desired field is not found 88 * 89 * @see #getField(Class, Class) 90 * @see #getField(Object, String) 91 * @see #setField(Class, String, Object) 92 */ 93 @Nullable 94 public static <T> T getField(@NonNull Class<?> classWithStaticField, @NonNull String fieldName) { 95 return FieldReflection.getField(classWithStaticField, fieldName, null); 96 } 97 98 /** 99 * Gets the value of a non-accessible static field defined in a given class, <em>assuming</em> there is only one 100 * field declared in the given class whose type can receive values of the specified field type. 101 * 102 * @param <T> 103 * interface or class type to which the returned value should be assignable 104 * @param classWithStaticField 105 * the class from which to get the field value 106 * @param fieldType 107 * the declared type of the field, or a sub-type of the declared field type 108 * 109 * @return the field 110 * 111 * @throws IllegalArgumentException 112 * if either the desired field is not found, or more than one is 113 * 114 * @see #getField(Class, String) 115 * @see #getField(Object, Class) 116 * @see #setField(Class, Object) 117 */ 118 @Nullable 119 public static <T> T getField(@NonNull Class<?> classWithStaticField, @NonNull Class<T> fieldType) { 120 return FieldReflection.getField(classWithStaticField, fieldType, null); 121 } 122 123 /** 124 * Sets the value of a non-accessible field on a given object. 125 * 126 * @param objectWithField 127 * the instance on which to set the field value 128 * @param fieldName 129 * the name of the field to set 130 * @param fieldValue 131 * the value to set the field to 132 * 133 * @throws IllegalArgumentException 134 * if the desired field is not found 135 * 136 * @see #setField(Class, String, Object) 137 * @see #setField(Object, Object) 138 * @see #getField(Object, String) 139 */ 140 public static void setField(@NonNull Object objectWithField, @NonNull String fieldName, 141 @Nullable Object fieldValue) { 142 FieldReflection.setField(objectWithField.getClass(), objectWithField, fieldName, fieldValue); 143 } 144 145 /** 146 * Sets the value of a non-accessible field on a given object. The field is looked up by the type of the given field 147 * value instead of by name. 148 * 149 * @param objectWithField 150 * the object with field 151 * @param fieldValue 152 * the field value 153 * 154 * @throws IllegalArgumentException 155 * if either the desired field is not found, or more than one is 156 * 157 * @see #setField(Object, String, Object) 158 * @see #setField(Class, String, Object) 159 * @see #getField(Object, String) 160 */ 161 public static void setField(@NonNull Object objectWithField, @NonNull Object fieldValue) { 162 FieldReflection.setField(objectWithField.getClass(), objectWithField, null, fieldValue); 163 } 164 165 /** 166 * Sets the value of a non-accessible static field on a given class. 167 * 168 * @param classWithStaticField 169 * the class on which the static field is defined 170 * @param fieldName 171 * the name of the field to set 172 * @param fieldValue 173 * the value to set the field to 174 * 175 * @throws IllegalArgumentException 176 * if the desired field is not found 177 * 178 * @see #setField(Class, Object) 179 * @see #setField(Object, String, Object) 180 * @see #getField(Class, String) 181 */ 182 public static void setField(@NonNull Class<?> classWithStaticField, @NonNull String fieldName, 183 @Nullable Object fieldValue) { 184 FieldReflection.setField(classWithStaticField, null, fieldName, fieldValue); 185 } 186 187 /** 188 * Sets the value of a non-accessible static field on a given class. The field is looked up by the type of the given 189 * field value instead of by name. 190 * 191 * @param classWithStaticField 192 * the class on which the static field is defined 193 * @param fieldValue 194 * the value to set the field to 195 * 196 * @throws IllegalArgumentException 197 * if either the desired field is not found, or more than one is 198 * 199 * @see #setField(Class, String, Object) 200 * @see #setField(Object, Object) 201 * @see #getField(Class, Class) 202 */ 203 public static void setField(@NonNull Class<?> classWithStaticField, @NonNull Object fieldValue) { 204 FieldReflection.setField(classWithStaticField, null, null, fieldValue); 205 } 206 207 /** 208 * Invokes a non-accessible (eg {@code private}) instance method from a given class with the given arguments. 209 * 210 * @param <T> 211 * type to which the returned value should be assignable 212 * @param objectWithMethod 213 * the instance on which the invocation is to be done 214 * @param methodName 215 * the name of the method to invoke 216 * @param parameterTypes 217 * the types of the parameters as declared in the desired method 218 * @param methodArgs 219 * zero or more parameter values for the invocation 220 * 221 * @return the return value from the invoked method 222 * 223 * @throws IllegalArgumentException 224 * if the desired method is not found 225 * 226 * @see #invoke(Class, String, Object...) 227 */ 228 public static <T> T invoke(Object objectWithMethod, String methodName, Class<?>[] parameterTypes, 229 Object... methodArgs) { 230 Class<?> theClass = objectWithMethod.getClass(); 231 return MethodReflection.invoke(theClass, objectWithMethod, methodName, parameterTypes, methodArgs); 232 } 233 234 /** 235 * Invokes a non-accessible (eg {@code private}) instance method from a given class with the given arguments. 236 * 237 * @param <T> 238 * type to which the returned value should be assignable 239 * @param objectWithMethod 240 * the instance on which the invocation is to be done 241 * @param methodName 242 * the name of the method to invoke 243 * @param nonNullArgs 244 * zero or more non-null parameter values for the invocation; if a null value needs to be passed, the 245 * {@code Class} object for the corresponding parameter type must be passed instead 246 * 247 * @return the return value from the invoked method 248 * 249 * @throws IllegalArgumentException 250 * if the desired method is not found, or a null reference was provided for a parameter 251 * 252 * @see #invoke(Class, String, Object...) 253 */ 254 public static <T> T invoke(Object objectWithMethod, String methodName, Object... nonNullArgs) { 255 Class<?> theClass = objectWithMethod.getClass(); 256 return MethodReflection.invoke(theClass, objectWithMethod, methodName, nonNullArgs); 257 } 258 259 /** 260 * Invokes a non-accessible (eg {@code private}) {@code static} method with the given arguments. 261 * 262 * @param <T> 263 * type to which the returned value should be assignable 264 * @param classWithStaticMethod 265 * the class on which the invocation is to be done 266 * @param methodName 267 * the name of the static method to invoke 268 * @param parameterTypes 269 * the types of the parameters as declared in the desired method 270 * @param methodArgs 271 * zero or more parameter values for the invocation 272 * 273 * @return the return value from the invoked method 274 * 275 * @see #invoke(String, String, Object...) 276 */ 277 public static <T> T invoke(Class<?> classWithStaticMethod, String methodName, Class<?>[] parameterTypes, 278 Object... methodArgs) { 279 return MethodReflection.invoke(classWithStaticMethod, null, methodName, parameterTypes, methodArgs); 280 } 281 282 /** 283 * Invokes a non-accessible (eg {@code private}) {@code static} method with the given arguments. 284 * 285 * @param <T> 286 * type to which the returned value should be assignable 287 * @param classWithStaticMethod 288 * the class on which the invocation is to be done 289 * @param methodName 290 * the name of the static method to invoke 291 * @param nonNullArgs 292 * zero or more non-null parameter values for the invocation; if a null value needs to be passed, the 293 * {@code Class} object for the corresponding parameter type must be passed instead 294 * 295 * @return the return value from the invoked method 296 * 297 * @throws IllegalArgumentException 298 * if the desired method is not found, or a null reference was provided for a parameter 299 * 300 * @see #invoke(String, String, Object...) 301 */ 302 public static <T> T invoke(Class<?> classWithStaticMethod, String methodName, Object... nonNullArgs) { 303 return MethodReflection.invoke(classWithStaticMethod, null, methodName, nonNullArgs); 304 } 305 306 /** 307 * Invokes a non-accessible (eg {@code private}) {@code static} method with the given arguments. 308 * 309 * @param <T> 310 * type to which the returned value should be assignable 311 * @param classWithStaticMethod 312 * the (fully qualified) name of the class on which the invocation is to be done; must not be null 313 * @param methodName 314 * the name of the static method to invoke 315 * @param nonNullArgs 316 * zero or more non-null parameter values for the invocation; if a null value needs to be passed, the 317 * {@code Class} object for the corresponding parameter type must be passed instead 318 * 319 * @return the return value from the invoked method 320 * 321 * @throws IllegalArgumentException 322 * if the desired method is not found, or a null reference was provided for a parameter 323 * 324 * @see #invoke(Class, String, Object...) 325 */ 326 public static <T> T invoke(String classWithStaticMethod, String methodName, Object... nonNullArgs) { 327 Class<Object> theClass = ClassLoad.loadClass(classWithStaticMethod); 328 return MethodReflection.invoke(theClass, null, methodName, nonNullArgs); 329 } 330 }