Browse Source

SPR-5673: fix for problems with expressions that use the same symbols as are used in the template prefix/suffix

pull/23217/head
Andy Clement 17 years ago
parent
commit
4c42597cbc
  1. 4
      org.springframework.expression/src/main/java/org/springframework/expression/common/CompositeStringExpression.java
  2. 2
      org.springframework.expression/src/main/java/org/springframework/expression/common/TemplateAwareExpressionParser.java
  3. 77
      org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java
  4. 14
      org.springframework.expression/src/test/java/org/springframework/expression/spel/TemplateExpressionParsingTests.java

4
org.springframework.expression/src/main/java/org/springframework/expression/common/CompositeStringExpression.java

@ -95,5 +95,9 @@ public class CompositeStringExpression implements Expression { @@ -95,5 +95,9 @@ public class CompositeStringExpression implements Expression {
public boolean isWritable(EvaluationContext context) {
return false;
}
public Expression[] getExpressions() {
return expressions;
}
}

2
org.springframework.expression/src/main/java/org/springframework/expression/common/TemplateAwareExpressionParser.java

File diff suppressed because one or more lines are too long

77
org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
package org.springframework.expression.spel;
import org.springframework.expression.Expression;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.antlr.SpelAntlrExpressionParser;
/**
@ -26,20 +27,82 @@ import org.springframework.expression.spel.antlr.SpelAntlrExpressionParser; @@ -26,20 +27,82 @@ import org.springframework.expression.spel.antlr.SpelAntlrExpressionParser;
*/
public class SpringEL300Tests extends ExpressionTestCase {
public static final ParserContext DOLLARSQUARE_TEMPLATE_PARSER_CONTEXT = new ParserContext() {
public String getExpressionPrefix() {
return "$[";
}
public String getExpressionSuffix() {
return "]";
}
public boolean isTemplate() {
return true;
}
};
public void testNPE_5661() {
evaluate("joinThreeStrings('a',null,'c')", "anullc", String.class);
}
public void testNPE_5673() throws Exception {
SpelAntlrExpressionParser parser = new SpelAntlrExpressionParser();
Expression ex = parser.parseExpression("#{'Unable to render embedded object: File ({#this == 2\\}'}", TemplateExpressionParsingTests.HASH_DELIMITED_PARSER_CONTEXT);
assertEquals("Unable to render embedded object: File ({#this == 2}",ex.getValue());
ParserContext hashes = TemplateExpressionParsingTests.HASH_DELIMITED_PARSER_CONTEXT;
ParserContext dollars = TemplateExpressionParsingTests.DEFAULT_TEMPLATE_PARSER_CONTEXT;
checkTemplateParsing("abc${'def'} ghi","abcdef ghi");
ex = parser.parseExpression("This is the last odd number in the list: ${listOfNumbersUpToTen.$[#this%2==1]}",TemplateExpressionParsingTests.DEFAULT_TEMPLATE_PARSER_CONTEXT);
assertEquals("This is the last odd number in the list: 9",ex.getValue(TestScenarioCreator.getTestEvaluationContext()));
checkTemplateParsingError("abc${ {}( 'abc'","Missing closing ')' for '(' at position 8");
checkTemplateParsingError("abc${ {}[ 'abc'","Missing closing ']' for '[' at position 8");
checkTemplateParsingError("abc${ {}{ 'abc'","Missing closing '}' for '{' at position 8");
checkTemplateParsingError("abc${ ( 'abc' }","Found closing '}' at position 14 but most recent opening is '(' at position 6");
checkTemplateParsingError("abc${ '... }","Found non terminating string literal starting at position 6");
checkTemplateParsingError("abc${ \"... }","Found non terminating string literal starting at position 6");
checkTemplateParsingError("abc${ ) }","Found closing ')' at position 6 without an opening '('");
checkTemplateParsingError("abc${ ] }","Found closing ']' at position 6 without an opening '['");
checkTemplateParsingError("abc${ } }","No expression defined within delimiter '${}' at character 3");
checkTemplateParsingError("abc$[ } ]",DOLLARSQUARE_TEMPLATE_PARSER_CONTEXT,"Found closing '}' at position 6 without an opening '{'");
checkTemplateParsing("abc ${\"def''g}hi\"} jkl","abc def'g}hi jkl");
checkTemplateParsing("abc ${'def''g}hi'} jkl","abc def'g}hi jkl");
checkTemplateParsing("}","}");
checkTemplateParsing("${'hello'} world","hello world");
checkTemplateParsing("Hello ${'}'}]","Hello }]");
checkTemplateParsing("Hello ${'}'}","Hello }");
checkTemplateParsingError("Hello ${ ( ","No ending suffix '}' for expression starting at character 6: ${ ( ");
checkTemplateParsingError("Hello ${ ( }","Found closing '}' at position 11 but most recent opening is '(' at position 9");
checkTemplateParsing("#{'Unable to render embedded object: File ({#this == 2}'}", hashes,"Unable to render embedded object: File ({#this == 2}");
checkTemplateParsing("This is the last odd number in the list: ${listOfNumbersUpToTen.$[#this%2==1]}",dollars,"This is the last odd number in the list: 9");
checkTemplateParsing("Hello ${'here is a curly bracket }'}",dollars,"Hello here is a curly bracket }");
checkTemplateParsing("He${'${'}llo ${'here is a curly bracket }'}}",dollars,"He${llo here is a curly bracket }}");
checkTemplateParsing("Hello ${'()()()}{}{}{][]{}{][}[][][}{()()'} World",dollars,"Hello ()()()}{}{}{][]{}{][}[][][}{()() World");
checkTemplateParsing("Hello ${'inner literal that''s got {[(])]}an escaped quote in it'} World","Hello inner literal that's got {[(])]}an escaped quote in it World");
checkTemplateParsingError("Hello ${","No ending suffix '}' for expression starting at character 6: ${");
}
private void checkTemplateParsing(String expression, String expectedValue) throws Exception {
checkTemplateParsing(expression,TemplateExpressionParsingTests.DEFAULT_TEMPLATE_PARSER_CONTEXT, expectedValue);
}
private void checkTemplateParsing(String expression, ParserContext context, String expectedValue) throws Exception {
SpelAntlrExpressionParser parser = new SpelAntlrExpressionParser();
Expression expr = parser.parseExpression(expression,context);
assertEquals(expectedValue,expr.getValue(TestScenarioCreator.getTestEvaluationContext()));
}
ex = parser.parseExpression("Hello ${'here is a curly bracket \\}'}",TemplateExpressionParsingTests.DEFAULT_TEMPLATE_PARSER_CONTEXT);
assertEquals("Hello here is a curly bracket }",ex.getValue());
private void checkTemplateParsingError(String expression,String expectedMessage) throws Exception {
checkTemplateParsingError(expression, TemplateExpressionParsingTests.DEFAULT_TEMPLATE_PARSER_CONTEXT,expectedMessage);
}
private void checkTemplateParsingError(String expression,ParserContext context, String expectedMessage) throws Exception {
SpelAntlrExpressionParser parser = new SpelAntlrExpressionParser();
try {
Expression expr = parser.parseExpression(expression,context);
fail("Should have failed");
} catch (Exception e) {
if (!e.getMessage().equals(expectedMessage)) {
e.printStackTrace();
}
assertEquals(expectedMessage,e.getMessage());
}
}
}

14
org.springframework.expression/src/test/java/org/springframework/expression/spel/TemplateExpressionParsingTests.java

@ -20,6 +20,7 @@ import org.springframework.expression.EvaluationContext; @@ -20,6 +20,7 @@ import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ParseException;
import org.springframework.expression.ParserContext;
import org.springframework.expression.common.CompositeStringExpression;
import org.springframework.expression.spel.antlr.SpelAntlrExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
@ -111,6 +112,11 @@ public class TemplateExpressionParsingTests extends ExpressionTestCase { @@ -111,6 +112,11 @@ public class TemplateExpressionParsingTests extends ExpressionTestCase {
// not a useful expression but tests nested expression syntax that clashes with template prefix/suffix
ex = parser.parseExpression("hello ${listOfNumbersUpToTen.$[#root.listOfNumbersUpToTen.$[#this%2==1]==3]} world",DEFAULT_TEMPLATE_PARSER_CONTEXT);
assertEquals(CompositeStringExpression.class,ex.getClass());
CompositeStringExpression cse = (CompositeStringExpression)ex;
Expression[] exprs = cse.getExpressions();
assertEquals(3,exprs.length);
assertEquals("listOfNumbersUpToTen.$[#root.listOfNumbersUpToTen.$[#this%2==1]==3]",exprs[1].getExpressionString());
s = ex.getValue(TestScenarioCreator.getTestEvaluationContext(),String.class);
assertEquals("hello world",s);
@ -126,10 +132,10 @@ public class TemplateExpressionParsingTests extends ExpressionTestCase { @@ -126,10 +132,10 @@ public class TemplateExpressionParsingTests extends ExpressionTestCase {
}
try {
ex = parser.parseExpression("hello ${listOfNumbersUpToTen.${#root.listOfNumbersUpToTen.${#this%2==1==3}} world",DEFAULT_TEMPLATE_PARSER_CONTEXT);
ex = parser.parseExpression("hello ${listOfNumbersUpToTen.$[#root.listOfNumbersUpToTen.$[#this%2==1==3]} world",DEFAULT_TEMPLATE_PARSER_CONTEXT);
fail("Should have failed");
} catch (ParseException pe) {
assertEquals("No ending suffix '}' for expression starting at character 6: ${listOfNumbersUpToTen.${#root.listOfNumbersUpToTen.${#this%2==1==3}} world",pe.getMessage());
assertEquals("Found closing '}' at position 74 but most recent opening is '[' at position 30",pe.getMessage());
}
}
@ -139,11 +145,11 @@ public class TemplateExpressionParsingTests extends ExpressionTestCase { @@ -139,11 +145,11 @@ public class TemplateExpressionParsingTests extends ExpressionTestCase {
String s = ex.getValue(TestScenarioCreator.getTestEvaluationContext(),String.class);
assertEquals("hello 7 world",s);
ex = parser.parseExpression("hello ${3+4} wo\\${rld",DEFAULT_TEMPLATE_PARSER_CONTEXT);
ex = parser.parseExpression("hello ${3+4} wo${'${'}rld",DEFAULT_TEMPLATE_PARSER_CONTEXT);
s = ex.getValue(TestScenarioCreator.getTestEvaluationContext(),String.class);
assertEquals("hello 7 wo${rld",s);
ex = parser.parseExpression("hello ${3+4} wo\\}rld",DEFAULT_TEMPLATE_PARSER_CONTEXT);
ex = parser.parseExpression("hello ${3+4} wo}rld",DEFAULT_TEMPLATE_PARSER_CONTEXT);
s = ex.getValue(TestScenarioCreator.getTestEvaluationContext(),String.class);
assertEquals("hello 7 wo}rld",s);
}

Loading…
Cancel
Save