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