https://issues.apache.org/jira/browse/AMQ-6137 - deal with 'special' escape chars in like selector expression

This commit is contained in:
gtully 2016-01-22 15:29:42 +00:00
parent 4ee29c363f
commit acbe31fcb5
2 changed files with 41 additions and 14 deletions

View File

@ -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()
*/

View File

@ -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;