diff --git a/org.springframework.context/src/main/java/org/springframework/context/expression/StandardBeanExpressionResolver.java b/org.springframework.context/src/main/java/org/springframework/context/expression/StandardBeanExpressionResolver.java index 2bfe4b7e47e..80a981850a2 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/expression/StandardBeanExpressionResolver.java +++ b/org.springframework.context/src/main/java/org/springframework/context/expression/StandardBeanExpressionResolver.java @@ -23,11 +23,14 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanExpressionException; import org.springframework.beans.factory.config.BeanExpressionContext; import org.springframework.beans.factory.config.BeanExpressionResolver; +import org.springframework.core.convert.ConversionService; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.ParserContext; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.expression.spel.support.StandardTypeConverter; +import org.springframework.expression.spel.support.StandardTypeLocator; import org.springframework.util.Assert; /** @@ -96,7 +99,7 @@ public class StandardBeanExpressionResolver implements BeanExpressionResolver { /** * Specify the EL parser to use for expression parsing. - *

Default is a {@link org.springframework.expression.spel.SpelExpressionParser}, + *

Default is a {@link org.springframework.expression.spel.standard.SpelExpressionParser}, * compatible with standard Unified EL style expression syntax. */ public void setExpressionParser(ExpressionParser expressionParser) { @@ -119,6 +122,11 @@ public class StandardBeanExpressionResolver implements BeanExpressionResolver { sec.addPropertyAccessor(new BeanExpressionContextAccessor()); sec.addPropertyAccessor(new BeanFactoryAccessor()); sec.addPropertyAccessor(new MapAccessor()); + sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader())); + ConversionService conversionService = evalContext.getBeanFactory().getConversionService(); + if (conversionService != null) { + sec.setTypeConverter(new StandardTypeConverter(conversionService)); + } customizeEvaluationContext(sec); this.evaluationCache.put(evalContext, sec); } diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/EvaluationContext.java b/org.springframework.expression/src/main/java/org/springframework/expression/EvaluationContext.java index 105a630b3ae..9930e2131f6 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/EvaluationContext.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/EvaluationContext.java @@ -21,11 +21,11 @@ import java.util.List; /** * Expressions are executed in an evaluation context. It is in this context that references * are resolved when encountered during expression evaluation. - * - * There is a default implementation of the EvaluationContext, + * + *

There is a default implementation of the EvaluationContext, * {@link org.springframework.expression.spel.support.StandardEvaluationContext} * that can be extended, rather than having to implement everything. - * + * * @author Andy Clement * @author Juergen Hoeller * @since 3.0 @@ -36,27 +36,6 @@ public interface EvaluationContext { * @return the root context object against which unqualified properties/methods/etc should be resolved */ TypedValue getRootObject(); - - - /** - * @param rootObject the root object against which unqualified properties/methods/etc should be resolved - */ - void setRootObject(Object object); - - - /** - * Set a named variable within this execution context to a specified value. - * @param name variable to set - * @param value value to be placed in the variable - */ - void setVariable(String name, Object value); - - /** - * Look up a named variable within this execution context. - * @param name variable to lookup - * @return the value of the variable - */ - Object lookupVariable(String name); /** * @return a list of resolvers that will be asked in turn to locate a constructor @@ -78,20 +57,34 @@ public interface EvaluationContext { */ TypeLocator getTypeLocator(); - /** - * @return a type comparator for comparing pairs of objects for equality. - */ - TypeComparator getTypeComparator(); - /** * @return a type converter that can convert (or coerce) a value from one type to another. */ TypeConverter getTypeConverter(); + /** + * @return a type comparator for comparing pairs of objects for equality. + */ + TypeComparator getTypeComparator(); + /** * @return an operator overloader that may support mathematical operations between more than the standard set of * types */ OperatorOverloader getOperatorOverloader(); + /** + * Set a named variable within this evaluation context to a specified value. + * @param name variable to set + * @param value value to be placed in the variable + */ + void setVariable(String name, Object value); + + /** + * Look up a named variable within this evaluation context. + * @param name variable to lookup + * @return the value of the variable + */ + Object lookupVariable(String name); + } diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ExpressionState.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ExpressionState.java index fa8b932d86e..62f365c3575 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ExpressionState.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ExpressionState.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.expression.spel; import java.util.HashMap; @@ -36,7 +37,7 @@ import org.springframework.expression.spel.standard.SpelExpressionParserConfigur * communicate state. This is in contrast to the EvaluationContext, which is shared amongst expression evaluations, and * any changes to it will be seen by other expressions or any code that chooses to ask questions of the context. * - * It also acts as a place for to define common utility routines that the various Ast nodes might need. + *

It also acts as a place for to define common utility routines that the various Ast nodes might need. * * @author Andy Clement * @since 3.0 @@ -75,7 +76,8 @@ public class ExpressionState { TypedValue rootObject = this.relatedContext.getRootObject(); if (rootObject == null) { return TypedValue.NULL_TYPED_VALUE; - } else { + } + else { return rootObject; } } @@ -94,7 +96,8 @@ public class ExpressionState { TypedValue root = this.relatedContext.getRootObject(); if (root == null) { return TypedValue.NULL_TYPED_VALUE; - } else { + } + else { return root; } } @@ -105,10 +108,11 @@ public class ExpressionState { public TypedValue lookupVariable(String name) { Object value = this.relatedContext.lookupVariable(name); - if (value==null) { + if (value == null) { return TypedValue.NULL_TYPED_VALUE; - } else { - return new TypedValue(value,TypeDescriptor.forObject(value)); + } + else { + return new TypedValue(value, TypeDescriptor.forObject(value)); } } diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/StandardEvaluationContext.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/StandardEvaluationContext.java index b02029cbf04..3a55f3fee49 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/StandardEvaluationContext.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/StandardEvaluationContext.java @@ -47,8 +47,6 @@ public class StandardEvaluationContext implements EvaluationContext { private TypedValue rootObject; - private final Map variables = new HashMap(); - private final List constructorResolvers = new ArrayList(); private final List methodResolvers = new ArrayList(); @@ -57,12 +55,15 @@ public class StandardEvaluationContext implements EvaluationContext { private TypeLocator typeLocator = new StandardTypeLocator(); - private TypeComparator typeComparator = new StandardTypeComparator(); - private TypeConverter typeConverter = new StandardTypeConverter(); + private TypeComparator typeComparator = new StandardTypeComparator(); + private OperatorOverloader operatorOverloader = new StandardOperatorOverloader(); + private final Map variables = new HashMap(); + + public StandardEvaluationContext() { this.methodResolvers.add(new ReflectiveMethodResolver()); this.constructorResolvers.add(new ReflectiveConstructorResolver()); @@ -74,34 +75,19 @@ public class StandardEvaluationContext implements EvaluationContext { setRootObject(rootObject); } + public void setRootObject(Object rootObject) { - this.rootObject = new TypedValue(rootObject,TypeDescriptor.forObject(rootObject)); + this.rootObject = new TypedValue(rootObject, TypeDescriptor.forObject(rootObject)); } public void setRootObject(Object rootObject, TypeDescriptor typeDescriptor) { - this.rootObject = new TypedValue(rootObject,typeDescriptor); + this.rootObject = new TypedValue(rootObject, typeDescriptor); } public TypedValue getRootObject() { return this.rootObject; } - public void setVariable(String name, Object value) { - this.variables.put(name, value); - } - - public void setVariables(Map variables) { - this.variables.putAll(variables); - } - - public void registerFunction(String name, Method method) { - this.variables.put(name, method); - } - - public Object lookupVariable(String name) { - return this.variables.get(name); - } - public void addConstructorResolver(ConstructorResolver resolver) { this.constructorResolvers.add(this.constructorResolvers.size() - 1, resolver); } @@ -135,15 +121,6 @@ public class StandardEvaluationContext implements EvaluationContext { return this.typeLocator; } - public void setTypeComparator(TypeComparator typeComparator) { - Assert.notNull(typeComparator, "TypeComparator must not be null"); - this.typeComparator = typeComparator; - } - - public TypeComparator getTypeComparator() { - return this.typeComparator; - } - public void setTypeConverter(TypeConverter typeConverter) { Assert.notNull(typeConverter, "TypeConverter must not be null"); this.typeConverter = typeConverter; @@ -153,6 +130,15 @@ public class StandardEvaluationContext implements EvaluationContext { return this.typeConverter; } + public void setTypeComparator(TypeComparator typeComparator) { + Assert.notNull(typeComparator, "TypeComparator must not be null"); + this.typeComparator = typeComparator; + } + + public TypeComparator getTypeComparator() { + return this.typeComparator; + } + public void setOperatorOverloader(OperatorOverloader operatorOverloader) { Assert.notNull(operatorOverloader, "OperatorOverloader must not be null"); this.operatorOverloader = operatorOverloader; @@ -162,4 +148,20 @@ public class StandardEvaluationContext implements EvaluationContext { return this.operatorOverloader; } + public void setVariable(String name, Object value) { + this.variables.put(name, value); + } + + public void setVariables(Map variables) { + this.variables.putAll(variables); + } + + public void registerFunction(String name, Method method) { + this.variables.put(name, method); + } + + public Object lookupVariable(String name) { + return this.variables.get(name); + } + } diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/ExpressionStateTests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/ExpressionStateTests.java index f16dddcfe31..ca19e048c59 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/ExpressionStateTests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/ExpressionStateTests.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.expression.spel; import java.util.HashMap; @@ -29,7 +30,6 @@ import org.springframework.expression.TypedValue; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.testresources.Inventor; - /** * Tests for the expression state object - some features are not yet exploited in the language (eg nested scopes) * @@ -47,7 +47,6 @@ public class ExpressionStateTests extends ExpressionTestCase { // Local variables are in variable scopes which come and go during evaluation. Normal variables are // accessible through the evaluation context - @Test public void testLocalVariables() { ExpressionState state = getState(); @@ -62,7 +61,6 @@ public class ExpressionStateTests extends ExpressionTestCase { state.setLocalVariable("foo",null); value = state.lookupLocalVariable("foo"); Assert.assertEquals(null,value); - } @Test @@ -119,8 +117,8 @@ public class ExpressionStateTests extends ExpressionTestCase { ExpressionState state = getState(); Assert.assertEquals(Inventor.class,state.getRootContextObject().getValue().getClass()); - state.getEvaluationContext().setRootObject(null); - Assert.assertEquals(null,state.getRootContextObject().getValue()); + ((StandardEvaluationContext) state.getEvaluationContext()).setRootObject(null); + Assert.assertEquals(null, state.getRootContextObject().getValue()); state = new ExpressionState(new StandardEvaluationContext()); Assert.assertEquals(TypedValue.NULL_TYPED_VALUE,state.getRootContextObject()); @@ -259,4 +257,5 @@ public class ExpressionStateTests extends ExpressionTestCase { ExpressionState state = new ExpressionState(context); return state; } + } diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpelDocumentationTests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpelDocumentationTests.java index 93e0a4750b5..02709cad162 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpelDocumentationTests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpelDocumentationTests.java @@ -48,8 +48,6 @@ public class SpelDocumentationTests extends ExpressionTestCase { static Inventor tesla ; static Inventor pupin ; - - static { GregorianCalendar c = new GregorianCalendar(); @@ -115,7 +113,7 @@ public class SpelDocumentationTests extends ExpressionTestCase { ExpressionParser parser = new SpelExpressionParser(); Expression exp = parser.parseExpression("name"); - EvaluationContext context = new StandardEvaluationContext(); + StandardEvaluationContext context = new StandardEvaluationContext(); context.setRootObject(tesla); String name = (String) exp.getValue(context); @@ -124,10 +122,9 @@ public class SpelDocumentationTests extends ExpressionTestCase { @Test public void testEqualityCheck() throws Exception { - ExpressionParser parser = new SpelExpressionParser(); - EvaluationContext context = new StandardEvaluationContext(); + StandardEvaluationContext context = new StandardEvaluationContext(); context.setRootObject(tesla); Expression exp = parser.parseExpression("name == 'Nikola Tesla'");