activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gtu...@apache.org
Subject [1/3] activemq git commit: https://issues.apache.org/jira/browse/AMQ-5724 - fix up mbean object name property clashes and attribute selection. add --invoke flag to invoke simple mbean operations with void or string params, Additional test that verifies h
Date Tue, 16 Jun 2015 14:55:04 GMT
Repository: activemq
Updated Branches:
  refs/heads/master c2310391b -> ffef4dc5f


https://issues.apache.org/jira/browse/AMQ-5724 - fix up mbean object name property clashes
and attribute selection. add --invoke flag to invoke simple mbean operations with void or
string params, Additional test that verifies help suggestions


Project: http://git-wip-us.apache.org/repos/asf/activemq/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq/commit/1787edaf
Tree: http://git-wip-us.apache.org/repos/asf/activemq/tree/1787edaf
Diff: http://git-wip-us.apache.org/repos/asf/activemq/diff/1787edaf

Branch: refs/heads/master
Commit: 1787edaf3e0d44bbce36b0cc22644cfe6f1e661f
Parents: 1b08858
Author: gtully <gary.tully@gmail.com>
Authored: Tue Jun 16 15:03:04 2015 +0100
Committer: gtully <gary.tully@gmail.com>
Committed: Tue Jun 16 15:04:13 2015 +0100

----------------------------------------------------------------------
 .../activemq/console/command/QueryCommand.java  | 113 ++++++++++--
 .../activemq/console/util/JmxMBeansUtil.java    |   6 +-
 .../activemq/console/QueryCommandTest.java      | 183 +++++++++++++++++++
 3 files changed, 288 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/activemq/blob/1787edaf/activemq-console/src/main/java/org/apache/activemq/console/command/QueryCommand.java
----------------------------------------------------------------------
diff --git a/activemq-console/src/main/java/org/apache/activemq/console/command/QueryCommand.java
b/activemq-console/src/main/java/org/apache/activemq/console/command/QueryCommand.java
index bdb6b88..0a5ee17 100644
--- a/activemq-console/src/main/java/org/apache/activemq/console/command/QueryCommand.java
+++ b/activemq-console/src/main/java/org/apache/activemq/console/command/QueryCommand.java
@@ -16,6 +16,7 @@
  */
 package org.apache.activemq.console.command;
 
+import javax.management.ObjectName;
 import org.apache.activemq.console.util.JmxMBeansUtil;
 
 import java.util.*;
@@ -25,12 +26,12 @@ public class QueryCommand extends AbstractJmxCommand {
     private static final Properties PREDEFINED_OBJNAME_QUERY = new Properties();
 
     static {
-        PREDEFINED_OBJNAME_QUERY.setProperty("Broker", "type=Broker,brokerName=%1");
-        PREDEFINED_OBJNAME_QUERY.setProperty("Connection", "type=Broker,connector=clientConnectors,connectionName=%1,*");
-        PREDEFINED_OBJNAME_QUERY.setProperty("Connector", "type=Broker,brokerName=*,connector=clientConnectors,connectorName=%1");
-        PREDEFINED_OBJNAME_QUERY.setProperty("NetworkConnector", "type=Broker,brokerName=%1,connector=networkConnectors,networkConnectorName=*");
-        PREDEFINED_OBJNAME_QUERY.setProperty("Queue", "type=Broker,brokerName=*,destinationType=Queue,destinationName=%1");
-        PREDEFINED_OBJNAME_QUERY.setProperty("Topic", "type=Broker,brokerName=*,destinationType=Topic,destinationName=%1,*");
+        PREDEFINED_OBJNAME_QUERY.setProperty("Broker", "brokerName=%1");
+        PREDEFINED_OBJNAME_QUERY.setProperty("Connection", "connector=clientConnectors,connectionViewType=*,connectionName=%1,*");
+        PREDEFINED_OBJNAME_QUERY.setProperty("Connector", "connector=clientConnectors,connectorName=%1");
+        PREDEFINED_OBJNAME_QUERY.setProperty("NetworkConnector", "connector=networkConnectors,networkConnectorName=%1");
+        PREDEFINED_OBJNAME_QUERY.setProperty("Queue", "destinationType=Queue,destinationName=%1");
+        PREDEFINED_OBJNAME_QUERY.setProperty("Topic", "destinationType=Topic,destinationName=%1");
     };
 
     protected String[] helpFile = new String[] {
@@ -48,6 +49,7 @@ public class QueryCommand extends AbstractJmxCommand {
         "                                  similar to the JMX object name format.",
         "    --view <attr1>,<attr2>,...    Select the specific attribute of the
object to view.",
         "                                  By default all attributes will be displayed.",
+        "    --invoke <operation>          Specify the operation to invoke on matching
objects",
         "    --jmxurl <url>                Set the JMX URL to connect to.",
         "    --pid <pid>                   Set the pid to connect to (only on Sun JVM).",
           
         "    --jmxuser <user>              Set the JMX user used for authenticating.",
@@ -79,18 +81,23 @@ public class QueryCommand extends AbstractJmxCommand {
         "        - Print all attributes of all topics except those that has a name that begins",
         "          with \"ActiveMQ.Advisory\".",
         "",
-        "    query --objname Type=*Connect*,BrokerName=local* -xQNetworkConnector=*",
+        "    query --objname type=Broker,brokerName=*,connector=clientConnectors,connectorName=*
-xQNetworkConnector=*",
         "        - Print all attributes of all connectors, connections excluding network
connectors",
         "          that belongs to the broker that begins with local.", 
         "", 
         "    query -QQueue=* -xQQueue=????", 
         "        - Print all attributes of all queues except those that are 4 letters long.",
         "",
+        "    query -QQueue=* --invoke pause",
+        "        - Pause all queues.",
+        "",
+
     };
 
     private final List<String> queryAddObjects = new ArrayList<String>(10);
     private final List<String> querySubObjects = new ArrayList<String>(10);
     private final Set queryViews = new LinkedHashSet();
+    private final List<String> opAndParams = new ArrayList<String>(10);
 
     @Override
     public String getName() {
@@ -111,21 +118,55 @@ public class QueryCommand extends AbstractJmxCommand {
     protected void runTask(List<String> tokens) throws Exception {
         try {
             // Query for the mbeans to add
-            Map<String,List> addMBeans = JmxMBeansUtil.queryMBeansAsMap(createJmxConnection(),
queryAddObjects, queryViews);
+            Map<Object,List> addMBeans = JmxMBeansUtil.queryMBeansAsMap(createJmxConnection(),
queryAddObjects, queryViews);
             // Query for the mbeans to sub
             if (querySubObjects.size() > 0) {
-                Map<String,List> subMBeans = JmxMBeansUtil.queryMBeansAsMap(createJmxConnection(),
querySubObjects, queryViews);
+                Map<Object,List> subMBeans = JmxMBeansUtil.queryMBeansAsMap(createJmxConnection(),
querySubObjects, queryViews);
                 addMBeans.keySet().removeAll(subMBeans.keySet());
             }
-            context.printMBean(JmxMBeansUtil.filterMBeansView(new ArrayList(addMBeans.values()),
queryViews));
+
+            if (opAndParams.isEmpty()) {
+                context.printMBean(JmxMBeansUtil.filterMBeansView(new ArrayList(addMBeans.values()),
queryViews));
+            } else {
+                context.print(doInvoke(addMBeans.keySet(), opAndParams));
+            }
         } catch (Exception e) {
             context.printException(new RuntimeException("Failed to execute query task. Reason:
" + e));
             throw new Exception(e);
         }
     }
 
+    private Collection doInvoke(Set<Object> mBeans, List<String> opAndParams)
throws Exception {
+        LinkedList<String> results = new LinkedList<>();
+        for (Object objectName : mBeans) {
+            Object result = createJmxConnection().invoke((ObjectName) objectName, opAndParams.get(0),
+                    params(opAndParams), stringSignature(opAndParams));
+            results.add("[" + objectName + "]." + opAndParams.get(0) + " = " + result);
+        }
+        return results;
+    }
+
+    private Object[] params(List<String> opAndParams) {
+        if (opAndParams.size() > 1) {
+            return opAndParams.subList(1, opAndParams.size()).toArray();
+        } else {
+            return null;
+        }
+    }
+
+    private String[] stringSignature(List<String> opAndParams) {
+        if (opAndParams.size() > 1) {
+            String[] sig = new String[opAndParams.size() - 1];
+            Arrays.fill(sig, String.class.getName());
+            return sig;
+        } else {
+            return null;
+        }
+    }
+
+
     /**
-     * Handle the -Q, -xQ, --objname, --xobjname, --view options.
+     * Handle the -Q, -xQ, --objname, --xobjname, --view --invoke options.
      * 
      * @param token - option token to handle
      * @param tokens - succeeding command arguments
@@ -153,6 +194,7 @@ public class QueryCommand extends AbstractJmxCommand {
             while (queryTokens.hasMoreTokens()) {
                 queryAddObjects.add(queryTokens.nextToken());
             }
+            normaliseObjectName(queryAddObjects);
         } else if (token.startsWith("-xQ")) {
             // If token is a substractive predefined query define option
             String key = token.substring(3);
@@ -174,6 +216,7 @@ public class QueryCommand extends AbstractJmxCommand {
             while (queryTokens.hasMoreTokens()) {
                 querySubObjects.add(queryTokens.nextToken());
             }
+            normaliseObjectName(querySubObjects);
         } else if (token.startsWith("--objname")) {
             // If token is an additive object name query option
 
@@ -216,12 +259,60 @@ public class QueryCommand extends AbstractJmxCommand {
             while (viewTokens.hasMoreElements()) {
                 queryViews.add(viewTokens.nextElement());
             }
+        } else if (token.startsWith("--invoke")) {
+
+            if (tokens.isEmpty() || ((String)tokens.get(0)).startsWith("-")) {
+                context.printException(new IllegalArgumentException("operation to invoke
is not specified"));
+                return;
+            }
+
+            // add op and params
+            Enumeration viewTokens = new StringTokenizer((String)tokens.remove(0), COMMAND_OPTION_DELIMETER);
+            while (viewTokens.hasMoreElements()) {
+                opAndParams.add((String)viewTokens.nextElement());
+            }
+
         } else {
             // Let super class handle unknown option
             super.handleOption(token, tokens);
         }
     }
 
+    private void normaliseObjectName(List<String> queryAddObjects) {
+        ensurePresent(queryAddObjects, "type", "Broker");
+        ensurePresent(queryAddObjects, "brokerName", "*");
+
+        // -QQueue && -QTopic
+        ensureUnique(queryAddObjects, "destinationType", "?????");
+        ensureUnique(queryAddObjects, "destinationName", "*");
+    }
+
+    private void ensurePresent(List<String> queryAddObjects, String id, String wildcard)
{
+        List<String> matches = findMatchingKeys(queryAddObjects, id);
+        if (matches.size() == 0) {
+            queryAddObjects.add(id + "=" + wildcard);
+        }
+    }
+
+    private void ensureUnique(List<String> queryAddObjects, String id, String wildcard)
{
+        List<String> matches = findMatchingKeys(queryAddObjects, id);
+        if (matches.size() > 1) {
+            queryAddObjects.removeAll(matches);
+            queryAddObjects.add(id + "=" + wildcard);
+        }
+    }
+
+    private List<String> findMatchingKeys(List<String> queryAddObjects, String
id) {
+        List<String> matches = new LinkedList<>();
+        for (String prop : queryAddObjects) {
+            String[] keyValue = prop.split("=");
+            if (keyValue.length == 2 && keyValue[0].equals(id)) {
+                matches.add(prop);
+            }
+        }
+        return matches;
+    }
+
     /**
      * Print the help messages for the browse command
      */

http://git-wip-us.apache.org/repos/asf/activemq/blob/1787edaf/activemq-console/src/main/java/org/apache/activemq/console/util/JmxMBeansUtil.java
----------------------------------------------------------------------
diff --git a/activemq-console/src/main/java/org/apache/activemq/console/util/JmxMBeansUtil.java
b/activemq-console/src/main/java/org/apache/activemq/console/util/JmxMBeansUtil.java
index baa40be..24fe46b 100644
--- a/activemq-console/src/main/java/org/apache/activemq/console/util/JmxMBeansUtil.java
+++ b/activemq-console/src/main/java/org/apache/activemq/console/util/JmxMBeansUtil.java
@@ -57,12 +57,12 @@ public final class JmxMBeansUtil {
         }
     }
 
-    public static Map<String, List> queryMBeansAsMap(MBeanServerConnection jmxConnection,
List queryList, Set attributes) throws Exception {
-        Map answer = new HashMap<String, List>();
+    public static Map<Object, List> queryMBeansAsMap(MBeanServerConnection jmxConnection,
List queryList, Set attributes) throws Exception {
+        Map<Object, List> answer = new HashMap<Object, List>();
         List<AttributeList> mbeans = queryMBeans(jmxConnection, queryList, attributes);
         for (AttributeList mbean : mbeans) {
             for(Attribute attr: mbean.asList()) {
-                if (attr.getName().equals("Name")) {
+                if (attr.getName().equals(MBeansAttributeQueryFilter.KEY_OBJECT_NAME_ATTRIBUTE))
{
                     answer.put(attr.getValue(), mbean);
                 }
             }

http://git-wip-us.apache.org/repos/asf/activemq/blob/1787edaf/activemq-console/src/test/java/org/apache/activemq/console/QueryCommandTest.java
----------------------------------------------------------------------
diff --git a/activemq-console/src/test/java/org/apache/activemq/console/QueryCommandTest.java
b/activemq-console/src/test/java/org/apache/activemq/console/QueryCommandTest.java
new file mode 100644
index 0000000..b6a154e
--- /dev/null
+++ b/activemq-console/src/test/java/org/apache/activemq/console/QueryCommandTest.java
@@ -0,0 +1,183 @@
+/**
+ * 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;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Arrays;
+import java.util.LinkedList;
+import javax.jms.Connection;
+import org.apache.activemq.ActiveMQConnectionFactory;
+import org.apache.activemq.broker.BrokerService;
+import org.apache.activemq.command.ActiveMQDestination;
+import org.apache.activemq.command.ActiveMQQueue;
+import org.apache.activemq.command.ActiveMQTopic;
+import org.apache.activemq.console.command.QueryCommand;
+import org.apache.activemq.console.formatter.CommandShellOutputFormatter;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.LoggerFactory;
+
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class QueryCommandTest {
+    private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(QueryCommandTest.class);
+
+    final String CONNECTOR_NAME="tcp-openWire";
+    final String CLIENT_ID="some-id";
+
+    BrokerService brokerService;
+
+
+    @Before
+    public void createBroker() throws Exception {
+        brokerService = new BrokerService();
+        brokerService.getManagementContext().setCreateConnector(false);
+        brokerService.setPersistent(false);
+        brokerService.setDestinations(new ActiveMQDestination[]{new ActiveMQQueue("Q1"),
new ActiveMQQueue("Q2"), new ActiveMQTopic("T1")});
+        brokerService.addConnector("tcp://0.0.0.0:0").setName(CONNECTOR_NAME);
+        brokerService.start();
+    }
+
+    @After
+    public void stopBroker() throws Exception {
+        if (brokerService != null) {
+            brokerService.stop();
+        }
+    }
+
+    @Test
+    public void tryQuery() throws Exception {
+
+        String result = executeQuery("-QQueue=* --view destinationName,EnqueueCount,DequeueCount");
+        assertTrue("Output valid", result.contains("Q1"));
+        assertTrue("Output valid", result.contains("Q2"));
+        assertFalse("Output valid", result.contains("T1"));
+
+        result = executeQuery("-QQueue=Q2 --view destinationName,QueueSize");
+        assertTrue("size present", result.contains("QueueSize"));
+        assertTrue("Output valid", result.contains("Q2"));
+        assertFalse("Output valid", result.contains("Q1"));
+        assertFalse("Output valid", result.contains("T1"));
+
+        result = executeQuery("-QQueue=* -xQQueue=Q1 --view destinationName,QueueSize");
+        assertTrue("size present", result.contains("QueueSize"));
+        assertTrue("q2", result.contains("Q2"));
+        assertFalse("!q1: " + result, result.contains("Q1"));
+        assertFalse("!t1", result.contains("T1"));
+
+        result = executeQuery("-QTopic=* -QQueue=* --view destinationName");
+        assertTrue("got Q1", result.contains("Q1"));
+        assertTrue("got Q2", result.contains("Q2"));
+        assertTrue("got T1", result.contains("T1"));
+
+        result = executeQuery("-QQueue=*");
+        assertTrue("got Q1", result.contains("Q1"));
+        assertTrue("got Q2", result.contains("Q2"));
+        assertFalse("!T1", result.contains("T1"));
+
+        result = executeQuery("-QBroker=*");
+        assertTrue("got localhost", result.contains("localhost"));
+
+        result = executeQuery("--view destinationName");
+        // all mbeans with a destinationName attribute
+        assertTrue("got Q1", result.contains("Q1"));
+        assertTrue("got Q2", result.contains("Q2"));
+        assertTrue("got T1", result.contains("T1"));
+
+        result = executeQuery("--objname type=Broker,brokerName=*,destinationType=Queue,destinationName=*");
+        assertTrue("got Q1", result.contains("Q1"));
+        assertTrue("got Q2", result.contains("Q2"));
+        assertFalse("!T1", result.contains("T1"));
+
+        result = executeQuery("--objname type=Broker,brokerName=*,destinationType=*,destinationName=*
--xobjname type=Broker,brokerName=*,destinationType=Queue,destinationName=Q1");
+        assertFalse("!Q1", result.contains("Q1"));
+        assertTrue("got Q2", result.contains("Q2"));
+        assertTrue("T1", result.contains("T1"));
+
+    }
+
+    @Test
+    public void testConnection() throws Exception {
+
+        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerService.getTransportConnectors().get(0).getPublishableConnectURI());
+        Connection connection = connectionFactory.createConnection();
+        connection.setClientID(CLIENT_ID);
+        connection.start();
+
+        String result = executeQuery("-QConnection=* --view ClientId");
+        assertTrue("got client id", result.contains(CLIENT_ID));
+
+        result = executeQuery("--objname type=Broker,brokerName=*,connector=clientConnectors,connectorName=*
-xQNetworkConnector=*");
+        assertTrue("got named", result.contains(CONNECTOR_NAME));
+
+        result = executeQuery("-QConnector=*");
+        assertTrue("got named", result.contains(CONNECTOR_NAME));
+    }
+
+
+    @Test
+    public void testInvoke() throws Exception {
+
+        String result = executeQuery("-QQueue=Q* --view Paused");
+        assertTrue("got pause status", result.contains("Paused = false"));
+
+        result = executeQuery("-QQueue=* --invoke pause");
+        LOG.info("result of invoke: " + result);
+        assertTrue("invoked", result.contains("Q1"));
+        assertTrue("invoked", result.contains("Q2"));
+
+        result = executeQuery("-QQueue=Q2 --view Paused");
+        assertTrue("got pause status", result.contains("Paused = true"));
+
+        result = executeQuery("-QQueue=Q2 --invoke resume");
+        LOG.info("result of invoke: " + result);
+        assertTrue("invoked", result.contains("Q2"));
+
+        result = executeQuery("-QQueue=Q2 --view Paused");
+        assertTrue("pause status", result.contains("Paused = false"));
+
+        result = executeQuery("-QQueue=Q1 --view Paused");
+        assertTrue("pause status", result.contains("Paused = true"));
+
+        // op with string param
+        result = executeQuery("-QQueue=Q2 --invoke sendTextMessage,hi");
+        LOG.info("result of invoke: " + result);
+        assertTrue("invoked", result.contains("Q2"));
+
+        result = executeQuery("-QQueue=Q2 --view EnqueueCount");
+        assertTrue("enqueueCount", result.contains("EnqueueCount = 1"));
+    }
+
+    private String executeQuery(String query) throws Exception {
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);
+        CommandContext context = new CommandContext();
+        context.setFormatter(new CommandShellOutputFormatter(byteArrayOutputStream));
+
+        QueryCommand queryCommand = new QueryCommand();
+        queryCommand.setJmxUseLocal(true);
+        queryCommand.setCommandContext(context);
+
+        LinkedList<String> args = new LinkedList<>();
+        args.addAll(Arrays.asList(query.split(" ")));
+        queryCommand.execute(args);
+
+        return byteArrayOutputStream.toString();
+    }
+}


Mime
View raw message