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