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.math.MathTestSuite;
|
||||
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.time.TimeTestSuite;
|
||||
|
||||
@ -64,6 +65,7 @@ public static Test suite() {
|
||||
suite.addTest(ExceptionTestSuite.suite());
|
||||
suite.addTest(MathTestSuite.suite());
|
||||
suite.addTest(MutableTestSuite.suite());
|
||||
suite.addTest(ReflectTestSuite.suite());
|
||||
suite.addTest(TextTestSuite.suite());
|
||||
suite.addTest(TimeTestSuite.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