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