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 */
017 package org.apache.activemq.console.command;
018
019 import java.util.ArrayList;
020 import java.util.Enumeration;
021 import java.util.HashSet;
022 import java.util.List;
023 import java.util.Properties;
024 import java.util.Set;
025 import java.util.StringTokenizer;
026
027 import org.apache.activemq.console.util.JmxMBeansUtil;
028
029 public 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 }