diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/DefaultELContextFactory.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/DefaultELContextFactory.java new file mode 100644 index 00000000..5ea94e34 --- /dev/null +++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/DefaultELContextFactory.java @@ -0,0 +1,21 @@ +package org.springframework.binding.expression.support; + +import javax.el.ELContext; + +public class DefaultELContextFactory implements ELContextFactory { + + /** + * Configures and returns a {@link DelegatingELContext} to be used in evaluating EL expressions on the given base + * target object. + * + * @return DelegatingELContext The configured DelegatingELContext instance. + */ + public ELContext getELContext(Object target) { + DelegatingELContext context = new DelegatingELContext(); + DefaultELResolver baseResolver = new DefaultELResolver(); + baseResolver.setTarget(target); + context.setELResolver(baseResolver); + return context; + } + +} diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/DefaultELResolver.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/DefaultELResolver.java index 932ec12a..53e60091 100644 --- a/spring-binding/src/main/java/org/springframework/binding/expression/support/DefaultELResolver.java +++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/DefaultELResolver.java @@ -12,66 +12,65 @@ import org.springframework.binding.collection.MapAdaptable; import org.springframework.util.Assert; /** - * A generic ELResolver to be used as a default when no other ELResolvers have been - * configured by the client application. + * A generic ELResolver to be used as a default when no other ELResolvers have been configured by the client + * application. * - * This implementation will resolve the first part of the expression to - * the pre-configured base object, and will then delegate through the - * chain of standard resolvers for the rest of the expression. + * This implementation will resolve the first part of the expression to the pre-configured base object, and will then + * delegate through the chain of standard resolvers for the rest of the expression. * * Note - Requires Java 5 or higher due to the use of generics in the API's basic resolvers. - * + * * @author Jeremy Grelle - * + * */ public class DefaultELResolver extends CompositeELResolver { - private Object target; + private Object target; - public DefaultELResolver() { - configureResolvers(); - } - - public Class getType(ELContext context, Object base, Object property) { - return super.getType(context, adaptIfNecessary(base), property); - } + public DefaultELResolver() { + configureResolvers(); + } - public Object getValue(ELContext context, Object base, Object property) { - Assert.notNull(target,"The DefaultELResolver must have a target base property set."); - if (base == null) { - return super.getValue(context, target, property); - } - return super.getValue(context, adaptIfNecessary(base), property); - } + public Class getType(ELContext context, Object base, Object property) { + return super.getType(context, adaptIfNecessary(base), property); + } - public void setValue(ELContext context, Object base, Object property, Object val) { - Assert.notNull(target,"The DefaultELResolver must have a target base property set."); - if (base == null) - super.setValue(context, target, property, val); - else - super.setValue(context, adaptIfNecessary(base), property, val); + public Object getValue(ELContext context, Object base, Object property) { + Assert.notNull(target, "The DefaultELResolver must have a target base property set."); + if (base == null) { + return super.getValue(context, target, property); } + return super.getValue(context, adaptIfNecessary(base), property); + } - public Object getTarget() { - return target; - } + public void setValue(ELContext context, Object base, Object property, Object val) { + Assert.notNull(target, "The DefaultELResolver must have a target base property set."); + if (base == null) + super.setValue(context, target, property, val); + else + super.setValue(context, adaptIfNecessary(base), property, val); + } - public void setTarget(Object target) { - this.target = adaptIfNecessary(target); - } - - private Object adaptIfNecessary(Object base) { - if (base instanceof MapAdaptable) - return ((MapAdaptable)base).asMap(); - return base; - } - - private void configureResolvers() { - add(new ArrayELResolver()); - add(new ListELResolver()); - add(new MapELResolver()); - add(new ResourceBundleELResolver()); - add(new BeanELResolver()); - } + public Object getTarget() { + return target; + } + + public void setTarget(Object target) { + this.target = adaptIfNecessary(target); + } + + private Object adaptIfNecessary(Object base) { + if (base instanceof MapAdaptable) + return ((MapAdaptable) base).asMap(); + return base; + } + + private void configureResolvers() { + add(new ArrayELResolver()); + add(new ListELResolver()); + add(new MapELResolver()); + add(new ResourceBundleELResolver()); + add(new BeanELResolver()); + } } diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/DelegatingELContext.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/DelegatingELContext.java index ad98c45d..be5ad871 100644 --- a/spring-binding/src/main/java/org/springframework/binding/expression/support/DelegatingELContext.java +++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/DelegatingELContext.java @@ -11,122 +11,86 @@ import javax.el.FunctionMapper; import javax.el.VariableMapper; /** - * An {@link ELContext} implementation that is meant to aggregate the {@link ELResolver}s of - * pre-existing {@link ELContext}s. Can also be used standalone if no other {@link ELContext} - * exists in the current environment. + * An {@link ELContext} implementation that is meant to aggregate the {@link ELResolver}s of pre-existing + * {@link ELContext}s. Can also be used standalone if no other {@link ELContext} exists in the current environment. * * Note - Using this context standalone requires Java 5 or higher. * * @author Jeremy Grelle - * + * */ public class DelegatingELContext extends ELContext { - private ELResolver resolver; + private ELResolver resolver; - private FunctionMapper functionMapper; + private FunctionMapper functionMapper; - private VariableMapper variableMapper; - - private List delegates = new ArrayList(); + private VariableMapper variableMapper; - public ELResolver getELResolver() { - return resolver; + private List delegates = new ArrayList(); + + public ELResolver getELResolver() { + return resolver; + } + + public void setELResolver(ELResolver resolver) { + this.resolver = resolver; + } + + public FunctionMapper getFunctionMapper() { + return functionMapper; + } + + public void setFunctionMapper(FunctionMapper functionMapper) { + this.functionMapper = functionMapper; + } + + public VariableMapper getVariableMapper() { + return variableMapper; + } + + public void setVariableMapper(VariableMapper variableMapper) { + this.variableMapper = variableMapper; + } + + /** + * Add a delegate {@link ELContext}. + * + * If this context is currently configured with the {@link DefaultELResolver}, that resolver instance will be + * replaced with a new {@link CompositeELResolver}. + * + * The delegate's base {@link ELResolver} will be added to this context's base {@link CompositeELResolver}. + * + * @param context + * The {@link ELContext} whose base {@link ELResolver} needs to be included in this context's base + * {@link CompositeELResolver}. + */ + public void addDelegate(ELContext context) { + delegates.add(context); + if (getELResolver() == null || getELResolver() instanceof DefaultELResolver) { + CompositeELResolver composite = new CompositeELResolver(); + composite.add(context.getELResolver()); + setELResolver(composite); + } else if (getELResolver() instanceof CompositeELResolver) { + ((CompositeELResolver) getELResolver()).add(context.getELResolver()); + } + } + + public Object getContext(Class key) { + Object context = super.getContext(key); + if (context != null) { + return context; } - public void setELResolver(ELResolver resolver) { - this.resolver = resolver; + Iterator i = delegates.iterator(); + while (i.hasNext()) { + ELContext delegate = (ELContext) i.next(); + context = delegate.getContext(key); + if (context != null) { + return context; + } } + return null; + } - public FunctionMapper getFunctionMapper() { - return functionMapper; - } - - public void setFunctionMapper(FunctionMapper functionMapper) { - this.functionMapper = functionMapper; - } - - public VariableMapper getVariableMapper() { - return variableMapper; - } - - public void setVariableMapper(VariableMapper variableMapper) { - this.variableMapper = variableMapper; - } - - /** - * Add a delegate {@link ELContext}. - * - * If this context is currently configured with the {@link DefaultELResolver}, that resolver - * instance will be replaced with a new {@link CompositeELResolver}. - * - * The delegate's base {@link ELResolver} will be added to this context's base {@link CompositeELResolver}. - * - * @param context The {@link ELContext} whose base {@link ELResolver} needs to be included in this - * context's base {@link CompositeELResolver}. - */ - public void addDelegate(ELContext context) { - delegates.add(context); - if (getELResolver() == null || getELResolver() instanceof DefaultELResolver) { - CompositeELResolver composite = new CompositeELResolver(); - composite.add(context.getELResolver()); - setELResolver(composite); - } - else if (getELResolver() instanceof CompositeELResolver) { - ((CompositeELResolver) getELResolver()).add(context.getELResolver()); - } - } - - public Object getContext(Class key) { - Object context = super.getContext(key); - if (context != null) - return context; - - Iterator i = delegates.iterator(); - while(i.hasNext()) - { - ELContext delegate = (ELContext) i.next(); - context = delegate.getContext(key); - if (context != null) - return context; - } - return null; - } - - /** - * The ThreadLocal variable used to record the - * {@link ELContext} instance for each processing thread. - */ - private static ThreadLocal instance = new ThreadLocal() { - protected Object initialValue() { - return null; - } - }; - - /** - * Return the {@link ELContext} instance for the request that is - * being processed by the current thread, if any. - */ - public static DelegatingELContext getCurrentInstance() { - if (instance.get() == null) - setCurrentInstance(defaultInstance()); - return ((DelegatingELContext) instance.get()); - } - - /** - * Set the {@link ELContext} instance for the request that is - * being processed by the current thread. - * - * @param context The {@link ELContext} instance for the current - * thread, or null if this thread no longer has an - * ELContext instance. - * - */ - public static void setCurrentInstance(DelegatingELContext context) { - instance.set(context); - } - - private static DelegatingELContext defaultInstance() { - return new DelegatingELContext(); - } } diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/ELContextFactory.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/ELContextFactory.java new file mode 100644 index 00000000..c0fe5f0d --- /dev/null +++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/ELContextFactory.java @@ -0,0 +1,15 @@ +package org.springframework.binding.expression.support; + +import javax.el.ELContext; + +public interface ELContextFactory { + + /** + * Configures and returns a {@link DelegatingELContext} to be used in evaluating EL expressions on the given base + * target object. + * + * @return DelegatingELContext The configured DelegatingELContext instance. + */ + public ELContext getELContext(Object target); + +} \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/ELExpression.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/ELExpression.java index 18da0658..8c11df49 100644 --- a/spring-binding/src/main/java/org/springframework/binding/expression/support/ELExpression.java +++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/ELExpression.java @@ -16,73 +16,67 @@ import org.springframework.binding.expression.SettableExpression; */ public class ELExpression implements SettableExpression { - ValueExpression expression; + ELContextFactory factory; - public ELExpression(ValueExpression expression) { - this.expression = expression; - } + ValueExpression expression; - public void evaluateToSet(Object target, Object value, EvaluationContext context) throws EvaluationException { - ELContext ctx = getELContext(target); - try { - expression.setValue(ctx, value); - } - catch (ELException ex) { - throw new EvaluationException(new EvaluationAttempt(this, target, context), ex); - } - } + public ELExpression(ELContextFactory factory, ValueExpression expression) { + this.factory = factory; + this.expression = expression; + } - public Object evaluate(Object target, EvaluationContext context) throws EvaluationException { - ELContext ctx = getELContext(target); - try { - return expression.getValue(ctx); - } - catch (ELException ex) { - throw new EvaluationException(new EvaluationAttempt(this, target, context), ex); - } - } - - protected Class getType(Object target, EvaluationContext context) throws EvaluationException{ - ELContext ctx = getELContext(target); - try { - return expression.getType(ctx); - } - catch (ELException ex) { - throw new EvaluationException(new EvaluationAttempt(this, target, context), ex); - } - } - - /** - * Retrieves the thread-bound {@link ELContext} instance, configured with a DefaultELResolver if - * no other resolvers have been configured. - * - * @return {@link ELContext} The thread-bound {@link ELContext} instance. - */ - private ELContext getELContext(Object target) { - ELContext ctx = DelegatingELContext.getCurrentInstance(); - if (ctx.getELResolver() == null) - ((DelegatingELContext)ctx).setELResolver(new DefaultELResolver()); - if (ctx.getELResolver() instanceof DefaultELResolver) - ((DefaultELResolver)ctx.getELResolver()).setTarget(target); - return ctx; + public void evaluateToSet(Object target, Object value, EvaluationContext context) throws EvaluationException { + ELContext ctx = getELContext(target); + try { + expression.setValue(ctx, value); + } catch (ELException ex) { + throw new EvaluationException(new EvaluationAttempt(this, target, context), ex); } + } - public int hashCode() { - return expression.hashCode(); + public Object evaluate(Object target, EvaluationContext context) throws EvaluationException { + ELContext ctx = getELContext(target); + try { + return expression.getValue(ctx); + } catch (ELException ex) { + throw new EvaluationException(new EvaluationAttempt(this, target, context), ex); } + } - public boolean equals(Object o) { - if (!(o instanceof ELExpression)) { - return false; - } - ELExpression other = (ELExpression) o; - return expression.equals(other.expression); + protected Class getType(Object target, EvaluationContext context) throws EvaluationException { + ELContext ctx = getELContext(target); + try { + return expression.getType(ctx); + } catch (ELException ex) { + throw new EvaluationException(new EvaluationAttempt(this, target, context), ex); } - - public String toString() - { - return expression.getExpressionString(); + } + + /** + * Retrieves an {@link ELContext} instance, configured with a DefaultELResolver if no other resolvers have been + * configured. + * + * @return {@link ELContext} The thread-bound {@link ELContext} instance. + */ + protected ELContext getELContext(Object target) { + ELContext ctx = factory.getELContext(target); + return ctx; + } + + public int hashCode() { + return expression.hashCode(); + } + + public boolean equals(Object o) { + if (!(o instanceof ELExpression)) { + return false; } - + ELExpression other = (ELExpression) o; + return expression.equals(other.expression); + } + + public String toString() { + return expression.getExpressionString(); + } } diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/ELExpressionParser.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/ELExpressionParser.java index e9d374f9..a5ed15e0 100644 --- a/spring-binding/src/main/java/org/springframework/binding/expression/support/ELExpressionParser.java +++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/ELExpressionParser.java @@ -11,109 +11,119 @@ import org.springframework.binding.expression.ParserException; import org.springframework.binding.expression.SettableExpression; /** - * An expression parser that parses EL expressions. Beyond standard EL expression parsing, it - * makes use of the ability of the JBoss-EL implementation to parse dynamic method invocations - * such as foo.bar() (the EL spec currently only provides out-of-the-box support for functions). + * An expression parser that parses EL expressions. Beyond standard EL expression parsing, it makes use of the ability + * of the JBoss-EL implementation to parse dynamic method invocations such as foo.bar() (the EL spec currently only + * provides out-of-the-box support for functions). * * @author Jeremy Grelle */ public class ELExpressionParser implements ExpressionParser { - /** - * The expression prefix for deferred EL expressions. - */ - private static final String DEFERRED_EL_EXPRESSION_PREFIX = "#{"; + /** + * The expression prefix for deferred EL expressions. + */ + private static final String DEFERRED_EL_EXPRESSION_PREFIX = "#{"; - /** - * The expression suffix for deferred EL expressions. - */ - private static final String DEFERRED_EL_EXPRESSION_SUFFIX = "}"; - - /** - * The marked expression delimiter prefix. - */ - private String expressionPrefix = DEFERRED_EL_EXPRESSION_PREFIX; + /** + * The expression suffix for deferred EL expressions. + */ + private static final String DEFERRED_EL_EXPRESSION_SUFFIX = "}"; - /** - * The marked expression delimiter suffix. - */ - private String expressionSuffix = DEFERRED_EL_EXPRESSION_SUFFIX; + /** + * The marked expression delimiter prefix. + */ + private String expressionPrefix = DEFERRED_EL_EXPRESSION_PREFIX; - /** - * The ExpressionFactory for constructing EL expressions - */ - private ExpressionFactory factory = new ExpressionFactoryImpl(); + /** + * The marked expression delimiter suffix. + */ + private String expressionSuffix = DEFERRED_EL_EXPRESSION_SUFFIX; - public String getExpressionPrefix() { - return expressionPrefix; + /** + * The {@link ELContextFactory} for retrieving a configured ELContext. + */ + private ELContextFactory contextFactory = new DefaultELContextFactory(); + + /** + * The ExpressionFactory for constructing EL expressions + */ + private ExpressionFactory factory = new ExpressionFactoryImpl(); + + public String getExpressionPrefix() { + return expressionPrefix; + } + + public String getExpressionSuffix() { + return expressionSuffix; + } + + /** + * Check whether or not given criteria are expressed as an expression. + */ + public boolean isDelimitedExpression(String expressionString) { + int prefixIndex = expressionString.indexOf(getExpressionPrefix()); + if (prefixIndex == -1) { + return false; } + int suffixIndex = expressionString.indexOf(getExpressionSuffix(), prefixIndex); + if (suffixIndex == -1) { + return false; + } else { + if (suffixIndex == prefixIndex + getExpressionPrefix().length()) { + return false; + } else { + return true; + } + } + } - public String getExpressionSuffix() { - return expressionSuffix; + public Expression parseExpression(String expressionString) throws ParserException { + if (!isDelimitedExpression(expressionString)) { + expressionString = getExpressionPrefix() + expressionString + getExpressionSuffix(); } + return doParseExpression(expressionString); + } - /** - * Check whether or not given criteria are expressed as an expression. - */ - public boolean isDelimitedExpression(String expressionString) { - int prefixIndex = expressionString.indexOf(getExpressionPrefix()); - if (prefixIndex == -1) { - return false; - } - int suffixIndex = expressionString.indexOf(getExpressionSuffix(), prefixIndex); - if (suffixIndex == -1) { - return false; - } - else { - if (suffixIndex == prefixIndex + getExpressionPrefix().length()) { - return false; - } - else { - return true; - } - } + public SettableExpression parseSettableExpression(String expressionString) throws ParserException, + UnsupportedOperationException { + if (!isDelimitedExpression(expressionString)) { + expressionString = getExpressionPrefix() + expressionString + getExpressionSuffix(); } + return doParseSettableExpression(expressionString); + } - public Expression parseExpression(String expressionString) throws ParserException { - if (!isDelimitedExpression(expressionString)) { - expressionString = getExpressionPrefix() + expressionString + getExpressionSuffix(); - } - return doParseExpression(expressionString); - } + /** + * Parses the expression string into an EL value expression. + * + * @param expressionString + * @throws ParserException + */ + protected Expression doParseExpression(String expressionString) throws ParserException { + return doParseSettableExpression(expressionString); + } - public SettableExpression parseSettableExpression(String expressionString) throws ParserException, - UnsupportedOperationException { - if (!isDelimitedExpression(expressionString)) { - expressionString = getExpressionPrefix() + expressionString + getExpressionSuffix(); - } - return doParseSettableExpression(expressionString); + /** + * Parses the expression string into an EL value expression. + * + * @param expressionString + * @throws ParserException + */ + protected SettableExpression doParseSettableExpression(String expressionString) throws ParserException { + ELContext ctx = getELContextFactory().getELContext(null); + try { + return new ELExpression(getELContextFactory(), factory.createValueExpression(ctx, expressionString, + Object.class)); + } catch (ELException ex) { + throw new ParserException(expressionString, ex); } + } - /** - * Parses the expression string into an EL value expression. - * @param expressionString - * @throws ParserException - */ - protected Expression doParseExpression(String expressionString) throws ParserException { - return doParseSettableExpression(expressionString); - } - - /** - * Parses the expression string into an EL value expression. - * @param expressionString - * @throws ParserException - */ - protected SettableExpression doParseSettableExpression(String expressionString) throws ParserException { - ELContext ctx = getELContext(); - try { - return new ELExpression(factory.createValueExpression(ctx, expressionString, Object.class)); - } - catch (ELException ex) { - throw new ParserException(expressionString, ex); - } - } - - private ELContext getELContext() { - return DelegatingELContext.getCurrentInstance(); - } + /** + * Returns the proper {@link ELContextFactory} for the current environment. + * + * @return ELContextFactory The ELContextFactory for the current environment. + */ + protected ELContextFactory getELContextFactory() { + return contextFactory; + } } diff --git a/spring-binding/src/test/java/org/springframework/binding/expression/support/ELContextDelegationTests.java b/spring-binding/src/test/java/org/springframework/binding/expression/support/ELContextDelegationTests.java index 1a7310da..e535d3d5 100644 --- a/spring-binding/src/test/java/org/springframework/binding/expression/support/ELContextDelegationTests.java +++ b/spring-binding/src/test/java/org/springframework/binding/expression/support/ELContextDelegationTests.java @@ -20,87 +20,92 @@ import org.springframework.binding.expression.ExpressionParser; */ public class ELContextDelegationTests extends TestCase { - private ELContext context = new MockELContext(); - private ExpressionParser expressionParser = new ELExpressionParser(); - private TestBean bean; - - protected void setUp() throws Exception { - bean = new TestBean(); - bean.setFlag(true); + private ELContext mockContext = new MockELContext(); + private ExpressionParser expressionParser = new DelegatingELExpressionParser(); + private TestBean bean; + + protected void setUp() throws Exception { + bean = new TestBean(); + bean.setFlag(true); + } + + public final void testGetValueByContextDelegation() { + assertEquals(Boolean.TRUE, expressionParser.parseExpression("#{bean.flag}").evaluate(bean, null)); + assertEquals(Boolean.TRUE, expressionParser.parseExpression("#{bean.flag}").evaluate(null, null)); + } + + private class DelegatingELExpressionParser extends ELExpressionParser { + + protected ELContextFactory getELContextFactory() { + ELContextFactory stubFactory = new ELContextFactory() { + + public ELContext getELContext(Object target) { + DelegatingELContext ctx = new DelegatingELContext(); + ctx.addDelegate(mockContext); + return ctx; + } + + }; + return stubFactory; } - - public final void testGetValueByContextDelegation() - { - DelegatingELContext internalContext = DelegatingELContext.getCurrentInstance(); - internalContext.addDelegate(context); - assertEquals(Boolean.TRUE, expressionParser.parseExpression("#{bean.flag}").evaluate(bean, null)); - assertEquals(Boolean.TRUE, expressionParser.parseExpression("#{bean.flag}").evaluate(null, null)); - assertFalse(internalContext.getELResolver() instanceof DefaultELResolver); + } + + private class MockELContext extends ELContext { + + ELResolver resolver = new MockELResolver(); + + public ELResolver getELResolver() { + return resolver; } - private class MockELContext extends ELContext - { - - ELResolver resolver = new MockELResolver(); - - public ELResolver getELResolver() { - return resolver; - } - - public FunctionMapper getFunctionMapper() { - return null; - } - - public VariableMapper getVariableMapper() { - return null; - } - + public FunctionMapper getFunctionMapper() { + return null; } - - private class MockELResolver extends ELResolver - { - - public Class getCommonPropertyType(ELContext context, Object base) { - return null; - } - public Iterator getFeatureDescriptors(ELContext context, Object base) { - return null; - } - - public Class getType(ELContext context, Object base, Object property) { - if (base != null) - return base.getClass(); - return null; - } - - public Object getValue(ELContext context, Object base, Object property) { - if (base == null && "bean".equals(property)) - { - context.setPropertyResolved(true); - return bean; - } - if (base == bean) - { - return new BeanELResolver().getValue(context, base, property); - } - return null; - } - - public boolean isReadOnly(ELContext context, Object base, Object property) { - return false; - } - - public void setValue(ELContext context, Object base, Object property, Object value) { - if (base == null && "bean".equals(property)) - { - context.setPropertyResolved(true); - } - else if (base == bean) - { - new BeanELResolver().setValue(context, base, property, value); - } - } - + public VariableMapper getVariableMapper() { + return null; } + + } + + private class MockELResolver extends ELResolver { + + public Class getCommonPropertyType(ELContext context, Object base) { + return null; + } + + public Iterator getFeatureDescriptors(ELContext context, Object base) { + return null; + } + + public Class getType(ELContext context, Object base, Object property) { + if (base != null) + return base.getClass(); + return null; + } + + public Object getValue(ELContext context, Object base, Object property) { + if (base == null && "bean".equals(property)) { + context.setPropertyResolved(true); + return bean; + } + if (base == bean) { + return new BeanELResolver().getValue(context, base, property); + } + return null; + } + + public boolean isReadOnly(ELContext context, Object base, Object property) { + return false; + } + + public void setValue(ELContext context, Object base, Object property, Object value) { + if (base == null && "bean".equals(property)) { + context.setPropertyResolved(true); + } else if (base == bean) { + new BeanELResolver().setValue(context, base, property, value); + } + } + + } } diff --git a/spring-binding/src/test/java/org/springframework/binding/expression/support/SimpleExpressionTests.java b/spring-binding/src/test/java/org/springframework/binding/expression/support/SimpleExpressionTests.java index a274e57d..7a22ac23 100644 --- a/spring-binding/src/test/java/org/springframework/binding/expression/support/SimpleExpressionTests.java +++ b/spring-binding/src/test/java/org/springframework/binding/expression/support/SimpleExpressionTests.java @@ -26,75 +26,73 @@ import junit.framework.TestCase; import junit.framework.TestSuite; /** - * Tests simple expressions. Any expression language capable enough for - * real life usage should be able to pass these tests. - * + * Tests simple expressions. Any expression language capable enough for real life usage should be able to pass these + * tests. + * * @author Erwin Vervaet * @author Jeremy Grelle */ public class SimpleExpressionTests extends TestCase { - - private ExpressionParser expressionParser; - private String expressionPrefix; - private TestBean bean; - - public static TestSuite suite() { - TestSuite suite = new TestSuite(); - suite.addTest(new SimpleExpressionTests("testGetValue", new OgnlExpressionParser(), "$")); - suite.addTest(new SimpleExpressionTests("testSetValue", new OgnlExpressionParser(), "$")); - suite.addTest(new SimpleExpressionTests("testSyntaxError", new OgnlExpressionParser(), "$")); - suite.addTest(new SimpleExpressionTests("testGetValue", new BeanWrapperExpressionParser(), "$")); - suite.addTest(new SimpleExpressionTests("testSetValue", new BeanWrapperExpressionParser(), "$")); - suite.addTest(new SimpleExpressionTests("testSyntaxError", new BeanWrapperExpressionParser(), "$")); - suite.addTest(new SimpleExpressionTests("testGetValue", new ELExpressionParser(), "#")); - suite.addTest(new SimpleExpressionTests("testSetValue", new ELExpressionParser(), "#")); - suite.addTest(new SimpleExpressionTests("testSyntaxError", new ELExpressionParser(), "#")); - return suite; - } - - public SimpleExpressionTests(String name, ExpressionParser expressionParser, String expressionPrefix) { - super(name); - this.expressionParser = expressionParser; - this.expressionPrefix = expressionPrefix; - } - - protected void setUp() throws Exception { - bean = new TestBean(); - bean.setFlag(true); - List list = new ArrayList(); - list.add("foo"); - list.add("bar"); - bean.setList(list); - } - - public void testGetValue() { - assertEquals(Boolean.TRUE, expressionParser.parseExpression(expressionPrefix+"{flag}").evaluate(bean, null)); - assertEquals(Boolean.TRUE, expressionParser.parseExpression("flag").evaluate(bean, null)); - assertSame(bean.getList(), expressionParser.parseExpression(expressionPrefix+"{list}").evaluate(bean, null)); - assertEquals("foo", expressionParser.parseExpression(expressionPrefix+"{list[0]}").evaluate(bean, null)); - } - public void testSetValue() { - expressionParser.parseSettableExpression(expressionPrefix+"{flag}").evaluateToSet(bean, Boolean.FALSE, null); - assertFalse(bean.isFlag()); - expressionParser.parseSettableExpression("flag").evaluateToSet(bean, Boolean.TRUE, null); - assertTrue(bean.isFlag()); - List newList = new ArrayList(); - newList.add("boo"); - expressionParser.parseSettableExpression(expressionPrefix+"{list}").evaluateToSet(bean, newList, null); - assertSame(newList, bean.getList()); - expressionParser.parseSettableExpression(expressionPrefix+"{list[0]}").evaluateToSet(bean, "baa", null); - assertEquals("baa", bean.getList().get(0)); - } - - public void testSyntaxError() { - try { - expressionParser.parseExpression("foo(").evaluate(bean, null); - fail("should have failed"); - } - catch (ParserException e) { - } - catch (EvaluationException e) { - } + private ExpressionParser expressionParser; + private String expressionPrefix; + private TestBean bean; + + public static TestSuite suite() { + TestSuite suite = new TestSuite(); + suite.addTest(new SimpleExpressionTests("testGetValue", new OgnlExpressionParser(), "$")); + suite.addTest(new SimpleExpressionTests("testSetValue", new OgnlExpressionParser(), "$")); + suite.addTest(new SimpleExpressionTests("testSyntaxError", new OgnlExpressionParser(), "$")); + suite.addTest(new SimpleExpressionTests("testGetValue", new BeanWrapperExpressionParser(), "$")); + suite.addTest(new SimpleExpressionTests("testSetValue", new BeanWrapperExpressionParser(), "$")); + suite.addTest(new SimpleExpressionTests("testSyntaxError", new BeanWrapperExpressionParser(), "$")); + suite.addTest(new SimpleExpressionTests("testGetValue", new ELExpressionParser(), "#")); + suite.addTest(new SimpleExpressionTests("testSetValue", new ELExpressionParser(), "#")); + suite.addTest(new SimpleExpressionTests("testSyntaxError", new ELExpressionParser(), "#")); + return suite; + } + + public SimpleExpressionTests(String name, ExpressionParser expressionParser, String expressionPrefix) { + super(name); + this.expressionParser = expressionParser; + this.expressionPrefix = expressionPrefix; + } + + protected void setUp() throws Exception { + bean = new TestBean(); + bean.setFlag(true); + List list = new ArrayList(); + list.add("foo"); + list.add("bar"); + bean.setList(list); + } + + public void testGetValue() { + assertEquals(Boolean.TRUE, expressionParser.parseExpression(expressionPrefix + "{flag}").evaluate(bean, null)); + assertEquals(Boolean.TRUE, expressionParser.parseExpression("flag").evaluate(bean, null)); + assertSame(bean.getList(), expressionParser.parseExpression(expressionPrefix + "{list}").evaluate(bean, null)); + assertEquals("foo", expressionParser.parseExpression(expressionPrefix + "{list[0]}").evaluate(bean, null)); + } + + public void testSetValue() { + expressionParser.parseSettableExpression(expressionPrefix + "{flag}").evaluateToSet(bean, Boolean.FALSE, null); + assertFalse(bean.isFlag()); + expressionParser.parseSettableExpression("flag").evaluateToSet(bean, Boolean.TRUE, null); + assertTrue(bean.isFlag()); + List newList = new ArrayList(); + newList.add("boo"); + expressionParser.parseSettableExpression(expressionPrefix + "{list}").evaluateToSet(bean, newList, null); + assertSame(newList, bean.getList()); + expressionParser.parseSettableExpression(expressionPrefix + "{list[0]}").evaluateToSet(bean, "baa", null); + assertEquals("baa", bean.getList().get(0)); + } + + public void testSyntaxError() { + try { + expressionParser.parseExpression("foo(").evaluate(bean, null); + fail("should have failed"); + } catch (ParserException e) { + } catch (EvaluationException e) { } + } }