corrected use of AccessException (no longer used in ReflectionUtils)

git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@85 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
Andy Clement 2008-08-18 00:22:36 +00:00
parent 67bcc88a13
commit d57863038b
3 changed files with 119 additions and 94 deletions

View File

@ -21,6 +21,7 @@ import java.lang.reflect.InvocationTargetException;
import org.springframework.expression.AccessException; import org.springframework.expression.AccessException;
import org.springframework.expression.ConstructorExecutor; import org.springframework.expression.ConstructorExecutor;
import org.springframework.expression.EvaluationContext; import org.springframework.expression.EvaluationContext;
import org.springframework.expression.EvaluationException;
/** /**
* A simple CommandExecutor implementation that runs a constructor using reflective invocation. * A simple CommandExecutor implementation that runs a constructor using reflective invocation.
@ -36,7 +37,7 @@ public class ReflectionConstructorExecutor implements ConstructorExecutor {
private final Integer[] argsRequiringConversion; private final Integer[] argsRequiringConversion;
public ReflectionConstructorExecutor(Constructor<?> constructor, Integer[] argsRequiringConversion) { public ReflectionConstructorExecutor(Constructor<?> constructor, Integer[] argsRequiringConversion) {
this.c = constructor; c = constructor;
this.argsRequiringConversion = argsRequiringConversion; this.argsRequiringConversion = argsRequiringConversion;
} }
@ -45,7 +46,12 @@ public class ReflectionConstructorExecutor implements ConstructorExecutor {
*/ */
public Object execute(EvaluationContext context, Object... arguments) throws AccessException { public Object execute(EvaluationContext context, Object... arguments) throws AccessException {
if (argsRequiringConversion != null && arguments != null) { if (argsRequiringConversion != null && arguments != null) {
ReflectionUtils.convertArguments(c.getParameterTypes(), c.isVarArgs(), context.getTypeUtils().getTypeConverter(), argsRequiringConversion, arguments); try {
ReflectionUtils.convertArguments(c.getParameterTypes(), c.isVarArgs(), context.getTypeUtils()
.getTypeConverter(), argsRequiringConversion, arguments);
} catch (EvaluationException ex) {
throw new AccessException("Problem invoking constructor on '" + c + "': " + ex.getMessage(), ex);
}
} }
if (c.isVarArgs()) { if (c.isVarArgs()) {
arguments = ReflectionUtils.setupArgumentsForVarargsInvocation(c.getParameterTypes(), arguments); arguments = ReflectionUtils.setupArgumentsForVarargsInvocation(c.getParameterTypes(), arguments);

View File

@ -20,6 +20,7 @@ import java.lang.reflect.Method;
import org.springframework.expression.AccessException; import org.springframework.expression.AccessException;
import org.springframework.expression.EvaluationContext; import org.springframework.expression.EvaluationContext;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.MethodExecutor; import org.springframework.expression.MethodExecutor;
public class ReflectionMethodExecutor implements MethodExecutor { public class ReflectionMethodExecutor implements MethodExecutor {
@ -31,14 +32,19 @@ public class ReflectionMethodExecutor implements MethodExecutor {
private final Integer[] argsRequiringConversion; private final Integer[] argsRequiringConversion;
public ReflectionMethodExecutor(Method theMethod, Integer[] argumentsRequiringConversion) { public ReflectionMethodExecutor(Method theMethod, Integer[] argumentsRequiringConversion) {
this.m = theMethod; m = theMethod;
this.argsRequiringConversion = argumentsRequiringConversion; argsRequiringConversion = argumentsRequiringConversion;
} }
public Object execute(EvaluationContext context, Object target, Object... arguments) throws AccessException { public Object execute(EvaluationContext context, Object target, Object... arguments) throws AccessException {
if (argsRequiringConversion != null && arguments != null) { if (argsRequiringConversion != null && arguments != null) {
ReflectionUtils.convertArguments(m.getParameterTypes(),m.isVarArgs(),context.getTypeUtils().getTypeConverter(), argsRequiringConversion, arguments); try {
ReflectionUtils.convertArguments(m.getParameterTypes(), m.isVarArgs(), context.getTypeUtils()
.getTypeConverter(), argsRequiringConversion, arguments);
} catch (EvaluationException ex) {
throw new AccessException("Problem invoking method '" + m.getName() + "' on '" + target.getClass()
+ "': " + ex.getMessage(), ex);
}
} }
if (m.isVarArgs()) { if (m.isVarArgs()) {
arguments = ReflectionUtils.setupArgumentsForVarargsInvocation(m.getParameterTypes(), arguments); arguments = ReflectionUtils.setupArgumentsForVarargsInvocation(m.getParameterTypes(), arguments);

View File

@ -22,7 +22,6 @@ import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.springframework.expression.AccessException;
import org.springframework.expression.EvaluationException; import org.springframework.expression.EvaluationException;
import org.springframework.expression.TypeConverter; import org.springframework.expression.TypeConverter;
import org.springframework.expression.spel.SpelException; import org.springframework.expression.spel.SpelException;
@ -33,7 +32,6 @@ import org.springframework.expression.spel.SpelMessages;
* should be used in expressions. * should be used in expressions.
* *
* @author Andy Clement * @author Andy Clement
*
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class ReflectionUtils { public class ReflectionUtils {
@ -70,10 +68,12 @@ public class ReflectionUtils {
ArgumentsMatchInfo matchInfo = null; ArgumentsMatchInfo matchInfo = null;
if (method.isVarArgs() && argumentTypes.length >= (method.getParameterTypes().length - 1)) { if (method.isVarArgs() && argumentTypes.length >= (method.getParameterTypes().length - 1)) {
// *sigh* complicated // *sigh* complicated
matchInfo = compareArgumentsVarargs(method.getParameterTypes(), argumentTypes, typeConverter, conversionAllowed); matchInfo = compareArgumentsVarargs(method.getParameterTypes(), argumentTypes, typeConverter,
conversionAllowed);
} else if (method.getParameterTypes().length == argumentTypes.length) { } else if (method.getParameterTypes().length == argumentTypes.length) {
// name and parameter number match, check the arguments // name and parameter number match, check the arguments
matchInfo = compareArguments(method.getParameterTypes(), argumentTypes, typeConverter, conversionAllowed); matchInfo = compareArguments(method.getParameterTypes(), argumentTypes, typeConverter,
conversionAllowed);
} }
if (matchInfo != null) { if (matchInfo != null) {
if (matchInfo.kind == ArgsMatchKind.EXACT) { if (matchInfo.kind == ArgsMatchKind.EXACT) {
@ -127,10 +127,13 @@ public class ReflectionUtils {
Constructor ctor = ctors[i]; Constructor ctor = ctors[i];
if (ctor.isVarArgs() && argumentTypes.length >= (ctor.getParameterTypes().length - 1)) { if (ctor.isVarArgs() && argumentTypes.length >= (ctor.getParameterTypes().length - 1)) {
// *sigh* complicated // *sigh* complicated
// Basically.. we have to have all parameters match up until the varargs one, then the rest of what is being provided should be // Basically.. we have to have all parameters match up until the varargs one, then the rest of what is
// the same type whilst the final argument to the method must be an array of that (oh, how easy...not) - or the final parameter // being provided should be
// the same type whilst the final argument to the method must be an array of that (oh, how easy...not) -
// or the final parameter
// we are supplied does match exactly (it is an array already). // we are supplied does match exactly (it is an array already).
ArgumentsMatchInfo matchInfo = compareArgumentsVarargs(ctor.getParameterTypes(), argumentTypes, typeConverter, conversionAllowed); ArgumentsMatchInfo matchInfo = compareArgumentsVarargs(ctor.getParameterTypes(), argumentTypes,
typeConverter, conversionAllowed);
if (matchInfo != null) { if (matchInfo != null) {
if (matchInfo.kind == ArgsMatchKind.EXACT) { if (matchInfo.kind == ArgsMatchKind.EXACT) {
return new DiscoveredConstructor(ctor, null); return new DiscoveredConstructor(ctor, null);
@ -228,7 +231,8 @@ public class ReflectionUtils {
* @return a MatchInfo object indicating what kind of match it was or null if it was not a match * @return a MatchInfo object indicating what kind of match it was or null if it was not a match
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static ArgumentsMatchInfo compareArgumentsVarargs(Class[] expectedArgTypes, Class[] suppliedArgTypes, TypeConverter typeConverter, boolean conversionAllowed) { private static ArgumentsMatchInfo compareArgumentsVarargs(Class[] expectedArgTypes, Class[] suppliedArgTypes,
TypeConverter typeConverter, boolean conversionAllowed) {
ArgsMatchKind match = ArgsMatchKind.EXACT; ArgsMatchKind match = ArgsMatchKind.EXACT;
List<Integer> argsRequiringConversion = null; List<Integer> argsRequiringConversion = null;
@ -260,20 +264,23 @@ public class ReflectionUtils {
return null; return null;
} }
// Special case: there is one parameter left and it is an array and it matches the varargs expected argument - that is a match, the caller has already built the array // Special case: there is one parameter left and it is an array and it matches the varargs expected argument -
if (suppliedArgTypes.length==expectedArgTypes.length && expectedArgTypes[expectedArgTypes.length-1]==suppliedArgTypes[suppliedArgTypes.length-1]) { // that is a match, the caller has already built the array
if (suppliedArgTypes.length == expectedArgTypes.length
&& expectedArgTypes[expectedArgTypes.length - 1] == suppliedArgTypes[suppliedArgTypes.length - 1]) {
} else { } else {
// Now... we have the final argument in the method we are checking as a match and we have 0 or more other
// Now... we have the final argument in the method we are checking as a match and we have 0 or more other arguments left to pass to it. // arguments left to pass to it.
Class varargsParameterType = expectedArgTypes[expectedArgTypes.length - 1].getComponentType(); Class varargsParameterType = expectedArgTypes[expectedArgTypes.length - 1].getComponentType();
// All remaining parameters must be of this type or convertable to this type // All remaining parameters must be of this type or convertable to this type
for (int i = expectedArgTypes.length - 1; i < suppliedArgTypes.length; i++) { for (int i = expectedArgTypes.length - 1; i < suppliedArgTypes.length; i++) {
Class suppliedArg = suppliedArgTypes[i]; Class suppliedArg = suppliedArgTypes[i];
if (varargsParameterType != suppliedArg) { if (varargsParameterType != suppliedArg) {
if (varargsParameterType.isAssignableFrom(suppliedArg) || areBoxingCompatible(varargsParameterType, suppliedArg) if (varargsParameterType.isAssignableFrom(suppliedArg)
|| areBoxingCompatible(varargsParameterType, suppliedArg)
/* || isWidenableTo(expectedArg, suppliedArg) */) { /* || isWidenableTo(expectedArg, suppliedArg) */) {
if (match != ArgsMatchKind.REQUIRES_CONVERSION) { if (match != ArgsMatchKind.REQUIRES_CONVERSION) {
match = ArgsMatchKind.CLOSE; match = ArgsMatchKind.CLOSE;
@ -302,7 +309,6 @@ public class ReflectionUtils {
} }
} }
// TODO optimize implementation of areBoxingCompatible // TODO optimize implementation of areBoxingCompatible
private static boolean areBoxingCompatible(Class class1, Class class2) { private static boolean areBoxingCompatible(Class class1, Class class2) {
if (class1 == Integer.class && class2 == Integer.TYPE) if (class1 == Integer.class && class2 == Integer.TYPE)
@ -402,7 +408,7 @@ public class ReflectionUtils {
ArgumentsMatchInfo(ArgsMatchKind kind, Integer[] integers) { ArgumentsMatchInfo(ArgsMatchKind kind, Integer[] integers) {
this.kind = kind; this.kind = kind;
this.argsRequiringConversion = integers; argsRequiringConversion = integers;
} }
ArgumentsMatchInfo(ArgsMatchKind kind) { ArgumentsMatchInfo(ArgsMatchKind kind) {
@ -424,7 +430,7 @@ public class ReflectionUtils {
public DiscoveredConstructor(Constructor theConstructor, Integer[] argsToConvert) { public DiscoveredConstructor(Constructor theConstructor, Integer[] argsToConvert) {
this.theConstructor = theConstructor; this.theConstructor = theConstructor;
this.argumentsRequiringConversion = argsToConvert; argumentsRequiringConversion = argsToConvert;
} }
} }
@ -438,11 +444,12 @@ public class ReflectionUtils {
public DiscoveredMethod(Method theMethod, Integer[] argsToConvert) { public DiscoveredMethod(Method theMethod, Integer[] argsToConvert) {
this.theMethod = theMethod; this.theMethod = theMethod;
this.argumentsRequiringConversion = argsToConvert; argumentsRequiringConversion = argsToConvert;
} }
} }
static void convertArguments(Class[] parameterTypes,boolean isVarargs, TypeConverter converter ,Integer[] argsRequiringConversion, Object... arguments) throws AccessException { static void convertArguments(Class[] parameterTypes, boolean isVarargs, TypeConverter converter,
Integer[] argsRequiringConversion, Object... arguments) throws EvaluationException {
Class varargsType = null; Class varargsType = null;
if (isVarargs) { if (isVarargs) {
varargsType = parameterTypes[parameterTypes.length - 1].getComponentType(); varargsType = parameterTypes[parameterTypes.length - 1].getComponentType();
@ -455,16 +462,17 @@ public class ReflectionUtils {
} else { } else {
targetType = parameterTypes[argPosition]; targetType = parameterTypes[argPosition];
} }
try { // try {
arguments[argPosition] = converter.convertValue(arguments[argPosition], targetType); arguments[argPosition] = converter.convertValue(arguments[argPosition], targetType);
} catch (EvaluationException e) { // } catch (EvaluationException e) {
throw new AccessException("Converter failed to convert '" + arguments[argPosition] + " to type '" // throw new SpelException(e, SpelMessages.PROBLEM_DURING_TYPE_CONVERSION, "Converter failed to convert '"
+ targetType + "'", e); // + arguments[argPosition] + " to type '" + targetType + "'");
} // }
} }
} }
static void convertArguments(Class[] parameterTypes,boolean isVarargs, TypeConverter converter , Object... arguments) throws AccessException { static void convertArguments(Class[] parameterTypes, boolean isVarargs, TypeConverter converter,
Object... arguments) throws EvaluationException {
Class varargsType = null; Class varargsType = null;
if (isVarargs) { if (isVarargs) {
varargsType = parameterTypes[parameterTypes.length - 1].getComponentType(); varargsType = parameterTypes[parameterTypes.length - 1].getComponentType();
@ -481,16 +489,17 @@ public class ReflectionUtils {
arguments[i] = converter.convertValue(arguments[i], targetType); arguments[i] = converter.convertValue(arguments[i], targetType);
} }
} catch (EvaluationException e) { } catch (EvaluationException e) {
throw new AccessException("Converter failed to convert '" + arguments[i] + " to type '" throw new SpelException(e, SpelMessages.PROBLEM_DURING_TYPE_CONVERSION, "Converter failed to convert '"
+ targetType + "'", e); + arguments[i] + " to type '" + targetType + "'");
} }
} }
} }
/** /**
* Package up the arguments so that they correctly match what is expected in parameterTypes. For example, if parameterTypes is (int, String[]) * Package up the arguments so that they correctly match what is expected in parameterTypes. For example, if
* because the second parameter was declared String... then if arguments is [1,"a","b"] then it must be repackaged as [1,new String[]{"a","b"}] * parameterTypes is (int, String[]) because the second parameter was declared String... then if arguments is
* in order to match the expected parameterTypes. * [1,"a","b"] then it must be repackaged as [1,new String[]{"a","b"}] in order to match the expected
* parameterTypes.
* *
* @param parameterTypes the types of the parameters for the invocation * @param parameterTypes the types of the parameters for the invocation
* @param arguments the arguments to be setup ready for the invocation * @param arguments the arguments to be setup ready for the invocation
@ -502,12 +511,15 @@ public class ReflectionUtils {
int nArgs = arguments.length; int nArgs = arguments.length;
// Check if repackaging is needed: // Check if repackaging is needed:
if (nParams!=arguments.length || parameterTypes[nParams-1]!=(arguments[nArgs-1]==null?null:arguments[nArgs-1].getClass())) { if (nParams != arguments.length
|| parameterTypes[nParams - 1] != (arguments[nArgs - 1] == null ? null : arguments[nArgs - 1]
.getClass())) {
int arraySize = 0; // zero size array if nothing to pass as the varargs parameter int arraySize = 0; // zero size array if nothing to pass as the varargs parameter
if (arguments != null && nArgs >= nParams) { if (arguments != null && nArgs >= nParams) {
arraySize = nArgs - (nParams - 1); arraySize = nArgs - (nParams - 1);
} }
Object[] repackagedArguments = (Object[])Array.newInstance(parameterTypes[nParams-1].getComponentType(),arraySize); Object[] repackagedArguments = (Object[]) Array.newInstance(parameterTypes[nParams - 1].getComponentType(),
arraySize);
// Copy all but the varargs arguments // Copy all but the varargs arguments
for (int i = 0; i < arraySize; i++) { for (int i = 0; i < arraySize; i++) {
@ -524,7 +536,8 @@ public class ReflectionUtils {
return arguments; return arguments;
} }
public static Object[] prepareArguments(TypeConverter converter, Method m, Object[] arguments) throws AccessException {//TODO should not be accessexception public static Object[] prepareArguments(TypeConverter converter, Method m, Object[] arguments)
throws EvaluationException {
if (arguments != null) { if (arguments != null) {
ReflectionUtils.convertArguments(m.getParameterTypes(), m.isVarArgs(), converter, arguments); ReflectionUtils.convertArguments(m.getParameterTypes(), m.isVarArgs(), converter, arguments);
} }