From e01cfb7fa8c0432e0ed6389da3ee471f323c21f9 Mon Sep 17 00:00:00 2001 From: Eamonn McManus Date: Thu, 5 Jun 2008 13:40:09 +0200 Subject: [PATCH] 6701498: Change JMX query language to use * and ? as wildcards rather than % and _ Reviewed-by: dfuchs --- .../javax/management/MatchQueryExp.java | 31 +-------------- .../classes/javax/management/ObjectName.java | 2 +- .../share/classes/javax/management/Query.java | 19 +++------ .../management/QueryNotificationFilter.java | 6 --- .../classes/javax/management/QueryParser.java | 39 +------------------ .../management/query/QueryExpStringTest.java | 39 ++++--------------- .../management/query/QueryParseTest.java | 33 +++++++++------- 7 files changed, 35 insertions(+), 134 deletions(-) diff --git a/jdk/src/share/classes/javax/management/MatchQueryExp.java b/jdk/src/share/classes/javax/management/MatchQueryExp.java index 779fac1989f..e5fd45bea51 100644 --- a/jdk/src/share/classes/javax/management/MatchQueryExp.java +++ b/jdk/src/share/classes/javax/management/MatchQueryExp.java @@ -109,36 +109,7 @@ class MatchQueryExp extends QueryEval implements QueryExp { * Returns the string representing the object */ public String toString() { - return exp + " like " + new StringValueExp(likeTranslate(pattern)); - } - - private static String likeTranslate(String s) { - StringBuilder sb = new StringBuilder(); - int c; - for (int i = 0; i < s.length(); i += Character.charCount(c)) { - c = s.codePointAt(i); - switch (c) { - case '\\': - i += Character.charCount(c); - sb.append('\\'); - if (i < s.length()) { - c = s.codePointAt(i); - sb.appendCodePoint(c); - } - break; - case '*': - sb.append('%'); break; - case '?': - sb.append('_'); break; - case '%': - sb.append("\\%"); break; - case '_': - sb.append("\\_"); break; - default: - sb.appendCodePoint(c); break; - } - } - return sb.toString(); + return exp + " like " + new StringValueExp(pattern); } /* diff --git a/jdk/src/share/classes/javax/management/ObjectName.java b/jdk/src/share/classes/javax/management/ObjectName.java index 2844f70e695..dea45a3a09f 100644 --- a/jdk/src/share/classes/javax/management/ObjectName.java +++ b/jdk/src/share/classes/javax/management/ObjectName.java @@ -1781,7 +1781,7 @@ public class ObjectName implements Comparable, QueryExp { } String toQueryString() { - return "LIKE " + Query.value(toString()); + return "like " + Query.value(toString()); } /** diff --git a/jdk/src/share/classes/javax/management/Query.java b/jdk/src/share/classes/javax/management/Query.java index fbfae6c2015..a768fb8bd53 100644 --- a/jdk/src/share/classes/javax/management/Query.java +++ b/jdk/src/share/classes/javax/management/Query.java @@ -108,13 +108,13 @@ package javax.management; *
Selects MBeans that have a {@code Status} attribute whose value * is one of those three strings. * - *
{@code Message like 'OK: %'} + *
{@code Message like 'OK: *'} *
Selects MBeans that have a {@code Message} attribute whose value * is a string beginning with {@code "OK: "}. Notice that the - * wildcard characters are SQL's ones. In the query language, + * wildcard characters are not the ones that SQL uses. In SQL, * {@code %} means "any sequence of characters" and {@code _} - * means "any single character". In the rest of the JMX API, these - * correspond to {@code *} and {@code %} respectively. + * means "any single character". Here, as in the rest of the JMX API, + * those are represented by {@code *} and {@code ?} respectively. * *
{@code instanceof 'javax.management.NotificationBroadcaster'} *
Selects MBeans that are instances of @@ -319,11 +319,11 @@ package javax.management; * * value LIKE stringLiteral * {@link Query#match Query.match}(q(value), - * translateWildcards(q(stringLiteral))) + * q(stringLiteral)) * * value NOT LIKE stringLiteral * {@link Query#not Query.not}({@link Query#match Query.match}(q(value), - * translateWildcards(q(stringLiteral)))) + * q(stringLiteral))) * * value1 + value2 * {@link Query#plus Query.plus}(q(value1), q(value2)) @@ -360,13 +360,6 @@ package javax.management; * -->floatingPointLiteral)) * * - *

Here, translateWildcards is a function - * that translates from the SQL notation for wildcards, using {@code %} and - * {@code _}, to the JMX API notation, using {@code *} and {@code ?}. If the - * LIKE string already contains {@code *} or {@code ?}, these characters - * have their literal meanings, and will be quoted in the call to - * {@link Query#match Query.match}.

- * * @since 1.5 */ public class Query extends Object { diff --git a/jdk/src/share/classes/javax/management/QueryNotificationFilter.java b/jdk/src/share/classes/javax/management/QueryNotificationFilter.java index c6c10393902..08565220d9c 100644 --- a/jdk/src/share/classes/javax/management/QueryNotificationFilter.java +++ b/jdk/src/share/classes/javax/management/QueryNotificationFilter.java @@ -43,12 +43,6 @@ import java.util.Set; * on both the client and the server in the remote case, so using this class * instead is recommended where possible.

* - * - * *

This class uses the {@linkplain Query Query API} to specify the * filtering logic. For example, to select only notifications where the * {@linkplain Notification#getType() type} is {@code "com.example.mytype"}, diff --git a/jdk/src/share/classes/javax/management/QueryParser.java b/jdk/src/share/classes/javax/management/QueryParser.java index 5e24e3bfbd3..babf05c7a20 100644 --- a/jdk/src/share/classes/javax/management/QueryParser.java +++ b/jdk/src/share/classes/javax/management/QueryParser.java @@ -490,8 +490,7 @@ class QueryParser { } AttributeValueExp alhs = (AttributeValueExp) lhs; StringValueExp sve = stringvalue(); - String s = sve.getValue(); - q = Query.match(alhs, patternValueExp(s)); + q = Query.match(alhs, sve); break; } @@ -624,40 +623,4 @@ class QueryParser { throw new IllegalArgumentException("Expected string: " + t); return Query.value(t.string); } - - // Convert the SQL pattern syntax, using % and _, to the Query.match - // syntax, using * and ?. The tricky part is recognizing \% and - // \_ as literal values, and also not replacing them inside []. - // But Query.match does not recognize \ inside [], which makes our - // job a tad easier. - private StringValueExp patternValueExp(String s) { - int c; - for (int i = 0; i < s.length(); i += Character.charCount(c)) { - c = s.codePointAt(i); - switch (c) { - case '\\': - i++; // i += Character.charCount(c), but we know it's 1! - if (i >= s.length()) - throw new IllegalArgumentException("\\ at end of pattern"); - break; - case '[': - i = s.indexOf(']', i); - if (i < 0) - throw new IllegalArgumentException("[ without ]"); - break; - case '%': - s = s.substring(0, i) + "*" + s.substring(i + 1); - break; - case '_': - s = s.substring(0, i) + "?" + s.substring(i + 1); - break; - case '*': - case '?': - s = s.substring(0, i) + '\\' + (char) c + s.substring(i + 1); - i++; - break; - } - } - return Query.value(s); - } } diff --git a/jdk/test/javax/management/query/QueryExpStringTest.java b/jdk/test/javax/management/query/QueryExpStringTest.java index be6a515b8fb..07003fc357b 100644 --- a/jdk/test/javax/management/query/QueryExpStringTest.java +++ b/jdk/test/javax/management/query/QueryExpStringTest.java @@ -121,14 +121,14 @@ public class QueryExpStringTest { eq, "(12345678) = (2.5)", between, "(12345678) between (2.5) and (2.5)", match, "attr like 'simpleString'", - initial, "attr like 'simpleString%'", - initialStar, "attr like '\\*%'", - initialPercent, "attr like '\\%%'", - any, "attr like '%simpleString%'", - anyStar, "attr like '%\\*%'", - anyPercent, "attr like '%\\%%'", - ffinal, "attr like '%simpleString'", - finalMagic, "attr like '%\\?\\*\\[\\\\'", + initial, "attr like 'simpleString*'", + initialStar, "attr like '\\**'", + initialPercent, "attr like '%*'", + any, "attr like '*simpleString*'", + anyStar, "attr like '*\\**'", + anyPercent, "attr like '*%*'", + ffinal, "attr like '*simpleString'", + finalMagic, "attr like '*\\?\\*\\[\\\\'", in, "12345678 in (12345678, 2.5)", and, "((12345678) > (2.5)) and ((12345678) < (2.5))", or, "((12345678) > (2.5)) or ((12345678) < (2.5))", @@ -207,7 +207,6 @@ public class QueryExpStringTest { exp + " like " + pat); } StringValueExp spat = (StringValueExp) pat; - spat = Query.value(translateMatch(spat.getValue())); return Query.match((AttributeValueExp) exp, spat); } @@ -226,28 +225,6 @@ public class QueryExpStringTest { throw new Exception("Expected in or like after expression"); } - private static String translateMatch(String s) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < s.length(); i++) { // logic not correct for wide chars - char c = s.charAt(i); - switch (c) { - case '\\': - sb.append(c).append(s.charAt(++i)); break; - case '%': - sb.append('*'); break; - case '_': - sb.append('?'); break; - case '*': - sb.append("\\*"); break; - case '?': - sb.append("\\?"); break; - default: - sb.append(c); break; - } - } - return sb.toString(); - } - private static QueryExp parseQueryAfterParen(String[] ss) throws Exception { /* This is very ugly. We might have "(q1) and (q2)" here, or diff --git a/jdk/test/javax/management/query/QueryParseTest.java b/jdk/test/javax/management/query/QueryParseTest.java index a6004b5c150..62b64bf710e 100644 --- a/jdk/test/javax/management/query/QueryParseTest.java +++ b/jdk/test/javax/management/query/QueryParseTest.java @@ -347,30 +347,30 @@ public class QueryParseTest { // LIKE - "A like 'b%m'", + "A like 'b*m'", expectTrue("blim"), expectTrue("bm"), expectFalse(""), expectFalse("blimmo"), expectFalse("mmm"), - "A not like 'b%m'", + "A not like 'b*m'", expectFalse("blim"), expectFalse("bm"), expectTrue(""), expectTrue("blimmo"), expectTrue("mmm"), - "A like 'b_m'", + "A like 'b?m'", expectTrue("bim"), expectFalse("blim"), - "A like '%can''t%'", + "A like '*can''t*'", expectTrue("can't"), expectTrue("I'm sorry Dave, I'm afraid I can't do that"), expectFalse("cant"), expectFalse("can''t"), - "A like '\\%%\\%'", - expectTrue("%blim%"), expectTrue("%%"), - expectFalse("blim"), expectFalse("%asdf"), expectFalse("asdf%"), + "A like '\\**\\*'", + expectTrue("*blim*"), expectTrue("**"), + expectFalse("blim"), expectFalse("*asdf"), expectFalse("asdf*"), - "A LIKE '*%?_'", - expectTrue("*blim?!"), expectTrue("*?_"), - expectFalse("blim"), expectFalse("blim?"), - expectFalse("?*"), expectFalse("??"), expectFalse(""), expectFalse("?"), + "A LIKE '%*_?'", + expectTrue("%blim_?"), expectTrue("%_?"), expectTrue("%blim_!"), + expectFalse("blim"), expectFalse("blim_"), + expectFalse("_%"), expectFalse("??"), expectFalse(""), expectFalse("?"), Query.toString( Query.initialSubString(Query.attr("A"), Query.value("*?%_"))), @@ -483,7 +483,7 @@ public class QueryParseTest { // note the little {} at the end which means this is a subclass // and therefore QualifiedAttributeValue should return false. - MBeanServerDelegate.class.getName() + "#SpecificationName LIKE '%'", + MBeanServerDelegate.class.getName() + "#SpecificationName LIKE '*'", new Wrapped(new MBeanServerDelegate(), true), new Tester(new String[] {"SpecificationName"}, new Object[] {"JMX"}, false), @@ -497,7 +497,7 @@ public class QueryParseTest { "A.class.name = 'java.lang.String'", expectTrue("blim"), expectFalse(95), expectFalse((Object) null), - "A.canonicalName like 'JMImpl%:%'", + "A.canonicalName like 'JMImpl*:*'", expectTrue(MBeanServerDelegate.DELEGATE_NAME), expectFalse(ObjectName.WILDCARD), @@ -544,12 +544,15 @@ public class QueryParseTest { "a in b, c", "a in 23", "a in (2, 3", "a in (2, 3x)", "a like \"foo\"", "a like b", "a like 23", "like \"foo\"", "like b", "like 23", "like 'a:b'", - "5 like 'a'", "'a' like '%'", + "5 like 'a'", "'a' like '*'", "a not= b", "a not = b", "a not b", "a not b c", "a = +b", "a = +'b'", "a = +true", "a = -b", "a = -'b'", "a#5 = b", "a#'b' = c", "a instanceof b", "a instanceof 17", "a instanceof", - "a like 'oops\\'", "a like '[oops'", + // "a like 'oops\\'", "a like '[oops'", + // We don't check the above because Query.match doesn't. If LIKE + // rejected bad patterns then there would be some QueryExp values + // that could not be converted to a string and back. // Check that -Long.MIN_VALUE is an illegal constant. This is one more // than Long.MAX_VALUE and, like the Java language, we only allow it