diff --git a/activemq-console/src/main/java/org/apache/activemq/console/command/PurgeCommand.java b/activemq-console/src/main/java/org/apache/activemq/console/command/PurgeCommand.java index dd841aeb5b..4974925f4f 100644 --- a/activemq-console/src/main/java/org/apache/activemq/console/command/PurgeCommand.java +++ b/activemq-console/src/main/java/org/apache/activemq/console/command/PurgeCommand.java @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; - import javax.management.MBeanServerInvocationHandler; import javax.management.ObjectInstance; import javax.management.ObjectName; @@ -118,15 +117,10 @@ public class PurgeCommand extends AbstractJmxCommand { // We then need to construct the SQL-92 query out of // this list. - String sqlQuery = null; - if (queryAddObjects.size() > 1) { - sqlQuery = convertToSQL92(queryAddObjects); - } else { - sqlQuery = queryAddObjects.get(0); - } + String sqlQuery = convertToSQL92(queryAddObjects); removed = proxy.removeMatchingMessages(sqlQuery); context.printInfo("Removed: " + removed - + " messages for message selector " + sqlQuery.toString()); + + " messages for message selector " + sqlQuery); if (resetStatistics) { proxy.resetStatistics(); @@ -208,22 +202,28 @@ public class PurgeCommand extends AbstractJmxCommand { * @return SQL-92 string of that query. */ public String convertToSQL92(List tokens) { - String selector = ""; + StringBuilder selector = new StringBuilder(); - // Convert to message selector + boolean isFirstToken = true; for (Iterator i = tokens.iterator(); i.hasNext(); ) { - selector = selector + "(" + i.next().toString() + ") AND "; + String token = i.next().toString(); + if (token.matches("^[^=]*='.*[\\*\\?].*'$")) { + token = token.replace('?', '_') + .replace('*', '%') + .replaceFirst("=", " LIKE "); + } + if (isFirstToken) { + isFirstToken = false; + } else { + selector.append(" AND "); + } + selector.append('(') + .append(token) + .append(')'); } - - // Remove last AND and replace '*' with '%' - if (!selector.equals("")) { - selector = selector.substring(0, selector.length() - 5); - selector = selector.replace('*', '%'); - } - return selector; + return selector.toString(); } - /** * Print the help messages for the browse command */ diff --git a/activemq-console/src/test/java/org/apache/activemq/console/command/PurgeCommandTest.java b/activemq-console/src/test/java/org/apache/activemq/console/command/PurgeCommandTest.java new file mode 100644 index 0000000000..1779cdbdf7 --- /dev/null +++ b/activemq-console/src/test/java/org/apache/activemq/console/command/PurgeCommandTest.java @@ -0,0 +1,124 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.apache.activemq.console.command; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class PurgeCommandTest { + + private final List datum; + private final String expected; + + /** + * Produces the data for the test. + * + * @return + */ + @Parameters(name = "{index}: convertToSQL92({0})={1}") + public static Collection produceTestData() { + List params = new ArrayList<>(); + // wildcard query enclosed by single quotes must be converted into + // SQL92 LIKE-statement + params.add(toParameterArray( + "(JMSMessageId LIKE '%:10_')", + "JMSMessageId='*:10?'") + ); + + // query parameter containing wildcard characters but not enclosed by + // single quotes must be taken as literal + params.add(toParameterArray( + "(JMSMessageId=*:10?)", + "JMSMessageId=*:10?") + ); + params.add(toParameterArray( + "(JMSMessageId=%:10_)", + "JMSMessageId=%:10_") + ); + + // query parameter not enclosed by single quotes must be taken as literal + params.add(toParameterArray( + "(JMSMessageId=SOME_ID)", + "JMSMessageId=SOME_ID") + ); + + // query parameter not containing wildcard characters but enclosed by + // single quotes must not be converted into a SQL92 LIKE-statement + params.add(toParameterArray( + "(JMSMessageId='SOME_ID')", + "JMSMessageId='SOME_ID'") + ); + params.add(toParameterArray( + "(JMSMessageId='%:10_')", + "JMSMessageId='%:10_'") + ); + + // multiple query parameter must be concatenated by 'AND' + params.add(toParameterArray( + "(JMSMessageId LIKE '%:10_') AND (JMSPriority>5)", + "JMSMessageId='*:10?'", "JMSPriority>5") + ); + params.add(toParameterArray( + "(JMSPriority>5) AND (JMSMessageId LIKE '%:10_')", + "JMSPriority>5", "JMSMessageId='*:10?'") + ); + + // a query which is already in SQL92 syntax should not be altered + params.add(toParameterArray( + "((JMSPriority>5) AND (JMSMessageId LIKE '%:10_'))", + "(JMSPriority>5) AND (JMSMessageId LIKE '%:10_')") + ); + return params; + } + + /** + * Test if the wildcard queries correctly converted into a valid SQL92 + * statement. + */ + @Test + public void testConvertToSQL92() { + System.out.print("testTokens = " + datum); + System.out.println(" output = " + expected); + PurgeCommand pc = new PurgeCommand(); + Assert.assertEquals(expected, pc.convertToSQL92(datum)); + } + + /** + * Convert the passed parameter into an object array which is used for + * the unit tests of method convertToSQL92. + * + * @param datum the tokens which are passed as list to the method + * @param expected the expected value returned by the method + * @return object array with the values used for the unit test + */ + static Object[] toParameterArray(String expected, String... tokens) { + return new Object[]{Arrays.asList(tokens), expected}; + } + + public PurgeCommandTest(List datum, String expected) { + this.datum = datum; + this.expected = expected; + } +}