Java tutorial
/******************************************************************************* * Copyright (c) 2010, 2012 AGETO Service GmbH and others. * 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. * * Contributors: * Gunnar Wagenknecht - initial API and implementation *******************************************************************************/ package org.eclipse.gyrex.monitoring.internal.mbeans; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.management.Attribute; import javax.management.AttributeList; import javax.management.AttributeNotFoundException; import javax.management.DynamicMBean; import javax.management.InvalidAttributeValueException; import javax.management.MBeanException; import javax.management.MBeanInfo; import javax.management.MBeanNotificationInfo; import javax.management.MBeanOperationInfo; import javax.management.ReflectionException; import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.CompositeType; import javax.management.openmbean.OpenDataException; import javax.management.openmbean.OpenMBeanAttributeInfoSupport; import javax.management.openmbean.OpenMBeanConstructorInfoSupport; import javax.management.openmbean.OpenMBeanInfoSupport; import javax.management.openmbean.OpenMBeanOperationInfoSupport; import javax.management.openmbean.OpenType; import javax.management.openmbean.SimpleType; import javax.management.openmbean.TabularDataSupport; import javax.management.openmbean.TabularType; import org.eclipse.gyrex.monitoring.metrics.BaseMetric; import org.eclipse.gyrex.monitoring.metrics.MetricAttribute; import org.eclipse.gyrex.monitoring.metrics.MetricSet; import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; import org.apache.commons.lang.StringUtils; /** * {@link MetricSetJmxMBean} implementation. */ public class MetricSetMBean implements DynamicMBean { private static final String RESET_STATS = "resetStats"; private static final String PROPERTIES = "properties"; private static final String DESCRIPTION = "description"; private static final String ID = "id"; private final MetricSet metricSet; private final ServiceReference<MetricSet> reference; private MBeanInfo beanInfo; private TabularDataSupport properties; private CompositeType propertyType; private TabularType propertyTableType; private Map<String, CompositeType> metricTypesByAttributeName; private Map<String, BaseMetric> metricByAttributeName; /** * Creates a new instance. * * @param reference */ public MetricSetMBean(final MetricSet metricSet, final ServiceReference<MetricSet> reference) { this.metricSet = metricSet; this.reference = reference; initialize(); } private OpenType detectType(final Class type) { if ((Long.class == type) || (Long.TYPE == type)) { return SimpleType.LONG; } else if ((Integer.class == type) || (Integer.TYPE == type)) { return SimpleType.INTEGER; } else if ((Double.class == type) || (Double.TYPE == type)) { return SimpleType.DOUBLE; } else if ((Float.class == type) || (Float.TYPE == type)) { return SimpleType.FLOAT; } else if ((Byte.class == type) || (Byte.TYPE == type)) { return SimpleType.BYTE; } else if ((Short.class == type) || (Short.TYPE == type)) { return SimpleType.SHORT; } else if ((Boolean.class == type) || (Boolean.TYPE == type)) { return SimpleType.BOOLEAN; } else if (BigDecimal.class == type) { return SimpleType.BIGDECIMAL; } else if (BigInteger.class == type) { return SimpleType.BIGINTEGER; } else if ((Character.class == type) || (Character.TYPE == type)) { return SimpleType.CHARACTER; } // last fallback to strings if (isConvertibleToString(type)) { return SimpleType.STRING; } // give up return null; } @Override public Object getAttribute(final String attributeName) throws AttributeNotFoundException, MBeanException, ReflectionException { if (ID.equals(attributeName)) { return metricSet.getId(); } else if (DESCRIPTION.equals(attributeName)) { return metricSet.getDescription(); } else if (PROPERTIES.equals(attributeName)) { return properties; } else if (metricTypesByAttributeName.containsKey(attributeName)) { final CompositeType type = metricTypesByAttributeName.get(attributeName); final BaseMetric metric = metricByAttributeName.get(attributeName); if ((type != null) && (metric != null)) { final Map<String, ?> rawValues = metric.getAttributeValues(); final String[] metricAttributeNames = type.keySet().toArray(new String[0]); final Object[] metricValues = new Object[metricAttributeNames.length]; for (int i = 0; i < metricValues.length; i++) { Object rawValue = rawValues.get(metricAttributeNames[i]); // convert if necessary if (null != rawValue) { final OpenType detectedTyp = detectType(rawValue.getClass()); if ((SimpleType.STRING == detectedTyp) && !(rawValue instanceof String)) { rawValue = String.valueOf(rawValue); } } metricValues[i] = rawValue; } try { return new CompositeDataSupport(type, metricAttributeNames, metricValues); } catch (final OpenDataException e) { throw new MBeanException(e); } } } throw new AttributeNotFoundException(String.format("attribute %s not found", attributeName)); } @Override public AttributeList getAttributes(final String[] attributes) { final AttributeList attributeList = new AttributeList(); for (final String attributeName : attributes) { try { attributeList.add(new Attribute(attributeName, getAttribute(attributeName))); } catch (final AttributeNotFoundException e) { // ignore } catch (final MBeanException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (final ReflectionException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return attributeList; } public String getId() { return metricSet.getId(); } @Override public MBeanInfo getMBeanInfo() { return beanInfo; } private CompositeType getType(final BaseMetric metric) throws OpenDataException { // get attributes final List<MetricAttribute> attributes = metric.getAttributes(); // collect names, descriptions and types final List<String> names = new ArrayList<String>(attributes.size()); final List<String> descriptions = new ArrayList<String>(attributes.size()); final List<OpenType> types = new ArrayList<OpenType>(attributes.size()); for (final MetricAttribute attribute : attributes) { final OpenType openType = detectType(attribute.getType()); if (null != openType) { names.add(attribute.getName()); descriptions.add(attribute.getDescription()); types.add(openType); } } return new CompositeType(metric.getClass().getSimpleName(), "Metric of type " + metric.getClass().getName(), names.toArray(new String[names.size()]), descriptions.toArray(new String[descriptions.size()]), types.toArray(new OpenType[types.size()])); } private void initialize() { final List<OpenMBeanAttributeInfoSupport> attributes = new ArrayList<OpenMBeanAttributeInfoSupport>(); final OpenMBeanConstructorInfoSupport[] constructors = new OpenMBeanConstructorInfoSupport[0]; final List<OpenMBeanOperationInfoSupport> operations = new ArrayList<OpenMBeanOperationInfoSupport>(1); final MBeanNotificationInfo[] notifications = new MBeanNotificationInfo[0]; // common attribute attributes .add(new OpenMBeanAttributeInfoSupport(ID, "MetricSet Id", SimpleType.STRING, true, false, false)); attributes.add(new OpenMBeanAttributeInfoSupport(DESCRIPTION, "MetricSet Description", SimpleType.STRING, true, false, false)); // service property attributes try { final String[] propertyTypeNames = new String[] { "key", "value" }; propertyType = new CompositeType("property", "A property with name and value.", propertyTypeNames, new String[] { "Name", "Value" }, new OpenType[] { SimpleType.STRING, SimpleType.STRING }); propertyTableType = new TabularType(PROPERTIES, "A lst of properties.", propertyType, new String[] { "key" }); attributes.add(new OpenMBeanAttributeInfoSupport(PROPERTIES, "MetricSet Properties", propertyTableType, true, false, false)); // pre-build service properties properties = new TabularDataSupport(propertyTableType); final String[] propertyKeys = reference.getPropertyKeys(); for (final String serviceProperty : propertyKeys) { if (serviceProperty.startsWith("gyrex.") || serviceProperty.equals(Constants.SERVICE_DESCRIPTION) || serviceProperty.equals(Constants.SERVICE_VENDOR)) { final Object value = reference.getProperty(serviceProperty); if (value == null) { continue; } if (isConvertibleToString(value.getClass())) { final Object[] values = { serviceProperty, String.valueOf(value) }; properties.put(new CompositeDataSupport(propertyType, propertyTypeNames, values)); } } } } catch (final OpenDataException e) { attributes.add(new OpenMBeanAttributeInfoSupport("propertiesError", "Exception occured while determining properties. " + e.toString(), SimpleType.STRING, true, false, false)); } // metrics final List<BaseMetric> metrics = metricSet.getMetrics(); metricTypesByAttributeName = new HashMap<String, CompositeType>(metrics.size()); metricByAttributeName = new HashMap<String, BaseMetric>(metrics.size()); for (final BaseMetric metric : metrics) { final String attributeName = StringUtils.removeStart(metric.getId(), metricSet.getId() + "."); try { final CompositeType type = getType(metric); if (type != null) { metricTypesByAttributeName.put(attributeName, type); metricByAttributeName.put(attributeName, metric); attributes.add(new OpenMBeanAttributeInfoSupport(attributeName, metric.getId(), type, true, false, false)); } } catch (final OpenDataException e) { attributes.add(new OpenMBeanAttributeInfoSupport(attributeName + "Error", "Exception occured while determining properties. " + e.toString(), SimpleType.STRING, true, false, false)); } } // reset operation for metric operations.add(new OpenMBeanOperationInfoSupport(RESET_STATS, "reset the metric statistics", null, SimpleType.VOID, MBeanOperationInfo.ACTION)); // build the info beanInfo = new OpenMBeanInfoSupport(this.getClass().getName(), metricSet.getDescription(), attributes.toArray(new OpenMBeanAttributeInfoSupport[attributes.size()]), constructors, operations.toArray(new OpenMBeanOperationInfoSupport[operations.size()]), notifications); } @Override public Object invoke(final String actionName, final Object[] params, final String[] signature) throws MBeanException, ReflectionException { if (RESET_STATS.equals(actionName)) { metricSet.resetStats(); } return null; } private boolean isConvertibleToString(final Class type) { return (type == String.class) || type.isPrimitive() || (type == Boolean.class) || Number.class.isAssignableFrom(type); } @Override public void setAttribute(final Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { // not supported } @Override public AttributeList setAttributes(final AttributeList attributes) { // not supported return null; } }