001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      https://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.lang3.reflect;
018
019import java.lang.annotation.Annotation;
020import java.lang.reflect.AccessibleObject;
021import java.lang.reflect.Field;
022import java.lang.reflect.Modifier;
023import java.util.ArrayList;
024import java.util.Collections;
025import java.util.List;
026import java.util.Objects;
027import java.util.stream.Collectors;
028
029import org.apache.commons.lang3.ArrayUtils;
030import org.apache.commons.lang3.ClassUtils;
031import org.apache.commons.lang3.JavaVersion;
032import org.apache.commons.lang3.StringUtils;
033import org.apache.commons.lang3.SystemUtils;
034import org.apache.commons.lang3.Validate;
035
036/**
037 * Utilities for working with {@link Field}s by reflection. Adapted and refactored from the dormant [reflect] Commons
038 * sandbox component.
039 * <p>
040 * The ability is provided to break the scoping restrictions coded by the programmer. This can allow fields to be
041 * changed that shouldn't be. This facility should be used with care.
042 * </p>
043 * @since 2.5
044 */
045public class FieldUtils {
046
047    /**
048     * Gets all fields of the given class and its parents (if any).
049     *
050     * @param cls
051     *            the {@link Class} to query
052     * @return an array of Fields (possibly empty).
053     * @throws NullPointerException
054     *             if the class is {@code null}.
055     * @since 3.2
056     */
057    public static Field[] getAllFields(final Class<?> cls) {
058        return getAllFieldsList(cls).toArray(ArrayUtils.EMPTY_FIELD_ARRAY);
059    }
060
061    /**
062     * Gets all fields of the given class and its parents (if any).
063     *
064     * @param cls
065     *            the {@link Class} to query
066     * @return a list of Fields (possibly empty).
067     * @throws NullPointerException
068     *             if the class is {@code null}.
069     * @since 3.2
070     */
071    public static List<Field> getAllFieldsList(final Class<?> cls) {
072        Objects.requireNonNull(cls, "cls");
073        final List<Field> allFields = new ArrayList<>();
074        Class<?> currentClass = cls;
075        while (currentClass != null) {
076            Collections.addAll(allFields, currentClass.getDeclaredFields());
077            currentClass = currentClass.getSuperclass();
078        }
079        return allFields;
080    }
081
082    /**
083     * Gets an accessible {@link Field} by name respecting scope. Only the specified class will be considered.
084     *
085     * @param cls
086     *            the {@link Class} to reflect, must not be {@code null}
087     * @param fieldName
088     *            the field name to obtain.
089     * @return the Field object.
090     * @throws NullPointerException
091     *             if the class is {@code null}.
092     * @throws IllegalArgumentException
093     *             if the field name is {@code null}, blank, or empty.
094     * @throws SecurityException if an underlying accessible object's method denies the request.
095     * @see SecurityManager#checkPermission
096     */
097    public static Field getDeclaredField(final Class<?> cls, final String fieldName) {
098        return getDeclaredField(cls, fieldName, false);
099    }
100
101    /**
102     * Gets an accessible {@link Field} by name, breaking scope if requested. Only the specified class will be
103     * considered.
104     *
105     * @param cls
106     *            the {@link Class} to reflect, must not be {@code null}.
107     * @param fieldName
108     *            the field name to obtain.
109     * @param forceAccess
110     *            whether to break scope restrictions using the
111     *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
112     *            match {@code public} fields.
113     * @return the Field object
114     * @throws NullPointerException
115     *             if the class is {@code null}.
116     * @throws IllegalArgumentException
117     *             if the field name is {@code null}, blank, or empty.
118     * @throws SecurityException if an underlying accessible object's method denies the request.
119     * @see SecurityManager#checkPermission
120     */
121    public static Field getDeclaredField(final Class<?> cls, final String fieldName, final boolean forceAccess) {
122        Objects.requireNonNull(cls, "cls");
123        Validate.isTrue(StringUtils.isNotBlank(fieldName), "The field name must not be blank/empty");
124        try {
125            // only consider the specified class by using getDeclaredField()
126            final Field field = cls.getDeclaredField(fieldName);
127            if (!MemberUtils.isAccessible(field)) {
128                if (!forceAccess) {
129                    return null;
130                }
131                field.setAccessible(true);
132            }
133            return field;
134        } catch (final NoSuchFieldException ignored) {
135            // ignore
136        }
137        return null;
138    }
139
140    /**
141     * Gets an accessible {@link Field} by name respecting scope. Superclasses/interfaces will be considered.
142     *
143     * @param cls
144     *            the {@link Class} to reflect, must not be {@code null}.
145     * @param fieldName
146     *            the field name to obtain.
147     * @return the Field object.
148     * @throws NullPointerException
149     *             if the class is {@code null}.
150     * @throws IllegalArgumentException
151     *             if the field name is {@code null}, blank, or empty
152     * @throws SecurityException if an underlying accessible object's method denies the request.
153     * @see SecurityManager#checkPermission
154     */
155    public static Field getField(final Class<?> cls, final String fieldName) {
156        return MemberUtils.setAccessibleWorkaround(getField(cls, fieldName, false));
157    }
158
159    /**
160     * Gets an accessible {@link Field} by name, breaking scope if requested. Superclasses/interfaces will be
161     * considered.
162     *
163     * @param cls
164     *            the {@link Class} to reflect, must not be {@code null}.
165     * @param fieldName
166     *            the field name to obtain.
167     * @param forceAccess
168     *            whether to break scope restrictions using the
169     *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
170     *            match {@code public} fields.
171     * @return the Field object.
172     * @throws NullPointerException if the class is {@code null}.
173     * @throws IllegalArgumentException if the field name is blank or empty or is matched at multiple places
174     * in the inheritance hierarchy.
175     * @throws SecurityException if an underlying accessible object's method denies the request.
176     * @see SecurityManager#checkPermission
177     */
178    public static Field getField(final Class<?> cls, final String fieldName, final boolean forceAccess) {
179        Objects.requireNonNull(cls, "cls");
180        Validate.isTrue(StringUtils.isNotBlank(fieldName), "The field name must not be blank/empty");
181        // FIXME is this workaround still needed? lang requires Java 6
182        // Sun Java 1.3 has a bugged implementation of getField hence we write the
183        // code ourselves
184
185        // getField() will return the Field object with the declaring class
186        // set correctly to the class that declares the field. Thus requesting the
187        // field on a subclass will return the field from the superclass.
188        //
189        // priority order for lookup:
190        // searchclass private/protected/package/public
191        // superclass protected/package/public
192        // private/different package blocks access to further superclasses
193        // implementedinterface public
194
195        // check up the superclass hierarchy
196        for (Class<?> acls = cls; acls != null; acls = acls.getSuperclass()) {
197            try {
198                final Field field = acls.getDeclaredField(fieldName);
199                // getDeclaredField checks for non-public scopes as well
200                // and it returns accurate results
201                if (!MemberUtils.isPublic(field)) {
202                    if (!forceAccess) {
203                        continue;
204                    }
205                    field.setAccessible(true);
206                }
207                return field;
208            } catch (final NoSuchFieldException ignored) {
209                // ignore
210            }
211        }
212        // check the public interface case. This must be manually searched for
213        // incase there is a public supersuperclass field hidden by a private/package
214        // superclass field.
215        Field match = null;
216        for (final Class<?> class1 : ClassUtils.getAllInterfaces(cls)) {
217            try {
218                final Field test = class1.getField(fieldName);
219                Validate.isTrue(match == null,
220                        "Reference to field %s is ambiguous relative to %s; a matching field exists on two or more implemented interfaces.", fieldName, cls);
221                match = test;
222            } catch (final NoSuchFieldException ignored) {
223                // ignore
224            }
225        }
226        return match;
227    }
228
229    /**
230     * Gets all fields of the given class and its parents (if any) that are annotated with the given annotation.
231     * @param cls
232     *            the {@link Class} to query.
233     * @param annotationCls
234     *            the {@link Annotation} that must be present on a field to be matched.
235     * @return a list of Fields (possibly empty).
236     * @throws NullPointerException
237     *            if the class or annotation are {@code null}.
238     * @since 3.4
239     */
240    public static List<Field> getFieldsListWithAnnotation(final Class<?> cls, final Class<? extends Annotation> annotationCls) {
241        Objects.requireNonNull(annotationCls, "annotationCls");
242        return getAllFieldsList(cls).stream().filter(field -> field.getAnnotation(annotationCls) != null).collect(Collectors.toList());
243    }
244
245    /**
246     * Gets all fields of the given class and its parents (if any) that are annotated with the given annotation.
247     * @param cls
248     *            the {@link Class} to query.
249     * @param annotationCls
250     *            the {@link Annotation} that must be present on a field to be matched
251     * @return an array of Fields (possibly empty).
252     * @throws NullPointerException
253     *            if the class or annotation are {@code null}.
254     * @since 3.4
255     */
256    public static Field[] getFieldsWithAnnotation(final Class<?> cls, final Class<? extends Annotation> annotationCls) {
257        return getFieldsListWithAnnotation(cls, annotationCls).toArray(ArrayUtils.EMPTY_FIELD_ARRAY);
258    }
259
260    /**
261     * Reads the named {@code public} {@link Field}. Only the class of the specified object will be considered.
262     *
263     * @param target
264     *            the object to reflect, must not be {@code null}.
265     * @param fieldName
266     *            the field name to obtain.
267     * @return the value of the field.
268     * @throws NullPointerException
269     *             if {@code target} is {@code null}.
270     * @throws IllegalArgumentException
271     *             if {@code fieldName} is {@code null}, blank or empty, or could not be found.
272     * @throws IllegalAccessException
273     *             if the named field is not {@code public}
274     * @throws SecurityException if an underlying accessible object's method denies the request.
275     * @see SecurityManager#checkPermission
276     */
277    public static Object readDeclaredField(final Object target, final String fieldName) throws IllegalAccessException {
278        return readDeclaredField(target, fieldName, false);
279    }
280
281    /**
282     * Gets a {@link Field} value by name. Only the class of the specified object will be considered.
283     *
284     * @param target
285     *            the object to reflect, must not be {@code null}.
286     * @param fieldName
287     *            the field name to obtain.
288     * @param forceAccess
289     *            whether to break scope restrictions using the
290     *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
291     *            match public fields.
292     * @return the Field object.
293     * @throws NullPointerException
294     *             if {@code target} is {@code null}.
295     * @throws IllegalArgumentException
296     *             if {@code fieldName} is {@code null}, blank or empty, or could not be found.
297     * @throws IllegalAccessException
298     *             if the field is not made accessible.
299     * @throws SecurityException if an underlying accessible object's method denies the request.
300     * @see SecurityManager#checkPermission
301     */
302    public static Object readDeclaredField(final Object target, final String fieldName, final boolean forceAccess) throws IllegalAccessException {
303        Objects.requireNonNull(target, "target");
304        final Class<?> cls = target.getClass();
305        final Field field = getDeclaredField(cls, fieldName, forceAccess);
306        Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls, fieldName);
307        // already forced access above, don't repeat it here:
308        return readField(field, target, false);
309    }
310
311    /**
312     * Gets the value of a {@code static} {@link Field} by name. The field must be {@code public}. Only the specified
313     * class will be considered.
314     *
315     * @param cls
316     *            the {@link Class} to reflect, must not be {@code null}.
317     * @param fieldName
318     *            the field name to obtain.
319     * @return the value of the field.
320     * @throws NullPointerException
321     *             if the class is {@code null}, or the field could not be found.
322     * @throws IllegalArgumentException
323     *             if the field name is {@code null}, blank, empty, or is not {@code static}.
324     * @throws IllegalAccessException
325     *             if the field is not accessible
326     * @throws SecurityException if an underlying accessible object's method denies the request.
327     * @see SecurityManager#checkPermission
328     */
329    public static Object readDeclaredStaticField(final Class<?> cls, final String fieldName) throws IllegalAccessException {
330        return readDeclaredStaticField(cls, fieldName, false);
331    }
332
333    /**
334     * Gets the value of a {@code static} {@link Field} by name. Only the specified class will be considered.
335     *
336     * @param cls
337     *            the {@link Class} to reflect, must not be {@code null}.
338     * @param fieldName
339     *            the field name to obtain.
340     * @param forceAccess
341     *            whether to break scope restrictions using the
342     *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
343     *            match {@code public} fields.
344     * @return the Field object
345     * @throws NullPointerException
346     *             if the class is {@code null}, or the field could not be found.
347     * @throws IllegalArgumentException
348     *             if the field name is blank or empty, is not {@code static}.
349     * @throws IllegalAccessException
350     *             if the field is not made accessible
351     * @throws SecurityException if an underlying accessible object's method denies the request.
352     * @see SecurityManager#checkPermission
353     */
354    public static Object readDeclaredStaticField(final Class<?> cls, final String fieldName, final boolean forceAccess) throws IllegalAccessException {
355        final Field field = getDeclaredField(cls, fieldName, forceAccess);
356        Validate.notNull(field, "Cannot locate declared field %s.%s", cls.getName(), fieldName);
357        // already forced access above, don't repeat it here:
358        return readStaticField(field, false);
359    }
360
361    /**
362     * Reads an accessible {@link Field}.
363     *
364     * @param field
365     *            the field to use.
366     * @param target
367     *            the object to call on, may be {@code null} for {@code static} fields.
368     * @return the field value
369     * @throws NullPointerException
370     *             if the field is {@code null}.
371     * @throws IllegalAccessException
372     *             if the field is not accessible.
373     * @throws SecurityException if an underlying accessible object's method denies the request.
374     * @see SecurityManager#checkPermission
375     */
376    public static Object readField(final Field field, final Object target) throws IllegalAccessException {
377        return readField(field, target, false);
378    }
379
380    /**
381     * Reads a {@link Field}.
382     *
383     * @param field
384     *            the field to use.
385     * @param target
386     *            the object to call on, may be {@code null} for {@code static} fields.
387     * @param forceAccess
388     *            whether to break scope restrictions using the
389     *            {@link AccessibleObject#setAccessible(boolean)} method.
390     * @return the field value
391     * @throws NullPointerException
392     *             if the field is {@code null}.
393     * @throws IllegalAccessException
394     *             if the field is not made accessible.
395     * @throws SecurityException if an underlying accessible object's method denies the request.
396     * @see SecurityManager#checkPermission
397     * @throws SecurityException if an underlying accessible object's method denies the request.
398     * @see SecurityManager#checkPermission
399     */
400    public static Object readField(final Field field, final Object target, final boolean forceAccess) throws IllegalAccessException {
401        Objects.requireNonNull(field, "field");
402        return setAccessible(field, forceAccess).get(target);
403    }
404
405    /**
406     * Reads the named {@code public} {@link Field}. Superclasses will be considered.
407     *
408     * @param target
409     *            the object to reflect, must not be {@code null}.
410     * @param fieldName
411     *            the field name to obtain.
412     * @return the value of the field.
413     * @throws NullPointerException
414     *             if the target is {@code null}.
415     * @throws IllegalArgumentException
416     *             if the field name is {@code null}, blank, empty, or could not be found.
417     * @throws IllegalAccessException
418     *             if the named field is not {@code public}.
419     * @throws SecurityException if an underlying accessible object's method denies the request.
420     * @see SecurityManager#checkPermission
421     */
422    public static Object readField(final Object target, final String fieldName) throws IllegalAccessException {
423        return readField(target, fieldName, false);
424    }
425
426    /**
427     * Reads the named {@link Field}. Superclasses will be considered.
428     *
429     * @param target
430     *            the object to reflect, must not be {@code null}.
431     * @param fieldName
432     *            the field name to obtain.
433     * @param forceAccess
434     *            whether to break scope restrictions using the
435     *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
436     *            match {@code public} fields.
437     * @return the field value
438     * @throws NullPointerException
439     *             if {@code target} is {@code null}.
440     * @throws IllegalArgumentException
441     *             if the field name is {@code null}, blank, empty, or could not be found.
442     * @throws IllegalAccessException
443     *             if the named field is not made accessible.
444     * @throws SecurityException if an underlying accessible object's method denies the request.
445     * @see SecurityManager#checkPermission
446     */
447    public static Object readField(final Object target, final String fieldName, final boolean forceAccess) throws IllegalAccessException {
448        Objects.requireNonNull(target, "target");
449        final Class<?> cls = target.getClass();
450        final Field field = getField(cls, fieldName, forceAccess);
451        Validate.isTrue(field != null, "Cannot locate field %s on %s", fieldName, cls);
452        // already forced access above, don't repeat it here:
453        return readField(field, target, false);
454    }
455
456    /**
457     * Reads the named {@code public static} {@link Field}. Superclasses will be considered.
458     *
459     * @param cls
460     *            the {@link Class} to reflect, must not be {@code null}.
461     * @param fieldName
462     *            the field name to obtain.
463     * @return the value of the field.
464     * @throws NullPointerException
465     *             if the class is {@code null}, or the field could not be found.
466     * @throws IllegalArgumentException
467     *             if the field name is {@code null}, blank or empty, or is not {@code static}.
468     * @throws IllegalAccessException
469     *             if the field is not accessible.
470     * @throws SecurityException if an underlying accessible object's method denies the request.
471     * @see SecurityManager#checkPermission
472     */
473    public static Object readStaticField(final Class<?> cls, final String fieldName) throws IllegalAccessException {
474        return readStaticField(cls, fieldName, false);
475    }
476
477    /**
478     * Reads the named {@code static} {@link Field}. Superclasses will be considered.
479     *
480     * @param cls
481     *            the {@link Class} to reflect, must not be {@code null}.
482     * @param fieldName
483     *            the field name to obtain.
484     * @param forceAccess
485     *            whether to break scope restrictions using the
486     *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
487     *            match {@code public} fields.
488     * @return the Field object.
489     * @throws NullPointerException
490     *             if the class is {@code null}, or the field could not be found.
491     * @throws IllegalArgumentException
492     *             if the field name is {@code null}, blank or empty, or is not {@code static}.
493     * @throws IllegalAccessException
494     *             if the field is not made accessible.
495     * @throws SecurityException if an underlying accessible object's method denies the request.
496     * @see SecurityManager#checkPermission
497     */
498    public static Object readStaticField(final Class<?> cls, final String fieldName, final boolean forceAccess) throws IllegalAccessException {
499        final Field field = getField(cls, fieldName, forceAccess);
500        Validate.notNull(field, "Cannot locate field '%s' on %s", fieldName, cls);
501        // already forced access above, don't repeat it here:
502        return readStaticField(field, false);
503    }
504
505    /**
506     * Reads an accessible {@code static} {@link Field}.
507     *
508     * @param field
509     *            to read.
510     * @return the field value.
511     * @throws NullPointerException
512     *             if the field is {@code null}.
513     * @throws IllegalArgumentException
514     *             if the field is not {@code static}.
515     * @throws IllegalAccessException
516     *             if the field is not accessible
517     * @throws SecurityException if an underlying accessible object's method denies the request.
518     * @see SecurityManager#checkPermission
519     */
520    public static Object readStaticField(final Field field) throws IllegalAccessException {
521        return readStaticField(field, false);
522    }
523
524    /**
525     * Reads a static {@link Field}.
526     *
527     * @param field
528     *            to read.
529     * @param forceAccess
530     *            whether to break scope restrictions using the
531     *            {@link AccessibleObject#setAccessible(boolean)} method.
532     * @return the field value.
533     * @throws NullPointerException
534     *             if the field is {@code null}.
535     * @throws IllegalArgumentException
536     *             if the field is not {@code static}.
537     * @throws IllegalAccessException
538     *             if the field is not made accessible.
539     * @throws SecurityException if an underlying accessible object's method denies the request.
540     * @see SecurityManager#checkPermission
541     */
542    public static Object readStaticField(final Field field, final boolean forceAccess) throws IllegalAccessException {
543        Objects.requireNonNull(field, "field");
544        Validate.isTrue(MemberUtils.isStatic(field), "The field '%s' is not static", field.getName());
545        return readField(field, (Object) null, forceAccess);
546    }
547
548    /**
549     * Removes the final modifier from a {@link Field}.
550     *
551     * @param field
552     *            to remove the final modifier.
553     * @throws NullPointerException
554     *             if the field is {@code null}.
555     * @throws SecurityException if an underlying accessible object's method denies the request.
556     * @see SecurityManager#checkPermission
557     * @since 3.2
558     */
559    public static void removeFinalModifier(final Field field) {
560        removeFinalModifier(field, true);
561    }
562
563    /**
564     * Removes the final modifier from a {@link Field}.
565     *
566     * @param field
567     *            to remove the final modifier.
568     * @param forceAccess
569     *            whether to break scope restrictions using the
570     *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
571     *            match {@code public} fields.
572     * @throws NullPointerException
573     *             if the field is {@code null}.
574     * @throws SecurityException if an underlying accessible object's method denies the request.
575     * @see SecurityManager#checkPermission
576     * @deprecated As of Java 12, we can no longer drop the {@code final} modifier, thus
577     *             rendering this method obsolete. The JDK discussion about this change can be found
578     *             here: https://mail.openjdk.java.net/pipermail/core-libs-dev/2018-November/056486.html
579     * @since 3.3
580     */
581    @Deprecated
582    public static void removeFinalModifier(final Field field, final boolean forceAccess) {
583        Objects.requireNonNull(field, "field");
584        try {
585            if (Modifier.isFinal(field.getModifiers())) {
586                // Do all JREs implement Field with a private ivar called "modifiers"?
587                final Field modifiersField = Field.class.getDeclaredField("modifiers");
588                final boolean doForceAccess = forceAccess && !modifiersField.isAccessible();
589                if (doForceAccess) {
590                    modifiersField.setAccessible(true);
591                }
592                try {
593                    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
594                } finally {
595                    if (doForceAccess) {
596                        modifiersField.setAccessible(false);
597                    }
598                }
599            }
600        } catch (final NoSuchFieldException | IllegalAccessException e) {
601            if (SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_12)) {
602                throw new UnsupportedOperationException("In java 12+ final cannot be removed.", e);
603            }
604            // else no exception is thrown because we can modify final.
605        }
606    }
607
608    static Field setAccessible(final Field field, final boolean forceAccess) {
609        if (forceAccess && !field.isAccessible()) {
610            field.setAccessible(true);
611        } else {
612            MemberUtils.setAccessibleWorkaround(field);
613        }
614        return field;
615    }
616
617    /**
618     * Writes a {@code public} {@link Field}. Only the specified class will be considered.
619     *
620     * @param target
621     *            the object to reflect, must not be {@code null}.
622     * @param fieldName
623     *            the field name to obtain.
624     * @param value
625     *            the new value.
626     * @throws NullPointerException
627     *             if {@code target} is {@code null}.
628     * @throws IllegalArgumentException
629     *             if {@code fieldName} is {@code null}, blank or empty, or could not be found,
630     *             or {@code value} is not assignable.
631     * @throws IllegalAccessException
632     *             if the field is not made accessible
633     * @throws SecurityException if an underlying accessible object's method denies the request.
634     * @see SecurityManager#checkPermission
635     */
636    public static void writeDeclaredField(final Object target, final String fieldName, final Object value) throws IllegalAccessException {
637        writeDeclaredField(target, fieldName, value, false);
638    }
639
640    /**
641     * Writes a {@code public} {@link Field}. Only the specified class will be considered.
642     *
643     * @param target
644     *            the object to reflect, must not be {@code null}.
645     * @param fieldName
646     *            the field name to obtain.
647     * @param value
648     *            the new value.
649     * @param forceAccess
650     *            whether to break scope restrictions using the
651     *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
652     *            match {@code public} fields.
653     * @throws IllegalArgumentException
654     *             if {@code fieldName} is {@code null}, blank or empty, or could not be found,
655     *             or {@code value} is not assignable
656     * @throws IllegalAccessException
657     *             if the field is not made accessible
658     * @throws SecurityException if an underlying accessible object's method denies the request.
659     * @see SecurityManager#checkPermission
660     */
661    public static void writeDeclaredField(final Object target, final String fieldName, final Object value, final boolean forceAccess)
662            throws IllegalAccessException {
663        Objects.requireNonNull(target, "target");
664        final Class<?> cls = target.getClass();
665        final Field field = getDeclaredField(cls, fieldName, forceAccess);
666        Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName);
667        // already forced access above, don't repeat it here:
668        writeField(field, target, value, false);
669    }
670
671    /**
672     * Writes a named {@code public static} {@link Field}. Only the specified class will be considered.
673     *
674     * @param cls
675     *            {@link Class} on which the field is to be found.
676     * @param fieldName
677     *            to write.
678     * @param value
679     *            the new value.
680     * @throws NullPointerException
681     *             if {@code cls} is {@code null} or the field cannot be located.
682     * @throws IllegalArgumentException
683     *             if the field name is {@code null}, blank, empty, not {@code static}, or {@code value} is not assignable.
684     * @throws IllegalAccessException
685     *             if the field is not {@code public} or is {@code final}
686     * @throws SecurityException if an underlying accessible object's method denies the request.
687     * @see SecurityManager#checkPermission
688     */
689    public static void writeDeclaredStaticField(final Class<?> cls, final String fieldName, final Object value) throws IllegalAccessException {
690        writeDeclaredStaticField(cls, fieldName, value, false);
691    }
692
693    /**
694     * Writes a named {@code static} {@link Field}. Only the specified class will be considered.
695     *
696     * @param cls
697     *            {@link Class} on which the field is to be found.
698     * @param fieldName
699     *            to write
700     * @param value
701     *            the new value.
702     * @param forceAccess
703     *            whether to break scope restrictions using the {@code AccessibleObject#setAccessible(boolean)} method.
704     *            {@code false} will only match {@code public} fields.
705     * @throws NullPointerException
706     *             if {@code cls} is {@code null} or the field cannot be located.
707     * @throws IllegalArgumentException
708     *             if the field name is {@code null}, blank, empty, not {@code static}, or {@code value} is not assignable.
709     * @throws IllegalAccessException
710     *             if the field is not made accessible or is {@code final}
711     * @throws SecurityException if an underlying accessible object's method denies the request.
712     * @see SecurityManager#checkPermission
713     */
714    public static void writeDeclaredStaticField(final Class<?> cls, final String fieldName, final Object value, final boolean forceAccess)
715            throws IllegalAccessException {
716        final Field field = getDeclaredField(cls, fieldName, forceAccess);
717        Validate.notNull(field, "Cannot locate declared field %s.%s", cls.getName(), fieldName);
718        // already forced access above, don't repeat it here:
719        writeField(field, (Object) null, value, false);
720    }
721
722    /**
723     * Writes an accessible {@link Field}.
724     *
725     * @param field
726     *            to write.
727     * @param target
728     *            the object to call on, may be {@code null} for {@code static} fields.
729     * @param value
730     *            the new value.
731     * @throws NullPointerException
732     *             if the field is {@code null}.
733     * @throws IllegalArgumentException
734     *             if {@code value} is not assignable.
735     * @throws IllegalAccessException
736     *             if the field is not accessible or is {@code final}.
737     * @throws SecurityException if an underlying accessible object's method denies the request.
738     * @see SecurityManager#checkPermission
739     */
740    public static void writeField(final Field field, final Object target, final Object value) throws IllegalAccessException {
741        writeField(field, target, value, false);
742    }
743
744    /**
745     * Writes a {@link Field}.
746     *
747     * @param field
748     *            to write.
749     * @param target
750     *            the object to call on, may be {@code null} for {@code static} fields
751     * @param value
752     *            the new value.
753     * @param forceAccess
754     *            whether to break scope restrictions using the
755     *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
756     *            match {@code public} fields.
757     * @throws NullPointerException
758     *             if the field is {@code null}.
759     * @throws IllegalArgumentException
760     *             if {@code value} is not assignable.
761     * @throws IllegalAccessException
762     *             if the field is not made accessible or is {@code final}
763     * @throws SecurityException if an underlying accessible object's method denies the request.
764     * @see SecurityManager#checkPermission
765     */
766    public static void writeField(final Field field, final Object target, final Object value, final boolean forceAccess)
767            throws IllegalAccessException {
768        Objects.requireNonNull(field, "field");
769        setAccessible(field, forceAccess).set(target, value);
770    }
771
772    /**
773     * Writes a {@code public} {@link Field}. Superclasses will be considered.
774     *
775     * @param target
776     *            the object to reflect, must not be {@code null}.
777     * @param fieldName
778     *            the field name to obtain.
779     * @param value
780     *            the new value.
781     * @throws NullPointerException
782     *             if {@code target} is {@code null}.
783     * @throws IllegalArgumentException
784     *             if {@code fieldName} is {@code null}, blank, empty, or could not be found,
785     *             or {@code value} is not assignable.
786     * @throws IllegalAccessException
787     *             if the field is not accessible.
788     * @throws SecurityException if an underlying accessible object's method denies the request.
789     * @see SecurityManager#checkPermission
790     */
791    public static void writeField(final Object target, final String fieldName, final Object value) throws IllegalAccessException {
792        writeField(target, fieldName, value, false);
793    }
794
795    /**
796     * Writes a {@link Field}. Superclasses will be considered.
797     *
798     * @param target
799     *            the object to reflect, must not be {@code null}.
800     * @param fieldName
801     *            the field name to obtain.
802     * @param value
803     *            the new value.
804     * @param forceAccess
805     *            whether to break scope restrictions using the
806     *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
807     *            match {@code public} fields.
808     * @throws NullPointerException
809     *             if {@code target} is {@code null}.
810     * @throws IllegalArgumentException
811     *             if {@code fieldName} is {@code null}, blank, empty, or could not be found,
812     *             or {@code value} is not assignable.
813     * @throws IllegalAccessException
814     *             if the field is not made accessible.
815     * @throws SecurityException if an underlying accessible object's method denies the request.
816     * @see SecurityManager#checkPermission
817     */
818    public static void writeField(final Object target, final String fieldName, final Object value, final boolean forceAccess)
819            throws IllegalAccessException {
820        Objects.requireNonNull(target, "target");
821        final Class<?> cls = target.getClass();
822        final Field field = getField(cls, fieldName, forceAccess);
823        Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName);
824        // already forced access above, don't repeat it here:
825        writeField(field, target, value, false);
826    }
827
828    /**
829     * Writes a named {@code public static} {@link Field}. Superclasses will be considered.
830     *
831     * @param cls
832     *            {@link Class} on which the field is to be found.
833     * @param fieldName
834     *            to write.
835     * @param value
836     *            the new value.
837     * @throws NullPointerException
838     *             if {@code target} is {@code null}.
839     * @throws IllegalArgumentException
840     *             if {@code fieldName} is {@code null}, blank or empty, the field cannot be located or is
841     *             not {@code static}, or {@code value} is not assignable.
842     * @throws IllegalAccessException
843     *             if the field is not {@code public} or is {@code final}
844     * @throws SecurityException if an underlying accessible object's method denies the request.
845     * @see SecurityManager#checkPermission
846     */
847    public static void writeStaticField(final Class<?> cls, final String fieldName, final Object value) throws IllegalAccessException {
848        writeStaticField(cls, fieldName, value, false);
849    }
850
851    /**
852     * Writes a named {@code static} {@link Field}. Superclasses will be considered.
853     *
854     * @param cls
855     *            {@link Class} on which the field is to be found.
856     * @param fieldName
857     *            to write.
858     * @param value
859     *            the new value.
860     * @param forceAccess
861     *            whether to break scope restrictions using the
862     *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
863     *            match {@code public} fields.
864     * @throws NullPointerException
865     *             if {@code cls} is {@code null} or the field cannot be located.
866     * @throws IllegalArgumentException
867     *             if {@code fieldName} is {@code null}, blank or empty, the field not {@code static}, or {@code value} is not assignable.
868     * @throws IllegalAccessException
869     *             if the field is not made accessible or is {@code final}.
870     * @throws SecurityException if an underlying accessible object's method denies the request.
871     * @see SecurityManager#checkPermission
872     */
873    public static void writeStaticField(final Class<?> cls, final String fieldName, final Object value, final boolean forceAccess)
874            throws IllegalAccessException {
875        final Field field = getField(cls, fieldName, forceAccess);
876        Validate.notNull(field, "Cannot locate field %s on %s", fieldName, cls);
877        // already forced access above, don't repeat it here:
878        writeStaticField(field, value, false);
879    }
880
881    /**
882     * Writes a {@code public static} {@link Field}.
883     *
884     * @param field
885     *            to write.
886     * @param value
887     *            the new value.
888     * @throws NullPointerException
889     *              if the field is {@code null}.
890     * @throws IllegalArgumentException
891     *              if the field is not {@code static}, or {@code value} is not assignable.
892     * @throws IllegalAccessException
893     *             if the field is not {@code public} or is {@code final}.
894     * @throws SecurityException if an underlying accessible object's method denies the request.
895     * @see SecurityManager#checkPermission
896     */
897    public static void writeStaticField(final Field field, final Object value) throws IllegalAccessException {
898        writeStaticField(field, value, false);
899    }
900
901    /**
902     * Writes a static {@link Field}.
903     *
904     * @param field
905     *            to write.
906     * @param value
907     *            the new value.
908     * @param forceAccess
909     *            whether to break scope restrictions using the
910     *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
911     *            match {@code public} fields.
912     * @throws NullPointerException
913     *              if the field is {@code null}.
914     * @throws IllegalArgumentException
915     *              if the field is not {@code static}, or {@code value} is not assignable.
916     * @throws IllegalAccessException
917     *             if the field is not made accessible or is {@code final}
918     * @throws SecurityException if an underlying accessible object's method denies the request.
919     * @see SecurityManager#checkPermission
920     */
921    public static void writeStaticField(final Field field, final Object value, final boolean forceAccess) throws IllegalAccessException {
922        Objects.requireNonNull(field, "field");
923        Validate.isTrue(MemberUtils.isStatic(field), "The field %s.%s is not static", field.getDeclaringClass().getName(),
924                field.getName());
925        writeField(field, (Object) null, value, forceAccess);
926    }
927
928    /**
929     * {@link FieldUtils} instances should NOT be constructed in standard programming.
930     * <p>
931     * This constructor is {@code public} to permit tools that require a JavaBean instance to operate.
932     * </p>
933     *
934     * @deprecated TODO Make private in 4.0.
935     */
936    @Deprecated
937    public FieldUtils() {
938        // empty
939    }
940}