6701498: Change JMX query language to use * and ? as wildcards rather than % and _
Reviewed-by: dfuchs
--- a/jdk/src/share/classes/javax/management/MatchQueryExp.java Thu Jun 05 04:08:41 2008 -0700
+++ b/jdk/src/share/classes/javax/management/MatchQueryExp.java Thu Jun 05 13:40:09 2008 +0200
@@ -109,36 +109,7 @@
* 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);
}
/*
--- a/jdk/src/share/classes/javax/management/ObjectName.java Thu Jun 05 04:08:41 2008 -0700
+++ b/jdk/src/share/classes/javax/management/ObjectName.java Thu Jun 05 13:40:09 2008 +0200
@@ -1781,7 +1781,7 @@
}
String toQueryString() {
- return "LIKE " + Query.value(toString());
+ return "like " + Query.value(toString());
}
/**
--- a/jdk/src/share/classes/javax/management/Query.java Thu Jun 05 04:08:41 2008 -0700
+++ b/jdk/src/share/classes/javax/management/Query.java Thu Jun 05 13:40:09 2008 +0200
@@ -108,13 +108,13 @@
* <dd>Selects MBeans that have a {@code Status} attribute whose value
* is one of those three strings.
*
- * <dt>{@code Message like 'OK: %'}
+ * <dt>{@code Message like 'OK: *'}
* <dd>Selects MBeans that have a {@code Message} attribute whose value
* is a string beginning with {@code "OK: "}. <b>Notice that the
- * wildcard characters are SQL's ones.</b> In the query language,
+ * wildcard characters are not the ones that SQL uses.</b> 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.
*
* <dt>{@code instanceof 'javax.management.NotificationBroadcaster'}
* <dd>Selects MBeans that are instances of
@@ -319,11 +319,11 @@
*
* <tr><td><i>value</i> <b>LIKE</b> <i>stringLiteral</i>
* <td>{@link Query#match Query.match}(<i>q(value)</i>,
- * <i><a href="#translateWildcards">translateWildcards</a>(q(stringLiteral))</i>)
+ * <i>q(stringLiteral)</i>)
*
* <tr><td><i>value</i> <b>NOT LIKE</b> <i>stringLiteral</i>
* <td>{@link Query#not Query.not}({@link Query#match Query.match}(<i>q(value)</i>,
- * <i><a href="#translateWildcards">translateWildcards</a>(q(stringLiteral))</i>))
+ * <i>q(stringLiteral)</i>))
*
* <tr><td><i>value1</i> <b>+</b> <i>value2</i>
* <td>{@link Query#plus Query.plus}(<i>q(value1)</i>, <i>q(value2)</i>)
@@ -360,13 +360,6 @@
* --><i>floatingPointLiteral</i>))
* </table>
*
- * <p id="translateWildcards">Here, <i>translateWildcards</i> 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
- * <b>LIKE</b> 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}.</p>
- *
* @since 1.5
*/
public class Query extends Object {
--- a/jdk/src/share/classes/javax/management/QueryNotificationFilter.java Thu Jun 05 04:08:41 2008 -0700
+++ b/jdk/src/share/classes/javax/management/QueryNotificationFilter.java Thu Jun 05 13:40:09 2008 +0200
@@ -43,12 +43,6 @@
* on both the client and the server in the remote case, so using this class
* instead is recommended where possible.</p>
*
- * <!-- <p>Because this class was introduced in version 2.0 of the JMX API,
- * it may not be present on a remote JMX agent that is running an earlier
- * version. The method {@link JMX#addListenerWithFilter JMX.addListenerWithFilter}
- * can be used when you cannot be sure whether this class is present in the
- * agent you are connecting to.</p> -->
- *
* <p>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"},
--- a/jdk/src/share/classes/javax/management/QueryParser.java Thu Jun 05 04:08:41 2008 -0700
+++ b/jdk/src/share/classes/javax/management/QueryParser.java Thu Jun 05 13:40:09 2008 +0200
@@ -490,8 +490,7 @@
}
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 @@
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);
- }
}
--- a/jdk/test/javax/management/query/QueryExpStringTest.java Thu Jun 05 04:08:41 2008 -0700
+++ b/jdk/test/javax/management/query/QueryExpStringTest.java Thu Jun 05 13:40:09 2008 +0200
@@ -121,14 +121,14 @@
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 @@
exp + " like " + pat);
}
StringValueExp spat = (StringValueExp) pat;
- spat = Query.value(translateMatch(spat.getValue()));
return Query.match((AttributeValueExp) exp, spat);
}
@@ -226,28 +225,6 @@
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
--- a/jdk/test/javax/management/query/QueryParseTest.java Thu Jun 05 04:08:41 2008 -0700
+++ b/jdk/test/javax/management/query/QueryParseTest.java Thu Jun 05 13:40:09 2008 +0200
@@ -347,30 +347,30 @@
// 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 @@
// 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 @@
"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 @@
"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