fixed up FunctionReference a bit - so it can call varargs methods
This commit is contained in:
parent
2f05d70067
commit
f79e2643a3
|
@ -17,16 +17,19 @@ package org.springframework.expression.spel.ast;
|
|||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.TypeConverter;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.reflection.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* A function reference is of the form "#someFunction(a,b,c)". Functions may be defined in the context prior to the
|
||||
|
@ -54,11 +57,12 @@ public class FunctionReference extends SpelNode {
|
|||
if (o == null) {
|
||||
throw new SpelException(SpelMessages.FUNCTION_NOT_DEFINED, name);
|
||||
}
|
||||
|
||||
// Two possibilities: a lambda function or a Java static method registered as a function
|
||||
if (!(o instanceof Lambda || o instanceof Method)) {
|
||||
throw new SpelException(SpelMessages.FUNCTION_REFERENCE_CANNOT_BE_INVOKED, name, o.getClass());
|
||||
}
|
||||
|
||||
// FUNCTION REF NEEDS TO DO ARG CONVERSION??
|
||||
if (o instanceof Lambda) {
|
||||
return executeLambdaFunction(state, (Lambda) o);
|
||||
} else { // o instanceof Method
|
||||
|
@ -66,28 +70,36 @@ public class FunctionReference extends SpelNode {
|
|||
}
|
||||
}
|
||||
|
||||
/* Execute a function represented as a java.lang.reflect.Method */
|
||||
/**
|
||||
* Execute a function represented as a java.lang.reflect.Method.
|
||||
*
|
||||
* @param state the expression evaluation state
|
||||
* @param the java method to invoke
|
||||
* @return the return value of the invoked Java method
|
||||
* @throws EvaluationException if there is any problem invoking the method
|
||||
*/
|
||||
private Object executeFunctionJLRMethod(ExpressionState state, Method m) throws EvaluationException {
|
||||
Object[] functionArgs = getArguments(state);
|
||||
if (m.getParameterTypes().length != functionArgs.length) {
|
||||
throw new SpelException(SpelMessages.INCORRECT_NUMBER_OF_ARGUMENTS_TO_FUNCTION, functionArgs.length, m
|
||||
.getParameterTypes().length);
|
||||
|
||||
// Only static methods can be called in this way
|
||||
if (!Modifier.isStatic(m.getModifiers())) {
|
||||
throw new SpelException(getCharPositionInLine(),SpelMessages.FUNCTION_MUST_BE_STATIC,m.getDeclaringClass().getName()+"."+m.getName(),name);
|
||||
}
|
||||
|
||||
// Check if arguments need converting
|
||||
Class<?>[] expectedParams = m.getParameterTypes();
|
||||
Object[] argsToPass = new Object[functionArgs.length];
|
||||
TypeConverter converter = state.getEvaluationContext().getTypeUtils().getTypeConverter();
|
||||
for (int arg=0; arg<argsToPass.length; arg++) {
|
||||
if (functionArgs[arg]==null || functionArgs[arg].getClass()==expectedParams[arg]) {
|
||||
argsToPass[arg]=functionArgs[arg];
|
||||
} else {
|
||||
argsToPass[arg]=converter.convertValue(functionArgs[arg], expectedParams[arg]);
|
||||
if (functionArgs != null) {
|
||||
EvaluationContext ctx = state.getEvaluationContext();
|
||||
TypeConverter converter = null;
|
||||
if (ctx.getTypeUtils()!=null) {
|
||||
converter = ctx.getTypeUtils().getTypeConverter();
|
||||
}
|
||||
ReflectionUtils.convertArguments(m.getParameterTypes(), m.isVarArgs(), converter, functionArgs);
|
||||
}
|
||||
if (m.isVarArgs()) {
|
||||
functionArgs = ReflectionUtils.setupArgumentsForVarargsInvocation(m.getParameterTypes(), functionArgs);
|
||||
}
|
||||
|
||||
try {
|
||||
return m.invoke(m.getClass(), argsToPass);
|
||||
return m.invoke(m.getClass(), functionArgs);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new SpelException(getCharPositionInLine(), e, SpelMessages.EXCEPTION_DURING_FUNCTION_CALL, name, e
|
||||
.getMessage());
|
||||
|
|
|
@ -323,16 +323,25 @@ public class StandardTypeConverter implements TypeConverter {
|
|||
|
||||
private static class ToIntegerConverter implements StandardIndividualTypeConverter {
|
||||
public Object convert(Object value) throws SpelException {
|
||||
try {
|
||||
return Integer.parseInt(((Long) value).toString());
|
||||
} catch (NumberFormatException nfe) {
|
||||
throw new SpelException(SpelMessages.PROBLEM_DURING_TYPE_CONVERSION, "long value '" + value
|
||||
+ "' cannot be represented as an int");
|
||||
if (value instanceof String) {
|
||||
try {
|
||||
return Integer.parseInt((String)value);
|
||||
} catch (NumberFormatException nfe) {
|
||||
throw new SpelException(SpelMessages.PROBLEM_DURING_TYPE_CONVERSION, "cannot parse string '" + value
|
||||
+ "' as an integer");
|
||||
}
|
||||
} else { // Long
|
||||
try {
|
||||
return Integer.parseInt(((Long) value).toString());
|
||||
} catch (NumberFormatException nfe) {
|
||||
throw new SpelException(SpelMessages.PROBLEM_DURING_TYPE_CONVERSION, "long value '" + value
|
||||
+ "' cannot be represented as an int");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Class<?>[] getFrom() {
|
||||
return new Class<?>[] { Long.class };
|
||||
return new Class<?>[] { Long.class, String.class };
|
||||
}
|
||||
|
||||
public Class<?> getTo() {
|
||||
|
|
Loading…
Reference in New Issue