diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/FunctionReference.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/FunctionReference.java index 5a9eb7c806..1b28e8f9bf 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/FunctionReference.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/FunctionReference.java @@ -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[] getFrom() { - return new Class[] { Long.class }; + return new Class[] { Long.class, String.class }; } public Class getTo() {