001    package biz.hammurapi.metrics.jmx;
002    
003    import java.util.Date;
004    import java.util.HashMap;
005    import java.util.Map;
006    
007    import javax.management.MBeanServer;
008    import javax.management.MalformedObjectNameException;
009    import javax.management.ObjectName;
010    import javax.management.StandardMBean;
011    
012    import biz.hammurapi.metrics.MeasurementCategoryFactory;
013    import biz.hammurapi.metrics.MeasurementConsumer;
014    import biz.hammurapi.metrics.SimpleSlice;
015    import biz.hammurapi.metrics.Slice;
016    
017    public abstract class JmxMeasurementCategoryFactory extends MeasurementCategoryFactory {
018            private String category;
019            
020            public void setCategory(String category) {
021                    this.category = category;
022            }
023            
024            private Map measurementConsumers = new HashMap();
025            
026            private static class JmxSliceImpl implements JmxSlice {
027                    
028                    private String name;
029                    private Slice master;
030    
031                    public JmxSliceImpl(String name) {
032                            this.name = name;
033                            reset();
034                    }
035    
036                    public double getAverage() {
037                            return master.getAvg();
038                    }
039    
040                    public double getDeviation() {
041                            return master.getDeviation();
042                    }
043    
044                    public Date getFrom() {
045                            return new Date(master.getFrom());
046                    }
047    
048                    public double getMax() {
049                            return master.getMax();
050                    }
051    
052                    public double getMin() {
053                            return master.getMin();
054                    }
055    
056                    public int getNumber() {
057                            return master.getNumber();
058                    }
059    
060                    public Date getTo() {
061                            return new Date(master.getTo());
062                    }
063    
064                    public double getTotal() {
065                            return master.getTotal();
066                    }
067    
068                    public void reset() {
069                            master = new SimpleSlice(name);
070                    }
071                    
072                    public Slice getMaster() {
073                            return master;
074                    }
075                    
076            }
077    
078            public synchronized MeasurementConsumer getMeasurementConsumer(final String categoryName) {
079                    MBeanServer mBeanServer = getMBeanServer();
080                    if (mBeanServer!=null 
081                                    && (category==null || category.equals(categoryName) || (categoryName!=null && categoryName.startsWith(category+".")))) {
082                            MeasurementConsumer ret = (MeasurementConsumer) measurementConsumers.get(categoryName);
083                            if (ret==null) {                                                                
084                                    ret = new MeasurementConsumer() {
085                                            private Map sliceMap = new HashMap();
086    
087                                            public synchronized void addMeasurement(String name, double value, long time) {
088                                                    JmxSliceImpl slice = (JmxSliceImpl) sliceMap.get(name);
089                                                    if (slice==null) {
090                                                            slice=new JmxSliceImpl(name);
091                                                            sliceMap.put(name, slice);
092                                                            
093                                                            try {
094                                                        MBeanServer mbs = getMBeanServer();
095                                                        if (mbs!=null) {
096                                                                mbs.registerMBean(new StandardMBean(slice, JmxSlice.class), objectName(categoryName, name));
097                                                        }
098                                                            } catch (Exception e) {
099                                                                    System.err.println("[JmxMeasurementCategoryFactory] ERROR: "+e);
100                                                                    return;
101                                                            }
102                                                    }
103                                                    slice.getMaster().add(value, time);
104                                            }
105                                            
106                                    };                              
107                            }
108                            return ret;             
109                    }
110                    return null;
111            }
112            
113            /**
114             * This implementation tries to use Java 5 management features.
115             * Returns null if JVM is not of version 5.
116             * @return MBean server to register MBeans with
117             */
118            protected abstract MBeanServer getMBeanServer();
119    
120            /**
121             * Constructs MBean name from category name and measurement name. 
122             * @param categoryName
123             * @param name
124             * @return
125             * @throws NullPointerException 
126             * @throws MalformedObjectNameException 
127             */
128            protected ObjectName objectName(final String categoryName, String name) throws MalformedObjectNameException {
129                    return new ObjectName("biz.hammurapi.metrics:category="+categoryName+",name="+name);
130            }
131    
132    }