Author: bayard
Date: Wed Sep 5 07:35:21 2007
New Revision: 572959
URL: http://svn.apache.org/viewvc?rev=572959&view=rev
Log:
Applying Jamie Taylor's patch from EL-8 - EL now correctly implements the spec
and is not affected when the function map is later modified
Added:
commons/proper/el/trunk/src/java/org/apache/commons/el/BoundFunctionInvocation.java
(with props)
commons/proper/el/trunk/src/test/org/apache/commons/el/FunctionBindingTest.java
(with props)
Modified:
commons/proper/el/trunk/NOTICE.txt
commons/proper/el/trunk/src/java/org/apache/commons/el/ArraySuffix.java
commons/proper/el/trunk/src/java/org/apache/commons/el/BinaryOperatorExpression.java
commons/proper/el/trunk/src/java/org/apache/commons/el/ComplexValue.java
commons/proper/el/trunk/src/java/org/apache/commons/el/ConditionalExpression.java
commons/proper/el/trunk/src/java/org/apache/commons/el/Expression.java
commons/proper/el/trunk/src/java/org/apache/commons/el/ExpressionEvaluatorImpl.java
commons/proper/el/trunk/src/java/org/apache/commons/el/ExpressionString.java
commons/proper/el/trunk/src/java/org/apache/commons/el/FunctionInvocation.java
commons/proper/el/trunk/src/java/org/apache/commons/el/Literal.java
commons/proper/el/trunk/src/java/org/apache/commons/el/NamedValue.java
commons/proper/el/trunk/src/java/org/apache/commons/el/UnaryOperatorExpression.java
commons/proper/el/trunk/src/java/org/apache/commons/el/ValueSuffix.java
Modified: commons/proper/el/trunk/NOTICE.txt
URL:
http://svn.apache.org/viewvc/commons/proper/el/trunk/NOTICE.txt?rev=572959&r1=572958&r2=572959&view=diff
==============================================================================
--- commons/proper/el/trunk/NOTICE.txt (original)
+++ commons/proper/el/trunk/NOTICE.txt Wed Sep 5 07:35:21 2007
@@ -3,3 +3,6 @@
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
+
+EL-8 patch - Copyright 2004-2007 Jamie Taylor
+http://issues.apache.org/jira/browse/EL-8
Modified:
commons/proper/el/trunk/src/java/org/apache/commons/el/ArraySuffix.java
URL:
http://svn.apache.org/viewvc/commons/proper/el/trunk/src/java/org/apache/commons/el/ArraySuffix.java?rev=572959&r1=572958&r2=572959&view=diff
==============================================================================
--- commons/proper/el/trunk/src/java/org/apache/commons/el/ArraySuffix.java
(original)
+++ commons/proper/el/trunk/src/java/org/apache/commons/el/ArraySuffix.java Wed
Sep 5 07:35:21 2007
@@ -296,5 +296,8 @@
return null;
}
+ public ValueSuffix bindFunctions(final FunctionMapper functions) throws
ELException {
+ return new ArraySuffix(mIndex.bindFunctions(functions));
+ }
//-------------------------------------
}
Modified:
commons/proper/el/trunk/src/java/org/apache/commons/el/BinaryOperatorExpression.java
URL:
http://svn.apache.org/viewvc/commons/proper/el/trunk/src/java/org/apache/commons/el/BinaryOperatorExpression.java?rev=572959&r1=572958&r2=572959&view=diff
==============================================================================
---
commons/proper/el/trunk/src/java/org/apache/commons/el/BinaryOperatorExpression.java
(original)
+++
commons/proper/el/trunk/src/java/org/apache/commons/el/BinaryOperatorExpression.java
Wed Sep 5 07:35:21 2007
@@ -17,6 +17,8 @@
package org.apache.commons.el;
import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
import javax.servlet.jsp.el.ELException;
import javax.servlet.jsp.el.FunctionMapper;
@@ -131,6 +133,19 @@
}
return value;
}
+
+ public Expression bindFunctions(final FunctionMapper functions) throws
ELException {
+ final List args = new ArrayList(mExpressions.size());
+ for (Iterator argIter = mExpressions.iterator(); argIter.hasNext();) {
+ args.add(((Expression)argIter.next()).bindFunctions(functions));
+ }
+ // it would be nice if we knew for sure that the operators list
+ // was immutable, but we'll just assume so for now.
+ return new BinaryOperatorExpression(
+ mExpression.bindFunctions(functions),
+ mOperators,
+ args);
+ }
//-------------------------------------
}
Added:
commons/proper/el/trunk/src/java/org/apache/commons/el/BoundFunctionInvocation.java
URL:
http://svn.apache.org/viewvc/commons/proper/el/trunk/src/java/org/apache/commons/el/BoundFunctionInvocation.java?rev=572959&view=auto
==============================================================================
---
commons/proper/el/trunk/src/java/org/apache/commons/el/BoundFunctionInvocation.java
(added)
+++
commons/proper/el/trunk/src/java/org/apache/commons/el/BoundFunctionInvocation.java
Wed Sep 5 07:35:21 2007
@@ -0,0 +1,57 @@
+/* $Id$ */
+/*
+ * 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.el;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import javax.servlet.jsp.el.ELException;
+import javax.servlet.jsp.el.FunctionMapper;
+
+/**
+ * A subclass of <code>FunctionInvocation</code> which is bound
+ * to a particular <code>Method</code>. A bound function does
+ * not require a <code>FunctionMapper</code> to be evaluated.
+ *
+ * @author Jamie Taylor
+ */
+public class BoundFunctionInvocation extends FunctionInvocation {
+ private final Method method;
+
+ /**
+ * @param functionName
+ * @param argumentList
+ */
+ public BoundFunctionInvocation(
+ final Method method,
+ final String functionName,
+ final List argumentList)
+ {
+ super(functionName, argumentList);
+ this.method = method;
+ }
+
+ /**
+ * Returns the <code>Method</code>supplied to the constructor.
+ * @param functions unused
+ */
+ protected Method resolveFunction(FunctionMapper functions)
+ throws ELException {
+ return method;
+ }
+}
Propchange:
commons/proper/el/trunk/src/java/org/apache/commons/el/BoundFunctionInvocation.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
commons/proper/el/trunk/src/java/org/apache/commons/el/ComplexValue.java
URL:
http://svn.apache.org/viewvc/commons/proper/el/trunk/src/java/org/apache/commons/el/ComplexValue.java?rev=572959&r1=572958&r2=572959&view=diff
==============================================================================
--- commons/proper/el/trunk/src/java/org/apache/commons/el/ComplexValue.java
(original)
+++ commons/proper/el/trunk/src/java/org/apache/commons/el/ComplexValue.java
Wed Sep 5 07:35:21 2007
@@ -17,6 +17,7 @@
package org.apache.commons.el;
import java.util.List;
+import java.util.ArrayList;
import javax.servlet.jsp.el.ELException;
import javax.servlet.jsp.el.FunctionMapper;
@@ -107,6 +108,15 @@
}
return ret;
+ }
+
+ public Expression bindFunctions(final FunctionMapper functions) throws
ELException {
+ final List suffixes = new ArrayList(mSuffixes.size());
+ for (int i = 0; mSuffixes != null && i < mSuffixes.size (); i++) {
+ ValueSuffix suffix = (ValueSuffix) mSuffixes.get (i);
+ suffixes.add(suffix.bindFunctions(functions));
+ }
+ return new ComplexValue(mPrefix.bindFunctions(functions), suffixes);
}
//-------------------------------------
Modified:
commons/proper/el/trunk/src/java/org/apache/commons/el/ConditionalExpression.java
URL:
http://svn.apache.org/viewvc/commons/proper/el/trunk/src/java/org/apache/commons/el/ConditionalExpression.java?rev=572959&r1=572958&r2=572959&view=diff
==============================================================================
---
commons/proper/el/trunk/src/java/org/apache/commons/el/ConditionalExpression.java
(original)
+++
commons/proper/el/trunk/src/java/org/apache/commons/el/ConditionalExpression.java
Wed Sep 5 07:35:21 2007
@@ -113,5 +113,12 @@
return mFalseBranch.evaluate(vr, f);
}
+ public Expression bindFunctions(final FunctionMapper functions) throws
ELException {
+ return new ConditionalExpression(
+ mCondition.bindFunctions(functions),
+ mTrueBranch.bindFunctions(functions),
+ mFalseBranch.bindFunctions(functions));
+ }
+
//-------------------------------------
}
Modified: commons/proper/el/trunk/src/java/org/apache/commons/el/Expression.java
URL:
http://svn.apache.org/viewvc/commons/proper/el/trunk/src/java/org/apache/commons/el/Expression.java?rev=572959&r1=572958&r2=572959&view=diff
==============================================================================
--- commons/proper/el/trunk/src/java/org/apache/commons/el/Expression.java
(original)
+++ commons/proper/el/trunk/src/java/org/apache/commons/el/Expression.java Wed
Sep 5 07:35:21 2007
@@ -53,4 +53,17 @@
//-------------------------------------
+ /**
+ * Returns an expression with all <code>FunctionInvocation</code>s replaced
by
+ * <code>BoundFunctionInvocation</code>s.
+ * @param functions the functions to use in this transformation
+ * @return an Expression identical to this expression except with all
+ * <code>FunctionInvocation</code>s replaced by
+ * <code>BoundFunctionInvocation</code>s.
+ * @throws ELException if any of the functions in this
<code>Expression</code> are
+ * not present in <code>functions</code>
+ */
+ public abstract Expression bindFunctions(FunctionMapper functions)
+ throws ELException;
+
}
Modified:
commons/proper/el/trunk/src/java/org/apache/commons/el/ExpressionEvaluatorImpl.java
URL:
http://svn.apache.org/viewvc/commons/proper/el/trunk/src/java/org/apache/commons/el/ExpressionEvaluatorImpl.java?rev=572959&r1=572958&r2=572959&view=diff
==============================================================================
---
commons/proper/el/trunk/src/java/org/apache/commons/el/ExpressionEvaluatorImpl.java
(original)
+++
commons/proper/el/trunk/src/java/org/apache/commons/el/ExpressionEvaluatorImpl.java
Wed Sep 5 07:35:21 2007
@@ -153,11 +153,14 @@
FunctionMapper fMapper)
throws ELException
{
- // Validate and then create an Expression object.
- Object parsedExpression = parseExpressionString (expression);
-
- // Create an Expression object that knows how to evaluate this.
- return new JSTLExpression (parsedExpression, expectedType, fMapper);
+ // Create an Expression object that knows how to evaluate this.
+ final Object parsedExpression = parseExpressionString(expression);
+ if (parsedExpression instanceof Expression) {
+ return new JSTLExpression(this, (Expression)parsedExpression,
expectedType, fMapper);
+ } else {
+ // this had better be a string
+ return new JSTLExpression(this, (String)parsedExpression,
expectedType, fMapper);
+ }
}
//-------------------------------------
@@ -208,36 +211,30 @@
public Object evaluate (Object parsedExpression, Class pExpectedType,
VariableResolver pResolver, FunctionMapper functions) throws ELException
{
- // Evaluate differently based on the parsed type
- if (parsedExpression instanceof String)
- {
- // Convert the String, and cache the conversion
- String strValue = (String) parsedExpression;
- return convertStaticValueToExpectedType (strValue, pExpectedType);
- }
-
- if (parsedExpression instanceof Expression)
- {
- // Evaluate the expression and convert
- Object value =
- ((Expression) parsedExpression).evaluate (pResolver,
- functions);
- return convertToExpectedType (value, pExpectedType);
- }
-
- if (parsedExpression instanceof ExpressionString)
- {
- // Evaluate the expression/string list and convert
- String strValue =
- ((ExpressionString) parsedExpression).evaluate (pResolver, functions);
- return convertToExpectedType (strValue, pExpectedType);
- }
+ return evaluateParsedValue(parsedExpression, pExpectedType, pResolver,
functions);
+ }
- else {
- // This should never be reached
- return null;
+ private Object evaluateParsedValue(Object parsedValue, Class pExpectedType,
VariableResolver pResolver, FunctionMapper functions) throws ELException {
+ // Evaluate differently based on the parsed type
+ if (parsedValue instanceof String) {
+ // Convert the String, and cache the conversion
+ String strValue = (String) parsedValue;
+ return convertStaticValueToExpectedType (strValue, pExpectedType);
+ }
+
+ else if (parsedValue instanceof Expression) {
+ // Evaluate the expression and convert
+ Object value =
+ ((Expression) parsedValue).evaluate (pResolver,
+ functions);
+ return convertToExpectedType (value, pExpectedType);
+ }
+
+ else {
+ // This should never be reached
+ return null;
+ }
}
- }
//-------------------------------------
/**
@@ -481,24 +478,40 @@
private class JSTLExpression
extends javax.servlet.jsp.el.Expression
{
+ private ExpressionEvaluatorImpl evaluator;
private Object parsedExpression;
private Class expectedType;
- private FunctionMapper fMapper;
- private JSTLExpression(Object parsedExpression, Class expectedType,
- FunctionMapper fMapper)
- {
- this.parsedExpression = parsedExpression;
+ public JSTLExpression(
+ final ExpressionEvaluatorImpl evaluator,
+ final Expression expression,
+ final Class expectedType,
+ final FunctionMapper fMapper)
+ throws ELException {
+ this.evaluator = evaluator;
+ this.parsedExpression = expression.bindFunctions(fMapper);
this.expectedType = expectedType;
- this.fMapper = fMapper;
}
-
- public Object evaluate (VariableResolver vResolver) throws ELException
- {
- return ExpressionEvaluatorImpl.this.evaluate
- (parsedExpression, expectedType, vResolver, fMapper);
- }
- }
+ public JSTLExpression(
+ final ExpressionEvaluatorImpl evaluator,
+ final String expressionString,
+ final Class expectedType,
+ final FunctionMapper fMapper)
+ throws ELException {
+ this.evaluator = evaluator;
+ this.parsedExpression = expressionString;
+ this.expectedType = expectedType;
+ }
+
+ public Object evaluate( VariableResolver vResolver )
+ throws ELException
+ {
+ return evaluator.evaluateParsedValue(this.parsedExpression,
+ this.expectedType,
+ vResolver,
+ null);
+ }
+ }
//-------------------------------------
Modified:
commons/proper/el/trunk/src/java/org/apache/commons/el/ExpressionString.java
URL:
http://svn.apache.org/viewvc/commons/proper/el/trunk/src/java/org/apache/commons/el/ExpressionString.java?rev=572959&r1=572958&r2=572959&view=diff
==============================================================================
---
commons/proper/el/trunk/src/java/org/apache/commons/el/ExpressionString.java
(original)
+++
commons/proper/el/trunk/src/java/org/apache/commons/el/ExpressionString.java
Wed Sep 5 07:35:21 2007
@@ -30,7 +30,7 @@
* @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author$
**/
-public class ExpressionString
+public class ExpressionString extends Expression
{
//-------------------------------------
// Properties
@@ -60,7 +60,7 @@
* converting it to a String (using toString, or "" for null values)
* and concatenating the results into a single String.
**/
- public String evaluate (VariableResolver pResolver,
+ public Object evaluate (VariableResolver pResolver,
FunctionMapper functions)
throws ELException
{
@@ -104,4 +104,16 @@
}
//-------------------------------------
+
+ public Expression bindFunctions(FunctionMapper functions) throws ELException
{
+ final Object[] boundElements = new Object[mElements.length];
+ for (int i = 0; i < mElements.length; i++) {
+ if (mElements[i] instanceof Expression) {
+ boundElements[i] =
((Expression)mElements[i]).bindFunctions(functions);
+ } else {
+ boundElements[i] = mElements[i];
+ }
+ }
+ return new ExpressionString(boundElements);
+ }
}
Modified:
commons/proper/el/trunk/src/java/org/apache/commons/el/FunctionInvocation.java
URL:
http://svn.apache.org/viewvc/commons/proper/el/trunk/src/java/org/apache/commons/el/FunctionInvocation.java?rev=572959&r1=572958&r2=572959&view=diff
==============================================================================
---
commons/proper/el/trunk/src/java/org/apache/commons/el/FunctionInvocation.java
(original)
+++
commons/proper/el/trunk/src/java/org/apache/commons/el/FunctionInvocation.java
Wed Sep 5 07:35:21 2007
@@ -20,6 +20,7 @@
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
+import java.util.ArrayList;
import javax.servlet.jsp.el.ELException;
import javax.servlet.jsp.el.FunctionMapper;
@@ -97,30 +98,7 @@
throws ELException
{
- // if the Map is null, then the function is invalid
- if (functions == null) {
- if (log.isErrorEnabled()) {
- String message = MessageUtil.getMessageWithArgs(
- Constants.UNKNOWN_FUNCTION, functionName);
- log.error(message);
- throw new ELException(message);
- }
- }
-
- // normalize function name
- String prefix = null;
- String localName = null;
- int index = functionName.indexOf( ':' );
- if (index == -1) {
- prefix = "";
- localName = functionName;
- } else {
- prefix = functionName.substring( 0, index );
- localName = functionName.substring( index + 1 );
- }
-
- // ensure that the function's name is mapped
- Method target = (Method) functions.resolveFunction(prefix, localName);
+ Method target = resolveFunction(functions);
if (target == null) {
if (log.isErrorEnabled()) {
String message = MessageUtil.getMessageWithArgs(
@@ -177,6 +155,50 @@
return null;
}
}
+
+ /**
+ * Returns the <code>Method</code> which is mapped to the function
+ * name used by this <code>FunctionInvocation</code>.
+ * @param functions The function mappings in use for this evaluation
+ * @return the <code>Method</code> to execute
+ * @throws ELException
+ */
+ protected Method resolveFunction(FunctionMapper functions) throws
ELException {
+ // if the Map is null, then the function is invalid
+ if (functions == null) {
+ return null;
+ }
+
+ // normalize function name
+ String prefix = null;
+ String localName = null;
+ int index = functionName.indexOf( ':' );
+ if (index == -1) {
+ prefix = "";
+ localName = functionName;
+ } else {
+ prefix = functionName.substring( 0, index );
+ localName = functionName.substring( index + 1 );
+ }
+
+ // ensure that the function's name is mapped
+ Method target = (Method) functions.resolveFunction(prefix, localName);
+
+ return target;
+ }
+
+ public Expression bindFunctions(final FunctionMapper functions)
+ throws ELException {
+ final List argList = new ArrayList(argumentList.size());
+ for (Iterator argIter = argumentList.iterator(); argIter.hasNext();) {
+ Expression arg = (Expression) argIter.next();
+ argList.add(arg.bindFunctions(functions));
+ }
+ return new BoundFunctionInvocation(
+ resolveFunction(functions),
+ functionName,
+ argList);
+ }
//-------------------------------------
}
Modified: commons/proper/el/trunk/src/java/org/apache/commons/el/Literal.java
URL:
http://svn.apache.org/viewvc/commons/proper/el/trunk/src/java/org/apache/commons/el/Literal.java?rev=572959&r1=572958&r2=572959&view=diff
==============================================================================
--- commons/proper/el/trunk/src/java/org/apache/commons/el/Literal.java
(original)
+++ commons/proper/el/trunk/src/java/org/apache/commons/el/Literal.java Wed Sep
5 07:35:21 2007
@@ -66,5 +66,10 @@
return mValue;
}
+ public Expression bindFunctions(FunctionMapper functions) throws ELException
{
+ return this;
+ }
+
+
//-------------------------------------
}
Modified: commons/proper/el/trunk/src/java/org/apache/commons/el/NamedValue.java
URL:
http://svn.apache.org/viewvc/commons/proper/el/trunk/src/java/org/apache/commons/el/NamedValue.java?rev=572959&r1=572958&r2=572959&view=diff
==============================================================================
--- commons/proper/el/trunk/src/java/org/apache/commons/el/NamedValue.java
(original)
+++ commons/proper/el/trunk/src/java/org/apache/commons/el/NamedValue.java Wed
Sep 5 07:35:21 2007
@@ -84,5 +84,9 @@
}
}
+ public Expression bindFunctions(FunctionMapper functions) throws ELException
{
+ return this;
+ }
+
//-------------------------------------
}
Modified:
commons/proper/el/trunk/src/java/org/apache/commons/el/UnaryOperatorExpression.java
URL:
http://svn.apache.org/viewvc/commons/proper/el/trunk/src/java/org/apache/commons/el/UnaryOperatorExpression.java?rev=572959&r1=572958&r2=572959&view=diff
==============================================================================
---
commons/proper/el/trunk/src/java/org/apache/commons/el/UnaryOperatorExpression.java
(original)
+++
commons/proper/el/trunk/src/java/org/apache/commons/el/UnaryOperatorExpression.java
Wed Sep 5 07:35:21 2007
@@ -126,5 +126,12 @@
return value;
}
+ public Expression bindFunctions(final FunctionMapper functions) throws
ELException {
+ return new UnaryOperatorExpression(
+ mOperator,
+ mOperators,
+ mExpression.bindFunctions(functions));
+ }
+
//-------------------------------------
}
Modified:
commons/proper/el/trunk/src/java/org/apache/commons/el/ValueSuffix.java
URL:
http://svn.apache.org/viewvc/commons/proper/el/trunk/src/java/org/apache/commons/el/ValueSuffix.java?rev=572959&r1=572958&r2=572959&view=diff
==============================================================================
--- commons/proper/el/trunk/src/java/org/apache/commons/el/ValueSuffix.java
(original)
+++ commons/proper/el/trunk/src/java/org/apache/commons/el/ValueSuffix.java Wed
Sep 5 07:35:21 2007
@@ -51,5 +51,8 @@
FunctionMapper functions)
throws ELException;
+ public abstract ValueSuffix bindFunctions(FunctionMapper functions)
+ throws ELException;
+
//-------------------------------------
}
Added:
commons/proper/el/trunk/src/test/org/apache/commons/el/FunctionBindingTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/el/trunk/src/test/org/apache/commons/el/FunctionBindingTest.java?rev=572959&view=auto
==============================================================================
---
commons/proper/el/trunk/src/test/org/apache/commons/el/FunctionBindingTest.java
(added)
+++
commons/proper/el/trunk/src/test/org/apache/commons/el/FunctionBindingTest.java
Wed Sep 5 07:35:21 2007
@@ -0,0 +1,96 @@
+/* $Id$ */
+/*
+ * 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.el;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.jsp.el.ELException;
+import javax.servlet.jsp.el.Expression;
+import javax.servlet.jsp.el.ExpressionEvaluator;
+import javax.servlet.jsp.el.FunctionMapper;
+import javax.servlet.jsp.el.VariableResolver;
+
+import org.apache.commons.el.ExpressionEvaluatorImpl;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Jamie Taylor
+ *
+ */
+public class FunctionBindingTest extends TestCase {
+ public static String before() {return "before";}
+ public static String after() {return "after";}
+ public static String echo(final String s) {return s;}
+ private static class UpdatableFunctionMapper implements FunctionMapper {
+ private Map mappings = new HashMap();
+ public void setMapping(
+ final String name,
+ final Method function)
+ {
+ mappings.put(name,function);
+ }
+ public Method resolveFunction(
+ final String prefix,
+ final String localName)
+ {
+ return (Method)mappings.get(localName);
+ }
+ }
+
+ public void testFunctionBinding() throws ELException,
NoSuchMethodException{
+ final String theExpression = "${theFunction()}";
+ final String nestedExpression = "${echo(theFunction())}";
+ final VariableResolver emptyVariableResolver = new VariableResolver() {
+ public Object resolveVariable(String arg0) throws ELException {
+ return null;
+ }
+ };
+ final UpdatableFunctionMapper fm = new UpdatableFunctionMapper();
+ final Method before =
FunctionBindingTest.class.getDeclaredMethod("before",new Class[0]);
+ final Method after =
FunctionBindingTest.class.getDeclaredMethod("after",new Class[0]);
+ final Method echo =
FunctionBindingTest.class.getDeclaredMethod("echo", new Class[]{String.class});
+ final ExpressionEvaluator evaluator = new ExpressionEvaluatorImpl();
+ fm.setMapping("theFunction",before);
+ fm.setMapping("echo", echo);
+
+ final Expression expr = evaluator.parseExpression(theExpression,
String.class, fm);
+ final Expression nestedExpr =
evaluator.parseExpression(nestedExpression, String.class, fm);
+ assertEquals(
+ "before",
+ expr.evaluate(emptyVariableResolver));
+ assertEquals(
+ "before",
+ nestedExpr.evaluate(emptyVariableResolver));
+
+ fm.setMapping("theFunction",after);
+ assertEquals(
+ "after",
+ evaluator.evaluate(theExpression, String.class,
emptyVariableResolver, fm));
+ assertEquals(
+ "before",
+ expr.evaluate(emptyVariableResolver));
+ assertEquals(
+ "after",
+ evaluator.evaluate(nestedExpression, String.class,
emptyVariableResolver, fm));
+ assertEquals(
+ "before",
+ nestedExpr.evaluate(emptyVariableResolver));
+ }
+}
Propchange:
commons/proper/el/trunk/src/test/org/apache/commons/el/FunctionBindingTest.java
------------------------------------------------------------------------------
svn:eol-style = native