mirror of
https://github.com/apache/commons-lang.git
synced 2025-03-01 05:29:11 +00:00
merge [LANG-416] from LANG_POST_2_4 branch
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@653918 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
504af2f2ed
commit
04e9eb14e7
340
src/java/org/apache/commons/lang/reflect/ConstructorUtils.java
Normal file
340
src/java/org/apache/commons/lang/reflect/ConstructorUtils.java
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.ArrayUtils;
|
||||||
|
import org.apache.commons.lang.ClassUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p> Utility reflection methods focussed on constructors, modelled after {@link MethodUtils}. </p>
|
||||||
|
*
|
||||||
|
* <h3>Known Limitations</h3>
|
||||||
|
* <h4>Accessing Public Constructors In A Default Access Superclass</h4>
|
||||||
|
* <p>There is an issue when invoking public constructors contained in a default access superclass.
|
||||||
|
* Reflection locates these constructors fine and correctly assigns them as public.
|
||||||
|
* However, an <code>IllegalAccessException</code> is thrown if the constructors is invoked.</p>
|
||||||
|
*
|
||||||
|
* <p><code>ConstructorUtils</code> contains a workaround for this situation.
|
||||||
|
* It will attempt to call <code>setAccessible</code> on this constructor.
|
||||||
|
* If this call succeeds, then the method can be invoked as normal.
|
||||||
|
* This call will only succeed when the application has sufficient security privilages.
|
||||||
|
* If this call fails then a warning will be logged and the method may fail.</p>
|
||||||
|
*
|
||||||
|
* @author Craig R. McClanahan
|
||||||
|
* @author Ralph Schaer
|
||||||
|
* @author Chris Audley
|
||||||
|
* @author Rey Francois
|
||||||
|
* @author Gregor Rayman
|
||||||
|
* @author Jan Sorensen
|
||||||
|
* @author Robert Burrell Donkin
|
||||||
|
* @author Rodney Waldhoff
|
||||||
|
* @since 2.5
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class ConstructorUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>ConstructorUtils instances should NOT be constructed in standard programming.
|
||||||
|
* Instead, the class should be used as
|
||||||
|
* <code>ConstructorUtils.invokeConstructor(cls, args)</code>.</p>
|
||||||
|
*
|
||||||
|
* <p>This constructor is public to permit tools that require a JavaBean
|
||||||
|
* instance to operate.</p>
|
||||||
|
*/
|
||||||
|
public ConstructorUtils() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Convenience method returning new instance of <code>klazz</code> using a single argument constructor.
|
||||||
|
* The formal parameter type is inferred from the actual values of <code>arg</code>.
|
||||||
|
* See {@link #invokeExactConstructor(Class, Object[], Class[])} for more details.</p>
|
||||||
|
*
|
||||||
|
* <p>The signatures should be assignment compatible.</p>
|
||||||
|
*
|
||||||
|
* @param cls the class to be constructed.
|
||||||
|
* @param arg the actual argument
|
||||||
|
* @return new instance of <code>klazz</code>
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException If the constructor cannot be found
|
||||||
|
* @throws IllegalAccessException If an error occurs accessing the constructor
|
||||||
|
* @throws InvocationTargetException If an error occurs invoking the constructor
|
||||||
|
* @throws InstantiationException If an error occurs instantiating the class
|
||||||
|
*
|
||||||
|
* @see #invokeConstructor(java.lang.Class, java.lang.Object[], java.lang.Class[])
|
||||||
|
*/
|
||||||
|
public static Object invokeConstructor(Class cls, Object arg)
|
||||||
|
throws NoSuchMethodException, IllegalAccessException,
|
||||||
|
InvocationTargetException, InstantiationException {
|
||||||
|
return invokeConstructor(cls, new Object[] { arg });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Returns new instance of <code>klazz</code> created using the actual arguments <code>args</code>.
|
||||||
|
* The formal parameter types are inferred from the actual values of <code>args</code>.
|
||||||
|
* See {@link #invokeExactConstructor(Class, Object[], Class[])} for more details.</p>
|
||||||
|
*
|
||||||
|
* <p>The signatures should be assignment compatible.</p>
|
||||||
|
*
|
||||||
|
* @param cls the class to be constructed.
|
||||||
|
* @param args actual argument array
|
||||||
|
* @return new instance of <code>klazz</code>
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException If the constructor cannot be found
|
||||||
|
* @throws IllegalAccessException If an error occurs accessing the constructor
|
||||||
|
* @throws InvocationTargetException If an error occurs invoking the constructor
|
||||||
|
* @throws InstantiationException If an error occurs instantiating the class
|
||||||
|
*
|
||||||
|
* @see #invokeConstructor(java.lang.Class, java.lang.Object[], java.lang.Class[])
|
||||||
|
*/
|
||||||
|
public static Object invokeConstructor(Class cls, Object[] args)
|
||||||
|
throws NoSuchMethodException, IllegalAccessException,
|
||||||
|
InvocationTargetException, InstantiationException {
|
||||||
|
if (null == args) {
|
||||||
|
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
|
||||||
|
}
|
||||||
|
Class parameterTypes[] = new Class[args.length];
|
||||||
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
parameterTypes[i] = args[i].getClass();
|
||||||
|
}
|
||||||
|
return invokeConstructor(cls, args, parameterTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Returns new instance of <code>klazz</code> created using constructor
|
||||||
|
* with signature <code>parameterTypes</code> and actual arguments <code>args</code>.</p>
|
||||||
|
*
|
||||||
|
* <p>The signatures should be assignment compatible.</p>
|
||||||
|
*
|
||||||
|
* @param cls the class to be constructed.
|
||||||
|
* @param args actual argument array
|
||||||
|
* @param parameterTypes parameter types array
|
||||||
|
* @return new instance of <code>klazz</code>
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException if matching constructor cannot be found
|
||||||
|
* @throws IllegalAccessException thrown on the constructor's invocation
|
||||||
|
* @throws InvocationTargetException thrown on the constructor's invocation
|
||||||
|
* @throws InstantiationException thrown on the constructor's invocation
|
||||||
|
* @see Constructor#newInstance
|
||||||
|
*/
|
||||||
|
public static Object invokeConstructor(Class cls, Object[] args,
|
||||||
|
Class[] parameterTypes) throws NoSuchMethodException,
|
||||||
|
IllegalAccessException, InvocationTargetException,
|
||||||
|
InstantiationException {
|
||||||
|
if (parameterTypes == null) {
|
||||||
|
parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
|
||||||
|
}
|
||||||
|
if (args == null) {
|
||||||
|
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
|
||||||
|
}
|
||||||
|
Constructor ctor = getMatchingAccessibleConstructor(cls, parameterTypes);
|
||||||
|
if (null == ctor) {
|
||||||
|
throw new NoSuchMethodException(
|
||||||
|
"No such accessible constructor on object: "
|
||||||
|
+ cls.getName());
|
||||||
|
}
|
||||||
|
return ctor.newInstance(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Convenience method returning new instance of <code>klazz</code> using a single argument constructor.
|
||||||
|
* The formal parameter type is inferred from the actual values of <code>arg</code>.
|
||||||
|
* See {@link #invokeExactConstructor(Class, Object[], Class[])} for more details.</p>
|
||||||
|
*
|
||||||
|
* <p>The signatures should match exactly.</p>
|
||||||
|
*
|
||||||
|
* @param cls the class to be constructed.
|
||||||
|
* @param arg the actual argument
|
||||||
|
* @return new instance of <code>klazz</code>
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException If the constructor cannot be found
|
||||||
|
* @throws IllegalAccessException If an error occurs accessing the constructor
|
||||||
|
* @throws InvocationTargetException If an error occurs invoking the constructor
|
||||||
|
* @throws InstantiationException If an error occurs instantiating the class
|
||||||
|
*
|
||||||
|
* @see #invokeExactConstructor(java.lang.Class, java.lang.Object[], java.lang.Class[])
|
||||||
|
*/
|
||||||
|
public static Object invokeExactConstructor(Class cls, Object arg)
|
||||||
|
throws NoSuchMethodException, IllegalAccessException,
|
||||||
|
InvocationTargetException, InstantiationException {
|
||||||
|
return invokeExactConstructor(cls, new Object[] { arg });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Returns new instance of <code>klazz</code> created using the actual arguments <code>args</code>.
|
||||||
|
* The formal parameter types are inferred from the actual values of <code>args</code>.
|
||||||
|
* See {@link #invokeExactConstructor(Class, Object[], Class[])} for more details.</p>
|
||||||
|
*
|
||||||
|
* <p>The signatures should match exactly.</p>
|
||||||
|
*
|
||||||
|
* @param cls the class to be constructed.
|
||||||
|
* @param args actual argument array
|
||||||
|
* @return new instance of <code>klazz</code>
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException If the constructor cannot be found
|
||||||
|
* @throws IllegalAccessException If an error occurs accessing the constructor
|
||||||
|
* @throws InvocationTargetException If an error occurs invoking the constructor
|
||||||
|
* @throws InstantiationException If an error occurs instantiating the class
|
||||||
|
*
|
||||||
|
* @see #invokeExactConstructor(java.lang.Class, java.lang.Object[], java.lang.Class[])
|
||||||
|
*/
|
||||||
|
public static Object invokeExactConstructor(Class cls, Object[] args)
|
||||||
|
throws NoSuchMethodException, IllegalAccessException,
|
||||||
|
InvocationTargetException, InstantiationException {
|
||||||
|
if (null == args) {
|
||||||
|
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
|
||||||
|
}
|
||||||
|
int arguments = args.length;
|
||||||
|
Class parameterTypes[] = new Class[arguments];
|
||||||
|
for (int i = 0; i < arguments; i++) {
|
||||||
|
parameterTypes[i] = args[i].getClass();
|
||||||
|
}
|
||||||
|
return invokeExactConstructor(cls, args, parameterTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Returns new instance of <code>klazz</code> created using constructor
|
||||||
|
* with signature <code>parameterTypes</code> and actual arguments
|
||||||
|
* <code>args</code>.</p>
|
||||||
|
*
|
||||||
|
* <p>The signatures should match exactly.</p>
|
||||||
|
*
|
||||||
|
* @param cls the class to be constructed.
|
||||||
|
* @param args actual argument array
|
||||||
|
* @param parameterTypes parameter types array
|
||||||
|
* @return new instance of <code>klazz</code>
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException if matching constructor cannot be found
|
||||||
|
* @throws IllegalAccessException thrown on the constructor's invocation
|
||||||
|
* @throws InvocationTargetException thrown on the constructor's invocation
|
||||||
|
* @throws InstantiationException thrown on the constructor's invocation
|
||||||
|
* @see Constructor#newInstance
|
||||||
|
*/
|
||||||
|
public static Object invokeExactConstructor(Class cls, Object[] args,
|
||||||
|
Class[] parameterTypes) throws NoSuchMethodException,
|
||||||
|
IllegalAccessException, InvocationTargetException,
|
||||||
|
InstantiationException {
|
||||||
|
if (args == null) {
|
||||||
|
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
|
||||||
|
}
|
||||||
|
if (parameterTypes == null) {
|
||||||
|
parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
|
||||||
|
}
|
||||||
|
Constructor ctor = getAccessibleConstructor(cls, parameterTypes);
|
||||||
|
if (null == ctor) {
|
||||||
|
throw new NoSuchMethodException(
|
||||||
|
"No such accessible constructor on object: "
|
||||||
|
+ cls.getName());
|
||||||
|
}
|
||||||
|
return ctor.newInstance(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a constructor with single argument.
|
||||||
|
* @param cls the class to be constructed
|
||||||
|
* @param parameterType The constructor parameter type
|
||||||
|
* @return null if matching accessible constructor can not be found.
|
||||||
|
* @see Class#getConstructor
|
||||||
|
* @see #getAccessibleConstructor(java.lang.reflect.Constructor)
|
||||||
|
*/
|
||||||
|
public static Constructor getAccessibleConstructor(Class cls,
|
||||||
|
Class parameterType) {
|
||||||
|
return getAccessibleConstructor(cls, new Class[] { parameterType });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a constructor given a class and signature.
|
||||||
|
* @param cls the class to be constructed
|
||||||
|
* @param parameterTypes the parameter array
|
||||||
|
* @return null if matching accessible constructor can not be found
|
||||||
|
* @see Class#getConstructor
|
||||||
|
* @see #getAccessibleConstructor(java.lang.reflect.Constructor)
|
||||||
|
*/
|
||||||
|
public static Constructor getAccessibleConstructor(Class cls,
|
||||||
|
Class[] parameterTypes) {
|
||||||
|
try {
|
||||||
|
return getAccessibleConstructor(cls.getConstructor(parameterTypes));
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns accessible version of the given constructor.
|
||||||
|
* @param ctor prototype constructor object.
|
||||||
|
* @return <code>null</code> if accessible constructor can not be found.
|
||||||
|
* @see java.lang.SecurityManager
|
||||||
|
*/
|
||||||
|
public static Constructor getAccessibleConstructor(Constructor ctor) {
|
||||||
|
return MemberUtils.isAccessible(ctor)
|
||||||
|
&& Modifier.isPublic(ctor.getDeclaringClass().getModifiers()) ? ctor
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Find an accessible constructor with compatible parameters.
|
||||||
|
* Compatible parameters mean that every method parameter is assignable from
|
||||||
|
* the given parameters. In other words, it finds constructor that will take
|
||||||
|
* the parameters given.</p>
|
||||||
|
*
|
||||||
|
* <p>First it checks if there is constructor matching the exact signature.
|
||||||
|
* If no such, all the constructors of the class are tested if their signatures
|
||||||
|
* are assignment compatible with the parameter types.
|
||||||
|
* The first matching constructor is returned.</p>
|
||||||
|
*
|
||||||
|
* @param cls find constructor for this class
|
||||||
|
* @param parameterTypes find method with compatible parameters
|
||||||
|
* @return a valid Constructor object. If there's no matching constructor, returns <code>null</code>.
|
||||||
|
*/
|
||||||
|
public static Constructor getMatchingAccessibleConstructor(Class cls,
|
||||||
|
Class[] parameterTypes) {
|
||||||
|
// see if we can find the constructor directly
|
||||||
|
// most of the time this works and it's much faster
|
||||||
|
try {
|
||||||
|
Constructor ctor = cls.getConstructor(parameterTypes);
|
||||||
|
MemberUtils.setAccessibleWorkaround(ctor);
|
||||||
|
return ctor;
|
||||||
|
} catch (NoSuchMethodException e) { /* SWALLOW */
|
||||||
|
}
|
||||||
|
Constructor result = null;
|
||||||
|
// search through all constructors
|
||||||
|
Constructor[] ctors = cls.getConstructors();
|
||||||
|
for (int i = 0; i < ctors.length; i++) {
|
||||||
|
// compare parameters
|
||||||
|
if (ClassUtils.isAssignable(parameterTypes, ctors[i]
|
||||||
|
.getParameterTypes(), true)) {
|
||||||
|
// get accessible version of method
|
||||||
|
Constructor ctor = getAccessibleConstructor(ctors[i]);
|
||||||
|
if (ctor != null) {
|
||||||
|
MemberUtils.setAccessibleWorkaround(ctor);
|
||||||
|
if (result == null
|
||||||
|
|| MemberUtils.compareParameterTypes(ctor
|
||||||
|
.getParameterTypes(), result
|
||||||
|
.getParameterTypes(), parameterTypes) < 0) {
|
||||||
|
result = ctor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
605
src/java/org/apache/commons/lang/reflect/FieldUtils.java
Normal file
605
src/java/org/apache/commons/lang/reflect/FieldUtils.java
Normal file
@ -0,0 +1,605 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilities for working with fields by reflection. Adapted and refactored
|
||||||
|
* from the dormant [reflect] Commons sandbox component.
|
||||||
|
* <p>
|
||||||
|
* The ability is provided to break the scoping restrictions coded by the
|
||||||
|
* programmer. This can allow fields to be changed that shouldn't be. This
|
||||||
|
* facility should be used with care.
|
||||||
|
*
|
||||||
|
* @author Stephen Colebourne
|
||||||
|
* @author Matt Benson
|
||||||
|
* @since 2.5
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class FieldUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FieldUtils instances should NOT be constructed in standard programming.
|
||||||
|
* <p>
|
||||||
|
* This constructor is public to permit tools that require a JavaBean instance
|
||||||
|
* to operate.
|
||||||
|
*/
|
||||||
|
public FieldUtils() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an accessible <code>Field</code> by name repecting scope.
|
||||||
|
* Superclasses/interfaces will be considered.
|
||||||
|
*
|
||||||
|
* @param cls the class to reflect, must not be null
|
||||||
|
* @param fieldName the field name to obtain
|
||||||
|
* @return the Field object
|
||||||
|
* @throws IllegalArgumentException if the class or field name is null
|
||||||
|
*/
|
||||||
|
public static Field getField(Class cls, String fieldName) {
|
||||||
|
Field field = getField(cls, fieldName, false);
|
||||||
|
MemberUtils.setAccessibleWorkaround(field);
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an accessible <code>Field</code> by name breaking scope
|
||||||
|
* if requested. Superclasses/interfaces will be considered.
|
||||||
|
*
|
||||||
|
* @param cls the class to reflect, must not be null
|
||||||
|
* @param fieldName the field name to obtain
|
||||||
|
* @param forceAccess whether to break scope restrictions using the
|
||||||
|
* <code>setAccessible</code> method. <code>False</code> will only
|
||||||
|
* match public fields.
|
||||||
|
* @return the Field object
|
||||||
|
* @throws IllegalArgumentException if the class or field name is null
|
||||||
|
*/
|
||||||
|
public static Field getField(final Class cls, String fieldName, boolean forceAccess) {
|
||||||
|
if (cls == null) {
|
||||||
|
throw new IllegalArgumentException("The class must not be null");
|
||||||
|
}
|
||||||
|
if (fieldName == null) {
|
||||||
|
throw new IllegalArgumentException("The field name must not be null");
|
||||||
|
}
|
||||||
|
// Sun Java 1.3 has a bugged implementation of getField hence we write the
|
||||||
|
// code ourselves
|
||||||
|
|
||||||
|
// getField() will return the Field object with the declaring class
|
||||||
|
// set correctly to the class that declares the field. Thus requesting the
|
||||||
|
// field on a subclass will return the field from the superclass.
|
||||||
|
//
|
||||||
|
// priority order for lookup:
|
||||||
|
// searchclass private/protected/package/public
|
||||||
|
// superclass protected/package/public
|
||||||
|
// private/different package blocks access to further superclasses
|
||||||
|
// implementedinterface public
|
||||||
|
|
||||||
|
// check up the superclass hierarchy
|
||||||
|
for (Class acls = cls; acls != null; acls = acls.getSuperclass()) {
|
||||||
|
try {
|
||||||
|
Field field = acls.getDeclaredField(fieldName);
|
||||||
|
// getDeclaredField checks for non-public scopes as well
|
||||||
|
// and it returns accurate results
|
||||||
|
if (!Modifier.isPublic(field.getModifiers())) {
|
||||||
|
if (forceAccess) {
|
||||||
|
field.setAccessible(true);
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
} catch (NoSuchFieldException ex) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check the public interface case. This must be manually searched for
|
||||||
|
// incase there is a public supersuperclass field hidden by a private/package
|
||||||
|
// superclass field.
|
||||||
|
Field match = null;
|
||||||
|
for (Class acls = cls; acls != null; acls = acls.getSuperclass()) {
|
||||||
|
Class[] ints = acls.getInterfaces();
|
||||||
|
for (int i = 0; i < ints.length; i++) {
|
||||||
|
// getField is fine here, because everything is public, and thus it works
|
||||||
|
try {
|
||||||
|
Field test = ints[i].getField(fieldName);
|
||||||
|
if (match != null) {
|
||||||
|
if (match.getDeclaringClass().equals(test.getDeclaringClass())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Reference to field "
|
||||||
|
+ fieldName
|
||||||
|
+ " is ambiguous relative to "
|
||||||
|
+ cls
|
||||||
|
+ "; a matching field exists on two or more parent interfaces.");
|
||||||
|
}
|
||||||
|
match = test;
|
||||||
|
} catch (NoSuchFieldException ex) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an accessible <code>Field</code> by name respecting scope.
|
||||||
|
* Only the specified class will be considered.
|
||||||
|
*
|
||||||
|
* @param cls the class to reflect, must not be null
|
||||||
|
* @param fieldName the field name to obtain
|
||||||
|
* @return the Field object
|
||||||
|
* @throws IllegalArgumentException if the class or field name is null
|
||||||
|
*/
|
||||||
|
public static Field getDeclaredField(Class cls, String fieldName) {
|
||||||
|
return getDeclaredField(cls, fieldName, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an accessible <code>Field</code> by name breaking scope
|
||||||
|
* if requested. Only the specified class will be considered.
|
||||||
|
*
|
||||||
|
* @param cls the class to reflect, must not be null
|
||||||
|
* @param fieldName the field name to obtain
|
||||||
|
* @param forceAccess whether to break scope restrictions using the
|
||||||
|
* <code>setAccessible</code> method. False will only match public fields.
|
||||||
|
* @return the Field object
|
||||||
|
* @throws IllegalArgumentException if the class or field name is null
|
||||||
|
*/
|
||||||
|
public static Field getDeclaredField(Class cls, String fieldName, boolean forceAccess) {
|
||||||
|
if (cls == null) {
|
||||||
|
throw new IllegalArgumentException("The class must not be null");
|
||||||
|
}
|
||||||
|
if (fieldName == null) {
|
||||||
|
throw new IllegalArgumentException("The field name must not be null");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// only consider the specified class by using getDeclaredField()
|
||||||
|
Field field = cls.getDeclaredField(fieldName);
|
||||||
|
if (!MemberUtils.isAccessible(field)) {
|
||||||
|
if (forceAccess) {
|
||||||
|
field.setAccessible(true);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read an accessible static Field.
|
||||||
|
* @param field to read
|
||||||
|
* @return the field value
|
||||||
|
* @throws IllegalArgumentException if the field is null or not static
|
||||||
|
* @throws IllegalAccessException if the field is not accessible
|
||||||
|
*/
|
||||||
|
public static Object readStaticField(Field field) throws IllegalAccessException {
|
||||||
|
return readStaticField(field, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a static Field.
|
||||||
|
* @param field to read
|
||||||
|
* @param forceAccess whether to break scope restrictions using the
|
||||||
|
* <code>setAccessible</code> method.
|
||||||
|
* @return the field value
|
||||||
|
* @throws IllegalArgumentException if the field is null or not static
|
||||||
|
* @throws IllegalAccessException if the field is not made accessible
|
||||||
|
*/
|
||||||
|
public static Object readStaticField(Field field, boolean forceAccess) throws IllegalAccessException {
|
||||||
|
if (field == null) {
|
||||||
|
throw new IllegalArgumentException("The field must not be null");
|
||||||
|
}
|
||||||
|
if (!Modifier.isStatic(field.getModifiers())) {
|
||||||
|
throw new IllegalArgumentException("The field '" + field.getName() + "' is not static");
|
||||||
|
}
|
||||||
|
return readField(field, (Object) null, forceAccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the named public static field. Superclasses will be considered.
|
||||||
|
* @param cls the class to reflect, must not be null
|
||||||
|
* @param fieldName the field name to obtain
|
||||||
|
* @return the value of the field
|
||||||
|
* @throws IllegalArgumentException if the class or field name is null
|
||||||
|
* @throws IllegalAccessException if the field is not accessible
|
||||||
|
*/
|
||||||
|
public static Object readStaticField(Class cls, String fieldName) throws IllegalAccessException {
|
||||||
|
return readStaticField(cls, fieldName, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the named static field. Superclasses will be considered.
|
||||||
|
* @param cls the class to reflect, must not be null
|
||||||
|
* @param fieldName the field name to obtain
|
||||||
|
* @param forceAccess whether to break scope restrictions using the
|
||||||
|
* <code>setAccessible</code> method. <code>False</code> will only
|
||||||
|
* match public fields.
|
||||||
|
* @return the Field object
|
||||||
|
* @throws IllegalArgumentException if the class or field name is null
|
||||||
|
* @throws IllegalAccessException if the field is not made accessible
|
||||||
|
*/
|
||||||
|
public static Object readStaticField(Class cls, String fieldName, boolean forceAccess) throws IllegalAccessException {
|
||||||
|
Field field = getField(cls, fieldName, forceAccess);
|
||||||
|
if (field == null) {
|
||||||
|
throw new IllegalArgumentException("Cannot locate field " + fieldName + " on " + cls);
|
||||||
|
}
|
||||||
|
//already forced access above, don't repeat it here:
|
||||||
|
return readStaticField(field, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a static Field value by name. The field must be public.
|
||||||
|
* Only the specified class will be considered.
|
||||||
|
*
|
||||||
|
* @param cls the class to reflect, must not be null
|
||||||
|
* @param fieldName the field name to obtain
|
||||||
|
* @return the value of the field
|
||||||
|
* @throws IllegalArgumentException if the class or field name is null
|
||||||
|
* @throws IllegalAccessException if the field is not accessible
|
||||||
|
*/
|
||||||
|
public static Object readDeclaredStaticField(Class cls, String fieldName) throws IllegalAccessException {
|
||||||
|
return readDeclaredStaticField(cls, fieldName, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a static Field value by name. Only the specified class will
|
||||||
|
* be considered.
|
||||||
|
*
|
||||||
|
* @param cls the class to reflect, must not be null
|
||||||
|
* @param fieldName the field name to obtain
|
||||||
|
* @param forceAccess whether to break scope restrictions using the
|
||||||
|
* <code>setAccessible</code> method. <code>False</code> will only
|
||||||
|
* match public fields.
|
||||||
|
* @return the Field object
|
||||||
|
* @throws IllegalArgumentException if the class or field name is null
|
||||||
|
* @throws IllegalAccessException if the field is not made accessible
|
||||||
|
*/
|
||||||
|
public static Object readDeclaredStaticField(Class cls, String fieldName, boolean forceAccess)
|
||||||
|
throws IllegalAccessException {
|
||||||
|
Field field = getDeclaredField(cls, fieldName, forceAccess);
|
||||||
|
if (field == null) {
|
||||||
|
throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
|
||||||
|
}
|
||||||
|
//already forced access above, don't repeat it here:
|
||||||
|
return readStaticField(field, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read an accessible Field.
|
||||||
|
* @param field the field to use
|
||||||
|
* @param target the object to call on, may be null for static fields
|
||||||
|
* @return the field value
|
||||||
|
* @throws IllegalArgumentException if the field is null
|
||||||
|
* @throws IllegalAccessException if the field is not accessible
|
||||||
|
*/
|
||||||
|
public static Object readField(Field field, Object target) throws IllegalAccessException {
|
||||||
|
return readField(field, target, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a Field.
|
||||||
|
* @param field the field to use
|
||||||
|
* @param target the object to call on, may be null for static fields
|
||||||
|
* @param forceAccess whether to break scope restrictions using the
|
||||||
|
* <code>setAccessible</code> method.
|
||||||
|
* @return the field value
|
||||||
|
* @throws IllegalArgumentException if the field is null
|
||||||
|
* @throws IllegalAccessException if the field is not made accessible
|
||||||
|
*/
|
||||||
|
public static Object readField(Field field, Object target, boolean forceAccess) throws IllegalAccessException {
|
||||||
|
if (field == null) {
|
||||||
|
throw new IllegalArgumentException("The field must not be null");
|
||||||
|
}
|
||||||
|
if (forceAccess && !field.isAccessible()) {
|
||||||
|
field.setAccessible(true);
|
||||||
|
} else {
|
||||||
|
MemberUtils.setAccessibleWorkaround(field);
|
||||||
|
}
|
||||||
|
return field.get(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the named public field. Superclasses will be considered.
|
||||||
|
* @param target the object to reflect, must not be null
|
||||||
|
* @param fieldName the field name to obtain
|
||||||
|
* @return the value of the field
|
||||||
|
* @throws IllegalArgumentException if the class or field name is null
|
||||||
|
* @throws IllegalAccessException if the named field is not public
|
||||||
|
*/
|
||||||
|
public static Object readField(Object target, String fieldName) throws IllegalAccessException {
|
||||||
|
return readField(target, fieldName, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the named field. Superclasses will be considered.
|
||||||
|
* @param target the object to reflect, must not be null
|
||||||
|
* @param fieldName the field name to obtain
|
||||||
|
* @param forceAccess whether to break scope restrictions using the
|
||||||
|
* <code>setAccessible</code> method. <code>False</code> will only
|
||||||
|
* match public fields.
|
||||||
|
* @return the field value
|
||||||
|
* @throws IllegalArgumentException if the class or field name is null
|
||||||
|
* @throws IllegalAccessException if the named field is not made accessible
|
||||||
|
*/
|
||||||
|
public static Object readField(Object target, String fieldName, boolean forceAccess) throws IllegalAccessException {
|
||||||
|
if (target == null) {
|
||||||
|
throw new IllegalArgumentException("target object must not be null");
|
||||||
|
}
|
||||||
|
Class cls = target.getClass();
|
||||||
|
Field field = getField(cls, fieldName, forceAccess);
|
||||||
|
if (field == null) {
|
||||||
|
throw new IllegalArgumentException("Cannot locate field " + fieldName + " on " + cls);
|
||||||
|
}
|
||||||
|
//already forced access above, don't repeat it here:
|
||||||
|
return readField(field, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the named public field. Only the class of the specified object will be considered.
|
||||||
|
* @param target the object to reflect, must not be null
|
||||||
|
* @param fieldName the field name to obtain
|
||||||
|
* @return the value of the field
|
||||||
|
* @throws IllegalArgumentException if the class or field name is null
|
||||||
|
* @throws IllegalAccessException if the named field is not public
|
||||||
|
*/
|
||||||
|
public static Object readDeclaredField(Object target, String fieldName) throws IllegalAccessException {
|
||||||
|
return readDeclaredField(target, fieldName, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p<>Gets a Field value by name. Only the class of the specified
|
||||||
|
* object will be considered.
|
||||||
|
*
|
||||||
|
* @param target the object to reflect, must not be null
|
||||||
|
* @param fieldName the field name to obtain
|
||||||
|
* @param forceAccess whether to break scope restrictions using the
|
||||||
|
* <code>setAccessible</code> method. <code>False</code> will only
|
||||||
|
* match public fields.
|
||||||
|
* @return the Field object
|
||||||
|
* @throws IllegalArgumentException if <code>target</code> or <code>fieldName</code> is null
|
||||||
|
* @throws IllegalAccessException if the field is not made accessible
|
||||||
|
*/
|
||||||
|
public static Object readDeclaredField(Object target, String fieldName, boolean forceAccess) throws IllegalAccessException {
|
||||||
|
if (target == null) {
|
||||||
|
throw new IllegalArgumentException("target object must not be null");
|
||||||
|
}
|
||||||
|
Class cls = target.getClass();
|
||||||
|
Field field = getDeclaredField(cls, fieldName, forceAccess);
|
||||||
|
if (field == null) {
|
||||||
|
throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
|
||||||
|
}
|
||||||
|
//already forced access above, don't repeat it here:
|
||||||
|
return readField(field, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a public static Field.
|
||||||
|
* @param field to write
|
||||||
|
* @param value to set
|
||||||
|
* @throws IllegalArgumentException if the field is null or not static
|
||||||
|
* @throws IllegalAccessException if the field is not public or is final
|
||||||
|
*/
|
||||||
|
public static void writeStaticField(Field field, Object value) throws IllegalAccessException {
|
||||||
|
writeStaticField(field, value, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a static Field.
|
||||||
|
* @param field to write
|
||||||
|
* @param value to set
|
||||||
|
* @param forceAccess whether to break scope restrictions using the
|
||||||
|
* <code>setAccessible</code> method. <code>False</code> will only
|
||||||
|
* match public fields.
|
||||||
|
* @throws IllegalArgumentException if the field is null or not static
|
||||||
|
* @throws IllegalAccessException if the field is not made accessible or is final
|
||||||
|
*/
|
||||||
|
public static void writeStaticField(Field field, Object value, boolean forceAccess) throws IllegalAccessException {
|
||||||
|
if (field == null) {
|
||||||
|
throw new IllegalArgumentException("The field must not be null");
|
||||||
|
}
|
||||||
|
if (!Modifier.isStatic(field.getModifiers())) {
|
||||||
|
throw new IllegalArgumentException("The field '" + field.getName() + "' is not static");
|
||||||
|
}
|
||||||
|
writeField(field, (Object) null, value, forceAccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a named public static Field. Superclasses will be considered.
|
||||||
|
* @param cls Class on which the Field is to be found
|
||||||
|
* @param fieldName to write
|
||||||
|
* @param value to set
|
||||||
|
* @throws IllegalArgumentException if the field cannot be located or is not static
|
||||||
|
* @throws IllegalAccessException if the field is not public or is final
|
||||||
|
*/
|
||||||
|
public static void writeStaticField(Class cls, String fieldName, Object value) throws IllegalAccessException {
|
||||||
|
writeStaticField(cls, fieldName, value, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a named static Field. Superclasses will be considered.
|
||||||
|
* @param cls Class on which the Field is to be found
|
||||||
|
* @param fieldName to write
|
||||||
|
* @param value to set
|
||||||
|
* @param forceAccess whether to break scope restrictions using the
|
||||||
|
* <code>setAccessible</code> method. <code>False</code> will only
|
||||||
|
* match public fields.
|
||||||
|
* @throws IllegalArgumentException if the field cannot be located or is not static
|
||||||
|
* @throws IllegalAccessException if the field is not made accessible or is final
|
||||||
|
*/
|
||||||
|
public static void writeStaticField(Class cls, String fieldName, Object value, boolean forceAccess)
|
||||||
|
throws IllegalAccessException {
|
||||||
|
Field field = getField(cls, fieldName, forceAccess);
|
||||||
|
if (field == null) {
|
||||||
|
throw new IllegalArgumentException("Cannot locate field " + fieldName + " on " + cls);
|
||||||
|
}
|
||||||
|
//already forced access above, don't repeat it here:
|
||||||
|
writeStaticField(field, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a named public static Field. Only the specified class will be considered.
|
||||||
|
* @param cls Class on which the Field is to be found
|
||||||
|
* @param fieldName to write
|
||||||
|
* @param value to set
|
||||||
|
* @throws IllegalArgumentException if the field cannot be located or is not static
|
||||||
|
* @throws IllegalAccessException if the field is not public or is final
|
||||||
|
*/
|
||||||
|
public static void writeDeclaredStaticField(Class cls, String fieldName, Object value)
|
||||||
|
throws IllegalAccessException {
|
||||||
|
writeDeclaredStaticField(cls, fieldName, value, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a named static Field. Only the specified class will be considered.
|
||||||
|
* @param cls Class on which the Field is to be found
|
||||||
|
* @param fieldName to write
|
||||||
|
* @param value to set
|
||||||
|
* @param forceAccess whether to break scope restrictions using the
|
||||||
|
* <code>setAccessible</code> method. <code>False</code> will only
|
||||||
|
* match public fields.
|
||||||
|
* @throws IllegalArgumentException if the field cannot be located or is not static
|
||||||
|
* @throws IllegalAccessException if the field is not made accessible or is final
|
||||||
|
*/
|
||||||
|
public static void writeDeclaredStaticField(Class cls, String fieldName, Object value, boolean forceAccess)
|
||||||
|
throws IllegalAccessException {
|
||||||
|
Field field = getDeclaredField(cls, fieldName, forceAccess);
|
||||||
|
if (field == null) {
|
||||||
|
throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
|
||||||
|
}
|
||||||
|
//already forced access above, don't repeat it here:
|
||||||
|
writeField(field, (Object) null, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write an accessible field.
|
||||||
|
* @param field to write
|
||||||
|
* @param target the object to call on, may be null for static fields
|
||||||
|
* @param value to set
|
||||||
|
* @throws IllegalArgumentException if the field is null
|
||||||
|
* @throws IllegalAccessException if the field is not accessible or is final
|
||||||
|
*/
|
||||||
|
public static void writeField(Field field, Object target, Object value) throws IllegalAccessException {
|
||||||
|
writeField(field, target, value, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a field.
|
||||||
|
* @param field to write
|
||||||
|
* @param target the object to call on, may be null for static fields
|
||||||
|
* @param value to set
|
||||||
|
* @param forceAccess whether to break scope restrictions using the
|
||||||
|
* <code>setAccessible</code> method. <code>False</code> will only
|
||||||
|
* match public fields.
|
||||||
|
* @throws IllegalArgumentException if the field is null
|
||||||
|
* @throws IllegalAccessException if the field is not made accessible or is final
|
||||||
|
*/
|
||||||
|
public static void writeField(Field field, Object target, Object value, boolean forceAccess) throws IllegalAccessException {
|
||||||
|
if (field == null) {
|
||||||
|
throw new IllegalArgumentException("The field must not be null");
|
||||||
|
}
|
||||||
|
if (forceAccess && !field.isAccessible()) {
|
||||||
|
field.setAccessible(true);
|
||||||
|
} else {
|
||||||
|
MemberUtils.setAccessibleWorkaround(field);
|
||||||
|
}
|
||||||
|
field.set(target, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a public field. Superclasses will be considered.
|
||||||
|
* @param target the object to reflect, must not be null
|
||||||
|
* @param fieldName the field name to obtain
|
||||||
|
* @param value to set
|
||||||
|
* @throws IllegalArgumentException if <code>target</code> or <code>fieldName</code> is null
|
||||||
|
* @throws IllegalAccessException if the field is not accessible
|
||||||
|
*/
|
||||||
|
public static void writeField(Object target, String fieldName, Object value) throws IllegalAccessException {
|
||||||
|
writeField(target, fieldName, value, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a field. Superclasses will be considered.
|
||||||
|
* @param target the object to reflect, must not be null
|
||||||
|
* @param fieldName the field name to obtain
|
||||||
|
* @param value to set
|
||||||
|
* @param forceAccess whether to break scope restrictions using the
|
||||||
|
* <code>setAccessible</code> method. <code>False</code> will only
|
||||||
|
* match public fields.
|
||||||
|
* @throws IllegalArgumentException if <code>target</code> or <code>fieldName</code> is null
|
||||||
|
* @throws IllegalAccessException if the field is not made accessible
|
||||||
|
*/
|
||||||
|
public static void writeField(Object target, String fieldName, Object value, boolean forceAccess)
|
||||||
|
throws IllegalAccessException {
|
||||||
|
if (target == null) {
|
||||||
|
throw new IllegalArgumentException("target object must not be null");
|
||||||
|
}
|
||||||
|
Class cls = target.getClass();
|
||||||
|
Field field = getField(cls, fieldName, forceAccess);
|
||||||
|
if (field == null) {
|
||||||
|
throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
|
||||||
|
}
|
||||||
|
//already forced access above, don't repeat it here:
|
||||||
|
writeField(field, target, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a public field. Only the specified class will be considered.
|
||||||
|
* @param target the object to reflect, must not be null
|
||||||
|
* @param fieldName the field name to obtain
|
||||||
|
* @param value to set
|
||||||
|
* @param forceAccess whether to break scope restrictions using the
|
||||||
|
* <code>setAccessible</code> method. <code>False</code> will only
|
||||||
|
* match public fields.
|
||||||
|
* @throws IllegalArgumentException if <code>target</code> or <code>fieldName</code> is null
|
||||||
|
* @throws IllegalAccessException if the field is not made accessible
|
||||||
|
*/
|
||||||
|
public static void writeDeclaredField(Object target, String fieldName, Object value) throws IllegalAccessException {
|
||||||
|
writeDeclaredField(target, fieldName, value, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a public field. Only the specified class will be considered.
|
||||||
|
* @param target the object to reflect, must not be null
|
||||||
|
* @param fieldName the field name to obtain
|
||||||
|
* @param value to set
|
||||||
|
* @param forceAccess whether to break scope restrictions using the
|
||||||
|
* <code>setAccessible</code> method. <code>False</code> will only
|
||||||
|
* match public fields.
|
||||||
|
* @throws IllegalArgumentException if <code>target</code> or <code>fieldName</code> is null
|
||||||
|
* @throws IllegalAccessException if the field is not made accessible
|
||||||
|
*/
|
||||||
|
public static void writeDeclaredField(Object target, String fieldName, Object value, boolean forceAccess)
|
||||||
|
throws IllegalAccessException {
|
||||||
|
if (target == null) {
|
||||||
|
throw new IllegalArgumentException("target object must not be null");
|
||||||
|
}
|
||||||
|
Class cls = target.getClass();
|
||||||
|
Field field = getDeclaredField(cls, fieldName, forceAccess);
|
||||||
|
if (field == null) {
|
||||||
|
throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
|
||||||
|
}
|
||||||
|
//already forced access above, don't repeat it here:
|
||||||
|
writeField(field, target, value);
|
||||||
|
}
|
||||||
|
}
|
220
src/java/org/apache/commons/lang/reflect/MemberUtils.java
Normal file
220
src/java/org/apache/commons/lang/reflect/MemberUtils.java
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect;
|
||||||
|
|
||||||
|
import java.lang.reflect.AccessibleObject;
|
||||||
|
import java.lang.reflect.Member;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.ArrayUtils;
|
||||||
|
import org.apache.commons.lang.ClassUtils;
|
||||||
|
import org.apache.commons.lang.SystemUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains common code for working with Methods/Constructors, extracted and
|
||||||
|
* refactored from <code>MethodUtils</code> when it was imported from Commons BeanUtils.
|
||||||
|
*
|
||||||
|
* @author Steve Cohen
|
||||||
|
* @author Matt Benson
|
||||||
|
* @since 2.5
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
abstract class MemberUtils {
|
||||||
|
// TODO extract an interface to implement compareParameterSets(...)?
|
||||||
|
|
||||||
|
private static final int ACCESS_TEST = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE;
|
||||||
|
|
||||||
|
private static final Method IS_SYNTHETIC;
|
||||||
|
static {
|
||||||
|
Method isSynthetic = null;
|
||||||
|
if (SystemUtils.isJavaVersionAtLeast(1.5f)) {
|
||||||
|
// cannot call synthetic methods:
|
||||||
|
try {
|
||||||
|
isSynthetic = Member.class.getMethod("isSynthetic",
|
||||||
|
ArrayUtils.EMPTY_CLASS_ARRAY);
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IS_SYNTHETIC = isSynthetic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Array of primitive number types ordered by "promotability" */
|
||||||
|
private static final Class[] ORDERED_PRIMITIVE_TYPES = { Byte.TYPE,
|
||||||
|
Short.TYPE, Character.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE,
|
||||||
|
Double.TYPE };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XXX Default access superclass workaround
|
||||||
|
*
|
||||||
|
* When a public class has a default access superclass with public
|
||||||
|
* members, these members are accessible. Calling them from
|
||||||
|
* compiled code works fine. Unfortunately, on some JVMs, using reflection to invoke these
|
||||||
|
* members seems to (wrongly) to prevent access even when the
|
||||||
|
* modifer is public. Calling setAccessible(true) solves the problem
|
||||||
|
* but will only work from sufficiently privileged code. Better
|
||||||
|
* workarounds would be gratefully accepted.
|
||||||
|
* @param o the AccessibleObject to set as accessible
|
||||||
|
*/
|
||||||
|
static void setAccessibleWorkaround(AccessibleObject o) {
|
||||||
|
if (o == null || o.isAccessible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Member m = (Member) o;
|
||||||
|
if (Modifier.isPublic(m.getModifiers()) && isPackageAccess(m.getDeclaringClass().getModifiers())) {
|
||||||
|
try {
|
||||||
|
o.setAccessible(true);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
// ignore in favor of subsequent IllegalAccessException
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Learn whether a given set of modifiers implies package access.
|
||||||
|
* @param modifiers to test
|
||||||
|
* @return true unless package/protected/private modifier detected
|
||||||
|
*/
|
||||||
|
static boolean isPackageAccess(int modifiers) {
|
||||||
|
return (modifiers & ACCESS_TEST) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check a Member for basic accessibility.
|
||||||
|
* @param m Member to check
|
||||||
|
* @return true if <code>m</code> is accessible
|
||||||
|
*/
|
||||||
|
static boolean isAccessible(Member m) {
|
||||||
|
return m != null && Modifier.isPublic(m.getModifiers())
|
||||||
|
&& !isSynthetic(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to learn whether a given member, on JDK >= 1.5, is synthetic.
|
||||||
|
* @param m Member to check
|
||||||
|
* @return true if <code>m</code> was introduced by the compiler.
|
||||||
|
*/
|
||||||
|
static boolean isSynthetic(Member m) {
|
||||||
|
if (IS_SYNTHETIC != null) {
|
||||||
|
try {
|
||||||
|
return ((Boolean) IS_SYNTHETIC.invoke(m, null)).booleanValue();
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare the relative fitness of two sets of parameter types in terms of
|
||||||
|
* matching a third set of runtime parameter types, such that a list ordered
|
||||||
|
* by the results of the comparison would return the best match first (least).
|
||||||
|
*
|
||||||
|
* @param left the "left" parameter set
|
||||||
|
* @param right the "right" parameter set
|
||||||
|
* @param actual the runtime parameter types to match against <code>left</code>/<code>right</code>
|
||||||
|
* @return int consistent with <code>compare</code> semantics
|
||||||
|
*/
|
||||||
|
static int compareParameterTypes(Class[] left, Class[] right, Class[] actual) {
|
||||||
|
float leftCost = getTotalTransformationCost(actual, left);
|
||||||
|
float rightCost = getTotalTransformationCost(actual, right);
|
||||||
|
return leftCost < rightCost ? -1 : rightCost < leftCost ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the sum of the object transformation cost for each class in the source
|
||||||
|
* argument list.
|
||||||
|
* @param srcArgs The source arguments
|
||||||
|
* @param destArgs The destination arguments
|
||||||
|
* @return The total transformation cost
|
||||||
|
*/
|
||||||
|
private static float getTotalTransformationCost(Class[] srcArgs,
|
||||||
|
Class[] destArgs) {
|
||||||
|
float totalCost = 0.0f;
|
||||||
|
for (int i = 0; i < srcArgs.length; i++) {
|
||||||
|
Class srcClass, destClass;
|
||||||
|
srcClass = srcArgs[i];
|
||||||
|
destClass = destArgs[i];
|
||||||
|
totalCost += getObjectTransformationCost(srcClass, destClass);
|
||||||
|
}
|
||||||
|
return totalCost;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of steps required needed to turn the source class into the
|
||||||
|
* destination class. This represents the number of steps in the object hierarchy
|
||||||
|
* graph.
|
||||||
|
* @param srcClass The source class
|
||||||
|
* @param destClass The destination class
|
||||||
|
* @return The cost of transforming an object
|
||||||
|
*/
|
||||||
|
private static float getObjectTransformationCost(Class srcClass,
|
||||||
|
Class destClass) {
|
||||||
|
if (destClass.isPrimitive()) {
|
||||||
|
return getPrimitivePromotionCost(srcClass, destClass);
|
||||||
|
}
|
||||||
|
float cost = 0.0f;
|
||||||
|
while (destClass != null && !destClass.equals(srcClass)) {
|
||||||
|
if (destClass.isInterface()
|
||||||
|
&& ClassUtils.isAssignable(srcClass, destClass)) {
|
||||||
|
// slight penalty for interface match.
|
||||||
|
// we still want an exact match to override an interface match,
|
||||||
|
// but
|
||||||
|
// an interface match should override anything where we have to
|
||||||
|
// get a superclass.
|
||||||
|
cost += 0.25f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cost++;
|
||||||
|
destClass = destClass.getSuperclass();
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If the destination class is null, we've travelled all the way up to
|
||||||
|
* an Object match. We'll penalize this by adding 1.5 to the cost.
|
||||||
|
*/
|
||||||
|
if (destClass == null) {
|
||||||
|
cost += 1.5f;
|
||||||
|
}
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of steps required to promote a primitive number to another type.
|
||||||
|
* @param srcClass the (primitive) source class
|
||||||
|
* @param destClass the (primitive) destination class
|
||||||
|
* @return The cost of promoting the primitive
|
||||||
|
*/
|
||||||
|
private static float getPrimitivePromotionCost(final Class srcClass,
|
||||||
|
final Class destClass) {
|
||||||
|
float cost = 0.0f;
|
||||||
|
Class cls = srcClass;
|
||||||
|
if (!cls.isPrimitive()) {
|
||||||
|
// slight unwrapping penalty
|
||||||
|
cost += 0.1f;
|
||||||
|
cls = ClassUtils.wrapperToPrimitive(cls);
|
||||||
|
}
|
||||||
|
for (int i = 0; cls != destClass && i < ORDERED_PRIMITIVE_TYPES.length; i++) {
|
||||||
|
if (cls == ORDERED_PRIMITIVE_TYPES[i]) {
|
||||||
|
cost += 0.1f;
|
||||||
|
if (i < ORDERED_PRIMITIVE_TYPES.length - 1) {
|
||||||
|
cls = ORDERED_PRIMITIVE_TYPES[i + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
847
src/java/org/apache/commons/lang/reflect/MethodUtils.java
Normal file
847
src/java/org/apache/commons/lang/reflect/MethodUtils.java
Normal file
@ -0,0 +1,847 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.ArrayUtils;
|
||||||
|
import org.apache.commons.lang.ClassUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p> Utility reflection methods focused on methods, originally from Commons BeanUtils.
|
||||||
|
* Differences from the BeanUtils version may be noted, especially where similar functionality
|
||||||
|
* already existed within Lang.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <h3>Known Limitations</h3>
|
||||||
|
* <h4>Accessing Public Methods In A Default Access Superclass</h4>
|
||||||
|
* <p>There is an issue when invoking public methods contained in a default access superclass on JREs prior to 1.4.
|
||||||
|
* Reflection locates these methods fine and correctly assigns them as public.
|
||||||
|
* However, an <code>IllegalAccessException</code> is thrown if the method is invoked.</p>
|
||||||
|
*
|
||||||
|
* <p><code>MethodUtils</code> contains a workaround for this situation.
|
||||||
|
* It will attempt to call <code>setAccessible</code> on this method.
|
||||||
|
* If this call succeeds, then the method can be invoked as normal.
|
||||||
|
* This call will only succeed when the application has sufficient security privileges.
|
||||||
|
* If this call fails then the method may fail.</p>
|
||||||
|
*
|
||||||
|
* @author Craig R. McClanahan
|
||||||
|
* @author Ralph Schaer
|
||||||
|
* @author Chris Audley
|
||||||
|
* @author Rey François
|
||||||
|
* @author Gregor Raýman
|
||||||
|
* @author Jan Sorensen
|
||||||
|
* @author Robert Burrell Donkin
|
||||||
|
* @author Niall Pemberton
|
||||||
|
* @author Matt Benson
|
||||||
|
* @since 2.5
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class MethodUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a cache of MethodDescriptor -> Method in a WeakHashMap.
|
||||||
|
* <p>
|
||||||
|
* The keys into this map only ever exist as temporary variables within
|
||||||
|
* methods of this class, and are never exposed to users of this class.
|
||||||
|
* This means that the WeakHashMap is used only as a mechanism for
|
||||||
|
* limiting the size of the cache, ie a way to tell the garbage collector
|
||||||
|
* that the contents of the cache can be completely garbage-collected
|
||||||
|
* whenever it needs the memory. Whether this is a good approach to
|
||||||
|
* this problem is doubtful; something like the commons-collections
|
||||||
|
* LRUMap may be more appropriate (though of course selecting an
|
||||||
|
* appropriate size is an issue).
|
||||||
|
* <p>
|
||||||
|
* This static variable is safe even when this code is deployed via a
|
||||||
|
* shared classloader because it is keyed via a MethodDescriptor object
|
||||||
|
* which has a Class as one of its members and that member is used in
|
||||||
|
* the MethodDescriptor.equals method. So two components that load the same
|
||||||
|
* class via different classloaders will generate non-equal MethodDescriptor
|
||||||
|
* objects and hence end up with different entries in the map.
|
||||||
|
*/
|
||||||
|
private static final WeakHashMap/* <MethodDescriptor, Method> */cache = new WeakHashMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether methods should be cached for improved performance.
|
||||||
|
* <p>
|
||||||
|
* Note that when this class is deployed via a shared classloader in
|
||||||
|
* a container, this will affect all webapps. However making this
|
||||||
|
* configurable per webapp would mean having a map keyed by context classloader
|
||||||
|
* which may introduce memory-leak problems.
|
||||||
|
*/
|
||||||
|
private static boolean cacheMethods = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>MethodUtils instances should NOT be constructed in standard programming.
|
||||||
|
* Instead, the class should be used as
|
||||||
|
* <code>MethodUtils.getAccessibleMethod(method)</code>.</p>
|
||||||
|
*
|
||||||
|
* <p>This constructor is public to permit tools that require a JavaBean
|
||||||
|
* instance to operate.</p>
|
||||||
|
*/
|
||||||
|
public MethodUtils() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether methods should be cached for greater performance or not,
|
||||||
|
* default is <code>true</code>.
|
||||||
|
*
|
||||||
|
* @param cacheMethods <code>true</code> if methods should be
|
||||||
|
* cached for greater performance, otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
public static synchronized void setCacheMethods(boolean cacheMethods) {
|
||||||
|
MethodUtils.cacheMethods = cacheMethods;
|
||||||
|
if (!MethodUtils.cacheMethods) {
|
||||||
|
clearCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the method cache.
|
||||||
|
* @return the number of cached methods cleared
|
||||||
|
*/
|
||||||
|
public static synchronized int clearCache() {
|
||||||
|
int size = cache.size();
|
||||||
|
cache.clear();
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Invoke a named method whose parameter type matches the object type.</p>
|
||||||
|
*
|
||||||
|
* <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p>
|
||||||
|
*
|
||||||
|
* <p>This method supports calls to methods taking primitive parameters
|
||||||
|
* via passing in wrapping classes. So, for example, a <code>Boolean</code> object
|
||||||
|
* would match a <code>boolean</code> primitive.</p>
|
||||||
|
*
|
||||||
|
* <p> This is a convenient wrapper for
|
||||||
|
* {@link #invokeMethod(Object object, String methodName, Object[] args)}.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param object invoke method on this object
|
||||||
|
* @param methodName get method with this name
|
||||||
|
* @param arg use this argument
|
||||||
|
* @return The value returned by the invoked method
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException if there is no such accessible method
|
||||||
|
* @throws InvocationTargetException wraps an exception thrown by the method invoked
|
||||||
|
* @throws IllegalAccessException if the requested method is not accessible via reflection
|
||||||
|
*/
|
||||||
|
public static Object invokeMethod(Object object, String methodName,
|
||||||
|
Object arg) throws NoSuchMethodException, IllegalAccessException,
|
||||||
|
InvocationTargetException {
|
||||||
|
return invokeMethod(object, methodName, new Object[] { arg });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Invoke a named method whose parameter type matches the object type.</p>
|
||||||
|
*
|
||||||
|
* <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p>
|
||||||
|
*
|
||||||
|
* <p>This method supports calls to methods taking primitive parameters
|
||||||
|
* via passing in wrapping classes. So, for example, a <code>Boolean</code> object
|
||||||
|
* would match a <code>boolean</code> primitive.</p>
|
||||||
|
*
|
||||||
|
* <p> This is a convenient wrapper for
|
||||||
|
* {@link #invokeMethod(Object object,String methodName, Object[] args, Class[] parameterTypes)}.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param object invoke method on this object
|
||||||
|
* @param methodName get method with this name
|
||||||
|
* @param args use these arguments - treat null as empty array
|
||||||
|
* @return The value returned by the invoked method
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException if there is no such accessible method
|
||||||
|
* @throws InvocationTargetException wraps an exception thrown by the method invoked
|
||||||
|
* @throws IllegalAccessException if the requested method is not accessible via reflection
|
||||||
|
*/
|
||||||
|
public static Object invokeMethod(Object object, String methodName,
|
||||||
|
Object[] args) throws NoSuchMethodException,
|
||||||
|
IllegalAccessException, InvocationTargetException {
|
||||||
|
if (args == null) {
|
||||||
|
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
|
||||||
|
}
|
||||||
|
int arguments = args.length;
|
||||||
|
Class[] parameterTypes = new Class[arguments];
|
||||||
|
for (int i = 0; i < arguments; i++) {
|
||||||
|
parameterTypes[i] = args[i].getClass();
|
||||||
|
}
|
||||||
|
return invokeMethod(object, methodName, args, parameterTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Invoke a named method whose parameter type matches the object type.</p>
|
||||||
|
*
|
||||||
|
* <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p>
|
||||||
|
*
|
||||||
|
* <p>This method supports calls to methods taking primitive parameters
|
||||||
|
* via passing in wrapping classes. So, for example, a <code>Boolean</code> object
|
||||||
|
* would match a <code>boolean</code> primitive.</p>
|
||||||
|
*
|
||||||
|
* @param object invoke method on this object
|
||||||
|
* @param methodName get method with this name
|
||||||
|
* @param args use these arguments - treat null as empty array
|
||||||
|
* @param parameterTypes match these parameters - treat null as empty array
|
||||||
|
* @return The value returned by the invoked method
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException if there is no such accessible method
|
||||||
|
* @throws InvocationTargetException wraps an exception thrown by the method invoked
|
||||||
|
* @throws IllegalAccessException if the requested method is not accessible via reflection
|
||||||
|
*/
|
||||||
|
public static Object invokeMethod(Object object, String methodName,
|
||||||
|
Object[] args, Class[] parameterTypes)
|
||||||
|
throws NoSuchMethodException, IllegalAccessException,
|
||||||
|
InvocationTargetException {
|
||||||
|
if (parameterTypes == null) {
|
||||||
|
parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
|
||||||
|
}
|
||||||
|
if (args == null) {
|
||||||
|
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
|
||||||
|
}
|
||||||
|
Method method = getMatchingAccessibleMethod(object.getClass(),
|
||||||
|
methodName, parameterTypes);
|
||||||
|
if (method == null) {
|
||||||
|
throw new NoSuchMethodException("No such accessible method: "
|
||||||
|
+ methodName + "() on object: "
|
||||||
|
+ object.getClass().getName());
|
||||||
|
}
|
||||||
|
return method.invoke(object, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Invoke a method whose parameter type matches exactly the object
|
||||||
|
* type.</p>
|
||||||
|
*
|
||||||
|
* <p> This is a convenient wrapper for
|
||||||
|
* {@link #invokeExactMethod(Object object,String methodName,Object [] args)}.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param object invoke method on this object
|
||||||
|
* @param methodName get method with this name
|
||||||
|
* @param arg use this argument
|
||||||
|
* @return The value returned by the invoked method
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException if there is no such accessible method
|
||||||
|
* @throws InvocationTargetException wraps an exception thrown by the
|
||||||
|
* method invoked
|
||||||
|
* @throws IllegalAccessException if the requested method is not accessible
|
||||||
|
* via reflection
|
||||||
|
*/
|
||||||
|
public static Object invokeExactMethod(Object object, String methodName,
|
||||||
|
Object arg) throws NoSuchMethodException, IllegalAccessException,
|
||||||
|
InvocationTargetException {
|
||||||
|
return invokeExactMethod(object, methodName, new Object[] { arg });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Invoke a method whose parameter types match exactly the object
|
||||||
|
* types.</p>
|
||||||
|
*
|
||||||
|
* <p> This uses reflection to invoke the method obtained from a call to
|
||||||
|
* <code>getAccessibleMethod()</code>.</p>
|
||||||
|
*
|
||||||
|
* @param object invoke method on this object
|
||||||
|
* @param methodName get method with this name
|
||||||
|
* @param args use these arguments - treat null as empty array
|
||||||
|
* @return The value returned by the invoked method
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException if there is no such accessible method
|
||||||
|
* @throws InvocationTargetException wraps an exception thrown by the
|
||||||
|
* method invoked
|
||||||
|
* @throws IllegalAccessException if the requested method is not accessible
|
||||||
|
* via reflection
|
||||||
|
*/
|
||||||
|
public static Object invokeExactMethod(Object object, String methodName,
|
||||||
|
Object[] args) throws NoSuchMethodException,
|
||||||
|
IllegalAccessException, InvocationTargetException {
|
||||||
|
if (args == null) {
|
||||||
|
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
|
||||||
|
}
|
||||||
|
int arguments = args.length;
|
||||||
|
Class[] parameterTypes = new Class[arguments];
|
||||||
|
for (int i = 0; i < arguments; i++) {
|
||||||
|
parameterTypes[i] = args[i].getClass();
|
||||||
|
}
|
||||||
|
return invokeExactMethod(object, methodName, args, parameterTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Invoke a method whose parameter types match exactly the parameter
|
||||||
|
* types given.</p>
|
||||||
|
*
|
||||||
|
* <p>This uses reflection to invoke the method obtained from a call to
|
||||||
|
* <code>getAccessibleMethod()</code>.</p>
|
||||||
|
*
|
||||||
|
* @param object invoke method on this object
|
||||||
|
* @param methodName get method with this name
|
||||||
|
* @param args use these arguments - treat null as empty array
|
||||||
|
* @param parameterTypes match these parameters - treat null as empty array
|
||||||
|
* @return The value returned by the invoked method
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException if there is no such accessible method
|
||||||
|
* @throws InvocationTargetException wraps an exception thrown by the
|
||||||
|
* method invoked
|
||||||
|
* @throws IllegalAccessException if the requested method is not accessible
|
||||||
|
* via reflection
|
||||||
|
*/
|
||||||
|
public static Object invokeExactMethod(Object object, String methodName,
|
||||||
|
Object[] args, Class[] parameterTypes)
|
||||||
|
throws NoSuchMethodException, IllegalAccessException,
|
||||||
|
InvocationTargetException {
|
||||||
|
if (args == null) {
|
||||||
|
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
|
||||||
|
}
|
||||||
|
if (parameterTypes == null) {
|
||||||
|
parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
|
||||||
|
}
|
||||||
|
Method method = getAccessibleMethod(object.getClass(), methodName,
|
||||||
|
parameterTypes);
|
||||||
|
if (method == null) {
|
||||||
|
throw new NoSuchMethodException("No such accessible method: "
|
||||||
|
+ methodName + "() on object: "
|
||||||
|
+ object.getClass().getName());
|
||||||
|
}
|
||||||
|
return method.invoke(object, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Invoke a static method whose parameter types match exactly the parameter
|
||||||
|
* types given.</p>
|
||||||
|
*
|
||||||
|
* <p>This uses reflection to invoke the method obtained from a call to
|
||||||
|
* {@link #getAccessibleMethod(Class, String, Class[])}.</p>
|
||||||
|
*
|
||||||
|
* @param cls invoke static method on this class
|
||||||
|
* @param methodName get method with this name
|
||||||
|
* @param args use these arguments - treat null as empty array
|
||||||
|
* @param parameterTypes match these parameters - treat null as empty array
|
||||||
|
* @return The value returned by the invoked method
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException if there is no such accessible method
|
||||||
|
* @throws InvocationTargetException wraps an exception thrown by the
|
||||||
|
* method invoked
|
||||||
|
* @throws IllegalAccessException if the requested method is not accessible
|
||||||
|
* via reflection
|
||||||
|
*/
|
||||||
|
public static Object invokeExactStaticMethod(Class cls, String methodName,
|
||||||
|
Object[] args, Class[] parameterTypes)
|
||||||
|
throws NoSuchMethodException, IllegalAccessException,
|
||||||
|
InvocationTargetException {
|
||||||
|
if (args == null) {
|
||||||
|
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
|
||||||
|
}
|
||||||
|
if (parameterTypes == null) {
|
||||||
|
parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
|
||||||
|
}
|
||||||
|
Method method = getAccessibleMethod(cls, methodName, parameterTypes);
|
||||||
|
if (method == null) {
|
||||||
|
throw new NoSuchMethodException("No such accessible method: "
|
||||||
|
+ methodName + "() on class: " + cls.getName());
|
||||||
|
}
|
||||||
|
return method.invoke(null, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Invoke a named static method whose parameter type matches the object type.</p>
|
||||||
|
*
|
||||||
|
* <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p>
|
||||||
|
*
|
||||||
|
* <p>This method supports calls to methods taking primitive parameters
|
||||||
|
* via passing in wrapping classes. So, for example, a <code>Boolean</code> class
|
||||||
|
* would match a <code>boolean</code> primitive.</p>
|
||||||
|
*
|
||||||
|
* <p> This is a convenient wrapper for
|
||||||
|
* {@link #invokeStaticMethod(Class objectClass,String methodName,Object [] args)}.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param cls invoke static method on this class
|
||||||
|
* @param methodName get method with this name
|
||||||
|
* @param arg use this argument
|
||||||
|
* @return The value returned by the invoked method
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException if there is no such accessible method
|
||||||
|
* @throws InvocationTargetException wraps an exception thrown by the
|
||||||
|
* method invoked
|
||||||
|
* @throws IllegalAccessException if the requested method is not accessible
|
||||||
|
* via reflection
|
||||||
|
*/
|
||||||
|
public static Object invokeStaticMethod(Class cls, String methodName,
|
||||||
|
Object arg) throws NoSuchMethodException, IllegalAccessException,
|
||||||
|
InvocationTargetException {
|
||||||
|
return invokeStaticMethod(cls, methodName, new Object[] { arg });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Invoke a named static method whose parameter type matches the object type.</p>
|
||||||
|
*
|
||||||
|
* <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p>
|
||||||
|
*
|
||||||
|
* <p>This method supports calls to methods taking primitive parameters
|
||||||
|
* via passing in wrapping classes. So, for example, a <code>Boolean</code> class
|
||||||
|
* would match a <code>boolean</code> primitive.</p>
|
||||||
|
*
|
||||||
|
* <p> This is a convenient wrapper for
|
||||||
|
* {@link #invokeStaticMethod(Class objectClass,String methodName,Object [] args,Class[] parameterTypes)}.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param cls invoke static method on this class
|
||||||
|
* @param methodName get method with this name
|
||||||
|
* @param args use these arguments - treat null as empty array
|
||||||
|
* @return The value returned by the invoked method
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException if there is no such accessible method
|
||||||
|
* @throws InvocationTargetException wraps an exception thrown by the
|
||||||
|
* method invoked
|
||||||
|
* @throws IllegalAccessException if the requested method is not accessible
|
||||||
|
* via reflection
|
||||||
|
*/
|
||||||
|
public static Object invokeStaticMethod(Class cls, String methodName,
|
||||||
|
Object[] args) throws NoSuchMethodException,
|
||||||
|
IllegalAccessException, InvocationTargetException {
|
||||||
|
if (args == null) {
|
||||||
|
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
|
||||||
|
}
|
||||||
|
int arguments = args.length;
|
||||||
|
Class[] parameterTypes = new Class[arguments];
|
||||||
|
for (int i = 0; i < arguments; i++) {
|
||||||
|
parameterTypes[i] = args[i].getClass();
|
||||||
|
}
|
||||||
|
return invokeStaticMethod(cls, methodName, args, parameterTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Invoke a named static method whose parameter type matches the object type.</p>
|
||||||
|
*
|
||||||
|
* <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p>
|
||||||
|
*
|
||||||
|
* <p>This method supports calls to methods taking primitive parameters
|
||||||
|
* via passing in wrapping classes. So, for example, a <code>Boolean</code> class
|
||||||
|
* would match a <code>boolean</code> primitive.</p>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param cls invoke static method on this class
|
||||||
|
* @param methodName get method with this name
|
||||||
|
* @param args use these arguments - treat null as empty array
|
||||||
|
* @param parameterTypes match these parameters - treat null as empty array
|
||||||
|
* @return The value returned by the invoked method
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException if there is no such accessible method
|
||||||
|
* @throws InvocationTargetException wraps an exception thrown by the
|
||||||
|
* method invoked
|
||||||
|
* @throws IllegalAccessException if the requested method is not accessible
|
||||||
|
* via reflection
|
||||||
|
*/
|
||||||
|
public static Object invokeStaticMethod(Class cls, String methodName,
|
||||||
|
Object[] args, Class[] parameterTypes)
|
||||||
|
throws NoSuchMethodException, IllegalAccessException,
|
||||||
|
InvocationTargetException {
|
||||||
|
if (parameterTypes == null) {
|
||||||
|
parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
|
||||||
|
}
|
||||||
|
if (args == null) {
|
||||||
|
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
|
||||||
|
}
|
||||||
|
Method method = getMatchingAccessibleMethod(cls, methodName,
|
||||||
|
parameterTypes);
|
||||||
|
if (method == null) {
|
||||||
|
throw new NoSuchMethodException("No such accessible method: "
|
||||||
|
+ methodName + "() on class: " + cls.getName());
|
||||||
|
}
|
||||||
|
return method.invoke(null, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Invoke a static method whose parameter type matches exactly the object
|
||||||
|
* type.</p>
|
||||||
|
*
|
||||||
|
* <p> This is a convenient wrapper for
|
||||||
|
* {@link #invokeExactStaticMethod(Class objectClass,String methodName,Object [] args)}.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param cls invoke static method on this class
|
||||||
|
* @param methodName get method with this name
|
||||||
|
* @param arg use this argument
|
||||||
|
* @return The value returned by the invoked method
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException if there is no such accessible method
|
||||||
|
* @throws InvocationTargetException wraps an exception thrown by the
|
||||||
|
* method invoked
|
||||||
|
* @throws IllegalAccessException if the requested method is not accessible
|
||||||
|
* via reflection
|
||||||
|
*/
|
||||||
|
public static Object invokeExactStaticMethod(Class cls, String methodName,
|
||||||
|
Object arg) throws NoSuchMethodException, IllegalAccessException,
|
||||||
|
InvocationTargetException {
|
||||||
|
return invokeExactStaticMethod(cls, methodName, new Object[] { arg });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Invoke a static method whose parameter types match exactly the object
|
||||||
|
* types.</p>
|
||||||
|
*
|
||||||
|
* <p> This uses reflection to invoke the method obtained from a call to
|
||||||
|
* {@link #getAccessibleMethod(Class, String, Class[])}.</p>
|
||||||
|
*
|
||||||
|
* @param cls invoke static method on this class
|
||||||
|
* @param methodName get method with this name
|
||||||
|
* @param args use these arguments - treat null as empty array
|
||||||
|
* @return The value returned by the invoked method
|
||||||
|
*
|
||||||
|
* @throws NoSuchMethodException if there is no such accessible method
|
||||||
|
* @throws InvocationTargetException wraps an exception thrown by the
|
||||||
|
* method invoked
|
||||||
|
* @throws IllegalAccessException if the requested method is not accessible
|
||||||
|
* via reflection
|
||||||
|
*/
|
||||||
|
public static Object invokeExactStaticMethod(Class cls, String methodName,
|
||||||
|
Object[] args) throws NoSuchMethodException,
|
||||||
|
IllegalAccessException, InvocationTargetException {
|
||||||
|
if (args == null) {
|
||||||
|
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
|
||||||
|
}
|
||||||
|
int arguments = args.length;
|
||||||
|
Class[] parameterTypes = new Class[arguments];
|
||||||
|
for (int i = 0; i < arguments; i++) {
|
||||||
|
parameterTypes[i] = args[i].getClass();
|
||||||
|
}
|
||||||
|
return invokeExactStaticMethod(cls, methodName, args, parameterTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Return an accessible method (that is, one that can be invoked via
|
||||||
|
* reflection) with given name and a single parameter. If no such method
|
||||||
|
* can be found, return <code>null</code>.
|
||||||
|
* Basically, a convenience wrapper that constructs a <code>Class</code>
|
||||||
|
* array for you.</p>
|
||||||
|
*
|
||||||
|
* @param cls get method from this class
|
||||||
|
* @param methodName get method with this name
|
||||||
|
* @param parameterType taking this type of parameter
|
||||||
|
* @return The accessible method
|
||||||
|
*/
|
||||||
|
public static Method getAccessibleMethod(Class cls, String methodName,
|
||||||
|
Class parameterType) {
|
||||||
|
return getAccessibleMethod(cls, methodName,
|
||||||
|
new Class[] { parameterType });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Return an accessible method (that is, one that can be invoked via
|
||||||
|
* reflection) with given name and parameters. If no such method
|
||||||
|
* can be found, return <code>null</code>.
|
||||||
|
* This is just a convenient wrapper for
|
||||||
|
* {@link #getAccessibleMethod(Method method)}.</p>
|
||||||
|
*
|
||||||
|
* @param cls get method from this class
|
||||||
|
* @param methodName get method with this name
|
||||||
|
* @param parameterTypes with these parameters types
|
||||||
|
* @return The accessible method
|
||||||
|
*/
|
||||||
|
public static Method getAccessibleMethod(Class cls, String methodName,
|
||||||
|
Class[] parameterTypes) {
|
||||||
|
try {
|
||||||
|
MethodDescriptor md = new MethodDescriptor(cls, methodName,
|
||||||
|
parameterTypes, true);
|
||||||
|
// Check the cache first
|
||||||
|
Method method = getCachedMethod(md);
|
||||||
|
if (method != null) {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
method = getAccessibleMethod(cls.getMethod(methodName,
|
||||||
|
parameterTypes));
|
||||||
|
cacheMethod(md, method);
|
||||||
|
return method;
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Return an accessible method (that is, one that can be invoked via
|
||||||
|
* reflection) that implements the specified Method. If no such method
|
||||||
|
* can be found, return <code>null</code>.</p>
|
||||||
|
*
|
||||||
|
* @param method The method that we wish to call
|
||||||
|
* @return The accessible method
|
||||||
|
*/
|
||||||
|
public static Method getAccessibleMethod(Method method) {
|
||||||
|
if (!MemberUtils.isAccessible(method)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// If the declaring class is public, we are done
|
||||||
|
Class cls = method.getDeclaringClass();
|
||||||
|
if (Modifier.isPublic(cls.getModifiers())) {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
String methodName = method.getName();
|
||||||
|
Class[] parameterTypes = method.getParameterTypes();
|
||||||
|
|
||||||
|
// Check the implemented interfaces and subinterfaces
|
||||||
|
method = getAccessibleMethodFromInterfaceNest(cls, methodName,
|
||||||
|
parameterTypes);
|
||||||
|
|
||||||
|
// Check the superclass chain
|
||||||
|
if (method == null) {
|
||||||
|
method = getAccessibleMethodFromSuperclass(cls, methodName,
|
||||||
|
parameterTypes);
|
||||||
|
}
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Return an accessible method (that is, one that can be invoked via
|
||||||
|
* reflection) by scanning through the superclasses. If no such method
|
||||||
|
* can be found, return <code>null</code>.</p>
|
||||||
|
*
|
||||||
|
* @param cls Class to be checked
|
||||||
|
* @param methodName Method name of the method we wish to call
|
||||||
|
* @param parameterTypes The parameter type signatures
|
||||||
|
*/
|
||||||
|
private static Method getAccessibleMethodFromSuperclass(Class cls,
|
||||||
|
String methodName, Class[] parameterTypes) {
|
||||||
|
Class parentClass = cls.getSuperclass();
|
||||||
|
while (parentClass != null) {
|
||||||
|
if (Modifier.isPublic(parentClass.getModifiers())) {
|
||||||
|
try {
|
||||||
|
return parentClass.getMethod(methodName, parameterTypes);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parentClass = parentClass.getSuperclass();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Return an accessible method (that is, one that can be invoked via
|
||||||
|
* reflection) that implements the specified method, by scanning through
|
||||||
|
* all implemented interfaces and subinterfaces. If no such method
|
||||||
|
* can be found, return <code>null</code>.</p>
|
||||||
|
*
|
||||||
|
* <p> There isn't any good reason why this method must be private.
|
||||||
|
* It is because there doesn't seem any reason why other classes should
|
||||||
|
* call this rather than the higher level methods.</p>
|
||||||
|
*
|
||||||
|
* @param cls Parent class for the interfaces to be checked
|
||||||
|
* @param methodName Method name of the method we wish to call
|
||||||
|
* @param parameterTypes The parameter type signatures
|
||||||
|
*/
|
||||||
|
private static Method getAccessibleMethodFromInterfaceNest(Class cls,
|
||||||
|
String methodName, Class[] parameterTypes) {
|
||||||
|
Method method = null;
|
||||||
|
|
||||||
|
// Search up the superclass chain
|
||||||
|
for (; cls != null; cls = cls.getSuperclass()) {
|
||||||
|
|
||||||
|
// Check the implemented interfaces of the parent class
|
||||||
|
Class[] interfaces = cls.getInterfaces();
|
||||||
|
for (int i = 0; i < interfaces.length; i++) {
|
||||||
|
// Is this interface public?
|
||||||
|
if (!Modifier.isPublic(interfaces[i].getModifiers())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Does the method exist on this interface?
|
||||||
|
try {
|
||||||
|
method = interfaces[i].getDeclaredMethod(methodName,
|
||||||
|
parameterTypes);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
/*
|
||||||
|
* Swallow, if no method is found after the loop then this
|
||||||
|
* method returns null.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
if (method != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Recursively check our parent interfaces
|
||||||
|
method = getAccessibleMethodFromInterfaceNest(interfaces[i],
|
||||||
|
methodName, parameterTypes);
|
||||||
|
if (method != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Find an accessible method that matches the given name and has compatible parameters.
|
||||||
|
* Compatible parameters mean that every method parameter is assignable from
|
||||||
|
* the given parameters.
|
||||||
|
* In other words, it finds a method with the given name
|
||||||
|
* that will take the parameters given.<p>
|
||||||
|
*
|
||||||
|
* <p>This method is used by
|
||||||
|
* {@link
|
||||||
|
* #invokeMethod(Object object, String methodName, Object[] args, Class[] parameterTypes)}.
|
||||||
|
*
|
||||||
|
* <p>This method can match primitive parameter by passing in wrapper classes.
|
||||||
|
* For example, a <code>Boolean</code> will match a primitive <code>boolean</code>
|
||||||
|
* parameter.
|
||||||
|
*
|
||||||
|
* @param cls find method in this class
|
||||||
|
* @param methodName find method with this name
|
||||||
|
* @param parameterTypes find method with most compatible parameters
|
||||||
|
* @return The accessible method
|
||||||
|
*/
|
||||||
|
public static Method getMatchingAccessibleMethod(Class cls,
|
||||||
|
String methodName, Class[] parameterTypes) {
|
||||||
|
MethodDescriptor md = new MethodDescriptor(cls, methodName,
|
||||||
|
parameterTypes, false);
|
||||||
|
// Check the cache first
|
||||||
|
Method method = getCachedMethod(md);
|
||||||
|
if (method != null) {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
// see if we can find the method directly
|
||||||
|
// most of the time this works and it's much faster
|
||||||
|
try {
|
||||||
|
method = cls.getMethod(methodName, parameterTypes);
|
||||||
|
MemberUtils.setAccessibleWorkaround(method);
|
||||||
|
cacheMethod(md, method);
|
||||||
|
return method;
|
||||||
|
} catch (NoSuchMethodException e) { /* SWALLOW */
|
||||||
|
}
|
||||||
|
// search through all methods
|
||||||
|
Method bestMatch = null;
|
||||||
|
Method[] methods = cls.getMethods();
|
||||||
|
for (int i = 0, size = methods.length; i < size; i++) {
|
||||||
|
if (methods[i].getName().equals(methodName)) {
|
||||||
|
// compare parameters
|
||||||
|
if (ClassUtils.isAssignable(parameterTypes, methods[i]
|
||||||
|
.getParameterTypes(), true)) {
|
||||||
|
// get accessible version of method
|
||||||
|
Method accessibleMethod = getAccessibleMethod(methods[i]);
|
||||||
|
if (accessibleMethod != null) {
|
||||||
|
if (bestMatch == null
|
||||||
|
|| MemberUtils.compareParameterTypes(
|
||||||
|
accessibleMethod.getParameterTypes(),
|
||||||
|
bestMatch.getParameterTypes(),
|
||||||
|
parameterTypes) < 0) {
|
||||||
|
bestMatch = accessibleMethod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bestMatch != null) {
|
||||||
|
MemberUtils.setAccessibleWorkaround(bestMatch);
|
||||||
|
cacheMethod(md, bestMatch);
|
||||||
|
}
|
||||||
|
return bestMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the method from the cache, if present.
|
||||||
|
*
|
||||||
|
* @param md The method descriptor
|
||||||
|
* @return The cached method
|
||||||
|
*/
|
||||||
|
private static Method getCachedMethod(MethodDescriptor md) {
|
||||||
|
if (cacheMethods) {
|
||||||
|
return (Method) cache.get(md);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a method to the cache.
|
||||||
|
*
|
||||||
|
* @param md The method descriptor
|
||||||
|
* @param method The method to cache
|
||||||
|
*/
|
||||||
|
private static void cacheMethod(MethodDescriptor md, Method method) {
|
||||||
|
if (cacheMethods) {
|
||||||
|
if (method != null) {
|
||||||
|
cache.put(md, method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the key to looking up a Method by reflection.
|
||||||
|
*/
|
||||||
|
private static class MethodDescriptor {
|
||||||
|
private Class cls;
|
||||||
|
private String methodName;
|
||||||
|
private Class[] paramTypes;
|
||||||
|
private boolean exact;
|
||||||
|
private int hashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sole constructor.
|
||||||
|
*
|
||||||
|
* @param cls the class to reflect, must not be null
|
||||||
|
* @param methodName the method name to obtain
|
||||||
|
* @param paramTypes the array of classes representing the paramater types
|
||||||
|
* @param exact whether the match has to be exact.
|
||||||
|
*/
|
||||||
|
public MethodDescriptor(Class cls, String methodName,
|
||||||
|
Class[] paramTypes, boolean exact) {
|
||||||
|
if (cls == null) {
|
||||||
|
throw new IllegalArgumentException("Class cannot be null");
|
||||||
|
}
|
||||||
|
if (methodName == null) {
|
||||||
|
throw new IllegalArgumentException("Method Name cannot be null");
|
||||||
|
}
|
||||||
|
if (paramTypes == null) {
|
||||||
|
paramTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
|
||||||
|
}
|
||||||
|
this.cls = cls;
|
||||||
|
this.methodName = methodName;
|
||||||
|
this.paramTypes = paramTypes;
|
||||||
|
this.exact = exact;
|
||||||
|
// is this adequate? :/
|
||||||
|
this.hashCode = methodName.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for equality.
|
||||||
|
* @param obj object to be tested for equality
|
||||||
|
* @return true, if the object describes the same Method.
|
||||||
|
*/
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (!(obj instanceof MethodDescriptor)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MethodDescriptor md = (MethodDescriptor) obj;
|
||||||
|
|
||||||
|
return exact == md.exact && methodName.equals(md.methodName)
|
||||||
|
&& cls.equals(md.cls)
|
||||||
|
&& Arrays.equals(paramTypes, md.paramTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string length of method name. I.e. if the
|
||||||
|
* hashcodes are different, the objects are different. If the
|
||||||
|
* hashcodes are the same, need to use the equals method to
|
||||||
|
* determine equality.
|
||||||
|
* @return the string length of method name.
|
||||||
|
*/
|
||||||
|
public int hashCode() {
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
src/java/org/apache/commons/lang/reflect/package.html
Normal file
28
src/java/org/apache/commons/lang/reflect/package.html
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!--
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
-->
|
||||||
|
<title></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
Accumulates common high-level uses of the <code>java.lang.reflect</code> APIs.
|
||||||
|
@since 2.5
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -26,6 +26,7 @@
|
|||||||
import org.apache.commons.lang.exception.ExceptionTestSuite;
|
import org.apache.commons.lang.exception.ExceptionTestSuite;
|
||||||
import org.apache.commons.lang.math.MathTestSuite;
|
import org.apache.commons.lang.math.MathTestSuite;
|
||||||
import org.apache.commons.lang.mutable.MutableTestSuite;
|
import org.apache.commons.lang.mutable.MutableTestSuite;
|
||||||
|
import org.apache.commons.lang.reflect.ReflectTestSuite;
|
||||||
import org.apache.commons.lang.text.TextTestSuite;
|
import org.apache.commons.lang.text.TextTestSuite;
|
||||||
import org.apache.commons.lang.time.TimeTestSuite;
|
import org.apache.commons.lang.time.TimeTestSuite;
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ public static Test suite() {
|
|||||||
suite.addTest(ExceptionTestSuite.suite());
|
suite.addTest(ExceptionTestSuite.suite());
|
||||||
suite.addTest(MathTestSuite.suite());
|
suite.addTest(MathTestSuite.suite());
|
||||||
suite.addTest(MutableTestSuite.suite());
|
suite.addTest(MutableTestSuite.suite());
|
||||||
|
suite.addTest(ReflectTestSuite.suite());
|
||||||
suite.addTest(TextTestSuite.suite());
|
suite.addTest(TextTestSuite.suite());
|
||||||
suite.addTest(TimeTestSuite.suite());
|
suite.addTest(TimeTestSuite.suite());
|
||||||
return suite;
|
return suite;
|
||||||
|
@ -0,0 +1,229 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.ArrayUtils;
|
||||||
|
import org.apache.commons.lang.math.NumberUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests ConstructorUtils
|
||||||
|
* @author mbenson
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class ConstructorUtilsTest extends TestCase {
|
||||||
|
public static class TestBean {
|
||||||
|
private String toString;
|
||||||
|
|
||||||
|
public TestBean() {
|
||||||
|
toString = "()";
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestBean(int i) {
|
||||||
|
toString = "(int)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestBean(Integer i) {
|
||||||
|
toString = "(Integer)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestBean(double d) {
|
||||||
|
toString = "(double)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestBean(String s) {
|
||||||
|
toString = "(String)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestBean(Object o) {
|
||||||
|
toString = "(Object)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return toString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class PrivateClass {
|
||||||
|
public PrivateClass() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map classCache;
|
||||||
|
|
||||||
|
public ConstructorUtilsTest(String name) {
|
||||||
|
super(name);
|
||||||
|
classCache = new HashMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the test cases as a suite.
|
||||||
|
* @return the Test
|
||||||
|
*/
|
||||||
|
public static Test suite() {
|
||||||
|
TestSuite suite = new TestSuite(ConstructorUtilsTest.class);
|
||||||
|
suite.setName("ConstructorUtils Tests");
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
classCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConstructor() throws Exception {
|
||||||
|
assertNotNull(MethodUtils.class.newInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInvokeConstructor() throws Exception {
|
||||||
|
assertEquals("()", ConstructorUtils.invokeConstructor(TestBean.class,
|
||||||
|
ArrayUtils.EMPTY_CLASS_ARRAY).toString());
|
||||||
|
assertEquals("()", ConstructorUtils.invokeConstructor(TestBean.class,
|
||||||
|
(Class[]) null).toString());
|
||||||
|
assertEquals("(String)", ConstructorUtils.invokeConstructor(
|
||||||
|
TestBean.class, "").toString());
|
||||||
|
assertEquals("(Object)", ConstructorUtils.invokeConstructor(
|
||||||
|
TestBean.class, new Object()).toString());
|
||||||
|
assertEquals("(Object)", ConstructorUtils.invokeConstructor(
|
||||||
|
TestBean.class, Boolean.TRUE).toString());
|
||||||
|
assertEquals("(Integer)", ConstructorUtils.invokeConstructor(
|
||||||
|
TestBean.class, NumberUtils.INTEGER_ONE).toString());
|
||||||
|
assertEquals("(int)", ConstructorUtils.invokeConstructor(
|
||||||
|
TestBean.class, NumberUtils.BYTE_ONE).toString());
|
||||||
|
assertEquals("(double)", ConstructorUtils.invokeConstructor(
|
||||||
|
TestBean.class, NumberUtils.LONG_ONE).toString());
|
||||||
|
assertEquals("(double)", ConstructorUtils.invokeConstructor(
|
||||||
|
TestBean.class, NumberUtils.DOUBLE_ONE).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInvokeExactConstructor() throws Exception {
|
||||||
|
assertEquals("()", ConstructorUtils.invokeExactConstructor(
|
||||||
|
TestBean.class, ArrayUtils.EMPTY_CLASS_ARRAY).toString());
|
||||||
|
assertEquals("()", ConstructorUtils.invokeExactConstructor(
|
||||||
|
TestBean.class, (Class[]) null).toString());
|
||||||
|
assertEquals("(String)", ConstructorUtils.invokeExactConstructor(
|
||||||
|
TestBean.class, "").toString());
|
||||||
|
assertEquals("(Object)", ConstructorUtils.invokeExactConstructor(
|
||||||
|
TestBean.class, new Object()).toString());
|
||||||
|
assertEquals("(Integer)", ConstructorUtils.invokeExactConstructor(
|
||||||
|
TestBean.class, NumberUtils.INTEGER_ONE).toString());
|
||||||
|
assertEquals("(double)", ConstructorUtils.invokeExactConstructor(
|
||||||
|
TestBean.class, new Object[] { NumberUtils.DOUBLE_ONE },
|
||||||
|
new Class[] { Double.TYPE }).toString());
|
||||||
|
|
||||||
|
try {
|
||||||
|
ConstructorUtils.invokeExactConstructor(TestBean.class,
|
||||||
|
NumberUtils.BYTE_ONE);
|
||||||
|
fail("should throw NoSuchMethodException");
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
ConstructorUtils.invokeExactConstructor(TestBean.class,
|
||||||
|
NumberUtils.LONG_ONE);
|
||||||
|
fail("should throw NoSuchMethodException");
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
ConstructorUtils.invokeExactConstructor(TestBean.class,
|
||||||
|
Boolean.TRUE);
|
||||||
|
fail("should throw NoSuchMethodException");
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetAccessibleConstructor() throws Exception {
|
||||||
|
assertNotNull(ConstructorUtils.getAccessibleConstructor(Object.class
|
||||||
|
.getConstructor(ArrayUtils.EMPTY_CLASS_ARRAY)));
|
||||||
|
assertNull(ConstructorUtils.getAccessibleConstructor(PrivateClass.class
|
||||||
|
.getConstructor(ArrayUtils.EMPTY_CLASS_ARRAY)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetAccessibleConstructorFromDescription() throws Exception {
|
||||||
|
assertNotNull(ConstructorUtils.getAccessibleConstructor(Object.class,
|
||||||
|
ArrayUtils.EMPTY_CLASS_ARRAY));
|
||||||
|
assertNull(ConstructorUtils.getAccessibleConstructor(
|
||||||
|
PrivateClass.class, ArrayUtils.EMPTY_CLASS_ARRAY));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetMatchingAccessibleMethod() throws Exception {
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
ArrayUtils.EMPTY_CLASS_ARRAY, ArrayUtils.EMPTY_CLASS_ARRAY);
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class, null,
|
||||||
|
ArrayUtils.EMPTY_CLASS_ARRAY);
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(String.class), singletonArray(String.class));
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(Object.class), singletonArray(Object.class));
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(Boolean.class), singletonArray(Object.class));
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(Byte.class), singletonArray(Integer.TYPE));
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(Byte.TYPE), singletonArray(Integer.TYPE));
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(Short.class), singletonArray(Integer.TYPE));
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(Short.TYPE), singletonArray(Integer.TYPE));
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(Character.class), singletonArray(Integer.TYPE));
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(Character.TYPE), singletonArray(Integer.TYPE));
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(Integer.class), singletonArray(Integer.class));
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(Integer.TYPE), singletonArray(Integer.TYPE));
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(Long.class), singletonArray(Double.TYPE));
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(Long.TYPE), singletonArray(Double.TYPE));
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(Float.class), singletonArray(Double.TYPE));
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(Float.TYPE), singletonArray(Double.TYPE));
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(Double.class), singletonArray(Double.TYPE));
|
||||||
|
expectMatchingAccessibleConstructorParameterTypes(TestBean.class,
|
||||||
|
singletonArray(Double.TYPE), singletonArray(Double.TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expectMatchingAccessibleConstructorParameterTypes(Class cls,
|
||||||
|
Class[] requestTypes, Class[] actualTypes) {
|
||||||
|
Constructor c = ConstructorUtils.getMatchingAccessibleConstructor(cls,
|
||||||
|
requestTypes);
|
||||||
|
assertTrue(Arrays.toString(c.getParameterTypes()) + " not equals "
|
||||||
|
+ Arrays.toString(actualTypes), Arrays.equals(actualTypes, c
|
||||||
|
.getParameterTypes()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Class[] singletonArray(Class c) {
|
||||||
|
Class[] result = (Class[]) classCache.get(c);
|
||||||
|
if (result == null) {
|
||||||
|
result = new Class[] { c };
|
||||||
|
classCache.put(c, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
920
src/test/org/apache/commons/lang/reflect/FieldUtilsTest.java
Normal file
920
src/test/org/apache/commons/lang/reflect/FieldUtilsTest.java
Normal file
@ -0,0 +1,920 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.reflect.testbed.Ambig;
|
||||||
|
import org.apache.commons.lang.reflect.testbed.Foo;
|
||||||
|
import org.apache.commons.lang.reflect.testbed.PrivatelyShadowedChild;
|
||||||
|
import org.apache.commons.lang.reflect.testbed.PublicChild;
|
||||||
|
import org.apache.commons.lang.reflect.testbed.PubliclyShadowedChild;
|
||||||
|
import org.apache.commons.lang.reflect.testbed.StaticContainer;
|
||||||
|
import org.apache.commons.lang.reflect.testbed.StaticContainerChild;
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests FieldUtils
|
||||||
|
* @author mbenson
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class FieldUtilsTest extends TestCase {
|
||||||
|
|
||||||
|
static final String S = "s";
|
||||||
|
static final String SS = "ss";
|
||||||
|
static final Integer I0 = new Integer(0);
|
||||||
|
static final Integer I1 = new Integer(1);
|
||||||
|
static final Double D0 = new Double(0.0);
|
||||||
|
static final Double D1 = new Double(1.0);
|
||||||
|
|
||||||
|
private PublicChild publicChild;
|
||||||
|
private PubliclyShadowedChild publiclyShadowedChild;
|
||||||
|
private PrivatelyShadowedChild privatelyShadowedChild;
|
||||||
|
private Class parentClass = PublicChild.class.getSuperclass();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the test cases as a suite.
|
||||||
|
* @return the Test
|
||||||
|
*/
|
||||||
|
public static Test suite() {
|
||||||
|
TestSuite suite = new TestSuite(FieldUtilsTest.class);
|
||||||
|
suite.setName("FieldUtils Tests");
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
StaticContainer.reset();
|
||||||
|
publicChild = new PublicChild();
|
||||||
|
publiclyShadowedChild = new PubliclyShadowedChild();
|
||||||
|
privatelyShadowedChild = new PrivatelyShadowedChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetField() {
|
||||||
|
assertEquals(Foo.class, FieldUtils.getField(PublicChild.class, "VALUE").getDeclaringClass());
|
||||||
|
assertEquals(parentClass, FieldUtils.getField(PublicChild.class, "s").getDeclaringClass());
|
||||||
|
assertNull(FieldUtils.getField(PublicChild.class, "b"));
|
||||||
|
assertNull(FieldUtils.getField(PublicChild.class, "i"));
|
||||||
|
assertNull(FieldUtils.getField(PublicChild.class, "d"));
|
||||||
|
assertEquals(Foo.class, FieldUtils.getField(PubliclyShadowedChild.class, "VALUE").getDeclaringClass());
|
||||||
|
assertEquals(PubliclyShadowedChild.class, FieldUtils.getField(PubliclyShadowedChild.class, "s")
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PubliclyShadowedChild.class, FieldUtils.getField(PubliclyShadowedChild.class, "b")
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PubliclyShadowedChild.class, FieldUtils.getField(PubliclyShadowedChild.class, "i")
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PubliclyShadowedChild.class, FieldUtils.getField(PubliclyShadowedChild.class, "d")
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(Foo.class, FieldUtils.getField(PrivatelyShadowedChild.class, "VALUE").getDeclaringClass());
|
||||||
|
assertEquals(parentClass, FieldUtils.getField(PrivatelyShadowedChild.class, "s").getDeclaringClass());
|
||||||
|
assertNull(FieldUtils.getField(PrivatelyShadowedChild.class, "b"));
|
||||||
|
assertNull(FieldUtils.getField(PrivatelyShadowedChild.class, "i"));
|
||||||
|
assertNull(FieldUtils.getField(PrivatelyShadowedChild.class, "d"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetFieldForceAccess() {
|
||||||
|
assertEquals(PublicChild.class, FieldUtils.getField(PublicChild.class, "VALUE", true).getDeclaringClass());
|
||||||
|
assertEquals(parentClass, FieldUtils.getField(PublicChild.class, "s", true).getDeclaringClass());
|
||||||
|
assertEquals(parentClass, FieldUtils.getField(PublicChild.class, "b", true).getDeclaringClass());
|
||||||
|
assertEquals(parentClass, FieldUtils.getField(PublicChild.class, "i", true).getDeclaringClass());
|
||||||
|
assertEquals(parentClass, FieldUtils.getField(PublicChild.class, "d", true).getDeclaringClass());
|
||||||
|
assertEquals(Foo.class, FieldUtils.getField(PubliclyShadowedChild.class, "VALUE", true).getDeclaringClass());
|
||||||
|
assertEquals(PubliclyShadowedChild.class, FieldUtils.getField(PubliclyShadowedChild.class, "s", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PubliclyShadowedChild.class, FieldUtils.getField(PubliclyShadowedChild.class, "b", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PubliclyShadowedChild.class, FieldUtils.getField(PubliclyShadowedChild.class, "i", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PubliclyShadowedChild.class, FieldUtils.getField(PubliclyShadowedChild.class, "d", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(Foo.class, FieldUtils.getField(PrivatelyShadowedChild.class, "VALUE", true).getDeclaringClass());
|
||||||
|
assertEquals(PrivatelyShadowedChild.class, FieldUtils.getField(PrivatelyShadowedChild.class, "s", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PrivatelyShadowedChild.class, FieldUtils.getField(PrivatelyShadowedChild.class, "b", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PrivatelyShadowedChild.class, FieldUtils.getField(PrivatelyShadowedChild.class, "i", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PrivatelyShadowedChild.class, FieldUtils.getField(PrivatelyShadowedChild.class, "d", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetDeclaredField() {
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PublicChild.class, "VALUE"));
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PublicChild.class, "s"));
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PublicChild.class, "b"));
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PublicChild.class, "i"));
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PublicChild.class, "d"));
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PubliclyShadowedChild.class, "VALUE"));
|
||||||
|
assertEquals(PubliclyShadowedChild.class, FieldUtils.getDeclaredField(PubliclyShadowedChild.class, "s")
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PubliclyShadowedChild.class, FieldUtils.getDeclaredField(PubliclyShadowedChild.class, "b")
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PubliclyShadowedChild.class, FieldUtils.getDeclaredField(PubliclyShadowedChild.class, "i")
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PubliclyShadowedChild.class, FieldUtils.getDeclaredField(PubliclyShadowedChild.class, "d")
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PrivatelyShadowedChild.class, "VALUE"));
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PrivatelyShadowedChild.class, "s"));
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PrivatelyShadowedChild.class, "b"));
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PrivatelyShadowedChild.class, "i"));
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PrivatelyShadowedChild.class, "d"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetDeclaredFieldForceAccess() {
|
||||||
|
assertEquals(PublicChild.class, FieldUtils.getDeclaredField(PublicChild.class, "VALUE", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PublicChild.class, "s", true));
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PublicChild.class, "b", true));
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PublicChild.class, "i", true));
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PublicChild.class, "d", true));
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PubliclyShadowedChild.class, "VALUE", true));
|
||||||
|
assertEquals(PubliclyShadowedChild.class, FieldUtils.getDeclaredField(PubliclyShadowedChild.class, "s", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PubliclyShadowedChild.class, FieldUtils.getDeclaredField(PubliclyShadowedChild.class, "b", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PubliclyShadowedChild.class, FieldUtils.getDeclaredField(PubliclyShadowedChild.class, "i", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PubliclyShadowedChild.class, FieldUtils.getDeclaredField(PubliclyShadowedChild.class, "d", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertNull(FieldUtils.getDeclaredField(PrivatelyShadowedChild.class, "VALUE", true));
|
||||||
|
assertEquals(PrivatelyShadowedChild.class, FieldUtils.getDeclaredField(PrivatelyShadowedChild.class, "s", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PrivatelyShadowedChild.class, FieldUtils.getDeclaredField(PrivatelyShadowedChild.class, "b", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PrivatelyShadowedChild.class, FieldUtils.getDeclaredField(PrivatelyShadowedChild.class, "i", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(PrivatelyShadowedChild.class, FieldUtils.getDeclaredField(PrivatelyShadowedChild.class, "d", true)
|
||||||
|
.getDeclaringClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadStaticField() throws Exception {
|
||||||
|
assertEquals(Foo.VALUE, FieldUtils.readStaticField(FieldUtils.getField(Foo.class, "VALUE")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadStaticFieldForceAccess() throws Exception {
|
||||||
|
assertEquals(Foo.VALUE, FieldUtils.readStaticField(FieldUtils.getField(Foo.class, "VALUE")));
|
||||||
|
assertEquals(Foo.VALUE, FieldUtils.readStaticField(FieldUtils.getField(PublicChild.class, "VALUE")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadNamedStaticField() throws Exception {
|
||||||
|
assertEquals(Foo.VALUE, FieldUtils.readStaticField(Foo.class, "VALUE"));
|
||||||
|
assertEquals(Foo.VALUE, FieldUtils.readStaticField(PubliclyShadowedChild.class, "VALUE"));
|
||||||
|
assertEquals(Foo.VALUE, FieldUtils.readStaticField(PrivatelyShadowedChild.class, "VALUE"));
|
||||||
|
assertEquals(Foo.VALUE, FieldUtils.readStaticField(PublicChild.class, "VALUE"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadNamedStaticFieldForceAccess() throws Exception {
|
||||||
|
assertEquals(Foo.VALUE, FieldUtils.readStaticField(Foo.class, "VALUE", true));
|
||||||
|
assertEquals(Foo.VALUE, FieldUtils.readStaticField(PubliclyShadowedChild.class, "VALUE", true));
|
||||||
|
assertEquals(Foo.VALUE, FieldUtils.readStaticField(PrivatelyShadowedChild.class, "VALUE", true));
|
||||||
|
assertEquals("child", FieldUtils.readStaticField(PublicChild.class, "VALUE", true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadDeclaredNamedStaticField() throws Exception {
|
||||||
|
assertEquals(Foo.VALUE, FieldUtils.readDeclaredStaticField(Foo.class, "VALUE"));
|
||||||
|
try {
|
||||||
|
assertEquals("child", FieldUtils.readDeclaredStaticField(PublicChild.class, "VALUE"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
assertEquals(Foo.VALUE, FieldUtils.readDeclaredStaticField(PubliclyShadowedChild.class, "VALUE"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
assertEquals(Foo.VALUE, FieldUtils.readDeclaredStaticField(PrivatelyShadowedChild.class, "VALUE"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadDeclaredNamedStaticFieldForceAccess() throws Exception {
|
||||||
|
assertEquals(Foo.VALUE, FieldUtils.readDeclaredStaticField(Foo.class, "VALUE", true));
|
||||||
|
assertEquals("child", FieldUtils.readDeclaredStaticField(PublicChild.class, "VALUE", true));
|
||||||
|
try {
|
||||||
|
assertEquals(Foo.VALUE, FieldUtils.readDeclaredStaticField(PubliclyShadowedChild.class, "VALUE", true));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
assertEquals(Foo.VALUE, FieldUtils.readDeclaredStaticField(PrivatelyShadowedChild.class, "VALUE", true));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadField() throws Exception {
|
||||||
|
Field parentS = FieldUtils.getDeclaredField(parentClass, "s");
|
||||||
|
assertEquals("s", FieldUtils.readField(parentS, publicChild));
|
||||||
|
assertEquals("s", FieldUtils.readField(parentS, publiclyShadowedChild));
|
||||||
|
assertEquals("s", FieldUtils.readField(parentS, privatelyShadowedChild));
|
||||||
|
Field parentB = FieldUtils.getDeclaredField(parentClass, "b", true);
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readField(parentB, publicChild));
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readField(parentB, publiclyShadowedChild));
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readField(parentB, privatelyShadowedChild));
|
||||||
|
Field parentI = FieldUtils.getDeclaredField(parentClass, "i", true);
|
||||||
|
assertEquals(I0, FieldUtils.readField(parentI, publicChild));
|
||||||
|
assertEquals(I0, FieldUtils.readField(parentI, publiclyShadowedChild));
|
||||||
|
assertEquals(I0, FieldUtils.readField(parentI, privatelyShadowedChild));
|
||||||
|
Field parentD = FieldUtils.getDeclaredField(parentClass, "d", true);
|
||||||
|
assertEquals(D0, FieldUtils.readField(parentD, publicChild));
|
||||||
|
assertEquals(D0, FieldUtils.readField(parentD, publiclyShadowedChild));
|
||||||
|
assertEquals(D0, FieldUtils.readField(parentD, privatelyShadowedChild));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadFieldForceAccess() throws Exception {
|
||||||
|
Field parentS = FieldUtils.getDeclaredField(parentClass, "s");
|
||||||
|
parentS.setAccessible(false);
|
||||||
|
assertEquals("s", FieldUtils.readField(parentS, publicChild, true));
|
||||||
|
assertEquals("s", FieldUtils.readField(parentS, publiclyShadowedChild, true));
|
||||||
|
assertEquals("s", FieldUtils.readField(parentS, privatelyShadowedChild, true));
|
||||||
|
Field parentB = FieldUtils.getDeclaredField(parentClass, "b", true);
|
||||||
|
parentB.setAccessible(false);
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readField(parentB, publicChild, true));
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readField(parentB, publiclyShadowedChild, true));
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readField(parentB, privatelyShadowedChild, true));
|
||||||
|
Field parentI = FieldUtils.getDeclaredField(parentClass, "i", true);
|
||||||
|
parentI.setAccessible(false);
|
||||||
|
assertEquals(I0, FieldUtils.readField(parentI, publicChild, true));
|
||||||
|
assertEquals(I0, FieldUtils.readField(parentI, publiclyShadowedChild, true));
|
||||||
|
assertEquals(I0, FieldUtils.readField(parentI, privatelyShadowedChild, true));
|
||||||
|
Field parentD = FieldUtils.getDeclaredField(parentClass, "d", true);
|
||||||
|
parentD.setAccessible(false);
|
||||||
|
assertEquals(D0, FieldUtils.readField(parentD, publicChild, true));
|
||||||
|
assertEquals(D0, FieldUtils.readField(parentD, publiclyShadowedChild, true));
|
||||||
|
assertEquals(D0, FieldUtils.readField(parentD, privatelyShadowedChild, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadNamedField() throws Exception {
|
||||||
|
assertEquals("s", FieldUtils.readField(publicChild, "s"));
|
||||||
|
assertEquals("ss", FieldUtils.readField(publiclyShadowedChild, "s"));
|
||||||
|
assertEquals("s", FieldUtils.readField(privatelyShadowedChild, "s"));
|
||||||
|
try {
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readField(publicChild, "b"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
assertEquals(Boolean.TRUE, FieldUtils.readField(publiclyShadowedChild, "b"));
|
||||||
|
try {
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readField(privatelyShadowedChild, "b"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
assertEquals(I0, FieldUtils.readField(publicChild, "i"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
assertEquals(I1, FieldUtils.readField(publiclyShadowedChild, "i"));
|
||||||
|
try {
|
||||||
|
assertEquals(I0, FieldUtils.readField(privatelyShadowedChild, "i"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
assertEquals(D0, FieldUtils.readField(publicChild, "d"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
assertEquals(D1, FieldUtils.readField(publiclyShadowedChild, "d"));
|
||||||
|
try {
|
||||||
|
assertEquals(D0, FieldUtils.readField(privatelyShadowedChild, "d"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadNamedFieldForceAccess() throws Exception {
|
||||||
|
assertEquals("s", FieldUtils.readField(publicChild, "s", true));
|
||||||
|
assertEquals("ss", FieldUtils.readField(publiclyShadowedChild, "s", true));
|
||||||
|
assertEquals("ss", FieldUtils.readField(privatelyShadowedChild, "s", true));
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readField(publicChild, "b", true));
|
||||||
|
assertEquals(Boolean.TRUE, FieldUtils.readField(publiclyShadowedChild, "b", true));
|
||||||
|
assertEquals(Boolean.TRUE, FieldUtils.readField(privatelyShadowedChild, "b", true));
|
||||||
|
assertEquals(I0, FieldUtils.readField(publicChild, "i", true));
|
||||||
|
assertEquals(I1, FieldUtils.readField(publiclyShadowedChild, "i", true));
|
||||||
|
assertEquals(I1, FieldUtils.readField(privatelyShadowedChild, "i", true));
|
||||||
|
assertEquals(D0, FieldUtils.readField(publicChild, "d", true));
|
||||||
|
assertEquals(D1, FieldUtils.readField(publiclyShadowedChild, "d", true));
|
||||||
|
assertEquals(D1, FieldUtils.readField(privatelyShadowedChild, "d", true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadDeclaredNamedField() throws Exception {
|
||||||
|
try {
|
||||||
|
assertEquals("s", FieldUtils.readDeclaredField(publicChild, "s"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
assertEquals("ss", FieldUtils.readDeclaredField(publiclyShadowedChild, "s"));
|
||||||
|
try {
|
||||||
|
assertEquals("s", FieldUtils.readDeclaredField(privatelyShadowedChild, "s"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readDeclaredField(publicChild, "b"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
assertEquals(Boolean.TRUE, FieldUtils.readDeclaredField(publiclyShadowedChild, "b"));
|
||||||
|
try {
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readDeclaredField(privatelyShadowedChild, "b"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
assertEquals(I0, FieldUtils.readDeclaredField(publicChild, "i"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
assertEquals(I1, FieldUtils.readDeclaredField(publiclyShadowedChild, "i"));
|
||||||
|
try {
|
||||||
|
assertEquals(I0, FieldUtils.readDeclaredField(privatelyShadowedChild, "i"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
assertEquals(D0, FieldUtils.readDeclaredField(publicChild, "d"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
assertEquals(D1, FieldUtils.readDeclaredField(publiclyShadowedChild, "d"));
|
||||||
|
try {
|
||||||
|
assertEquals(D0, FieldUtils.readDeclaredField(privatelyShadowedChild, "d"));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadDeclaredNamedFieldForceAccess() throws Exception {
|
||||||
|
try {
|
||||||
|
assertEquals("s", FieldUtils.readDeclaredField(publicChild, "s", true));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
assertEquals("ss", FieldUtils.readDeclaredField(publiclyShadowedChild, "s", true));
|
||||||
|
assertEquals("ss", FieldUtils.readDeclaredField(privatelyShadowedChild, "s", true));
|
||||||
|
try {
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readDeclaredField(publicChild, "b", true));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
assertEquals(Boolean.TRUE, FieldUtils.readDeclaredField(publiclyShadowedChild, "b", true));
|
||||||
|
assertEquals(Boolean.TRUE, FieldUtils.readDeclaredField(privatelyShadowedChild, "b", true));
|
||||||
|
try {
|
||||||
|
assertEquals(I0, FieldUtils.readDeclaredField(publicChild, "i", true));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
assertEquals(I1, FieldUtils.readDeclaredField(publiclyShadowedChild, "i", true));
|
||||||
|
assertEquals(I1, FieldUtils.readDeclaredField(privatelyShadowedChild, "i", true));
|
||||||
|
try {
|
||||||
|
assertEquals(D0, FieldUtils.readDeclaredField(publicChild, "d", true));
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
assertEquals(D1, FieldUtils.readDeclaredField(publiclyShadowedChild, "d", true));
|
||||||
|
assertEquals(D1, FieldUtils.readDeclaredField(privatelyShadowedChild, "d", true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteStaticField() throws Exception {
|
||||||
|
Field field = StaticContainer.class.getDeclaredField("mutablePublic");
|
||||||
|
FieldUtils.writeStaticField(field, "new");
|
||||||
|
assertEquals("new", StaticContainer.mutablePublic);
|
||||||
|
field = StaticContainer.class.getDeclaredField("mutableProtected");
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(field, "new");
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
field = StaticContainer.class.getDeclaredField("mutablePackage");
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(field, "new");
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
field = StaticContainer.class.getDeclaredField("mutablePrivate");
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(field, "new");
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
field = StaticContainer.class.getDeclaredField("IMMUTABLE_PUBLIC");
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(field, "new");
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
field = StaticContainer.class.getDeclaredField("IMMUTABLE_PROTECTED");
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(field, "new");
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
field = StaticContainer.class.getDeclaredField("IMMUTABLE_PACKAGE");
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(field, "new");
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
field = StaticContainer.class.getDeclaredField("IMMUTABLE_PRIVATE");
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(field, "new");
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteStaticFieldForceAccess() throws Exception {
|
||||||
|
Field field = StaticContainer.class.getDeclaredField("mutablePublic");
|
||||||
|
FieldUtils.writeStaticField(field, "new", true);
|
||||||
|
assertEquals("new", StaticContainer.mutablePublic);
|
||||||
|
field = StaticContainer.class.getDeclaredField("mutableProtected");
|
||||||
|
FieldUtils.writeStaticField(field, "new", true);
|
||||||
|
assertEquals("new", StaticContainer.getMutableProtected());
|
||||||
|
field = StaticContainer.class.getDeclaredField("mutablePackage");
|
||||||
|
FieldUtils.writeStaticField(field, "new", true);
|
||||||
|
assertEquals("new", StaticContainer.getMutablePackage());
|
||||||
|
field = StaticContainer.class.getDeclaredField("mutablePrivate");
|
||||||
|
FieldUtils.writeStaticField(field, "new", true);
|
||||||
|
assertEquals("new", StaticContainer.getMutablePrivate());
|
||||||
|
field = StaticContainer.class.getDeclaredField("IMMUTABLE_PUBLIC");
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(field, "new", true);
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
field = StaticContainer.class.getDeclaredField("IMMUTABLE_PROTECTED");
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(field, "new", true);
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
field = StaticContainer.class.getDeclaredField("IMMUTABLE_PACKAGE");
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(field, "new", true);
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
field = StaticContainer.class.getDeclaredField("IMMUTABLE_PRIVATE");
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(field, "new", true);
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteNamedStaticField() throws Exception {
|
||||||
|
FieldUtils.writeStaticField(StaticContainerChild.class, "mutablePublic", "new");
|
||||||
|
assertEquals("new", StaticContainer.mutablePublic);
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(StaticContainerChild.class, "mutableProtected", "new");
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(StaticContainerChild.class, "mutablePackage", "new");
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(StaticContainerChild.class, "mutablePrivate", "new");
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(StaticContainerChild.class, "IMMUTABLE_PUBLIC", "new");
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(StaticContainerChild.class, "IMMUTABLE_PROTECTED", "new");
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(StaticContainerChild.class, "IMMUTABLE_PACKAGE", "new");
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(StaticContainerChild.class, "IMMUTABLE_PRIVATE", "new");
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteNamedStaticFieldForceAccess() throws Exception {
|
||||||
|
FieldUtils.writeStaticField(StaticContainerChild.class, "mutablePublic", "new", true);
|
||||||
|
assertEquals("new", StaticContainer.mutablePublic);
|
||||||
|
FieldUtils.writeStaticField(StaticContainerChild.class, "mutableProtected", "new", true);
|
||||||
|
assertEquals("new", StaticContainer.getMutableProtected());
|
||||||
|
FieldUtils.writeStaticField(StaticContainerChild.class, "mutablePackage", "new", true);
|
||||||
|
assertEquals("new", StaticContainer.getMutablePackage());
|
||||||
|
FieldUtils.writeStaticField(StaticContainerChild.class, "mutablePrivate", "new", true);
|
||||||
|
assertEquals("new", StaticContainer.getMutablePrivate());
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(StaticContainerChild.class, "IMMUTABLE_PUBLIC", "new", true);
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(StaticContainerChild.class, "IMMUTABLE_PROTECTED", "new", true);
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(StaticContainerChild.class, "IMMUTABLE_PACKAGE", "new", true);
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeStaticField(StaticContainerChild.class, "IMMUTABLE_PRIVATE", "new", true);
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteDeclaredNamedStaticField() throws Exception {
|
||||||
|
FieldUtils.writeStaticField(StaticContainer.class, "mutablePublic", "new");
|
||||||
|
assertEquals("new", StaticContainer.mutablePublic);
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredStaticField(StaticContainer.class, "mutableProtected", "new");
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredStaticField(StaticContainer.class, "mutablePackage", "new");
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredStaticField(StaticContainer.class, "mutablePrivate", "new");
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredStaticField(StaticContainer.class, "IMMUTABLE_PUBLIC", "new");
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredStaticField(StaticContainer.class, "IMMUTABLE_PROTECTED", "new");
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredStaticField(StaticContainer.class, "IMMUTABLE_PACKAGE", "new");
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredStaticField(StaticContainer.class, "IMMUTABLE_PRIVATE", "new");
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteDeclaredNamedStaticFieldForceAccess() throws Exception {
|
||||||
|
FieldUtils.writeDeclaredStaticField(StaticContainer.class, "mutablePublic", "new", true);
|
||||||
|
assertEquals("new", StaticContainer.mutablePublic);
|
||||||
|
FieldUtils.writeDeclaredStaticField(StaticContainer.class, "mutableProtected", "new", true);
|
||||||
|
assertEquals("new", StaticContainer.getMutableProtected());
|
||||||
|
FieldUtils.writeDeclaredStaticField(StaticContainer.class, "mutablePackage", "new", true);
|
||||||
|
assertEquals("new", StaticContainer.getMutablePackage());
|
||||||
|
FieldUtils.writeDeclaredStaticField(StaticContainer.class, "mutablePrivate", "new", true);
|
||||||
|
assertEquals("new", StaticContainer.getMutablePrivate());
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredStaticField(StaticContainer.class, "IMMUTABLE_PUBLIC", "new", true);
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredStaticField(StaticContainer.class, "IMMUTABLE_PROTECTED", "new", true);
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredStaticField(StaticContainer.class, "IMMUTABLE_PACKAGE", "new", true);
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredStaticField(StaticContainer.class, "IMMUTABLE_PRIVATE", "new", true);
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteField() throws Exception {
|
||||||
|
Field field = parentClass.getDeclaredField("s");
|
||||||
|
FieldUtils.writeField(field, publicChild, "S");
|
||||||
|
assertEquals("S", field.get(publicChild));
|
||||||
|
field = parentClass.getDeclaredField("b");
|
||||||
|
try {
|
||||||
|
FieldUtils.writeField(field, publicChild, Boolean.TRUE);
|
||||||
|
fail("Expected IllegalAccessException");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
field = parentClass.getDeclaredField("i");
|
||||||
|
try {
|
||||||
|
FieldUtils.writeField(field, publicChild, new Integer(Integer.MAX_VALUE));
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
field = parentClass.getDeclaredField("d");
|
||||||
|
try {
|
||||||
|
FieldUtils.writeField(field, publicChild, new Double(Double.MAX_VALUE));
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteFieldForceAccess() throws Exception {
|
||||||
|
Field field = parentClass.getDeclaredField("s");
|
||||||
|
FieldUtils.writeField(field, publicChild, "S", true);
|
||||||
|
assertEquals("S", field.get(publicChild));
|
||||||
|
field = parentClass.getDeclaredField("b");
|
||||||
|
FieldUtils.writeField(field, publicChild, Boolean.TRUE, true);
|
||||||
|
assertEquals(Boolean.TRUE, field.get(publicChild));
|
||||||
|
field = parentClass.getDeclaredField("i");
|
||||||
|
FieldUtils.writeField(field, publicChild, new Integer(Integer.MAX_VALUE), true);
|
||||||
|
assertEquals(new Integer(Integer.MAX_VALUE), field.get(publicChild));
|
||||||
|
field = parentClass.getDeclaredField("d");
|
||||||
|
FieldUtils.writeField(field, publicChild, new Double(Double.MAX_VALUE), true);
|
||||||
|
assertEquals(new Double(Double.MAX_VALUE), field.get(publicChild));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteNamedField() throws Exception {
|
||||||
|
FieldUtils.writeField(publicChild, "s", "S");
|
||||||
|
assertEquals("S", FieldUtils.readField(publicChild, "s"));
|
||||||
|
try {
|
||||||
|
FieldUtils.writeField(publicChild, "b", Boolean.TRUE);
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeField(publicChild, "i", new Integer(1));
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeField(publicChild, "d", new Double(1.0));
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldUtils.writeField(publiclyShadowedChild, "s", "S");
|
||||||
|
assertEquals("S", FieldUtils.readField(publiclyShadowedChild, "s"));
|
||||||
|
FieldUtils.writeField(publiclyShadowedChild, "b", Boolean.FALSE);
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readField(publiclyShadowedChild, "b"));
|
||||||
|
FieldUtils.writeField(publiclyShadowedChild, "i", new Integer(0));
|
||||||
|
assertEquals(new Integer(0), FieldUtils.readField(publiclyShadowedChild, "i"));
|
||||||
|
FieldUtils.writeField(publiclyShadowedChild, "d", new Double(0.0));
|
||||||
|
assertEquals(new Double(0.0), FieldUtils.readField(publiclyShadowedChild, "d"));
|
||||||
|
|
||||||
|
FieldUtils.writeField(privatelyShadowedChild, "s", "S");
|
||||||
|
assertEquals("S", FieldUtils.readField(privatelyShadowedChild, "s"));
|
||||||
|
try {
|
||||||
|
FieldUtils.writeField(privatelyShadowedChild, "b", Boolean.TRUE);
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeField(privatelyShadowedChild, "i", new Integer(1));
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeField(privatelyShadowedChild, "d", new Double(1.0));
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteNamedFieldForceAccess() throws Exception {
|
||||||
|
FieldUtils.writeField(publicChild, "s", "S", true);
|
||||||
|
assertEquals("S", FieldUtils.readField(publicChild, "s", true));
|
||||||
|
FieldUtils.writeField(publicChild, "b", Boolean.TRUE, true);
|
||||||
|
assertEquals(Boolean.TRUE, FieldUtils.readField(publicChild, "b", true));
|
||||||
|
FieldUtils.writeField(publicChild, "i", new Integer(1), true);
|
||||||
|
assertEquals(new Integer(1), FieldUtils.readField(publicChild, "i", true));
|
||||||
|
FieldUtils.writeField(publicChild, "d", new Double(1.0), true);
|
||||||
|
assertEquals(new Double(1.0), FieldUtils.readField(publicChild, "d", true));
|
||||||
|
|
||||||
|
FieldUtils.writeField(publiclyShadowedChild, "s", "S", true);
|
||||||
|
assertEquals("S", FieldUtils.readField(publiclyShadowedChild, "s", true));
|
||||||
|
FieldUtils.writeField(publiclyShadowedChild, "b", Boolean.FALSE, true);
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readField(publiclyShadowedChild, "b", true));
|
||||||
|
FieldUtils.writeField(publiclyShadowedChild, "i", new Integer(0), true);
|
||||||
|
assertEquals(new Integer(0), FieldUtils.readField(publiclyShadowedChild, "i", true));
|
||||||
|
FieldUtils.writeField(publiclyShadowedChild, "d", new Double(0.0), true);
|
||||||
|
assertEquals(new Double(0.0), FieldUtils.readField(publiclyShadowedChild, "d", true));
|
||||||
|
|
||||||
|
FieldUtils.writeField(privatelyShadowedChild, "s", "S", true);
|
||||||
|
assertEquals("S", FieldUtils.readField(privatelyShadowedChild, "s", true));
|
||||||
|
FieldUtils.writeField(privatelyShadowedChild, "b", Boolean.FALSE, true);
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readField(privatelyShadowedChild, "b", true));
|
||||||
|
FieldUtils.writeField(privatelyShadowedChild, "i", new Integer(0), true);
|
||||||
|
assertEquals(new Integer(0), FieldUtils.readField(privatelyShadowedChild, "i", true));
|
||||||
|
FieldUtils.writeField(privatelyShadowedChild, "d", new Double(0.0), true);
|
||||||
|
assertEquals(new Double(0.0), FieldUtils.readField(privatelyShadowedChild, "d", true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteDeclaredNamedField() throws Exception {
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredField(publicChild, "s", "S");
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredField(publicChild, "b", Boolean.TRUE);
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredField(publicChild, "i", new Integer(1));
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredField(publicChild, "d", new Double(1.0));
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldUtils.writeDeclaredField(publiclyShadowedChild, "s", "S");
|
||||||
|
assertEquals("S", FieldUtils.readDeclaredField(publiclyShadowedChild, "s"));
|
||||||
|
FieldUtils.writeDeclaredField(publiclyShadowedChild, "b", Boolean.FALSE);
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readDeclaredField(publiclyShadowedChild, "b"));
|
||||||
|
FieldUtils.writeDeclaredField(publiclyShadowedChild, "i", new Integer(0));
|
||||||
|
assertEquals(new Integer(0), FieldUtils.readDeclaredField(publiclyShadowedChild, "i"));
|
||||||
|
FieldUtils.writeDeclaredField(publiclyShadowedChild, "d", new Double(0.0));
|
||||||
|
assertEquals(new Double(0.0), FieldUtils.readDeclaredField(publiclyShadowedChild, "d"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredField(privatelyShadowedChild, "s", "S");
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredField(privatelyShadowedChild, "b", Boolean.TRUE);
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredField(privatelyShadowedChild, "i", new Integer(1));
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredField(privatelyShadowedChild, "d", new Double(1.0));
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteDeclaredNamedFieldForceAccess() throws Exception {
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredField(publicChild, "s", "S", true);
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredField(publicChild, "b", Boolean.TRUE, true);
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredField(publicChild, "i", new Integer(1), true);
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FieldUtils.writeDeclaredField(publicChild, "d", new Double(1.0), true);
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldUtils.writeDeclaredField(publiclyShadowedChild, "s", "S", true);
|
||||||
|
assertEquals("S", FieldUtils.readDeclaredField(publiclyShadowedChild, "s", true));
|
||||||
|
FieldUtils.writeDeclaredField(publiclyShadowedChild, "b", Boolean.FALSE, true);
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readDeclaredField(publiclyShadowedChild, "b", true));
|
||||||
|
FieldUtils.writeDeclaredField(publiclyShadowedChild, "i", new Integer(0), true);
|
||||||
|
assertEquals(new Integer(0), FieldUtils.readDeclaredField(publiclyShadowedChild, "i", true));
|
||||||
|
FieldUtils.writeDeclaredField(publiclyShadowedChild, "d", new Double(0.0), true);
|
||||||
|
assertEquals(new Double(0.0), FieldUtils.readDeclaredField(publiclyShadowedChild, "d", true));
|
||||||
|
|
||||||
|
FieldUtils.writeDeclaredField(privatelyShadowedChild, "s", "S", true);
|
||||||
|
assertEquals("S", FieldUtils.readDeclaredField(privatelyShadowedChild, "s", true));
|
||||||
|
FieldUtils.writeDeclaredField(privatelyShadowedChild, "b", Boolean.FALSE, true);
|
||||||
|
assertEquals(Boolean.FALSE, FieldUtils.readDeclaredField(privatelyShadowedChild, "b", true));
|
||||||
|
FieldUtils.writeDeclaredField(privatelyShadowedChild, "i", new Integer(0), true);
|
||||||
|
assertEquals(new Integer(0), FieldUtils.readDeclaredField(privatelyShadowedChild, "i", true));
|
||||||
|
FieldUtils.writeDeclaredField(privatelyShadowedChild, "d", new Double(0.0), true);
|
||||||
|
assertEquals(new Double(0.0), FieldUtils.readDeclaredField(privatelyShadowedChild, "d", true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAmbig() {
|
||||||
|
try {
|
||||||
|
FieldUtils.getField(Ambig.class, "VALUE");
|
||||||
|
fail("should have failed on interface field ambiguity");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
342
src/test/org/apache/commons/lang/reflect/MethodUtilsTest.java
Normal file
342
src/test/org/apache/commons/lang/reflect/MethodUtilsTest.java
Normal file
@ -0,0 +1,342 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.ArrayUtils;
|
||||||
|
import org.apache.commons.lang.math.NumberUtils;
|
||||||
|
import org.apache.commons.lang.mutable.Mutable;
|
||||||
|
import org.apache.commons.lang.mutable.MutableObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests MethodUtils
|
||||||
|
* @author mbenson
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class MethodUtilsTest extends TestCase {
|
||||||
|
public static class TestBean {
|
||||||
|
|
||||||
|
public static String bar() {
|
||||||
|
return "bar()";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String bar(int i) {
|
||||||
|
return "bar(int)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String bar(Integer i) {
|
||||||
|
return "bar(Integer)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String bar(double d) {
|
||||||
|
return "bar(double)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String bar(String s) {
|
||||||
|
return "bar(String)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String bar(Object o) {
|
||||||
|
return "bar(Object)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String foo() {
|
||||||
|
return "foo()";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String foo(int i) {
|
||||||
|
return "foo(int)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String foo(Integer i) {
|
||||||
|
return "foo(Integer)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String foo(double d) {
|
||||||
|
return "foo(double)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String foo(String s) {
|
||||||
|
return "foo(String)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String foo(Object o) {
|
||||||
|
return "foo(Object)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestMutable implements Mutable {
|
||||||
|
public Object getValue() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(Object value) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TestBean testBean;
|
||||||
|
private Map classCache;
|
||||||
|
|
||||||
|
public MethodUtilsTest(String name) {
|
||||||
|
super(name);
|
||||||
|
classCache = new HashMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the test cases as a suite.
|
||||||
|
* @return the Test
|
||||||
|
*/
|
||||||
|
public static Test suite() {
|
||||||
|
TestSuite suite = new TestSuite(MethodUtilsTest.class);
|
||||||
|
suite.setName("MethodUtils Tests");
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
testBean = new TestBean();
|
||||||
|
classCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConstructor() throws Exception {
|
||||||
|
assertNotNull(MethodUtils.class.newInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInvokeMethod() throws Exception {
|
||||||
|
assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo",
|
||||||
|
ArrayUtils.EMPTY_CLASS_ARRAY));
|
||||||
|
assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo",
|
||||||
|
(Class[]) null));
|
||||||
|
assertEquals("foo(String)", MethodUtils.invokeMethod(testBean, "foo",
|
||||||
|
""));
|
||||||
|
assertEquals("foo(Object)", MethodUtils.invokeMethod(testBean, "foo",
|
||||||
|
new Object()));
|
||||||
|
assertEquals("foo(Object)", MethodUtils.invokeMethod(testBean, "foo",
|
||||||
|
Boolean.TRUE));
|
||||||
|
assertEquals("foo(Integer)", MethodUtils.invokeMethod(testBean, "foo",
|
||||||
|
NumberUtils.INTEGER_ONE));
|
||||||
|
assertEquals("foo(int)", MethodUtils.invokeMethod(testBean, "foo",
|
||||||
|
NumberUtils.BYTE_ONE));
|
||||||
|
assertEquals("foo(double)", MethodUtils.invokeMethod(testBean, "foo",
|
||||||
|
NumberUtils.LONG_ONE));
|
||||||
|
assertEquals("foo(double)", MethodUtils.invokeMethod(testBean, "foo",
|
||||||
|
NumberUtils.DOUBLE_ONE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInvokeExactMethod() throws Exception {
|
||||||
|
assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo",
|
||||||
|
ArrayUtils.EMPTY_CLASS_ARRAY));
|
||||||
|
assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo",
|
||||||
|
(Class[]) null));
|
||||||
|
assertEquals("foo(String)", MethodUtils.invokeExactMethod(testBean,
|
||||||
|
"foo", ""));
|
||||||
|
assertEquals("foo(Object)", MethodUtils.invokeExactMethod(testBean,
|
||||||
|
"foo", new Object()));
|
||||||
|
assertEquals("foo(Integer)", MethodUtils.invokeExactMethod(testBean,
|
||||||
|
"foo", NumberUtils.INTEGER_ONE));
|
||||||
|
assertEquals("foo(double)", MethodUtils.invokeExactMethod(testBean,
|
||||||
|
"foo", new Object[] { NumberUtils.DOUBLE_ONE },
|
||||||
|
new Class[] { Double.TYPE }));
|
||||||
|
|
||||||
|
try {
|
||||||
|
MethodUtils
|
||||||
|
.invokeExactMethod(testBean, "foo", NumberUtils.BYTE_ONE);
|
||||||
|
fail("should throw NoSuchMethodException");
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
MethodUtils
|
||||||
|
.invokeExactMethod(testBean, "foo", NumberUtils.LONG_ONE);
|
||||||
|
fail("should throw NoSuchMethodException");
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
MethodUtils.invokeExactMethod(testBean, "foo", Boolean.TRUE);
|
||||||
|
fail("should throw NoSuchMethodException");
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInvokeStaticMethod() throws Exception {
|
||||||
|
assertEquals("bar()", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"bar", ArrayUtils.EMPTY_CLASS_ARRAY));
|
||||||
|
assertEquals("bar()", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"bar", (Class[]) null));
|
||||||
|
assertEquals("bar(String)", MethodUtils.invokeStaticMethod(
|
||||||
|
TestBean.class, "bar", ""));
|
||||||
|
assertEquals("bar(Object)", MethodUtils.invokeStaticMethod(
|
||||||
|
TestBean.class, "bar", new Object()));
|
||||||
|
assertEquals("bar(Object)", MethodUtils.invokeStaticMethod(
|
||||||
|
TestBean.class, "bar", Boolean.TRUE));
|
||||||
|
assertEquals("bar(Integer)", MethodUtils.invokeStaticMethod(
|
||||||
|
TestBean.class, "bar", NumberUtils.INTEGER_ONE));
|
||||||
|
assertEquals("bar(int)", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"bar", NumberUtils.BYTE_ONE));
|
||||||
|
assertEquals("bar(double)", MethodUtils.invokeStaticMethod(
|
||||||
|
TestBean.class, "bar", NumberUtils.LONG_ONE));
|
||||||
|
assertEquals("bar(double)", MethodUtils.invokeStaticMethod(
|
||||||
|
TestBean.class, "bar", NumberUtils.DOUBLE_ONE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInvokeExactStaticMethod() throws Exception {
|
||||||
|
assertEquals("bar()", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"bar", ArrayUtils.EMPTY_CLASS_ARRAY));
|
||||||
|
assertEquals("bar()", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"bar", (Class[]) null));
|
||||||
|
assertEquals("bar(String)", MethodUtils.invokeExactStaticMethod(
|
||||||
|
TestBean.class, "bar", ""));
|
||||||
|
assertEquals("bar(Object)", MethodUtils.invokeExactStaticMethod(
|
||||||
|
TestBean.class, "bar", new Object()));
|
||||||
|
assertEquals("bar(Integer)", MethodUtils.invokeExactStaticMethod(
|
||||||
|
TestBean.class, "bar", NumberUtils.INTEGER_ONE));
|
||||||
|
assertEquals("bar(double)", MethodUtils.invokeExactStaticMethod(
|
||||||
|
TestBean.class, "bar", new Object[] { NumberUtils.DOUBLE_ONE },
|
||||||
|
new Class[] { Double.TYPE }));
|
||||||
|
|
||||||
|
try {
|
||||||
|
MethodUtils.invokeExactStaticMethod(TestBean.class, "bar",
|
||||||
|
NumberUtils.BYTE_ONE);
|
||||||
|
fail("should throw NoSuchMethodException");
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
MethodUtils.invokeExactStaticMethod(TestBean.class, "bar",
|
||||||
|
NumberUtils.LONG_ONE);
|
||||||
|
fail("should throw NoSuchMethodException");
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
MethodUtils.invokeExactStaticMethod(TestBean.class, "bar",
|
||||||
|
Boolean.TRUE);
|
||||||
|
fail("should throw NoSuchMethodException");
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetAccessibleInterfaceMethod() throws Exception {
|
||||||
|
|
||||||
|
Class[][] p = { ArrayUtils.EMPTY_CLASS_ARRAY, null };
|
||||||
|
for (int i = 0; i < p.length; i++) {
|
||||||
|
Method method = TestMutable.class.getMethod("getValue", p[i]);
|
||||||
|
Method accessibleMethod = MethodUtils.getAccessibleMethod(method);
|
||||||
|
assertNotSame(accessibleMethod, method);
|
||||||
|
assertSame(Mutable.class, accessibleMethod.getDeclaringClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetAccessibleInterfaceMethodFromDescription()
|
||||||
|
throws Exception {
|
||||||
|
Class[][] p = { ArrayUtils.EMPTY_CLASS_ARRAY, null };
|
||||||
|
for (int i = 0; i < p.length; i++) {
|
||||||
|
Method accessibleMethod = MethodUtils.getAccessibleMethod(
|
||||||
|
TestMutable.class, "getValue", p[i]);
|
||||||
|
assertSame(Mutable.class, accessibleMethod.getDeclaringClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetAccessiblePublicMethod() throws Exception {
|
||||||
|
assertSame(MutableObject.class, MethodUtils.getAccessibleMethod(
|
||||||
|
MutableObject.class.getMethod("getValue",
|
||||||
|
ArrayUtils.EMPTY_CLASS_ARRAY)).getDeclaringClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetAccessiblePublicMethodFromDescription() throws Exception {
|
||||||
|
assertSame(MutableObject.class, MethodUtils.getAccessibleMethod(
|
||||||
|
MutableObject.class, "getValue", ArrayUtils.EMPTY_CLASS_ARRAY)
|
||||||
|
.getDeclaringClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetMatchingAccessibleMethod() throws Exception {
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
ArrayUtils.EMPTY_CLASS_ARRAY, ArrayUtils.EMPTY_CLASS_ARRAY);
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
null, ArrayUtils.EMPTY_CLASS_ARRAY);
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(String.class), singletonArray(String.class));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(Object.class), singletonArray(Object.class));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(Boolean.class), singletonArray(Object.class));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(Byte.class), singletonArray(Integer.TYPE));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(Byte.TYPE), singletonArray(Integer.TYPE));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(Short.class), singletonArray(Integer.TYPE));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(Short.TYPE), singletonArray(Integer.TYPE));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(Character.class), singletonArray(Integer.TYPE));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(Character.TYPE), singletonArray(Integer.TYPE));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(Integer.class), singletonArray(Integer.class));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(Integer.TYPE), singletonArray(Integer.TYPE));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(Long.class), singletonArray(Double.TYPE));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(Long.TYPE), singletonArray(Double.TYPE));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(Float.class), singletonArray(Double.TYPE));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(Float.TYPE), singletonArray(Double.TYPE));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(Double.class), singletonArray(Double.TYPE));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
singletonArray(Double.TYPE), singletonArray(Double.TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expectMatchingAccessibleMethodParameterTypes(Class cls,
|
||||||
|
String methodName, Class[] requestTypes, Class[] actualTypes) {
|
||||||
|
Method m = MethodUtils.getMatchingAccessibleMethod(cls, methodName,
|
||||||
|
requestTypes);
|
||||||
|
assertTrue(Arrays.toString(m.getParameterTypes()) + " not equals "
|
||||||
|
+ Arrays.toString(actualTypes), Arrays.equals(actualTypes, m
|
||||||
|
.getParameterTypes()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSetCacheMethods() throws Exception {
|
||||||
|
MethodUtils.clearCache();
|
||||||
|
MethodUtils.setCacheMethods(true);
|
||||||
|
MethodUtils.invokeMethod(testBean, "foo", "");
|
||||||
|
assertEquals(1, MethodUtils.clearCache());
|
||||||
|
assertEquals(0, MethodUtils.clearCache());
|
||||||
|
MethodUtils.setCacheMethods(false);
|
||||||
|
MethodUtils.invokeMethod(testBean, "foo", "");
|
||||||
|
assertEquals(0, MethodUtils.clearCache());
|
||||||
|
MethodUtils.setCacheMethods(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Class[] singletonArray(Class c) {
|
||||||
|
Class[] result = (Class[]) classCache.get(c);
|
||||||
|
if (result == null) {
|
||||||
|
result = new Class[] { c };
|
||||||
|
classCache.put(c, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect;
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
import junit.textui.TestRunner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test suite for the reflect package.
|
||||||
|
*
|
||||||
|
* @author Matt Benson
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class ReflectTestSuite extends TestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new instance.
|
||||||
|
*/
|
||||||
|
public ReflectTestSuite(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command-line interface.
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
TestRunner.run(suite());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the suite of tests
|
||||||
|
*/
|
||||||
|
public static Test suite() {
|
||||||
|
TestSuite suite = new TestSuite();
|
||||||
|
suite.setName("Commons-Lang-Reflect Tests");
|
||||||
|
suite.addTest(ConstructorUtilsTest.suite());
|
||||||
|
suite.addTest(FieldUtilsTest.suite());
|
||||||
|
suite.addTest(MethodUtilsTest.suite());
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
24
src/test/org/apache/commons/lang/reflect/testbed/Ambig.java
Normal file
24
src/test/org/apache/commons/lang/reflect/testbed/Ambig.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect.testbed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author mbenson
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class Ambig implements Foo, Bar {
|
||||||
|
}
|
25
src/test/org/apache/commons/lang/reflect/testbed/Bar.java
Normal file
25
src/test/org/apache/commons/lang/reflect/testbed/Bar.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect.testbed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author mbenson
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public interface Bar {
|
||||||
|
public static final String VALUE = "bar";
|
||||||
|
}
|
25
src/test/org/apache/commons/lang/reflect/testbed/Foo.java
Normal file
25
src/test/org/apache/commons/lang/reflect/testbed/Foo.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect.testbed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author mbenson
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public interface Foo {
|
||||||
|
public static final String VALUE = "foo";
|
||||||
|
}
|
28
src/test/org/apache/commons/lang/reflect/testbed/Parent.java
Normal file
28
src/test/org/apache/commons/lang/reflect/testbed/Parent.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect.testbed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author mbenson
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
class Parent implements Foo {
|
||||||
|
public String s = "s";
|
||||||
|
protected boolean b = false;
|
||||||
|
int i = 0;
|
||||||
|
private double d = 0.0;
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect.testbed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author mbenson
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class PrivatelyShadowedChild extends Parent {
|
||||||
|
private String s = "ss";
|
||||||
|
private boolean b = true;
|
||||||
|
private int i = 1;
|
||||||
|
private double d = 1.0;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect.testbed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author mbenson
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class PublicChild extends Parent {
|
||||||
|
static final String VALUE = "child";
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect.testbed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author mbenson
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class PubliclyShadowedChild extends Parent {
|
||||||
|
public String s = "ss";
|
||||||
|
public boolean b = true;
|
||||||
|
public int i = 1;
|
||||||
|
public double d = 1.0;
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect.testbed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author mbenson
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class StaticContainer {
|
||||||
|
public static final Object IMMUTABLE_PUBLIC = "public";
|
||||||
|
protected static final Object IMMUTABLE_PROTECTED = "protected";
|
||||||
|
static final Object IMMUTABLE_PACKAGE = "";
|
||||||
|
private static final Object IMMUTABLE_PRIVATE = "private";
|
||||||
|
|
||||||
|
public static Object mutablePublic;
|
||||||
|
protected static Object mutableProtected;
|
||||||
|
static Object mutablePackage;
|
||||||
|
private static Object mutablePrivate;
|
||||||
|
|
||||||
|
public static void reset() {
|
||||||
|
mutablePublic = null;
|
||||||
|
mutableProtected = null;
|
||||||
|
mutablePackage = null;
|
||||||
|
mutablePrivate = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object getMutableProtected() {
|
||||||
|
return mutableProtected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object getMutablePackage() {
|
||||||
|
return mutablePackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object getMutablePrivate() {
|
||||||
|
return mutablePrivate;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.reflect.testbed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author mbenson
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class StaticContainerChild extends StaticContainer {
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user