diff --git a/build.gradle b/build.gradle index d6174fab..8f2ce8bd 100644 --- a/build.gradle +++ b/build.gradle @@ -121,9 +121,6 @@ subprojects { subproject -> project("spring-binding") { description = "Spring Binding" - dependencies { - compile("opensymphony:ognl:2.6.11") - } } project("spring-webflow") { @@ -131,7 +128,6 @@ project("spring-webflow") { dependencies { compile(project(":spring-binding")) - compile("opensymphony:ognl:2.6.11") compile("org.springframework:spring-web:$springVersion") compile("org.springframework:spring-webmvc:$springVersion") provided("javax.servlet:javax.servlet-api:$servletVersion") @@ -155,7 +151,6 @@ project("spring-webflow") { optional("org.apache.tiles:tiles-extras:$tiles3Version") { exclude group: "org.slf4j", module: "jcl-over-slf4j" exclude group: "org.springframework", module: "spring-web" - exclude group: "ognl", module: "ognl" } provided("junit:junit:3.8.2") testCompile("org.springframework:spring-aop:$springVersion") diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/Expression.java b/spring-binding/src/main/java/org/springframework/binding/expression/Expression.java index f4c586dd..89065c59 100644 --- a/spring-binding/src/main/java/org/springframework/binding/expression/Expression.java +++ b/spring-binding/src/main/java/org/springframework/binding/expression/Expression.java @@ -17,8 +17,8 @@ package org.springframework.binding.expression; /** * An expression capable of evaluating itself against context objects. Encapsulates the details of a previously parsed - * expression string. Provides a common abstraction for expression evaluation independent of any language like OGNL or - * the Unified EL. + * expression string. Provides a common abstraction for expression evaluation independent of any language like + * Spring EL or the Unified EL. * * @author Keith Donald */ diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpression.java b/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpression.java deleted file mode 100644 index adeffc12..00000000 --- a/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpression.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2004-2012 the original author or authors. - * - * Licensed 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.springframework.binding.expression.ognl; - -import java.lang.reflect.Member; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import ognl.NoSuchPropertyException; -import ognl.Ognl; -import ognl.OgnlException; -import ognl.TypeConverter; - -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.beans.BeansException; -import org.springframework.beans.InvalidPropertyException; -import org.springframework.binding.convert.ConversionException; -import org.springframework.binding.convert.ConversionService; -import org.springframework.binding.expression.EvaluationException; -import org.springframework.binding.expression.Expression; -import org.springframework.binding.expression.PropertyNotFoundException; -import org.springframework.binding.expression.ValueCoercionException; -import org.springframework.binding.expression.spel.SpringELExpression; - -/** - * Evaluates a parsed Ognl expression. - * - * @author Keith Donald - * @author Scott Andrews - * - * @deprecated in favor of Spring EL, see {@link SpringELExpression}. - */ -class OgnlExpression implements Expression { - - private Object expression; - - private Map variableExpressions; - - private Class expectedResultType; - - private String expressionString; - - private ConversionService conversionService; - - /** - * Creates a new OGNL expression. - */ - public OgnlExpression(Object expression, Map variableExpressions, Class expectedResultType, - String expressionString, ConversionService conversionService) { - this.expression = expression; - this.variableExpressions = variableExpressions; - this.expectedResultType = expectedResultType; - this.expressionString = expressionString; - this.conversionService = conversionService; - } - - public boolean equals(Object o) { - if (!(o instanceof OgnlExpression)) { - return false; - } - OgnlExpression other = (OgnlExpression) o; - return expressionString.equals(other.expressionString); - } - - public int hashCode() { - return expressionString.hashCode(); - } - - @SuppressWarnings("rawtypes") - public Object getValue(Object context) throws EvaluationException { - try { - Map evaluationContext = Ognl.addDefaultContext(context, getVariables(context)); - Ognl.setTypeConverter(evaluationContext, createTypeConverter()); - return Ognl.getValue(expression, evaluationContext, context, expectedResultType); - } catch (NoSuchPropertyException e) { - throw new PropertyNotFoundException(context.getClass(), getExpressionString(), e); - } catch (OgnlException e) { - if (e.getReason() instanceof ValueCoercionException) { - throw (ValueCoercionException) e.getReason(); - } else { - throw new EvaluationException(context.getClass(), getExpressionString(), - "An OgnlException occurred getting the value for expression '" + getExpressionString() - + "' on context [" + context.getClass() + "]", causeFor(e)); - } - } - } - - @SuppressWarnings("rawtypes") - public void setValue(Object context, Object value) { - try { - Map evaluationContext = Ognl.addDefaultContext(context, getVariables(context)); - Ognl.setTypeConverter(evaluationContext, createTypeConverter()); - Ognl.setValue(expression, evaluationContext, context, value); - } catch (NoSuchPropertyException e) { - throw new PropertyNotFoundException(context.getClass(), getExpressionString(), e); - } catch (OgnlException e) { - if (e.getReason() instanceof ValueCoercionException) { - throw (ValueCoercionException) e.getReason(); - } else { - throw new EvaluationException(context.getClass(), getExpressionString(), - "An OgnlException occurred setting the value of expression '" + getExpressionString() - + "' on context [" + context.getClass() + "] to [" + value + "]", causeFor(e)); - } - } - } - - public Class getValueType(Object context) { - try { - // OGNL has no native way to get this information - return new BeanWrapperImpl(context).getPropertyType(expressionString); - } catch (InvalidPropertyException e) { - throw new PropertyNotFoundException(context.getClass(), getExpressionString(), e); - } catch (BeansException e) { - throw new EvaluationException(context.getClass(), getExpressionString(), - "An BeansException occurred getting the value type for expression '" + getExpressionString() - + "' on context [" + context.getClass() + "]", e); - } - } - - public String getExpressionString() { - return expressionString; - } - - // internal helpers - - private Throwable causeFor(OgnlException e) { - if (e.getReason() != null) { - if (e.getCause() == null) { - try { - e.initCause(e.getReason()); - } catch (IllegalStateException ex) { - // we tried - } - } - return e; - } else { - return e; - } - } - - @SuppressWarnings("rawtypes") - private TypeConverter createTypeConverter() { - return new TypeConverter() { - public Object convertValue(Map context, Object target, Member member, String propertyName, Object value, - Class toType) throws ValueCoercionException { - try { - return conversionService.executeConversion(value, toType); - } catch (ConversionException e) { - throw new ValueCoercionException(context.getClass(), expressionString, value, toType, e); - } - } - }; - } - - private Map getVariables(Object context) { - if (variableExpressions == null) { - return Collections.emptyMap(); - } - Map variables = new HashMap(variableExpressions.size(), 1); - for (Map.Entry var : variableExpressions.entrySet()) { - Expression valueExpression = var.getValue(); - variables.put(var.getKey(), valueExpression.getValue(context)); - } - return variables; - } - - public String toString() { - return expressionString; - } -} diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpressionParser.java b/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpressionParser.java deleted file mode 100644 index 8f797542..00000000 --- a/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpressionParser.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2004-2012 the original author or authors. - * - * Licensed 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.springframework.binding.expression.ognl; - -import ognl.Ognl; -import ognl.OgnlException; -import ognl.OgnlRuntime; -import ognl.PropertyAccessor; - -import org.springframework.binding.convert.ConversionService; -import org.springframework.binding.convert.service.DefaultConversionService; -import org.springframework.binding.expression.Expression; -import org.springframework.binding.expression.ParserContext; -import org.springframework.binding.expression.ParserException; -import org.springframework.binding.expression.spel.SpringELExpressionParser; -import org.springframework.binding.expression.support.AbstractExpressionParser; - -/** - * An expression parser that parses Ognl expressions. - * - * @author Keith Donald - * - * @deprecated in favor of Spring EL, see {@link SpringELExpressionParser} - */ -public class OgnlExpressionParser extends AbstractExpressionParser { - - private ConversionService conversionService = new DefaultConversionService(); - - /** - * The conversion service to use to perform type conversions as needed by the OGNL system. If not specified, the - * default is an instance of {@link DefaultConversionService}. - */ - public ConversionService getConversionService() { - return conversionService; - } - - /** - * Sets the conversion service to use to perform type conversions as needed by the OGNL system. - * @param conversionService the conversion service to use - */ - public void setConversionService(ConversionService conversionService) { - this.conversionService = conversionService; - } - - /** - * Add a property access strategy for the given class. - * @param clazz the class that contains properties needing access - * @param propertyAccessor the property access strategy - */ - public void addPropertyAccessor(Class clazz, PropertyAccessor propertyAccessor) { - OgnlRuntime.setPropertyAccessor(clazz, propertyAccessor); - } - - protected Expression doParseExpression(String expressionString, ParserContext context) throws ParserException { - try { - return new OgnlExpression(Ognl.parseExpression(expressionString), - parseVariableExpressions(context.getExpressionVariables()), - context.getExpectedEvaluationResultType(), expressionString, conversionService); - } catch (OgnlException e) { - throw new ParserException(expressionString, e); - } - } -} diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/ognl/package-info.java b/spring-binding/src/main/java/org/springframework/binding/expression/ognl/package-info.java deleted file mode 100644 index 4a7d0bbb..00000000 --- a/spring-binding/src/main/java/org/springframework/binding/expression/ognl/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2004-2012 the original author or authors. - * - * Licensed 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. - */ - -/** - * Support for the OGNL Expression Language implemented by the OgnlExpressionParser. - */ -package org.springframework.binding.expression.ognl; - diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/AbstractExpressionParser.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/AbstractExpressionParser.java index 44eeabca..3c06e6bb 100644 --- a/spring-binding/src/main/java/org/springframework/binding/expression/support/AbstractExpressionParser.java +++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/AbstractExpressionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2004-2012 the original author or authors. + * Copyright 2004-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,9 +28,10 @@ import org.springframework.binding.expression.ParserException; import org.springframework.util.Assert; /** - * An expression parser that parses Ognl expressions. + * Abstract base class for parsing ${...} style expressions. * * @author Keith Donald + * @see org.springframework.binding.expression.beanwrapper.BeanWrapperExpressionParser */ public abstract class AbstractExpressionParser implements ExpressionParser { @@ -117,14 +118,15 @@ public abstract class AbstractExpressionParser implements ExpressionParser { if (!allowDelimitedEvalExpressions) { throw new ParserException( expressionString, - "The expression '" - + expressionString - + "' being parsed is expected be a standard OGNL expression. Do not attempt to enclose such expression strings in ${} delimiters--this is redundant. If you need to parse a template that mixes literal text with evaluatable blocks, set the 'template' parser context attribute to true.", + "The expression '" + expressionString + "' being parsed is expected be an expression. " + + "Do not enclose such expression strings in ${} delimiters as it's redundant. " + + "If you need to parse a template that mixes literal text with evaluatable blocks, " + + "set the 'template' parser context attribute to true.", null); } else { int lastIndex = expressionString.length() - getExpressionSuffix().length(); - String ognlExpression = expressionString.substring(getExpressionPrefix().length(), lastIndex); - return doParseExpression(ognlExpression, context); + String expression = expressionString.substring(getExpressionPrefix().length(), lastIndex); + return doParseExpression(expression, context); } } else { return doParseExpression(expressionString, context); diff --git a/spring-binding/src/test/java/org/springframework/binding/expression/beanwrapper/BeanWrapperExpressionParserTests.java b/spring-binding/src/test/java/org/springframework/binding/expression/beanwrapper/BeanWrapperExpressionParserTests.java index 6c289db3..0f764347 100644 --- a/spring-binding/src/test/java/org/springframework/binding/expression/beanwrapper/BeanWrapperExpressionParserTests.java +++ b/spring-binding/src/test/java/org/springframework/binding/expression/beanwrapper/BeanWrapperExpressionParserTests.java @@ -23,7 +23,6 @@ import org.springframework.binding.convert.service.GenericConversionService; import org.springframework.binding.expression.Expression; import org.springframework.binding.expression.ParserException; import org.springframework.binding.expression.ValueCoercionException; -import org.springframework.binding.expression.ognl.TestBean; import org.springframework.binding.expression.support.FluentParserContext; public class BeanWrapperExpressionParserTests extends TestCase { diff --git a/spring-binding/src/test/java/org/springframework/binding/expression/ognl/TestBean.java b/spring-binding/src/test/java/org/springframework/binding/expression/beanwrapper/TestBean.java similarity index 96% rename from spring-binding/src/test/java/org/springframework/binding/expression/ognl/TestBean.java rename to spring-binding/src/test/java/org/springframework/binding/expression/beanwrapper/TestBean.java index 9b040758..7fde4ef7 100644 --- a/spring-binding/src/test/java/org/springframework/binding/expression/ognl/TestBean.java +++ b/spring-binding/src/test/java/org/springframework/binding/expression/beanwrapper/TestBean.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.binding.expression.ognl; +package org.springframework.binding.expression.beanwrapper; import java.util.ArrayList; import java.util.Date; diff --git a/spring-binding/src/test/java/org/springframework/binding/expression/ognl/OgnlExpressionParserTests.java b/spring-binding/src/test/java/org/springframework/binding/expression/ognl/OgnlExpressionParserTests.java deleted file mode 100644 index 845a70ee..00000000 --- a/spring-binding/src/test/java/org/springframework/binding/expression/ognl/OgnlExpressionParserTests.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2004-2012 the original author or authors. - * - * Licensed 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.springframework.binding.expression.ognl; - -import junit.framework.TestCase; - -import org.springframework.binding.convert.converters.StringToDate; -import org.springframework.binding.convert.service.GenericConversionService; -import org.springframework.binding.expression.EvaluationException; -import org.springframework.binding.expression.Expression; -import org.springframework.binding.expression.ExpressionVariable; -import org.springframework.binding.expression.ParserException; -import org.springframework.binding.expression.ValueCoercionException; -import org.springframework.binding.expression.support.FluentParserContext; - -public class OgnlExpressionParserTests extends TestCase { - - private OgnlExpressionParser parser = new OgnlExpressionParser(); - - private TestBean bean = new TestBean(); - - public void testParseSimple() { - String exp = "flag"; - Expression e = parser.parseExpression(exp, null); - assertNotNull(e); - Boolean b = (Boolean) e.getValue(bean); - assertFalse(b); - } - - public void testParseSimpleAllowDelimited() { - parser.setAllowDelimitedEvalExpressions(true); - String exp = "${flag}"; - Expression e = parser.parseExpression(exp, null); - assertNotNull(e); - Boolean b = (Boolean) e.getValue(bean); - assertFalse(b); - } - - public void testParseSimpleDelimitedNotAllowed() { - String exp = "${flag}"; - try { - parser.parseExpression(exp, null); - fail("should have failed"); - } catch (ParserException e) { - } - } - - public void testParseTemplateSimpleLiteral() { - String exp = "flag"; - Expression e = parser.parseExpression(exp, new FluentParserContext().template()); - assertNotNull(e); - assertEquals("flag", e.getValue(bean)); - } - - public void testParseTemplateEmpty() { - Expression e = parser.parseExpression("", new FluentParserContext().template()); - assertNotNull(e); - assertEquals("", e.getValue(bean)); - } - - public void testParseTemplateComposite() { - String exp = "hello ${flag} ${flag} ${flag}"; - Expression e = parser.parseExpression(exp, new FluentParserContext().template()); - assertNotNull(e); - String str = (String) e.getValue(bean); - assertEquals("hello false false false", str); - } - - public void testTemplateEnclosedCompositeNotSupported() { - String exp = "${hello ${flag} ${flag} ${flag}}"; - try { - parser.parseExpression(exp, new FluentParserContext().template()); - fail("Should've failed - not intended use"); - } catch (ParserException e) { - } - } - - public void testSyntaxError1() { - try { - parser.parseExpression("${", new FluentParserContext().template()); - fail(); - } catch (ParserException e) { - } - try { - String exp = "hello ${flag} ${abcd defg"; - parser.parseExpression(exp, null); - fail("Should've failed - not intended use"); - } catch (ParserException e) { - } - } - - public void testSyntaxError2() { - try { - parser.parseExpression("${}", new FluentParserContext().template()); - fail("Should've failed - not intended use"); - } catch (ParserException e) { - } - try { - String exp = "hello ${flag} ${}"; - parser.parseExpression(exp, null); - fail("Should've failed - not intended use"); - } catch (ParserException e) { - } - } - - public void testCollectionConstructionSyntax() { - // lists - parser.parseExpression("name in {null, \"Untitled\"}", null); - parser.parseExpression("${name in {null, \"Untitled\"}}", new FluentParserContext().template()); - - // native arrays - parser.parseExpression("new int[] {1, 2, 3}", null); - parser.parseExpression("${new int[] {1, 2, 3}}", new FluentParserContext().template()); - - // maps - parser.parseExpression("#{ 'foo' : 'foo value', 'bar' : 'bar value' }", null); - parser.parseExpression("${#{ 'foo' : 'foo value', 'bar' : 'bar value' }}", new FluentParserContext().template()); - parser.parseExpression("#@java.util.LinkedHashMap@{ 'foo' : 'foo value', 'bar' : 'bar value' }", null); - parser.parseExpression("${#@java.util.LinkedHashMap@{ 'foo' : 'foo value', 'bar' : 'bar value' }}", - new FluentParserContext().template()); - - // complex examples - parser.parseExpression("b,#{1:2}", null); - parser.parseExpression("${b,#{1:2}}", new FluentParserContext().template()); - parser.parseExpression("a${b,#{1:2},e}f${g,#{3:4},j}k", new FluentParserContext().template()); - } - - public void testVariables() { - Expression exp = parser.parseExpression("#var", - new FluentParserContext().variable(new ExpressionVariable("var", "flag"))); - assertFalse((Boolean) exp.getValue(bean)); - } - - public void testVariablesWithCoersion() { - Expression exp = parser.parseExpression("#var", new FluentParserContext().variable(new ExpressionVariable( - "var", "number", new FluentParserContext().expectResult(Long.class)))); - assertEquals(new Long(0), exp.getValue(bean)); - } - - public void testNestedVariablesWithTemplates() { - Expression exp = parser.parseExpression("#var", new FluentParserContext().variable(new ExpressionVariable( - "var", "${flag}${#var}", new FluentParserContext().template().variable( - new ExpressionVariable("var", "number"))))); - assertEquals("false0", exp.getValue(bean)); - } - - public void testGetExpressionString() { - String expressionString = "maximum"; - Expression exp = parser.parseExpression(expressionString, null); - assertEquals("maximum", exp.getExpressionString()); - } - - public void testGetValueType() { - String exp = "flag"; - Expression e = parser.parseExpression(exp, null); - assertEquals(boolean.class, e.getValueType(bean)); - } - - public void testGetValueTypeNullCollectionValue() { - String exp = "list[0]"; - Expression e = parser.parseExpression(exp, null); - assertEquals(null, e.getValueType(bean)); - } - - public void testGetValueWithCoersion() { - String expressionString = "number"; - Expression exp = parser.parseExpression(expressionString, new FluentParserContext().expectResult(String.class)); - TestBean context = new TestBean(); - assertEquals("0", exp.getValue(context)); - } - - public void testGetValueCoersionError() { - String expressionString = "number"; - Expression exp = parser.parseExpression(expressionString, - new FluentParserContext().expectResult(TestBean.class)); - TestBean context = new TestBean(); - try { - exp.getValue(context); - fail("Should have failed with coersion"); - } catch (ValueCoercionException e) { - } - } - - public void testSetValue() { - String expressionString = "number"; - Expression exp = parser.parseExpression(expressionString, null); - TestBean context = new TestBean(); - exp.setValue(context, 5); - assertEquals(5, context.getNumber()); - } - - public void testSetValueWithCoersion() { - GenericConversionService cs = (GenericConversionService) parser.getConversionService(); - StringToDate converter = new StringToDate(); - converter.setPattern("yyyy-MM-dd"); - cs.addConverter(converter); - Expression e = parser.parseExpression("date", null); - e.setValue(bean, "2008-9-15"); - } - - public void testSetBogusValueWithCoersion() { - Expression e = parser.parseExpression("date", null); - try { - e.setValue(bean, "bogus"); - fail("Should have failed tme"); - } catch (ValueCoercionException ex) { - } - } - - public void testReasonCauseLinkingGetValue() { - String exp = "getException()"; - Expression e = parser.parseExpression(exp, null); - try { - e.getValue(bean); - } catch (EvaluationException ex) { - assertTrue(ex.getCause().getCause() instanceof IllegalStateException); - } - } - - public void testReasonCauseLinkingSetValue() { - String exp = "exceptionProperty"; - Expression e = parser.parseExpression(exp, null); - try { - e.setValue(bean, "does not matter"); - } catch (EvaluationException ex) { - assertTrue(ex.getCause().getCause() instanceof IllegalStateException); - } - } - -} diff --git a/spring-webflow/src/main/java/org/springframework/webflow/expression/WebFlowOgnlExpressionParser.java b/spring-webflow/src/main/java/org/springframework/webflow/expression/WebFlowOgnlExpressionParser.java deleted file mode 100644 index 8b07641b..00000000 --- a/spring-webflow/src/main/java/org/springframework/webflow/expression/WebFlowOgnlExpressionParser.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright 2004-2012 the original author or authors. - * - * Licensed 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.springframework.webflow.expression; - -import java.util.Map; - -import ognl.ObjectPropertyAccessor; -import ognl.Ognl; -import ognl.OgnlException; -import ognl.PropertyAccessor; - -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.support.StaticListableBeanFactory; -import org.springframework.binding.collection.MapAdaptable; -import org.springframework.binding.expression.ognl.OgnlExpressionParser; -import org.springframework.context.MessageSource; -import org.springframework.webflow.context.ExternalContext; -import org.springframework.webflow.context.ExternalContextHolder; -import org.springframework.webflow.core.collection.MutableAttributeMap; -import org.springframework.webflow.execution.Action; -import org.springframework.webflow.execution.AnnotatedAction; -import org.springframework.webflow.execution.RequestContext; -import org.springframework.webflow.expression.spel.WebFlowSpringELExpressionParser; - -/** - * An extension of {@link OgnlExpressionParser} that registers Web Flow-specific PropertyAccessors. - * - * @author Keith Donald - * - * @deprecated in favor of Spring EL, see {@link WebFlowSpringELExpressionParser} - */ -@SuppressWarnings("rawtypes") -public class WebFlowOgnlExpressionParser extends OgnlExpressionParser { - - /** - * Creates a Web Flow OGNL Expression Parser. - */ - public WebFlowOgnlExpressionParser() { - addPropertyAccessor(MapAdaptable.class, new MapAdaptablePropertyAccessor()); - addPropertyAccessor(MutableAttributeMap.class, new MutableAttributeMapPropertyAccessor()); - addPropertyAccessor(MessageSource.class, new MessageSourcePropertyAccessor()); - addPropertyAccessor(RequestContext.class, new RequestContextPropertyAccessor(new ObjectPropertyAccessor())); - addPropertyAccessor(Action.class, new ActionPropertyAccessor()); - } - - /** - * Resolves Map Adaptable properties. - */ - private static class MapAdaptablePropertyAccessor implements PropertyAccessor { - public Object getProperty(Map context, Object target, Object name) throws OgnlException { - return ((MapAdaptable) target).asMap().get(name); - } - - public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException { - throw new UnsupportedOperationException( - "Cannot mutate immutable attribute collections; operation disallowed"); - } - } - - /** - * Resolves Mutable Attribute Map properties, also capable of setting properties. - */ - private static class MutableAttributeMapPropertyAccessor extends MapAdaptablePropertyAccessor { - @SuppressWarnings("unchecked") - public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException { - ((MutableAttributeMap) target).put((String) name, value); - } - } - - /** - * Resolves RequestContext properties. Supports several implicit variables and scope searching routines. - */ - private static class RequestContextPropertyAccessor implements PropertyAccessor { - - private static final BeanFactory EMPTY_BEAN_FACTORY = new StaticListableBeanFactory(); - - private PropertyAccessor delegate; - - public RequestContextPropertyAccessor(PropertyAccessor delegate) { - this.delegate = delegate; - } - - public Object getProperty(Map context, Object target, Object name) throws OgnlException { - String property = name.toString(); - RequestContext requestContext = (RequestContext) target; - if (property.equals("flowRequestContext")) { - return requestContext; - } - if (property.equals("currentUser")) { - return requestContext.getExternalContext().getCurrentUser(); - } - if (property.equals("resourceBundle")) { - return requestContext.getActiveFlow().getApplicationContext(); - } - if (requestContext.getRequestScope().contains(property)) { - return requestContext.getRequestScope().get(property); - } else if (requestContext.getFlashScope().contains(property)) { - return requestContext.getFlashScope().get(property); - } else if (requestContext.inViewState() && requestContext.getViewScope().contains(property)) { - return requestContext.getViewScope().get(property); - } else if (requestContext.getFlowScope().contains(property)) { - return requestContext.getFlowScope().get(property); - } else if (requestContext.getConversationScope().contains(property)) { - return requestContext.getConversationScope().get(property); - } - BeanFactory bf = getBeanFactory(requestContext); - if (bf.containsBean(property)) { - return bf.getBean(property); - } - return delegate.getProperty(context, target, name); - } - - public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException { - String property = name.toString(); - RequestContext requestContext = (RequestContext) target; - if (property.equals("flowRequestContext")) { - throw new OgnlException("The 'flowRequestContext' variable is not writeable"); - } - if (property.equals("currentUser")) { - throw new OgnlException("The 'currentUser' variable is not writeable"); - } - if (property.equals("resourceBundle")) { - throw new OgnlException("The 'resourceBundle' variable is not writeable"); - } - if (requestContext.getRequestScope().contains(property)) { - requestContext.getRequestScope().put(property, value); - } else if (requestContext.getFlashScope().contains(property)) { - requestContext.getFlashScope().put(property, value); - } else if (requestContext.inViewState() && requestContext.getViewScope().contains(property)) { - requestContext.getViewScope().put(property, value); - } else if (requestContext.getFlowScope().contains(property)) { - requestContext.getFlowScope().put(property, value); - } else if (requestContext.getConversationScope().contains(property)) { - requestContext.getConversationScope().put(property, value); - } else { - delegate.setProperty(context, target, name, value); - } - } - - private BeanFactory getBeanFactory(RequestContext requestContext) { - BeanFactory beanFactory = requestContext.getActiveFlow().getApplicationContext(); - return beanFactory != null ? beanFactory : EMPTY_BEAN_FACTORY; - } - } - - /** - * Resolves multi action methods. - */ - private static class ActionPropertyAccessor implements PropertyAccessor { - public Object getProperty(Map context, Object target, Object name) throws OgnlException { - Action action = (Action) target; - AnnotatedAction annotated = new AnnotatedAction(action); - annotated.setMethod(name.toString()); - return annotated; - } - - public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException { - throw new OgnlException("Cannot set properties on a Action instance - operation not allowed"); - } - } - - /** - * Resolves messages. - */ - private static class MessageSourcePropertyAccessor implements PropertyAccessor { - public Object getProperty(Map context, Object target, Object name) throws OgnlException { - MessageSource messageSource = (MessageSource) target; - ExternalContext externalContext; - Object root = Ognl.getRoot(context); - if (root instanceof RequestContext) { - externalContext = ((RequestContext) root).getExternalContext(); - } else { - externalContext = ExternalContextHolder.getExternalContext(); - } - if (externalContext != null) { - return messageSource.getMessage(name.toString(), null, null, externalContext.getLocale()); - } else { - return messageSource.getMessage(name.toString(), null, null, null); - } - } - - public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException { - throw new OgnlException("Cannot set properties on a MessageSource instance - operation not allowed"); - } - } - -} diff --git a/spring-webflow/src/test/java/org/springframework/webflow/expression/WebFlowOgnlExpressionParserTests.java b/spring-webflow/src/test/java/org/springframework/webflow/expression/WebFlowOgnlExpressionParserTests.java deleted file mode 100644 index 09f62baa..00000000 --- a/spring-webflow/src/test/java/org/springframework/webflow/expression/WebFlowOgnlExpressionParserTests.java +++ /dev/null @@ -1,199 +0,0 @@ -package org.springframework.webflow.expression; - -import java.security.Principal; -import java.util.Locale; - -import junit.framework.TestCase; - -import org.springframework.binding.expression.Expression; -import org.springframework.binding.expression.support.FluentParserContext; -import org.springframework.context.support.StaticApplicationContext; -import org.springframework.webflow.TestBean; -import org.springframework.webflow.action.FormAction; -import org.springframework.webflow.core.collection.AttributeMap; -import org.springframework.webflow.core.collection.LocalAttributeMap; -import org.springframework.webflow.core.collection.MutableAttributeMap; -import org.springframework.webflow.engine.StubViewFactory; -import org.springframework.webflow.engine.ViewState; -import org.springframework.webflow.execution.AnnotatedAction; -import org.springframework.webflow.execution.Event; -import org.springframework.webflow.execution.RequestContext; -import org.springframework.webflow.execution.TestAction; -import org.springframework.webflow.test.MockRequestContext; -import org.springframework.webflow.test.MockRequestControlContext; - -public class WebFlowOgnlExpressionParserTests extends TestCase { - private WebFlowOgnlExpressionParser parser = new WebFlowOgnlExpressionParser(); - - public void testResolveMap() { - LocalAttributeMap map = new LocalAttributeMap(); - map.put("foo", "bar"); - Expression exp = parser.parseExpression("foo", new FluentParserContext().evaluate(AttributeMap.class)); - Expression exp2 = parser.parseExpression("bogus", new FluentParserContext().evaluate(AttributeMap.class)); - assertEquals("bar", exp.getValue(map)); - assertEquals(null, exp2.getValue(map)); - } - - public void testSetMap() { - LocalAttributeMap map = new LocalAttributeMap(); - map.put("foo", "bar"); - Expression exp = parser.parseExpression("foo", new FluentParserContext().evaluate(MutableAttributeMap.class)); - Expression exp2 = parser - .parseExpression("bogus", new FluentParserContext().evaluate(MutableAttributeMap.class)); - exp.setValue(map, "baz"); - exp2.setValue(map, "new"); - assertEquals("baz", exp.getValue(map)); - assertEquals("new", exp2.getValue(map)); - } - - public void testResolveFlowRequestContext() { - MockRequestContext context = new MockRequestContext(); - Expression exp = parser.parseExpression("flowRequestContext", - new FluentParserContext().evaluate(RequestContext.class)); - assertSame(context, exp.getValue(context)); - } - - public void testResolveCurrentUser() { - MockRequestContext context = new MockRequestContext(); - context.getMockExternalContext().setCurrentUser("Keith"); - Expression exp = parser - .parseExpression("currentUser", new FluentParserContext().evaluate(RequestContext.class)); - assertEquals("Keith", ((Principal) exp.getValue(context)).getName()); - } - - public void testResolveRequestScope() { - MockRequestContext context = new MockRequestContext(); - context.getRequestScope().put("foo", "bar"); - Expression exp = parser.parseExpression("foo", new FluentParserContext().evaluate(RequestContext.class)); - assertEquals("bar", exp.getValue(context)); - } - - public void testSetRequestScope() { - MockRequestContext context = new MockRequestContext(); - context.getRequestScope().put("foo", "bar"); - Expression exp = parser.parseExpression("foo", new FluentParserContext().evaluate(RequestContext.class)); - exp.setValue(context, "baz"); - assertEquals("baz", exp.getValue(context)); - } - - public void testResolveFlashScope() { - MockRequestContext context = new MockRequestContext(); - context.getFlashScope().put("foo", "bar"); - Expression exp = parser.parseExpression("foo", new FluentParserContext().evaluate(RequestContext.class)); - assertEquals("bar", exp.getValue(context)); - } - - public void testSetFlashScope() { - MockRequestContext context = new MockRequestContext(); - context.getFlashScope().put("foo", "bar"); - Expression exp = parser.parseExpression("foo", new FluentParserContext().evaluate(RequestContext.class)); - exp.setValue(context, "baz"); - assertEquals("baz", exp.getValue(context)); - } - - public void testResolveViewScope() { - MockRequestControlContext context = new MockRequestControlContext(); - ViewState state = new ViewState(context.getRootFlow(), "view", new StubViewFactory()); - context.setCurrentState(state); - context.getViewScope().put("foo", "bar"); - Expression exp = parser.parseExpression("foo", new FluentParserContext().evaluate(RequestContext.class)); - assertEquals("bar", exp.getValue(context)); - } - - public void testSetViewScope() { - MockRequestControlContext context = new MockRequestControlContext(); - ViewState state = new ViewState(context.getRootFlow(), "view", new StubViewFactory()); - context.setCurrentState(state); - context.getViewScope().put("foo", "bar"); - Expression exp = parser.parseExpression("foo", new FluentParserContext().evaluate(RequestContext.class)); - exp.setValue(context, "baz"); - assertEquals("baz", exp.getValue(context)); - } - - public void testResolveFlowScope() { - MockRequestContext context = new MockRequestContext(); - context.getFlowScope().put("foo", "bar"); - Expression exp = parser.parseExpression("foo", new FluentParserContext().evaluate(RequestContext.class)); - assertEquals("bar", exp.getValue(context)); - } - - public void testSetFlowScope() { - MockRequestContext context = new MockRequestContext(); - context.getFlowScope().put("foo", "bar"); - Expression exp = parser.parseExpression("foo", new FluentParserContext().evaluate(RequestContext.class)); - exp.setValue(context, "baz"); - assertEquals("baz", exp.getValue(context)); - } - - public void testResolveConversationScope() { - MockRequestContext context = new MockRequestContext(); - context.getConversationScope().put("foo", "bar"); - Expression exp = parser.parseExpression("foo", new FluentParserContext().evaluate(RequestContext.class)); - assertEquals("bar", exp.getValue(context)); - } - - public void testSetConversationScope() { - MockRequestContext context = new MockRequestContext(); - context.getConversationScope().put("foo", "bar"); - Expression exp = parser.parseExpression("foo", new FluentParserContext().evaluate(RequestContext.class)); - exp.setValue(context, "baz"); - assertEquals("baz", exp.getValue(context)); - } - - public void testResolveSpringBean() { - MockRequestContext context = new MockRequestContext(); - StaticApplicationContext ac = new StaticApplicationContext(); - ac.getBeanFactory().registerSingleton("testBean", new TestBean()); - ac.getBeanFactory().registerSingleton("action", new TestAction()); - ac.getBeanFactory().registerSingleton("multiAction", new FormAction(TestBean.class)); - context.getRootFlow().setApplicationContext(ac); - context.getConversationScope().put("foo", "bar"); - Expression exp = parser.parseExpression("foo", new FluentParserContext().evaluate(RequestContext.class)); - assertEquals("bar", exp.getValue(context)); - } - - public void testResolveAction() { - MockRequestContext context = new MockRequestContext(); - StaticApplicationContext ac = new StaticApplicationContext(); - ac.getBeanFactory().registerSingleton("testBean", new TestBean()); - ac.getBeanFactory().registerSingleton("action", new TestAction()); - context.getRootFlow().setApplicationContext(ac); - Expression exp = parser.parseExpression("action", new FluentParserContext().evaluate(RequestContext.class)); - assertSame(ac.getBean("action"), exp.getValue(context)); - } - - public void testResolveMultiAction() { - MockRequestContext context = new MockRequestContext(); - StaticApplicationContext ac = new StaticApplicationContext(); - ac.getBeanFactory().registerSingleton("multiAction", new FormAction()); - context.getRootFlow().setApplicationContext(ac); - Expression exp = parser.parseExpression("multiAction.setupForm", - new FluentParserContext().evaluate(RequestContext.class)); - AnnotatedAction action = (AnnotatedAction) exp.getValue(context); - assertSame(ac.getBean("multiAction"), action.getTargetAction()); - assertEquals("setupForm", action.getMethod()); - } - - public void testResolveEventAttributes() { - MockRequestContext context = new MockRequestContext(); - LocalAttributeMap attributes = new LocalAttributeMap(); - attributes.put("foo", "bar"); - context.setCurrentEvent(new Event(this, "event", attributes)); - Expression exp = parser.parseExpression("currentEvent.attributes.foo", - new FluentParserContext().evaluate(RequestContext.class)); - assertEquals("bar", exp.getValue(context)); - } - - public void testResolveMessage() { - MockRequestContext context = new MockRequestContext(); - StaticApplicationContext ac = new StaticApplicationContext(); - ac.getStaticMessageSource().addMessage("foo", Locale.FRANCE, "bar"); - ac.refresh(); - context.getRootFlow().setApplicationContext(ac); - context.getMockExternalContext().setLocale(Locale.FRANCE); - Expression exp = parser.parseExpression("resourceBundle.foo", - new FluentParserContext().evaluate(RequestContext.class)); - assertEquals("bar", exp.getValue(context)); - } - -} diff --git a/src/reference/el.xml b/src/reference/el.xml index 1ecd3ea5..4290d132 100644 --- a/src/reference/el.xml +++ b/src/reference/el.xml @@ -79,21 +79,19 @@ Spring EL - Starting with version 2.1 Web Flow uses the Spring Expression Language (Spring EL). + Web Flow uses the Spring Expression Language (Spring EL). Spring EL was created to provide a single, well-supported expression language for use across all the products in the Spring portfolio. It is distributed as a separate jar org.springframework.expression in the Spring Framework. - Existing applications will need to remove dependencies on org.jboss.el or org.ognl and use org.springframework.expression instead. - See the section below on EL Portability for other notes on upgrading. Unified EL - In Web Flow 2.0 Unified EL was the default expression language with jboss-el as the implementation. - Use of Unified EL also implies a dependency on el-api although that is typically provided by your web container. - Tomcat 6 includes it, for example. - Spring EL is the default and recommended expression language to use. - However it is possible to replace it with Unified EL if you wish to do so. + Use of Unified EL + also implies a dependency on el-api although that is typically provided + by your web container. + Although Spring EL is the default and recommended expression language to use, + it is possible to replace it with Unified EL if you wish to do so. You need the following Spring configuration to plug in the WebFlowELExpressionParser to the flow-builder-services: @@ -115,35 +113,6 @@ -]]> - - - - - OGNL - - - OGNL support is deprecated as of Web Flow version 2.4. - - - - OGNL is the third supported expression language. - OGNL is the EL most familiar to Web Flow version 1.0 users. - Please refer to the OGNL language guide for specifics on its EL syntax. - If you wish to use OGNL this is the Spring configuration necessary to plug it in: - - -]]> - - Note that if your application is registering custom converters it's important to ensure the WebFlowOgnlExpressionParser is configured with the conversion service that has those custom converters. - - - - - - ]]> @@ -152,7 +121,7 @@ EL portability - In general, you will find Spring EL, Unified EL and OGNL to have a very similar syntax. + In general, you will find Spring EL and Unified EL to have a very similar syntax. Note however there are some advantages to Spring EL. @@ -160,7 +129,7 @@ Specifically the automatic detection of generic types as well as the use of formatting annotations is currently supported with Spring EL only. - There are some minor changes to keep in mind when upgrading to Spring EL from Unified EL or OGNL as follows: + There are some minor changes to keep in mind when upgrading to Spring EL from Unified EL as follows: Expressions deliniated with ${} in flow definitions must be changed to #{}. Expressions testing the current event #{currentEvent == 'submit'} must be changed to #{currentEvent.id == 'submit'}. diff --git a/src/reference/spring-mvc.xml b/src/reference/spring-mvc.xml index 31bcafaf..feff802c 100644 --- a/src/reference/spring-mvc.xml +++ b/src/reference/spring-mvc.xml @@ -339,7 +339,7 @@ public class BookingFlowHandler extends AbstractFlowHandler { as a custom MessageCodesResolver. You may also enable data binding use Spring MVC's native BeanWrapper by setting the useSpringBinding flag to true. This is an alternative to - using OGNL or the Unified EL for view-to-model data binding. See the + using the Unified EL for view-to-model data binding. See the JavaDoc API of this class for more information. diff --git a/src/reference/system-setup.xml b/src/reference/system-setup.xml index 90ccac11..54308b2e 100644 --- a/src/reference/system-setup.xml +++ b/src/reference/system-setup.xml @@ -393,7 +393,7 @@ public ViewFactoryCreator viewFactoryCreator() { expression-parser Use the expression-parser attribute to customize the ExpressionParser used by the Web Flow system. - The default ExpressionParser uses the Unified EL if available on the classpath, otherwise OGNL is used. + The default ExpressionParser uses the Unified EL if available on the classpath, otherwise Spring EL is used.