diff --git a/java/org/apache/el/parser/AstFunction.java b/java/org/apache/el/parser/AstFunction.java index 2621d42c2bf0..edac458c2059 100644 --- a/java/org/apache/el/parser/AstFunction.java +++ b/java/org/apache/el/parser/AstFunction.java @@ -170,9 +170,16 @@ public Object getValue(EvaluationContext ctx) throws ELException { // Java semantics: an empty array is passed when no // varargs elements are supplied params[i] = new Object[0]; - } else if (inputParameterCount == methodParameterCount && - isArray(parameters.jjtGetChild(i).getValue(ctx))) { - params[i] = parameters.jjtGetChild(i).getValue(ctx); + } else if (inputParameterCount == methodParameterCount) { + // Evaluate the single argument once: it is either + // the varargs array itself or its only element + Object value = parameters.jjtGetChild(i).getValue(ctx); + if (isArray(value)) { + params[i] = value; + } else { + params[i] = new Object[] { ELSupport.coerceToType(ctx, value, + paramTypes[i].getComponentType()) }; + } } else { Object[] varargs = new Object[inputParameterCount - methodParameterCount + 1]; Class target = paramTypes[i].getComponentType(); diff --git a/test/org/apache/el/parser/TestAstFunction.java b/test/org/apache/el/parser/TestAstFunction.java index 2137afe56513..7604c891445d 100644 --- a/test/org/apache/el/parser/TestAstFunction.java +++ b/test/org/apache/el/parser/TestAstFunction.java @@ -25,6 +25,7 @@ import org.junit.Assert; import org.junit.Test; +import org.apache.el.TesterBeanK; import org.apache.el.TesterFunctions; public class TestAstFunction { @@ -108,6 +109,19 @@ public void testVarargMethod() throws NoSuchMethodException, SecurityException { Assert.assertEquals("one", result); } + @Test + public void testVarargMethodSingleArgumentEvaluatedOnce() throws NoSuchMethodException { + // The argument that alone fills the varargs parameter must be evaluated + // exactly once, as each argument is when there are several + ELProcessor processor = new ELProcessor(); + TesterBeanK bean = new TesterBeanK(); + processor.defineBean("beanK", bean); + processor.defineFunction("fn", "format", String.class.getMethod("format", String.class, Object[].class)); + + Assert.assertEquals("1", processor.getValue("fn:format('%s', beanK.next())", String.class)); + Assert.assertEquals(1, bean.argCalls); + } + @Test public void testVarargMethodEmptyVarargs01() throws NoSuchMethodException { // Java passes an empty array, never null, to a varargs method that is