org.jboss.mx.mxbean.MXBeanUtils Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.mx.mxbean;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import javax.management.DynamicMBean;
import javax.management.ObjectName;
import javax.management.openmbean.ArrayType;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import org.jboss.util.collection.WeakValueHashMap;
/**
* Utils.
*
* @author Adrian Brock
* @version $Revision: 1.1 $
*/
public class MXBeanUtils
{
/** A cache of methods to keys */
private static final Map compositeDataKeyCache = Collections.synchronizedMap(new WeakHashMap());
/** A cache of classes to key to getters */
private static final Map> compositeDataMethodCache = Collections.synchronizedMap(new WeakHashMap>());
/** The map key */
public static final String MAP_KEY = "key";
/** The map value */
public static final String MAP_VALUE = "value";
/** Map index names */
public static final String[] MAP_INDEX_NAMES = { MAP_KEY };
/** Map item names */
public static final String[] MAP_ITEM_NAMES = { MAP_KEY, MAP_VALUE };
/**
* Get the OpenType for a class
*
* @param type the type
* @return the open type
*/
public static OpenType getOpenType(Type type)
{
if (type == null)
throw new IllegalArgumentException("Null type");
OpenType result = checkType(type);
if (result != null)
return result;
Class clazz = (Class) type;
return CompositeTypeMetaDataFactory.getCompositeType(clazz);
}
/**
* Get the SimpleType for a class
*
* @param type the type
* @return the open type
* @throws Exception for any error
*/
public static SimpleType getSimpleType(Class type) throws Exception
{
SimpleType simpleType = checkSimpleType(type);
if (simpleType == null)
throw new IllegalArgumentException("Not a SimpleType: " + type.getName());
return simpleType;
}
/**
* Get the for a class that is not composite
*
* @param type the type
* @return the open type or null if composite
*/
public static OpenType checkType(Type type)
{
OpenType result = checkSimpleType(type);
if (result != null)
return result;
result = checkEnum(type);
if (result != null)
return result;
result = checkArray(type);
if (result != null)
return result;
result = checkCollection(type);
if (result != null)
return result;
return checkMap(type);
}
/**
* Create a composite data proxy
*
* @param the interface type
* @param intf the interface type
* @param compositeData the composite data
* @return the proxy
*/
public static T createCompositeDataProxy(Class intf, CompositeData compositeData)
{
if (intf == null)
throw new IllegalArgumentException("Null interface");
InvocationHandler handler = new CompositeDataInvocationHandler(compositeData);
Object object = Proxy.newProxyInstance(intf.getClassLoader(), new Class[] { intf }, handler);
return intf.cast(object);
}
/**
* Construct some open data
*
* @param type the type
* @param value the value
* @param context the context
* @return the open data
* @throws Exception for any error
*/
public static Object construct(Type type, Object value, Object context) throws Exception
{
OpenType openType = getOpenType(type);
return construct(openType, value, context);
}
/**
* Construct some open data
*
* @param openType the open type
* @param value the value
* @param context the context
* @return the open data
* @throws Exception for any error
*/
public static Object construct(OpenType openType, Object value, Object context) throws Exception
{
if (openType instanceof SimpleType)
return constructSimpleData(value);
if (openType.isArray())
return constructArrayData(openType, value, context);
if (openType instanceof TabularType)
return constructTabularData(openType, value, context);
return constructCompositeData(openType, value, context);
}
/**
* Reconstruct a type from an object
*
* @param type the type
* @param value the value
* @param context for error reporting
* @return the object
* @throws Exception for any error
*/
public static Object reconstruct(Type type, Object value, Object context) throws Exception
{
OpenType openType = MXBeanUtils.getOpenType(type);
return reconstruct(openType, type, value, context);
}
/**
* Reconstruct a type from an object
*
* @param openType the open type
* @param type the type
* @param value the value
* @param context for error reporting
* @return the object
* @throws Exception for any error
*/
public static Object reconstruct(OpenType openType, Type type, Object value, Object context) throws Exception
{
if (openType instanceof SimpleType)
return reconstructSimpleData(type, value, context);
if (openType.isArray())
return reconstructArrayData(openType, type, value, context);
if (openType instanceof TabularType)
return reconstructTabularData(openType, type, value, context);
return reconstructCompositeData(openType, type, value, context);
}
/**
* Get the SimpleType for a class
*
* @param type the type
* @return the simple type or null if not a simple type
*/
public static SimpleType checkSimpleType(Type type)
{
if (BigDecimal.class.equals(type))
return SimpleType.BIGDECIMAL;
if (BigInteger.class.equals(type))
return SimpleType.BIGINTEGER;
if (Boolean.class.equals(type))
return SimpleType.BOOLEAN;
if (Boolean.TYPE.equals(type))
return SimpleType.BOOLEAN;
if (Byte.class.equals(type))
return SimpleType.BYTE;
if (Byte.TYPE.equals(type))
return SimpleType.BYTE;
if (Character.class.equals(type))
return SimpleType.CHARACTER;
if (Character.TYPE.equals(type))
return SimpleType.CHARACTER;
if (Date.class.equals(type))
return SimpleType.DATE;
if (Double.class.equals(type))
return SimpleType.DOUBLE;
if (Double.TYPE.equals(type))
return SimpleType.DOUBLE;
if (Float.class.equals(type))
return SimpleType.FLOAT;
if (Float.TYPE.equals(type))
return SimpleType.FLOAT;
if (Integer.class.equals(type))
return SimpleType.INTEGER;
if (Integer.TYPE.equals(type))
return SimpleType.INTEGER;
if (Long.class.equals(type))
return SimpleType.LONG;
if (Long.TYPE.equals(type))
return SimpleType.LONG;
if (ObjectName.class.equals(type))
return SimpleType.OBJECTNAME;
if (Short.class.equals(type))
return SimpleType.SHORT;
if (Short.TYPE.equals(type))
return SimpleType.SHORT;
if (String.class.equals(type))
return SimpleType.STRING;
if (Void.class.equals(type))
return SimpleType.VOID;
return null;
}
/**
* Get the simple type for an enum
*
* @param type the type
* @return return the enum type or null if it is not an enum
*/
public static SimpleType checkEnum(Type type)
{
if (type instanceof Class == false)
return null;
Class clazz = (Class) type;
if (clazz.isEnum() || Enum.class.equals(clazz))
return SimpleType.STRING;
return null;
}
/**
* Construct a simple type open data
*
* @param value the value
* @return the simple type
*/
public static Object constructSimpleData(Object value)
{
if (value != null && value instanceof Enum)
{
Enum enumeration = (Enum) value;
return enumeration.name();
}
return value;
}
/**
* Reconstruct a simple type open data
*
* @param type the type
* @param value the value
* @param context the context
* @return the simple type
*/
@SuppressWarnings("unchecked")
private static Object reconstructSimpleData(Type type, Object value, Object context)
{
if (type instanceof Class)
{
if (value != null)
{
Class clazz = (Class) type;
if (clazz.isEnum() || Enum.class.equals(clazz))
{
String string = (String) value;
return Enum.valueOf(clazz, string);
}
}
else
{
Class clazz = (Class) type;
if (clazz.isPrimitive())
throw new IllegalArgumentException("Attempt to use null as a primitive for: " + context);
return null;
}
}
return value;
}
/**
* Get the array type for a class
*
* @param type the type
* @return return the array type or null if it is not an array
*/
public static ArrayType checkArray(Type type)
{
if (type instanceof Class)
{
Class clazz = (Class) type;
if (clazz.isArray() == false)
return null;
int dimension = 1;
Class componentType = clazz.getComponentType();
while (componentType.isArray())
{
++dimension;
componentType = componentType.getComponentType();
}
OpenType componentOpenType = getOpenType(componentType);
try
{
return new ArrayType(dimension, componentOpenType);
}
catch (RuntimeException e)
{
throw e;
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
if (type instanceof GenericArrayType)
{
GenericArrayType arrayType = (GenericArrayType) type;
int dimension = 1;
Type componentType = arrayType.getGenericComponentType();
while (componentType instanceof GenericArrayType)
{
++dimension;
arrayType = (GenericArrayType) componentType;
componentType = arrayType.getGenericComponentType();
}
OpenType componentOpenType = getOpenType(componentType);
try
{
return new ArrayType(dimension, componentOpenType);
}
catch (RuntimeException e)
{
throw e;
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
return null;
}
/**
* Get the collection type for a class
*
* @param type the type
* @return return the array type or null if it is not a collection
*/
public static ArrayType checkCollection(Type type)
{
if (type instanceof ParameterizedType == false)
{
if (type instanceof Class)
return checkCollectionClass((Class) type);
else
return null;
}
ParameterizedType parameterizedType = (ParameterizedType) type;
Type rawType = parameterizedType.getRawType();
if (rawType instanceof Class == false)
return null;
Class rawClass = (Class) rawType;
if (Collection.class.isAssignableFrom(rawClass) == false)
return null;
Type componentType = parameterizedType.getActualTypeArguments()[0];
OpenType componentOpenType = getOpenType(componentType);
try
{
return new ArrayType(1, componentOpenType);
}
catch (RuntimeException e)
{
throw e;
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/**
* Get the collection type for a class
*
* @param clazz the class
* @return return the array type or null if it is not a collection
*/
public static ArrayType checkCollectionClass(Class clazz)
{
if (Collection.class.isAssignableFrom(clazz) == false)
return null;
OpenType componentOpenType = getOpenType(Object.class);
try
{
return new ArrayType(1, componentOpenType);
}
catch (RuntimeException e)
{
throw e;
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/**
* Construct an array type open data
*
* @param openType the open type
* @param value the value
* @param context the context
* @return the open data
* @throws Exception for any error
*/
public static Object constructArrayData(OpenType openType, Object value, Object context) throws Exception
{
if (value == null)
return null;
ArrayType arrayType = (ArrayType) openType;
OpenType elementType = arrayType.getElementOpenType();
int dimension = arrayType.getDimension();
Class clazz = value.getClass();
if (clazz.isArray())
{
Object[] oldArray = (Object[]) value;
Class> componentType = Class.forName(arrayType.getClassName());
return constructArray(elementType, componentType.getComponentType(), dimension, oldArray, context);
}
if (value instanceof Collection)
{
Collection c = (Collection) value;
Object[] oldArray = c.toArray();
Class> componentType = Class.forName(arrayType.getClassName());
return constructArray(elementType, componentType.getComponentType(), dimension, oldArray, context);
}
throw new UnsupportedOperationException("Cannot construct array for: " + value);
}
/**
* Construct an array of open data
*
* @param elementType the element type
* @param componentType the componentType
* @param dimension the dimension
* @param oldArray the old array
* @param context the context
* @return the array
* @throws Exception for any error
*/
private static Object[] constructArray(OpenType elementType, Class> componentType, int dimension, Object[] oldArray, Object context) throws Exception
{
if (oldArray == null)
return null;
Object[] newArray = (Object[]) Array.newInstance(componentType, oldArray.length);
if (dimension > 1)
{
for (int i = 0; i < oldArray.length; ++i)
{
Object[] nestedOld = (Object[]) oldArray[i];
newArray[i] = constructArray(elementType, componentType.getComponentType(), dimension-1, nestedOld, context);
}
}
else
{
if (Object.class.equals(componentType))
{
for (int i = 0; i < oldArray.length; ++i)
newArray[i] = oldArray[i];
}
else
{
for (int i = 0; i < oldArray.length; ++i)
newArray[i] = construct(elementType, oldArray[i], context);
}
}
return newArray;
}
/**
* Reconstruct an array type
*
* @param openType the open type
* @param type the type
* @param value the value
* @param context the context
* @return the value
* @throws Exception for any error
*/
public static Object reconstructArrayData(OpenType openType, Type type, Object value, Object context) throws Exception
{
if (value == null)
return null;
ArrayType arrayType = (ArrayType) getOpenType(type);
OpenType elementType = arrayType.getElementOpenType();
int dimension = arrayType.getDimension();
Object[] oldArray = (Object[]) value;
if (type instanceof Class)
{
Class clazz = (Class) type;
if (clazz.isArray())
return reconstructArray(elementType, clazz.getComponentType(), dimension, oldArray, context);
// TODO FIXME
// else if (Set.class.isAssignableFrom(clazz))
// return createSet(oldArray);
// else if (Collection.class.isAssignableFrom(clazz))
// return createCollection(oldArray);
}
else if (type instanceof ParameterizedType)
{
ParameterizedType parameterizedType = (ParameterizedType) type;
Type rawType = parameterizedType.getRawType();
if (rawType instanceof Class)
{
Class raw = (Class) rawType;
if (Set.class.isAssignableFrom(raw))
return createSet(oldArray);
else if (Collection.class.isAssignableFrom(raw))
return createCollection(oldArray);
}
}
throw new UnsupportedOperationException("Cannot convert array type: " + type);
}
/**
* Reconstruct an array
*
* @param elementType the element type
* @param componentType the componentType
* @param dimension the dimension
* @param oldArray the old array of open data
* @param context the context
* @return the array
* @throws Exception for any error
*/
private static Object[] reconstructArray(OpenType elementType, Class componentType, int dimension, Object[] oldArray, Object context) throws Exception
{
if (oldArray == null)
return null;
Object[] newArray = (Object[]) Array.newInstance(componentType, oldArray.length);
if (dimension > 1)
{
for (int i = 0; i < oldArray.length; ++i)
{
Object[] nestedOld = (Object[]) oldArray[i];
newArray[i] = reconstructArray(elementType, componentType.getComponentType(), dimension-1, nestedOld, context);
}
}
else
{
for (int i = 0; i < oldArray.length; ++i)
newArray[i] = reconstruct(elementType, componentType, oldArray[i], context);
}
return newArray;
}
/**
* Create a collection
*
* @param array the array
* @return the collection
*/
private static Collection createCollection(Object[] array)
{
return Arrays.asList(array);
}
/**
* Create a set
*
* @param array the array
* @return the set
*/
@SuppressWarnings("unchecked")
private static Set createSet(Object[] array)
{
HashSet result = new HashSet(array.length);
for (int i = 0; i < array.length; ++i)
result.add(array[i]);
return result;
}
/**
* Get the map type for a class
*
* @param type the type
* @return return the tabular type or null if it is not a collection
*/
public static TabularType checkMap(Type type)
{
if (type instanceof ParameterizedType == false)
{
if (type instanceof Class)
return checkMapClass((Class) type);
else
return null;
}
ParameterizedType parameterizedType = (ParameterizedType) type;
Type rawType = parameterizedType.getRawType();
if (rawType instanceof Class == false)
return null;
Class rawClass = (Class) rawType;
if (Map.class.isAssignableFrom(rawClass) == false)
return null;
Type[] args = parameterizedType.getActualTypeArguments();
Type keyType = args[0];
Type valueType = args[1];
return createMapType(keyType, valueType);
}
/**
* Get the map type for a class
*
* @param clazz the class
* @return return the tabular type or null if it is not a collection
*/
public static TabularType checkMapClass(Class clazz)
{
if (Map.class.isAssignableFrom(clazz) == false)
return null;
return createMapType(Object.class, Object.class);
}
/**
* Create a map type
*
* @param keyType the key type
* @param valueType the value type
* @return the map type
*/
public static TabularType createMapType(Type keyType, Type valueType)
{
String name = Map.class.getName();
OpenType[] itemTypes = { getOpenType(keyType), getOpenType(valueType) };
try
{
CompositeType entryType = createMapEntryType(itemTypes);
return new TabularType(name, name, entryType, MAP_INDEX_NAMES);
}
catch (RuntimeException e)
{
throw e;
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/**
* Create a map type
*
* @param itemTypes the item types
* @return the map entry type
*/
private static CompositeType createMapEntryType(OpenType[] itemTypes)
{
String entryName = Map.Entry.class.getName();
try
{
return new CompositeType(entryName, entryName, MAP_ITEM_NAMES, MAP_ITEM_NAMES, itemTypes);
}
catch (RuntimeException e)
{
throw e;
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/**
* Construct a tabular type open data
*
* @param openType the open type
* @param value the value
* @param context the context
* @return the open data
* @throws Exception for any error
*/
@SuppressWarnings("unchecked")
public static Object constructTabularData(OpenType openType, Object value, Object context) throws Exception
{
if (value == null)
return null;
TabularType tabularType = (TabularType) openType;
if (value instanceof Map)
{
TabularDataSupport table = new TabularDataSupport(tabularType);
CompositeType entryType = tabularType.getRowType();
OpenType keyType = entryType.getType(MAP_KEY);
OpenType valueType = entryType.getType(MAP_VALUE);
Map
© 2015 - 2024 Weber Informatics LLC | Privacy Policy