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 }