Affects: 4.1.2 and up
I'm trying to use my own matching functions with spring-expression, but I came across a possible bug.
Here's some code for context:
import org.springframework.expression.spel.support.StandardEvaluationContext; public class RuleEvaluationContext extends StandardEvaluationContext { public RuleEvaluationContext(Object rootObject) { super(rootObject); registerFunctions(); } public RuleEvaluationContext() { super(); registerFunctions(); } private void registerFunctions() { for (Functions fun : Functions.values()) { this.registerFunction(fun.funcName(), fun.method()); } } }
enum Functions { /* Functions commented for the sake of simplicity CONTAINS(Contains.FUNC_NAME, getDeclaredMethod(Contains.class, Contains.FUNC_NAME, String.class, String[].class)), STARTS_WITH(StartsWith.FUNC_NAME, getDeclaredMethod(StartsWith.class, StartsWith.FUNC_NAME, String.class, String[].class)), */ MATCHES(Matches.FUNC_NAME, getDeclaredMethod(Matches.class, Matches.FUNC_NAME, String.class, String[].class)), /* EQUALS(Equals.FUNC_NAME, getDeclaredMethod(Equals.class, Equals.FUNC_NAME, String.class, String.class)), GREATER(GreaterThan.FUNC_NAME, getDeclaredMethod(GreaterThan.class, GreaterThan.FUNC_NAME, String.class, String.class)), LESS_THAN(LessThan.FUNC_NAME, getDeclaredMethod(LessThan.class, LessThan.FUNC_NAME, String.class, String.class)); */ private final String funcName; private final Method method; Functions(String funcName, Method method) { this.funcName = funcName; this.method = method; } public String funcName() { return funcName; } public Method method() { return method; } private static Method getDeclaredMethod(Class c, String name, Class<?>... parameterTypes) { try { return c.getDeclaredMethod(name, parameterTypes); } catch (NoSuchMethodException e) { throw new FunctionsException(e); } } }
This is one of the registered functions:
public class Matches { public static final String FUNC_NAME = "matches"; private Matches() { super(); } public static boolean matches(String text, String... regexps) { if (text != null) { for (String regex : regexps) { Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); Matcher matcher = pattern.matcher(text); if (matcher.find()) { return true; } } } return false; } }
@Test public void test() { final RuleEvaluationContext context = new RuleEvaluationContext(new FakeObject()); String originalRule = "#matches(prop, 'xyz,xyz')"; Expression expression = parser.parseExpression(originalRule); Boolean result = expression.getValue(context, Boolean.class); assertThat(result, is(false)); } private final ExpressionParser parser = new SpelExpressionParser(); private static class FakeObject { private String prop = "xyz"; public String getProp() { return prop; } }
This test fails when it should pass. Upon further inspection I've found that the problem is that spring-expression breaks the 'xyz,xyz' into ["xyz", "xyz"] as can be seen below.
However I've also found that using old versions of the library (pre 4.1.2), this doesn't happen.
As does putting more strings inside the argument:
@Test public void test() { final RuleEvaluationContext context = new RuleEvaluationContext(new FakeObject()); String originalRule = "#matches(prop, 'abc', 'xyz,xyz')"; Expression expression = parser.parseExpression(originalRule); Boolean result = expression.getValue(context, Boolean.class); assertThat(result, is(false)); }
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4