source: src/main/java/agents/org/apache/commons/lang/reflect/FieldUtils.java

Last change on this file was 127, checked in by Wouter Pasman, 6 years ago

#41 ROLL BACK of rev.126 . So this version is equal to rev. 125

File size: 26.1 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17package agents.org.apache.commons.lang.reflect;
18
19import java.lang.reflect.Field;
20import java.lang.reflect.Modifier;
21import java.util.Iterator;
22
23import agents.org.apache.commons.lang.ClassUtils;
24
25/**
26 * Utilities for working with fields by reflection. Adapted and refactored
27 * from the dormant [reflect] Commons sandbox component.
28 * <p>
29 * The ability is provided to break the scoping restrictions coded by the
30 * programmer. This can allow fields to be changed that shouldn't be. This
31 * facility should be used with care.
32 *
33 * @author Apache Software Foundation
34 * @author Matt Benson
35 * @since 2.5
36 * @version $Id: FieldUtils.java 1057009 2011-01-09 19:48:06Z niallp $
37 */
38public class FieldUtils {
39
40 /**
41 * FieldUtils instances should NOT be constructed in standard programming.
42 * <p>
43 * This constructor is public to permit tools that require a JavaBean instance
44 * to operate.
45 */
46 public FieldUtils() {
47 super();
48 }
49
50 /**
51 * Gets an accessible <code>Field</code> by name respecting scope.
52 * Superclasses/interfaces will be considered.
53 *
54 * @param cls the class to reflect, must not be null
55 * @param fieldName the field name to obtain
56 * @return the Field object
57 * @throws IllegalArgumentException if the class or field name is null
58 */
59 public static Field getField(Class cls, String fieldName) {
60 Field field = getField(cls, fieldName, false);
61 MemberUtils.setAccessibleWorkaround(field);
62 return field;
63 }
64
65 /**
66 * Gets an accessible <code>Field</code> by name breaking scope
67 * if requested. Superclasses/interfaces will be considered.
68 *
69 * @param cls the class to reflect, must not be null
70 * @param fieldName the field name to obtain
71 * @param forceAccess whether to break scope restrictions using the
72 * <code>setAccessible</code> method. <code>False</code> will only
73 * match public fields.
74 * @return the Field object
75 * @throws IllegalArgumentException if the class or field name is null
76 */
77 public static Field getField(final Class cls, String fieldName, boolean forceAccess) {
78 if (cls == null) {
79 throw new IllegalArgumentException("The class must not be null");
80 }
81 if (fieldName == null) {
82 throw new IllegalArgumentException("The field name must not be null");
83 }
84 // Sun Java 1.3 has a bugged implementation of getField hence we write the
85 // code ourselves
86
87 // getField() will return the Field object with the declaring class
88 // set correctly to the class that declares the field. Thus requesting the
89 // field on a subclass will return the field from the superclass.
90 //
91 // priority order for lookup:
92 // searchclass private/protected/package/public
93 // superclass protected/package/public
94 // private/different package blocks access to further superclasses
95 // implementedinterface public
96
97 // check up the superclass hierarchy
98 for (Class acls = cls; acls != null; acls = acls.getSuperclass()) {
99 try {
100 Field field = acls.getDeclaredField(fieldName);
101 // getDeclaredField checks for non-public scopes as well
102 // and it returns accurate results
103 if (!Modifier.isPublic(field.getModifiers())) {
104 if (forceAccess) {
105 field.setAccessible(true);
106 } else {
107 continue;
108 }
109 }
110 return field;
111 } catch (NoSuchFieldException ex) {
112 // ignore
113 }
114 }
115 // check the public interface case. This must be manually searched for
116 // incase there is a public supersuperclass field hidden by a private/package
117 // superclass field.
118 Field match = null;
119 for (Iterator intf = ClassUtils.getAllInterfaces(cls).iterator(); intf
120 .hasNext();) {
121 try {
122 Field test = ((Class) intf.next()).getField(fieldName);
123 if (match != null) {
124 throw new IllegalArgumentException(
125 "Reference to field "
126 + fieldName
127 + " is ambiguous relative to "
128 + cls
129 + "; a matching field exists on two or more implemented interfaces.");
130 }
131 match = test;
132 } catch (NoSuchFieldException ex) {
133 // ignore
134 }
135 }
136 return match;
137 }
138
139 /**
140 * Gets an accessible <code>Field</code> by name respecting scope.
141 * Only the specified class will be considered.
142 *
143 * @param cls the class to reflect, must not be null
144 * @param fieldName the field name to obtain
145 * @return the Field object
146 * @throws IllegalArgumentException if the class or field name is null
147 */
148 public static Field getDeclaredField(Class cls, String fieldName) {
149 return getDeclaredField(cls, fieldName, false);
150 }
151
152 /**
153 * Gets an accessible <code>Field</code> by name breaking scope
154 * if requested. Only the specified class will be considered.
155 *
156 * @param cls the class to reflect, must not be null
157 * @param fieldName the field name to obtain
158 * @param forceAccess whether to break scope restrictions using the
159 * <code>setAccessible</code> method. False will only match public fields.
160 * @return the Field object
161 * @throws IllegalArgumentException if the class or field name is null
162 */
163 public static Field getDeclaredField(Class cls, String fieldName, boolean forceAccess) {
164 if (cls == null) {
165 throw new IllegalArgumentException("The class must not be null");
166 }
167 if (fieldName == null) {
168 throw new IllegalArgumentException("The field name must not be null");
169 }
170 try {
171 // only consider the specified class by using getDeclaredField()
172 Field field = cls.getDeclaredField(fieldName);
173 if (!MemberUtils.isAccessible(field)) {
174 if (forceAccess) {
175 field.setAccessible(true);
176 } else {
177 return null;
178 }
179 }
180 return field;
181 } catch (NoSuchFieldException e) {
182 }
183 return null;
184 }
185
186 /**
187 * Read an accessible static Field.
188 * @param field to read
189 * @return the field value
190 * @throws IllegalArgumentException if the field is null or not static
191 * @throws IllegalAccessException if the field is not accessible
192 */
193 public static Object readStaticField(Field field) throws IllegalAccessException {
194 return readStaticField(field, false);
195 }
196
197 /**
198 * Read a static Field.
199 * @param field to read
200 * @param forceAccess whether to break scope restrictions using the
201 * <code>setAccessible</code> method.
202 * @return the field value
203 * @throws IllegalArgumentException if the field is null or not static
204 * @throws IllegalAccessException if the field is not made accessible
205 */
206 public static Object readStaticField(Field field, boolean forceAccess) throws IllegalAccessException {
207 if (field == null) {
208 throw new IllegalArgumentException("The field must not be null");
209 }
210 if (!Modifier.isStatic(field.getModifiers())) {
211 throw new IllegalArgumentException("The field '" + field.getName() + "' is not static");
212 }
213 return readField(field, (Object) null, forceAccess);
214 }
215
216 /**
217 * Read the named public static field. Superclasses will be considered.
218 * @param cls the class to reflect, must not be null
219 * @param fieldName the field name to obtain
220 * @return the value of the field
221 * @throws IllegalArgumentException if the class or field name is null
222 * @throws IllegalAccessException if the field is not accessible
223 */
224 public static Object readStaticField(Class cls, String fieldName) throws IllegalAccessException {
225 return readStaticField(cls, fieldName, false);
226 }
227
228 /**
229 * Read the named static field. Superclasses will be considered.
230 * @param cls the class to reflect, must not be null
231 * @param fieldName the field name to obtain
232 * @param forceAccess whether to break scope restrictions using the
233 * <code>setAccessible</code> method. <code>False</code> will only
234 * match public fields.
235 * @return the Field object
236 * @throws IllegalArgumentException if the class or field name is null
237 * @throws IllegalAccessException if the field is not made accessible
238 */
239 public static Object readStaticField(Class cls, String fieldName, boolean forceAccess) throws IllegalAccessException {
240 Field field = getField(cls, fieldName, forceAccess);
241 if (field == null) {
242 throw new IllegalArgumentException("Cannot locate field " + fieldName + " on " + cls);
243 }
244 //already forced access above, don't repeat it here:
245 return readStaticField(field, false);
246 }
247
248 /**
249 * Gets a static Field value by name. The field must be public.
250 * Only the specified class will be considered.
251 *
252 * @param cls the class to reflect, must not be null
253 * @param fieldName the field name to obtain
254 * @return the value of the field
255 * @throws IllegalArgumentException if the class or field name is null
256 * @throws IllegalAccessException if the field is not accessible
257 */
258 public static Object readDeclaredStaticField(Class cls, String fieldName) throws IllegalAccessException {
259 return readDeclaredStaticField(cls, fieldName, false);
260 }
261
262 /**
263 * Gets a static Field value by name. Only the specified class will
264 * be considered.
265 *
266 * @param cls the class to reflect, must not be null
267 * @param fieldName the field name to obtain
268 * @param forceAccess whether to break scope restrictions using the
269 * <code>setAccessible</code> method. <code>False</code> will only
270 * match public fields.
271 * @return the Field object
272 * @throws IllegalArgumentException if the class or field name is null
273 * @throws IllegalAccessException if the field is not made accessible
274 */
275 public static Object readDeclaredStaticField(Class cls, String fieldName, boolean forceAccess)
276 throws IllegalAccessException {
277 Field field = getDeclaredField(cls, fieldName, forceAccess);
278 if (field == null) {
279 throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
280 }
281 //already forced access above, don't repeat it here:
282 return readStaticField(field, false);
283 }
284
285 /**
286 * Read an accessible Field.
287 * @param field the field to use
288 * @param target the object to call on, may be null for static fields
289 * @return the field value
290 * @throws IllegalArgumentException if the field is null
291 * @throws IllegalAccessException if the field is not accessible
292 */
293 public static Object readField(Field field, Object target) throws IllegalAccessException {
294 return readField(field, target, false);
295 }
296
297 /**
298 * Read a Field.
299 * @param field the field to use
300 * @param target the object to call on, may be null for static fields
301 * @param forceAccess whether to break scope restrictions using the
302 * <code>setAccessible</code> method.
303 * @return the field value
304 * @throws IllegalArgumentException if the field is null
305 * @throws IllegalAccessException if the field is not made accessible
306 */
307 public static Object readField(Field field, Object target, boolean forceAccess) throws IllegalAccessException {
308 if (field == null) {
309 throw new IllegalArgumentException("The field must not be null");
310 }
311 if (forceAccess && !field.isAccessible()) {
312 field.setAccessible(true);
313 } else {
314 MemberUtils.setAccessibleWorkaround(field);
315 }
316 return field.get(target);
317 }
318
319 /**
320 * Read the named public field. Superclasses will be considered.
321 * @param target the object to reflect, must not be null
322 * @param fieldName the field name to obtain
323 * @return the value of the field
324 * @throws IllegalArgumentException if the class or field name is null
325 * @throws IllegalAccessException if the named field is not public
326 */
327 public static Object readField(Object target, String fieldName) throws IllegalAccessException {
328 return readField(target, fieldName, false);
329 }
330
331 /**
332 * Read the named field. Superclasses will be considered.
333 * @param target the object to reflect, must not be null
334 * @param fieldName the field name to obtain
335 * @param forceAccess whether to break scope restrictions using the
336 * <code>setAccessible</code> method. <code>False</code> will only
337 * match public fields.
338 * @return the field value
339 * @throws IllegalArgumentException if the class or field name is null
340 * @throws IllegalAccessException if the named field is not made accessible
341 */
342 public static Object readField(Object target, String fieldName, boolean forceAccess) throws IllegalAccessException {
343 if (target == null) {
344 throw new IllegalArgumentException("target object must not be null");
345 }
346 Class cls = target.getClass();
347 Field field = getField(cls, fieldName, forceAccess);
348 if (field == null) {
349 throw new IllegalArgumentException("Cannot locate field " + fieldName + " on " + cls);
350 }
351 //already forced access above, don't repeat it here:
352 return readField(field, target);
353 }
354
355 /**
356 * Read the named public field. Only the class of the specified object will be considered.
357 * @param target the object to reflect, must not be null
358 * @param fieldName the field name to obtain
359 * @return the value of the field
360 * @throws IllegalArgumentException if the class or field name is null
361 * @throws IllegalAccessException if the named field is not public
362 */
363 public static Object readDeclaredField(Object target, String fieldName) throws IllegalAccessException {
364 return readDeclaredField(target, fieldName, false);
365 }
366
367 /**
368 * <p<>Gets a Field value by name. Only the class of the specified
369 * object will be considered.
370 *
371 * @param target the object to reflect, must not be null
372 * @param fieldName the field name to obtain
373 * @param forceAccess whether to break scope restrictions using the
374 * <code>setAccessible</code> method. <code>False</code> will only
375 * match public fields.
376 * @return the Field object
377 * @throws IllegalArgumentException if <code>target</code> or <code>fieldName</code> is null
378 * @throws IllegalAccessException if the field is not made accessible
379 */
380 public static Object readDeclaredField(Object target, String fieldName, boolean forceAccess) throws IllegalAccessException {
381 if (target == null) {
382 throw new IllegalArgumentException("target object must not be null");
383 }
384 Class cls = target.getClass();
385 Field field = getDeclaredField(cls, fieldName, forceAccess);
386 if (field == null) {
387 throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
388 }
389 //already forced access above, don't repeat it here:
390 return readField(field, target);
391 }
392
393 /**
394 * Write a public static Field.
395 * @param field to write
396 * @param value to set
397 * @throws IllegalArgumentException if the field is null or not static
398 * @throws IllegalAccessException if the field is not public or is final
399 */
400 public static void writeStaticField(Field field, Object value) throws IllegalAccessException {
401 writeStaticField(field, value, false);
402 }
403
404 /**
405 * Write a static Field.
406 * @param field to write
407 * @param value to set
408 * @param forceAccess whether to break scope restrictions using the
409 * <code>setAccessible</code> method. <code>False</code> will only
410 * match public fields.
411 * @throws IllegalArgumentException if the field is null or not static
412 * @throws IllegalAccessException if the field is not made accessible or is final
413 */
414 public static void writeStaticField(Field field, Object value, boolean forceAccess) throws IllegalAccessException {
415 if (field == null) {
416 throw new IllegalArgumentException("The field must not be null");
417 }
418 if (!Modifier.isStatic(field.getModifiers())) {
419 throw new IllegalArgumentException("The field '" + field.getName() + "' is not static");
420 }
421 writeField(field, (Object) null, value, forceAccess);
422 }
423
424 /**
425 * Write a named public static Field. Superclasses will be considered.
426 * @param cls Class on which the Field is to be found
427 * @param fieldName to write
428 * @param value to set
429 * @throws IllegalArgumentException if the field cannot be located or is not static
430 * @throws IllegalAccessException if the field is not public or is final
431 */
432 public static void writeStaticField(Class cls, String fieldName, Object value) throws IllegalAccessException {
433 writeStaticField(cls, fieldName, value, false);
434 }
435
436 /**
437 * Write a named static Field. Superclasses will be considered.
438 * @param cls Class on which the Field is to be found
439 * @param fieldName to write
440 * @param value to set
441 * @param forceAccess whether to break scope restrictions using the
442 * <code>setAccessible</code> method. <code>False</code> will only
443 * match public fields.
444 * @throws IllegalArgumentException if the field cannot be located or is not static
445 * @throws IllegalAccessException if the field is not made accessible or is final
446 */
447 public static void writeStaticField(Class cls, String fieldName, Object value, boolean forceAccess)
448 throws IllegalAccessException {
449 Field field = getField(cls, fieldName, forceAccess);
450 if (field == null) {
451 throw new IllegalArgumentException("Cannot locate field " + fieldName + " on " + cls);
452 }
453 //already forced access above, don't repeat it here:
454 writeStaticField(field, value);
455 }
456
457 /**
458 * Write a named public static Field. Only the specified class will be considered.
459 * @param cls Class on which the Field is to be found
460 * @param fieldName to write
461 * @param value to set
462 * @throws IllegalArgumentException if the field cannot be located or is not static
463 * @throws IllegalAccessException if the field is not public or is final
464 */
465 public static void writeDeclaredStaticField(Class cls, String fieldName, Object value)
466 throws IllegalAccessException {
467 writeDeclaredStaticField(cls, fieldName, value, false);
468 }
469
470 /**
471 * Write a named static Field. Only the specified class will be considered.
472 * @param cls Class on which the Field is to be found
473 * @param fieldName to write
474 * @param value to set
475 * @param forceAccess whether to break scope restrictions using the
476 * <code>setAccessible</code> method. <code>False</code> will only
477 * match public fields.
478 * @throws IllegalArgumentException if the field cannot be located or is not static
479 * @throws IllegalAccessException if the field is not made accessible or is final
480 */
481 public static void writeDeclaredStaticField(Class cls, String fieldName, Object value, boolean forceAccess)
482 throws IllegalAccessException {
483 Field field = getDeclaredField(cls, fieldName, forceAccess);
484 if (field == null) {
485 throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
486 }
487 //already forced access above, don't repeat it here:
488 writeField(field, (Object) null, value);
489 }
490
491 /**
492 * Write an accessible field.
493 * @param field to write
494 * @param target the object to call on, may be null for static fields
495 * @param value to set
496 * @throws IllegalArgumentException if the field is null
497 * @throws IllegalAccessException if the field is not accessible or is final
498 */
499 public static void writeField(Field field, Object target, Object value) throws IllegalAccessException {
500 writeField(field, target, value, false);
501 }
502
503 /**
504 * Write a field.
505 * @param field to write
506 * @param target the object to call on, may be null for static fields
507 * @param value to set
508 * @param forceAccess whether to break scope restrictions using the
509 * <code>setAccessible</code> method. <code>False</code> will only
510 * match public fields.
511 * @throws IllegalArgumentException if the field is null
512 * @throws IllegalAccessException if the field is not made accessible or is final
513 */
514 public static void writeField(Field field, Object target, Object value, boolean forceAccess) throws IllegalAccessException {
515 if (field == null) {
516 throw new IllegalArgumentException("The field must not be null");
517 }
518 if (forceAccess && !field.isAccessible()) {
519 field.setAccessible(true);
520 } else {
521 MemberUtils.setAccessibleWorkaround(field);
522 }
523 field.set(target, value);
524 }
525
526 /**
527 * Write a public field. Superclasses will be considered.
528 * @param target the object to reflect, must not be null
529 * @param fieldName the field name to obtain
530 * @param value to set
531 * @throws IllegalArgumentException if <code>target</code> or <code>fieldName</code> is null
532 * @throws IllegalAccessException if the field is not accessible
533 */
534 public static void writeField(Object target, String fieldName, Object value) throws IllegalAccessException {
535 writeField(target, fieldName, value, false);
536 }
537
538 /**
539 * Write a field. Superclasses will be considered.
540 * @param target the object to reflect, must not be null
541 * @param fieldName the field name to obtain
542 * @param value to set
543 * @param forceAccess whether to break scope restrictions using the
544 * <code>setAccessible</code> method. <code>False</code> will only
545 * match public fields.
546 * @throws IllegalArgumentException if <code>target</code> or <code>fieldName</code> is null
547 * @throws IllegalAccessException if the field is not made accessible
548 */
549 public static void writeField(Object target, String fieldName, Object value, boolean forceAccess)
550 throws IllegalAccessException {
551 if (target == null) {
552 throw new IllegalArgumentException("target object must not be null");
553 }
554 Class cls = target.getClass();
555 Field field = getField(cls, fieldName, forceAccess);
556 if (field == null) {
557 throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
558 }
559 //already forced access above, don't repeat it here:
560 writeField(field, target, value);
561 }
562
563 /**
564 * Write a public field. Only the specified class will be considered.
565 * @param target the object to reflect, must not be null
566 * @param fieldName the field name to obtain
567 * @param value to set
568 * @throws IllegalArgumentException if <code>target</code> or <code>fieldName</code> is null
569 * @throws IllegalAccessException if the field is not made accessible
570 */
571 public static void writeDeclaredField(Object target, String fieldName, Object value) throws IllegalAccessException {
572 writeDeclaredField(target, fieldName, value, false);
573 }
574
575 /**
576 * Write a public field. Only the specified class will be considered.
577 * @param target the object to reflect, must not be null
578 * @param fieldName the field name to obtain
579 * @param value to set
580 * @param forceAccess whether to break scope restrictions using the
581 * <code>setAccessible</code> method. <code>False</code> will only
582 * match public fields.
583 * @throws IllegalArgumentException if <code>target</code> or <code>fieldName</code> is null
584 * @throws IllegalAccessException if the field is not made accessible
585 */
586 public static void writeDeclaredField(Object target, String fieldName, Object value, boolean forceAccess)
587 throws IllegalAccessException {
588 if (target == null) {
589 throw new IllegalArgumentException("target object must not be null");
590 }
591 Class cls = target.getClass();
592 Field field = getDeclaredField(cls, fieldName, forceAccess);
593 if (field == null) {
594 throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
595 }
596 //already forced access above, don't repeat it here:
597 writeField(field, target, value);
598 }
599}
Note: See TracBrowser for help on using the repository browser.