From acbe31fcb5d84c49c948a8816fd3a7cf50b58620 Mon Sep 17 00:00:00 2001 From: gtully Date: Fri, 22 Jan 2016 15:29:42 +0000 Subject: [PATCH] https://issues.apache.org/jira/browse/AMQ-6137 - deal with 'special' escape chars in like selector expression --- .../activemq/filter/ComparisonExpression.java | 38 ++++++++++++------- .../activemq/selector/SelectorTest.java | 17 +++++++++ 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/activemq-client/src/main/java/org/apache/activemq/filter/ComparisonExpression.java b/activemq-client/src/main/java/org/apache/activemq/filter/ComparisonExpression.java index 62d53d1d5e..4bb62de95e 100755 --- a/activemq-client/src/main/java/org/apache/activemq/filter/ComparisonExpression.java +++ b/activemq-client/src/main/java/org/apache/activemq/filter/ComparisonExpression.java @@ -88,25 +88,13 @@ public abstract class ComparisonExpression extends BinaryExpression implements B regexp.append("\\A"); // The beginning of the input for (int i = 0; i < like.length(); i++) { char c = like.charAt(i); - if (escape == (0xFFFF & c)) { + if (escape == (0xFFFF & c) && shouldEscapeNext(like, i, c)) { i++; - if (i >= like.length()) { - // nothing left to escape... - break; - } - char t = like.charAt(i); regexp.append("\\x"); regexp.append(Integer.toHexString(0xFFFF & t)); - } else if (c == '%') { - regexp.append(".*?"); // Do a non-greedy match - } else if (c == '_') { - regexp.append("."); // match one - } else if (REGEXP_CONTROL_CHARS.contains(new Character(c))) { - regexp.append("\\x"); - regexp.append(Integer.toHexString(0xFFFF & c)); } else { - regexp.append(c); + append(regexp, c); } } regexp.append("\\z"); // The end of the input @@ -114,6 +102,28 @@ public abstract class ComparisonExpression extends BinaryExpression implements B likePattern = Pattern.compile(regexp.toString(), Pattern.DOTALL); } + private boolean shouldEscapeNext(String selector, int i, char escape) { + int next = i+1; + if (next < selector.length()) { + final char c = selector.charAt(next); + return (c == '_' || c == '%' || c == escape); + } + return false; + } + + private void append(StringBuffer regexp, char c) { + if (c == '%') { + regexp.append(".*?"); // Do a non-greedy match + } else if (c == '_') { + regexp.append("."); // match one + } else if (REGEXP_CONTROL_CHARS.contains(new Character(c))) { + regexp.append("\\x"); + regexp.append(Integer.toHexString(0xFFFF & c)); + } else { + regexp.append(c); + } + } + /** * @see org.apache.activemq.filter.UnaryExpression#getExpressionSymbol() */ diff --git a/activemq-unit-tests/src/test/java/org/apache/activemq/selector/SelectorTest.java b/activemq-unit-tests/src/test/java/org/apache/activemq/selector/SelectorTest.java index 8279ae4852..84a87b499b 100755 --- a/activemq-unit-tests/src/test/java/org/apache/activemq/selector/SelectorTest.java +++ b/activemq-unit-tests/src/test/java/org/apache/activemq/selector/SelectorTest.java @@ -322,6 +322,21 @@ public class SelectorTest extends TestCase { assertSelector(message, "punctuation LIKE '!#$&()*+,-./:;<=>?@[\\]^`{|}~'", true); } + public void testSpecialEscapeLiteral() throws Exception { + Message message = createMessage(); + assertSelector(message, "foo LIKE '%_%' ESCAPE '%'", true); + assertSelector(message, "endingUnderScore LIKE '_D7xlJIQn$_' ESCAPE '$'", true); + assertSelector(message, "endingUnderScore LIKE '_D7xlJIQn__' ESCAPE '_'", true); + assertSelector(message, "endingUnderScore LIKE '%D7xlJIQn%_' ESCAPE '%'", true); + assertSelector(message, "endingUnderScore LIKE '%D7xlJIQn%' ESCAPE '%'", true); + + // literal '%' at the end, no match + assertSelector(message, "endingUnderScore LIKE '%D7xlJIQn%%' ESCAPE '%'", false); + + assertSelector(message, "endingUnderScore LIKE '_D7xlJIQn\\_' ESCAPE '\\'", true); + assertSelector(message, "endingUnderScore LIKE '%D7xlJIQn\\_' ESCAPE '\\'", true); + } + public void testInvalidSelector() throws Exception { Message message = createMessage(); assertInvalidSelector(message, "3+5"); @@ -367,6 +382,8 @@ public class SelectorTest extends TestCase { message.setStringProperty("quote", "'In God We Trust'"); message.setStringProperty("foo", "_foo"); message.setStringProperty("punctuation", "!#$&()*+,-./:;<=>?@[\\]^`{|}~"); + message.setStringProperty("endingUnderScore", "XD7xlJIQn_"); + message.setBooleanProperty("trueProp", true); message.setBooleanProperty("falseProp", false); return message;