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    }