/*******************************************************************************
* Copyright (c) 2007 Cambridge Semantics Incorporated.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* File: $Source$
* Created by: Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com </a>)
* Created on: Nov 29, 2007
* Revision: $Id$
*
* Contributors:
* Cambridge Semantics Incorporated - initial API and implementation
*******************************************************************************/
package org.openanzo.jmx;
import java.util.ArrayList;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.ReflectionException;
import javax.management.j2ee.statistics.Statistic;
import org.apache.activemq.management.CountStatisticImpl;
import org.apache.activemq.management.StatsImpl;
import org.apache.activemq.management.TimeStatisticImpl;
import org.openanzo.exceptions.LogUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* DynamicMBean for a statistics object
*
* @author Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com </a>)
*
*/
public class DynamicStatsMBean implements javax.management.DynamicMBean {
private static final Logger log = LoggerFactory.getLogger(DynamicStatsMBean.class);
private final StatsImpl stats;
/**
* Create a new DynamicMBean for the given statistics object
*
* @param stats
* stats to expose in mbean
*/
public DynamicStatsMBean(StatsImpl stats) {
this.stats = stats;
}
enum StatType {
/** Total time for execution of stat */
TotalTime,
/** Average time for execution of stat */
TimeAverage
}
private final static String ENABLED = "enabled";
public synchronized String getAttribute(String name) throws AttributeNotFoundException {
StatType type = null;
if (ENABLED.equals(name)) {
return Boolean.toString(stats.isEnabled());
}
if (name.endsWith(StatType.TotalTime.name())) {
type = StatType.TotalTime;
name = name.substring(0, name.length() - StatType.TotalTime.name().length());
} else if (name.endsWith(StatType.TimeAverage.name())) {
type = StatType.TimeAverage;
name = name.substring(0, name.length() - StatType.TimeAverage.name().length());
}
Statistic value = stats.getStatistic(name);
if (value != null) {
if (type != null) {
switch (type) {
case TotalTime:
if (value instanceof TimeStatisticImpl) {
return Double.toString(((TimeStatisticImpl) value).getTotalTime());
}
break;
case TimeAverage:
if (value instanceof TimeStatisticImpl) {
return Double.toString(((TimeStatisticImpl) value).getAverageTime());
}
break;
}
}
}
if (value instanceof CountStatisticImpl) {
return Long.toString(((CountStatisticImpl) value).getCount());
}
throw new AttributeNotFoundException("No such statistic: " + name);
}
public synchronized void setAttribute(Attribute attribute) throws InvalidAttributeValueException, MBeanException, AttributeNotFoundException {
String name = attribute.getName();
if (name.equals("enabled")) {
stats.setEnabled(Boolean.parseBoolean(attribute.getValue().toString()));
} else {
throw new InvalidAttributeValueException("Attribute value not settable: " + name);
}
}
public synchronized AttributeList getAttributes(String[] names) {
AttributeList list = new AttributeList();
for (String name : names) {
try {
String value = getAttribute(name);
if (value != null)
list.add(new Attribute(name, value));
} catch (AttributeNotFoundException exception) {
if (log.isWarnEnabled()) {
log.warn(LogUtils.LIFECYCLE_MARKER, "Error getting jmx attribute", exception);
}
}
}
return list;
}
public synchronized AttributeList setAttributes(AttributeList list) {
AttributeList retlist = new AttributeList();
try {
for (Object attrObject : list) {
if (attrObject instanceof Attribute) {
Attribute attr = (Attribute) attrObject;
setAttribute(attr);
retlist.add(getAttribute(attr.getName()));
}
}
} catch (MBeanException exception) {
if (log.isWarnEnabled()) {
log.warn(LogUtils.LIFECYCLE_MARKER, "Error setting JMX attribute", exception);
}
retlist = new AttributeList();
} catch (InvalidAttributeValueException exception) {
if (log.isWarnEnabled()) {
log.warn(LogUtils.LIFECYCLE_MARKER, "Error setting JMX attribute", exception);
}
retlist = new AttributeList();
} catch (AttributeNotFoundException exception) {
if (log.isWarnEnabled()) {
log.warn(LogUtils.LIFECYCLE_MARKER, "Error setting JMX attribute", exception);
}
retlist = new AttributeList();
}
return retlist;
}
public Object invoke(String name, Object[] args, String[] sig) throws MBeanException, ReflectionException {
if (name.equals("reset") && (args == null || args.length == 0) && (sig == null || sig.length == 0)) {
stats.reset();
return null;
}
throw new ReflectionException(new NoSuchMethodException(name));
}
public synchronized MBeanInfo getMBeanInfo() {
SortedSet<String> names = new TreeSet<String>();
for (String statistic : stats.getStatisticNames()) {
names.add(statistic);
}
ArrayList<MBeanAttributeInfo> attrs = new ArrayList<MBeanAttributeInfo>();
for (String name : names) {
Statistic statistic = stats.getStatistic(name);
if (!(statistic instanceof StatsImpl)) {
if (statistic instanceof CountStatisticImpl) {
attrs.add(new MBeanAttributeInfo(statistic.getName(), "java.lang.Long", statistic.getDescription(), true, false, false));
} else if (statistic instanceof TimeStatisticImpl) {
attrs.add(new MBeanAttributeInfo(statistic.getName() + StatType.TimeAverage.name(), "java.lang.Double", statistic.getDescription(), true, false, false));
attrs.add(new MBeanAttributeInfo(statistic.getName() + StatType.TotalTime.name(), "java.lang.Double", statistic.getDescription(), true, false, false));
}
}
}
attrs.add(new MBeanAttributeInfo("enabled", "java.lang.Boolean", "Enable Statistics ", true, true, true));
MBeanOperationInfo[] opers = { new MBeanOperationInfo("reset", "Reset the statistics", null, "void", MBeanOperationInfo.ACTION) };
return new MBeanInfo(this.getClass().getName(), "Statistics MBean", attrs.toArray(new MBeanAttributeInfo[0]), null, opers, null);
}
}