001    package com.hammurapi.eventbus.monitoring;
002    
003    import java.util.ArrayList;
004    import java.util.Collection;
005    import java.util.Map;
006    import java.util.concurrent.ConcurrentHashMap;
007    
008    import javax.management.MBeanServer;
009    import javax.management.ObjectName;
010    import javax.management.StandardMBean;
011    
012    import com.hammurapi.eventbus.EventBusException;
013    
014    /**
015     * Statistics collector which exposes statistics as MBeans.
016     * @author Pavel Vlasov
017     *
018     */
019    public class JmxStatsCollector implements StatsCollector {
020            
021            private static volatile long keyCounter;
022            
023            private MBeanServer mBeanServer;
024            private String objectNamePrefix;
025            
026            private Map<Stats, Iterable<ObjectName>> regInfo = new ConcurrentHashMap<Stats, Iterable<ObjectName>>();
027    
028            /**
029             * @param mBeanServer MBean server to register statistics MBeans.
030             * @param objectNamePrefix Object name prefix for statistics MBeans without trailing comma. 
031             * E.g. <code>mycategory:mykey=myvalue</code>.
032             */
033            public JmxStatsCollector(MBeanServer mBeanServer, String objectNamePrefix) {
034                    this.mBeanServer = mBeanServer;
035                    this.objectNamePrefix = objectNamePrefix;
036            }
037    
038            @Override
039            public void add(Stats root) {
040                    Collection<ObjectName> reg = new ArrayList<ObjectName>(); 
041                    add(root, objectNamePrefix, reg);
042            }
043    
044            private void add(Stats stats, String prefix, Collection<ObjectName> reg) {
045                    @SuppressWarnings("unchecked")
046                    Class<Stats> mBeanInterface = (Class<Stats>) stats.getClass().getInterfaces()[0];
047                    int idx = mBeanInterface.getName().lastIndexOf('.');
048                    String key = mBeanInterface.getName().substring(idx+1)+"("+(++keyCounter)+")"; 
049                    String name = prefix+","+key+"="+stats.getName();
050                    try {
051                            ObjectName oName = new ObjectName(name);
052                            reg.add(oName);
053                            mBeanServer.registerMBean(new StandardMBean(stats, mBeanInterface), oName);
054                    } catch (Exception e) {
055                            throw new EventBusException(e); 
056                    }
057                    for (Stats child: stats.children()) {
058                            add(child, name, reg);
059                    }
060            }
061            
062            public void remove(Stats root) {
063                    for (ObjectName oName: regInfo.get(root)) {
064                            try {
065                                    mBeanServer.unregisterMBean(oName);
066                            } catch (Exception e) {
067                                    throw new EventBusException(e);
068                            }
069                    }
070            }
071    
072    }