001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.activemq.console.command; 018 019import org.apache.activemq.console.util.JmxMBeansUtil; 020 021import java.util.*; 022 023public class QueryCommand extends AbstractJmxCommand { 024 // Predefined type=identifier query 025 private static final Properties PREDEFINED_OBJNAME_QUERY = new Properties(); 026 027 static { 028 PREDEFINED_OBJNAME_QUERY.setProperty("Broker", "type=Broker,brokerName=%1"); 029 PREDEFINED_OBJNAME_QUERY.setProperty("Connection", "type=Broker,connector=clientConnectors,connectionName=%1,*"); 030 PREDEFINED_OBJNAME_QUERY.setProperty("Connector", "type=Broker,brokerName=*,connector=clientConnectors,connectorName=%1"); 031 PREDEFINED_OBJNAME_QUERY.setProperty("NetworkConnector", "type=Broker,brokerName=%1,connector=networkConnectors,networkConnectorName=*"); 032 PREDEFINED_OBJNAME_QUERY.setProperty("Queue", "type=Broker,brokerName=*,destinationType=Queue,destinationName=%1"); 033 PREDEFINED_OBJNAME_QUERY.setProperty("Topic", "type=Broker,brokerName=*,destinationType=Topic,destinationName=%1,*"); 034 }; 035 036 protected String[] helpFile = new String[] { 037 "Task Usage: Main query [query-options]", 038 "Description: Display selected broker component's attributes and statistics.", 039 "", 040 "Query Options:", 041 " -Q<type>=<name> Add to the search list the specific object type matched", 042 " by the defined object identifier.", 043 " -xQ<type>=<name> Remove from the search list the specific object type", 044 " matched by the object identifier.", 045 " --objname <query> Add to the search list objects matched by the query similar", 046 " to the JMX object name format.", 047 " --xobjname <query> Remove from the search list objects matched by the query", 048 " similar to the JMX object name format.", 049 " --view <attr1>,<attr2>,... Select the specific attribute of the object to view.", 050 " By default all attributes will be displayed.", 051 " --jmxurl <url> Set the JMX URL to connect to.", 052 " --pid <pid> Set the pid to connect to (only on Sun JVM).", 053 " --jmxuser <user> Set the JMX user used for authenticating.", 054 " --jmxpassword <password> Set the JMX password used for authenticating.", 055 " --jmxlocal Use the local JMX server instead of a remote one.", 056 " --version Display the version information.", 057 " -h,-?,--help Display the query broker help information.", 058 "", "Examples:", 059 " query", 060 " - Print all the attributes of all registered objects queues, topics, connections, etc).", 061 "", 062 " query -QQueue=TEST.FOO", 063 " - Print all the attributes of the queue with destination name TEST.FOO.", 064 "", 065 " query -QTopic=*", 066 " - Print all the attributes of all registered topics.", 067 "", 068 " query --view EnqueueCount,DequeueCount", 069 " - Print the attributes EnqueueCount and DequeueCount of all registered objects.", 070 "", 071 " query -QTopic=* --view EnqueueCount,DequeueCount", 072 " - Print the attributes EnqueueCount and DequeueCount of all registered topics.", 073 "", 074 " query -QTopic=* -QQueue=* --view EnqueueCount,DequeueCount", 075 " - Print the attributes EnqueueCount and DequeueCount of all registered topics and", 076 " queues.", 077 "", 078 " query -QTopic=* -xQTopic=ActiveMQ.Advisory.*", 079 " - Print all attributes of all topics except those that has a name that begins", 080 " with \"ActiveMQ.Advisory\".", 081 "", 082 " query --objname Type=*Connect*,BrokerName=local* -xQNetworkConnector=*", 083 " - Print all attributes of all connectors, connections excluding network connectors", 084 " that belongs to the broker that begins with local.", 085 "", 086 " query -QQueue=* -xQQueue=????", 087 " - Print all attributes of all queues except those that are 4 letters long.", 088 "", 089 }; 090 091 private final List<String> queryAddObjects = new ArrayList<String>(10); 092 private final List<String> querySubObjects = new ArrayList<String>(10); 093 private final Set queryViews = new LinkedHashSet(); 094 095 @Override 096 public String getName() { 097 return "query"; 098 } 099 100 @Override 101 public String getOneLineDescription() { 102 return "Display selected broker component's attributes and statistics."; 103 } 104 105 /** 106 * Queries the mbeans registered in the specified JMX context 107 * 108 * @param tokens - command arguments 109 * @throws Exception 110 */ 111 protected void runTask(List<String> tokens) throws Exception { 112 try { 113 // Query for the mbeans to add 114 Map<String,List> addMBeans = JmxMBeansUtil.queryMBeansAsMap(createJmxConnection(), queryAddObjects, queryViews); 115 // Query for the mbeans to sub 116 if (querySubObjects.size() > 0) { 117 Map<String,List> subMBeans = JmxMBeansUtil.queryMBeansAsMap(createJmxConnection(), querySubObjects, queryViews); 118 addMBeans.keySet().removeAll(subMBeans.keySet()); 119 } 120 context.printMBean(JmxMBeansUtil.filterMBeansView(new ArrayList(addMBeans.values()), queryViews)); 121 } catch (Exception e) { 122 context.printException(new RuntimeException("Failed to execute query task. Reason: " + e)); 123 throw new Exception(e); 124 } 125 } 126 127 /** 128 * Handle the -Q, -xQ, --objname, --xobjname, --view options. 129 * 130 * @param token - option token to handle 131 * @param tokens - succeeding command arguments 132 * @throws Exception 133 */ 134 protected void handleOption(String token, List<String> tokens) throws Exception { 135 // If token is a additive predefined query define option 136 if (token.startsWith("-Q")) { 137 String key = token.substring(2); 138 String value = ""; 139 int pos = key.indexOf("="); 140 if (pos >= 0) { 141 value = key.substring(pos + 1); 142 key = key.substring(0, pos); 143 } 144 145 // If additive query 146 String predefQuery = PREDEFINED_OBJNAME_QUERY.getProperty(key); 147 if (predefQuery == null) { 148 context.printException(new IllegalArgumentException("Unknown query object type: " + key)); 149 return; 150 } 151 String queryStr = JmxMBeansUtil.createQueryString(predefQuery, value); 152 StringTokenizer queryTokens = new StringTokenizer(queryStr, COMMAND_OPTION_DELIMETER); 153 while (queryTokens.hasMoreTokens()) { 154 queryAddObjects.add(queryTokens.nextToken()); 155 } 156 } else if (token.startsWith("-xQ")) { 157 // If token is a substractive predefined query define option 158 String key = token.substring(3); 159 String value = ""; 160 int pos = key.indexOf("="); 161 if (pos >= 0) { 162 value = key.substring(pos + 1); 163 key = key.substring(0, pos); 164 } 165 166 // If subtractive query 167 String predefQuery = PREDEFINED_OBJNAME_QUERY.getProperty(key); 168 if (predefQuery == null) { 169 context.printException(new IllegalArgumentException("Unknown query object type: " + key)); 170 return; 171 } 172 String queryStr = JmxMBeansUtil.createQueryString(predefQuery, value); 173 StringTokenizer queryTokens = new StringTokenizer(queryStr, COMMAND_OPTION_DELIMETER); 174 while (queryTokens.hasMoreTokens()) { 175 querySubObjects.add(queryTokens.nextToken()); 176 } 177 } else if (token.startsWith("--objname")) { 178 // If token is an additive object name query option 179 180 // If no object name query is specified, or next token is a new 181 // option 182 if (tokens.isEmpty() || ((String)tokens.get(0)).startsWith("-")) { 183 context.printException(new IllegalArgumentException("Object name query not specified")); 184 return; 185 } 186 187 StringTokenizer queryTokens = new StringTokenizer((String)tokens.remove(0), COMMAND_OPTION_DELIMETER); 188 while (queryTokens.hasMoreTokens()) { 189 queryAddObjects.add(queryTokens.nextToken()); 190 } 191 } else if (token.startsWith("--xobjname")) { 192 // If token is a substractive object name query option 193 194 // If no object name query is specified, or next token is a new 195 // option 196 if (tokens.isEmpty() || ((String)tokens.get(0)).startsWith("-")) { 197 context.printException(new IllegalArgumentException("Object name query not specified")); 198 return; 199 } 200 201 StringTokenizer queryTokens = new StringTokenizer((String)tokens.remove(0), COMMAND_OPTION_DELIMETER); 202 while (queryTokens.hasMoreTokens()) { 203 querySubObjects.add(queryTokens.nextToken()); 204 } 205 } else if (token.startsWith("--view")) { 206 // If token is a view option 207 208 // If no view specified, or next token is a new option 209 if (tokens.isEmpty() || ((String)tokens.get(0)).startsWith("-")) { 210 context.printException(new IllegalArgumentException("Attributes to view not specified")); 211 return; 212 } 213 214 // Add the attributes to view 215 Enumeration viewTokens = new StringTokenizer((String)tokens.remove(0), COMMAND_OPTION_DELIMETER); 216 while (viewTokens.hasMoreElements()) { 217 queryViews.add(viewTokens.nextElement()); 218 } 219 } else { 220 // Let super class handle unknown option 221 super.handleOption(token, tokens); 222 } 223 } 224 225 /** 226 * Print the help messages for the browse command 227 */ 228 protected void printHelp() { 229 context.printHelp(helpFile); 230 } 231 232}