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