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
018 package org.apache.geronimo.console.jmxmanager;
019
020 import java.net.URI;
021 import java.net.URL;
022 import java.text.DateFormat;
023 import java.util.ArrayList;
024 import java.util.Arrays;
025 import java.util.Collection;
026 import java.util.Collections;
027 import java.util.Date;
028 import java.util.HashMap;
029 import java.util.Iterator;
030 import java.util.Map;
031 import java.util.Set;
032 import java.util.TreeMap;
033
034 import javax.management.ObjectName;
035 import javax.management.j2ee.statistics.BoundaryStatistic;
036 import javax.management.j2ee.statistics.BoundedRangeStatistic;
037 import javax.management.j2ee.statistics.CountStatistic;
038 import javax.management.j2ee.statistics.RangeStatistic;
039 import javax.management.j2ee.statistics.Statistic;
040 import javax.management.j2ee.statistics.Stats;
041 import javax.management.j2ee.statistics.TimeStatistic;
042
043 import org.apache.geronimo.gbean.AbstractName;
044 import org.apache.geronimo.gbean.AbstractNameQuery;
045 import org.apache.geronimo.gbean.GAttributeInfo;
046 import org.apache.geronimo.gbean.GBeanInfo;
047 import org.apache.geronimo.gbean.GOperationInfo;
048 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
049 import org.apache.geronimo.kernel.GBeanNotFoundException;
050 import org.apache.geronimo.kernel.Kernel;
051 import org.apache.geronimo.kernel.KernelRegistry;
052
053 /**
054 * The JMX manager helper
055 */
056 public class JMXManagerHelper {
057 /** Used to return all MBeans */
058 private static final String ALL_MBEANS = "AllMBeans";
059 private static final String SERVICEMODULE_KEY = "ServiceModule";
060 private static final String GBEANINFO_ATTRIB = "GBeanInfo";
061 private static final String STATSPROVIDER_ATTRIB = "statisticsProvider";
062 private static final String STATS_ATTRIB = "stats";
063
064
065 private final Kernel kernel;
066
067 /**
068 * Construct an JMX manager helper (default)
069 */
070 public JMXManagerHelper() {
071 kernel = KernelRegistry.getSingleKernel();
072 }
073
074 /**
075 * List MBeans using a domain
076 */
077 public Collection listByDomain(String domain) {
078 Collection result = new ArrayList();
079 if ((domain == null) || (domain.trim().length() == 0)) {
080 return result;
081 }
082
083 return listByPattern(domain + ":*");
084 }
085
086 /**
087 * List MBeans containing a substring in its object name
088 */
089 public Collection listBySubstring(String substring) {
090 Collection result = new ArrayList();
091 if ((substring == null) || (substring.trim().length() == 0)) {
092 return result;
093 }
094
095 Collection abstractNames = getAbstractNames(substring);
096 for (Iterator it = abstractNames.iterator(); it.hasNext();) {
097 AbstractName aname = (AbstractName) it.next();
098 ObjectName oname = aname.getObjectName();
099 String[] pair = { aname.toString(), oname.toString() };
100 result.add(pair);
101 }
102
103 return result;
104 }
105
106 /**
107 * List MBeans using a pattern (ObjectName)
108 */
109 public Collection listByPattern(String pattern) {
110 Collection result = new ArrayList();
111 if ((pattern == null) || (pattern.trim().length() == 0)) {
112 return result;
113 }
114
115 try {
116 // TODO: Use AbstractNameQuery
117 // Uses Object names for query pattern to support
118 // domain searches. Can't find a way to do it using
119 // AbstractNameQuery.
120 Map abstractNames = getAbstractNames();
121 ObjectName onamePattern = new ObjectName(pattern);
122 Set beans = kernel.listGBeans(onamePattern);
123 for (Iterator it = beans.iterator(); it.hasNext();) {
124 ObjectName oname = (ObjectName) it.next();
125 AbstractName aname = (AbstractName) abstractNames.get(oname);
126 String[] pair = { aname.toString(), oname.toString() };
127 result.add(pair);
128 }
129 } catch (Exception e) {
130 // Malformed object name, just return what you have
131 }
132
133 return result;
134 }
135
136 /**
137 * List MBeans using J2EE type
138 */
139 public Collection listByJ2EEType(String type) {
140 Collection result = new ArrayList();
141 Map m = null;
142
143 if ((type == null) || (type.trim().length() == 0)) {
144 return result;
145 } else {
146 if (ALL_MBEANS.equalsIgnoreCase(type)) {
147 m = Collections.EMPTY_MAP;
148 } else {
149 m = Collections.singletonMap(NameFactory.J2EE_TYPE, type);
150 }
151 }
152
153 AbstractNameQuery query = new AbstractNameQuery(null, m,
154 Collections.EMPTY_SET);
155 Set beans = kernel.listGBeans(query);
156 for (Iterator it = beans.iterator(); it.hasNext();) {
157 AbstractName abstractName = (AbstractName) it.next();
158 ObjectName objectName = abstractName.getObjectName();
159 String[] pair = { abstractName.toString(), objectName.toString() };
160 result.add(pair);
161 }
162
163 return result;
164 }
165
166 /**
167 * Return all service modules
168 */
169 public Collection getServiceModules() {
170 Map svcModules = new TreeMap();
171 Collection svcModuleMBeans = getAbstractNames(SERVICEMODULE_KEY + '=');
172 for (Iterator it = svcModuleMBeans.iterator(); it.hasNext();) {
173 AbstractName aname = (AbstractName) it.next();
174 String svcModule = aname.getNameProperty(SERVICEMODULE_KEY);
175 if (!svcModules.containsKey(svcModule)) {
176 svcModules.put(svcModule, null);
177 }
178 }
179
180 return svcModules.keySet();
181 }
182
183 /**
184 * Return abstract names containing a substring
185 */
186 private Collection getAbstractNames(String substring) {
187 Collection result = new ArrayList();
188 if ((substring == null) || (substring.trim().length() == 0)) {
189 return result;
190 }
191
192 Map abstractNames = getAbstractNames();
193 for (Iterator it = abstractNames.keySet().iterator(); it.hasNext();) {
194 ObjectName oname = (ObjectName) it.next();
195 if (oname.toString().indexOf(substring) > 0) {
196 AbstractName aname = (AbstractName) abstractNames.get(oname);
197 result.add(aname);
198 }
199 }
200
201 return result;
202 }
203
204 /**
205 * Return all abstract names as a map
206 */
207 private Map getAbstractNames() {
208 Map abstractNames = new HashMap();
209 // Create Map (Key = ObjectName, Value = AbstractName)
210 AbstractNameQuery query = new AbstractNameQuery(null,
211 Collections.EMPTY_MAP, Collections.EMPTY_SET);
212 Set allBeans = kernel.listGBeans(query);
213 for (Iterator it = allBeans.iterator(); it.hasNext();) {
214 AbstractName abstractName = (AbstractName) it.next();
215 ObjectName objectName = abstractName.getObjectName();
216 abstractNames.put(objectName, abstractName);
217 }
218
219 return abstractNames;
220 }
221
222 /**
223 * Return MBean attributes
224 */
225 public Collection getAttributes(String abstractName) {
226 Map attributes = new TreeMap();
227 try {
228 AbstractName aname = new AbstractName(URI.create(abstractName));
229 GBeanInfo info = kernel.getGBeanInfo(aname);
230 Set attribs = info.getAttributes();
231 for (Iterator i = attribs.iterator(); i.hasNext();) {
232 GAttributeInfo attribInfo = (GAttributeInfo) i.next();
233 // Don't include 'GBeanInfo' attributes
234 String attribName = attribInfo.getName();
235 if (!GBEANINFO_ATTRIB.equals(attribName)) {
236 Map attribInfoMap = getAttribInfoAsMap(aname, attribInfo);
237 attributes.put(attribName, attribInfoMap);
238 }
239 }
240 } catch (GBeanNotFoundException e) {
241 // GBean not found, just ignore
242 }
243
244 return attributes.values();
245 }
246
247 /**
248 * Return attribute info as map
249 */
250 private Map getAttribInfoAsMap(AbstractName abstractName,
251 GAttributeInfo attribInfo) {
252 Map map = new TreeMap();
253 String attribName = attribInfo.getName();
254 map.put("name", attribName);
255 map.put("getterName", attribInfo.getGetterName());
256 map.put("setterName", attribInfo.getSetterName());
257 map.put("type", attribInfo.getType());
258 map.put("manageable", String.valueOf(attribInfo.isManageable()));
259 map.put("persistent", String.valueOf(attribInfo.isPersistent()));
260 map.put("readable", String.valueOf(attribInfo.isReadable()));
261 map.put("writable", String.valueOf(attribInfo.isWritable()));
262 if (attribInfo.isReadable()) {
263 String attribValue = "";
264 try {
265 Object value = kernel.getAttribute(abstractName, attribName);
266 if (value != null) {
267 if (value instanceof String[]) {
268 attribValue = Arrays.asList((String[]) value)
269 .toString();
270 } else {
271 attribValue = value.toString();
272 }
273 }
274 } catch (Exception e) {
275 // GBean or attribute not found, just ignore
276 attribValue = "** EXCEPTION: " + e;
277 }
278 map.put("value", attribValue);
279 }
280 return map;
281 }
282
283 /**
284 * Return MBean operations
285 */
286 public Collection getOperations(String abstractName) {
287 Map operations = new TreeMap();
288 try {
289 AbstractName aname = new AbstractName(URI.create(abstractName));
290 GBeanInfo info = kernel.getGBeanInfo(aname);
291 Set opers = info.getOperations();
292 for (Iterator i = opers.iterator(); i.hasNext();) {
293 GOperationInfo operInfo = (GOperationInfo) i.next();
294 Map operInfoMap = getOperInfoAsMap(operInfo);
295 String operName = (String) operInfoMap.get("name");
296 operations.put(operName, operInfoMap);
297 }
298 } catch (Exception e) {
299 // GBean not found, just ignore
300 }
301
302 return operations.values();
303 }
304
305 /**
306 * Return operation info as map
307 */
308 private Map getOperInfoAsMap(GOperationInfo operInfo) {
309 Map map = new TreeMap();
310 map.put("methodName", operInfo.getMethodName());
311 map.put("name", operInfo.getName());
312 map.put("parameterList", operInfo.getParameterList());
313 return map;
314 }
315
316 /**
317 * Return MBean basic info
318 */
319 public Collection getMBeanInfo(String abstractName) {
320 Collection info = new ArrayList();
321 try {
322 AbstractName aname = new AbstractName(URI.create(abstractName));
323 info.add(new String[] { "abstractName", aname.toString() });
324 ObjectName oname = aname.getObjectName();
325 info.add(new String[] { "objectName", oname.toString() });
326 GBeanInfo beanInfo = kernel.getGBeanInfo(aname);
327 String className = beanInfo.getClassName();
328 info.add(new String[] { "className", className });
329 String domain = oname.getDomain();
330 info.add(new String[] { "domain", domain });
331 String j2eeType = beanInfo.getJ2eeType();
332 info.add(new String[] { "j2eeType", j2eeType });
333 // String sourceClass = beanInfo.getSourceClass();
334 // info.add(new String[] { "sourceClass", sourceClass });
335 } catch (Exception e) {
336 // GBean not found, just ignore
337 }
338
339 return info;
340 }
341
342 /**
343 * Return all MBeans that provide stats
344 */
345 public Collection getStatsProvidersMBeans() {
346 Collection result = new ArrayList();
347
348 Object[] allMBeans = listByPattern("*:*").toArray();
349 for (int i = 0; i < allMBeans.length; i++) {
350 try {
351 String[] mbean = (String[]) allMBeans[i];
352 AbstractName abstractName = new AbstractName(URI
353 .create(mbean[0]));
354 Boolean statisticsProvider = (Boolean) kernel.getAttribute(
355 abstractName, "statisticsProvider");
356 if (Boolean.TRUE.equals(statisticsProvider)) {
357 result.add(mbean);
358 }
359 } catch (Exception e) {
360 // ignore
361 }
362 }
363
364 return result;
365 }
366
367 /**
368 * Return MBean stats
369 */
370 public Collection getMBeanStats(String abstractName) {
371 Map mbeanStats = new TreeMap();
372 try {
373 AbstractName aname = new AbstractName(URI.create(abstractName));
374 Boolean statisticsProvider = (Boolean) kernel.getAttribute(aname,
375 STATSPROVIDER_ATTRIB);
376 Stats stats = (Stats) kernel.getAttribute(aname, STATS_ATTRIB);
377 if (statisticsProvider.booleanValue() == true && (stats != null)) {
378 String[] statisticNames = stats.getStatisticNames();
379 for (int i = 0; i < statisticNames.length; i++) {
380 Statistic statistic = stats.getStatistic(statisticNames[i]);
381
382 Collection mbeanStat = new ArrayList();
383 String name = statistic.getName();
384 mbeanStat.add(new String[] { "Name", name });
385 String className = statistic.getClass().getName();
386 // mbeanStat.add(new String[] { "Type", className });
387 mbeanStat.add(new String[] { "Description",
388 statistic.getDescription() });
389 mbeanStat.add(new String[] { "Unit", statistic.getUnit() });
390 Date startTime = new Date(statistic.getStartTime());
391 mbeanStat.add(new String[] { "Start Time",
392 startTime.toString() });
393 Date lastSampleTime = new Date(statistic
394 .getLastSampleTime());
395 mbeanStat.add(new String[] { "Last Sample Time",
396 lastSampleTime.toString() });
397
398 if (statistic instanceof CountStatistic) {
399 CountStatistic cStat = (CountStatistic) statistic;
400 long count = cStat.getCount();
401 mbeanStat.add(new String[] { "Count",
402 Long.toString(count) });
403 } else if (statistic instanceof TimeStatistic) {
404 TimeStatistic tStat = (TimeStatistic) statistic;
405 long count = tStat.getCount();
406 mbeanStat.add(new String[] { "Count",
407 Long.toString(count) });
408 Date maxTime = new Date(tStat.getMaxTime());
409 mbeanStat.add(new String[] { "Max Time",
410 maxTime.toString() });
411 Date minTime = new Date(tStat.getMinTime());
412 mbeanStat.add(new String[] { "Min Time",
413 minTime.toString() });
414 long totalTime = tStat.getTotalTime();
415 mbeanStat.add(new String[] { "Total Time",
416 Long.toString(totalTime) });
417 } else if (statistic instanceof BoundedRangeStatistic) {
418 BoundedRangeStatistic brStat = (BoundedRangeStatistic) statistic;
419 long upperBound = brStat.getUpperBound();
420 mbeanStat.add(new String[] { "Upper Bound",
421 Long.toString(upperBound) });
422 long lowerBound = brStat.getLowerBound();
423 mbeanStat.add(new String[] { "Lower Bound",
424 Long.toString(lowerBound) });
425 long highWaterMark = brStat.getHighWaterMark();
426 mbeanStat.add(new String[] { "High Water Mark",
427 Long.toString(highWaterMark) });
428 long lowWaterMark = brStat.getLowWaterMark();
429 mbeanStat.add(new String[] { "Low Water Mark",
430 Long.toString(lowWaterMark) });
431 long current = brStat.getCurrent();
432 mbeanStat.add(new String[] { "Current",
433 Long.toString(current) });
434 } else if (statistic instanceof BoundaryStatistic) {
435 BoundaryStatistic bStat = (BoundaryStatistic) statistic;
436 long upperBound = bStat.getUpperBound();
437 mbeanStat.add(new String[] { "Upper Bound",
438 Long.toString(upperBound) });
439 long lowerBound = bStat.getLowerBound();
440 mbeanStat.add(new String[] { "Lower Bound",
441 Long.toString(lowerBound) });
442 } else if (statistic instanceof RangeStatistic) {
443 RangeStatistic rStat = (RangeStatistic) statistic;
444 long highWaterMark = rStat.getHighWaterMark();
445 mbeanStat.add(new String[] { "High Water Mark",
446 Long.toString(highWaterMark) });
447 long lowWaterMark = rStat.getLowWaterMark();
448 mbeanStat.add(new String[] { "Low Water Mark",
449 Long.toString(lowWaterMark) });
450 long current = rStat.getCurrent();
451 mbeanStat.add(new String[] { "Current",
452 Long.toString(current) });
453 }
454
455 mbeanStats.put(name, mbeanStat);
456 }
457 }
458 } catch (Exception e) {
459 // GBean not found, just ignore
460 }
461
462 return mbeanStats.values();
463 }
464
465 /**
466 * Invoke MBean operation with arguments
467 */
468 public String[] invokeOperWithArgs(String abstractName, String methodName,
469 String[] args, String[] types) {
470 String[] result = new String[2]; // return method name & result
471 result[0] = methodName + "(...)";
472
473 try {
474 Object[] newArgs = processOperArgs(args, types);
475 AbstractName aname = new AbstractName(URI.create(abstractName));
476 Object res = kernel.invoke(aname, methodName, newArgs, types);
477 if (result != null) {
478 result[1] = res.toString();
479 } else {
480 result[1] = "<null>";
481 }
482 } catch (Exception e) {
483 result[1] = e.toString();
484 }
485
486 return result;
487 }
488
489 /**
490 * Invoke MBean operation without arguments
491 */
492 public String[] invokeOperNoArgs(String abstractName, String methodName) {
493 String[] result = new String[2]; // return method name & result
494 result[0] = methodName + "()";
495
496 try {
497 AbstractName aname = new AbstractName(URI.create(abstractName));
498 Object res = kernel.invoke(aname, methodName);
499 if (result != null) {
500 result[1] = res.toString();
501 } else {
502 result[1] = "<null>";
503 }
504 } catch (Exception e) {
505 result[1] = e.toString();
506 }
507
508 return result;
509 }
510
511 /**
512 * Process MBean operation arguments
513 */
514 private Object[] processOperArgs(String[] args, String[] types)
515 throws Exception {
516 // TODO: Modify this algorithm and add other classes
517 Object[] newArgs = new Object[args.length];
518 for (int i = 0; i < args.length; i++) {
519 String type = types[i];
520 String arg = args[i];
521 newArgs[i] = createObject(arg, type);
522 }
523
524 return newArgs;
525 }
526
527 /**
528 * Create MBean operation argument
529 */
530 private Object createObject(String arg, String type) throws Exception {
531 Object newArg = new Object();
532 if ("byte".equals(type) || "java.lang.Byte".equals(type)) {
533 newArg = new Byte(arg);
534 } else if ("short".equals(type) || "java.lang.Short".equals(type)) {
535 newArg = new Short(arg);
536 } else if ("int".equals(type) || "java.lang.Integer".equals(type)) {
537 newArg = new Integer(arg);
538 } else if ("long".equals(type) || "java.lang.Long".equals(type)) {
539 newArg = new Long(arg);
540 } else if ("float".equals(type) || "java.lang.Float".equals(type)) {
541 newArg = new Float(arg);
542 } else if ("double".equals(type) || "java.lang.Double".equals(type)) {
543 newArg = new Double(arg);
544 } else if ("char".equals(type) || "java.lang.Character".equals(type)) {
545 newArg = new Character(arg.charAt(0));
546 } else if ("boolean".equals(type) || "java.lang.Boolean".equals(type)) {
547 newArg = new Boolean(arg);
548 } else if ("java.lang.String".equals(type)) {
549 newArg = arg;
550 } else if ("java.lang.Object".equals(type)) {
551 newArg = arg;
552 } else if ("java.util.Date".equals(type)) {
553 newArg = DateFormat.getInstance().parse(arg);
554 } else if ("java.net.URL".equals(type)) {
555 newArg = new URL(arg);
556 } else if ("java.net.URI".equals(type)) {
557 newArg = new URI(arg);
558 } else if ("javax.management.ObjectName".equals(type)) {
559 newArg = new ObjectName(arg);
560 } else if ("org.apache.geronimo.gbean.AbstractName".equals(type)) {
561 newArg = new AbstractName(URI.create(arg));
562 } else {
563 // Unknown type, throw exception
564 String errorMsg = "Can't create instance of '" + type + "' using '"
565 + arg + "'.";
566 throw new IllegalArgumentException(errorMsg);
567 }
568
569 return newArg;
570 }
571
572 /**
573 * Set MBean attribute value
574 */
575 public String[] setAttribute(String abstractName, String attribName,
576 String attribValue, String attribType) {
577 String[] result = new String[2]; // return attribute name & result
578 result[0] = attribName;
579 result[1] = "<SUCCESS>";
580
581 try {
582 AbstractName aname = new AbstractName(URI.create(abstractName));
583 Object newAttribValue = createObject(attribValue, attribType);
584 kernel.setAttribute(aname, attribName, newAttribValue);
585 } catch (Exception e) {
586 result[1] = e.toString();
587 }
588
589 return result;
590 }
591
592 }