diff options
author | Andrew John Hughes <gnu_andrew@member.fsf.org> | 2007-03-11 22:15:45 +0000 |
---|---|---|
committer | Andrew John Hughes <gnu_andrew@member.fsf.org> | 2007-03-11 22:15:45 +0000 |
commit | 49d052d30cc7f5579709b69c5e1064dc102195fe (patch) | |
tree | f94e86fc56d27f976d38bfee9bb59977bda6b270 /javax | |
parent | 6d5bd4d5458504ff7f228c2902eb0e919f409f66 (diff) | |
download | classpath-49d052d30cc7f5579709b69c5e1064dc102195fe.tar.gz |
2007-03-11 Andrew John Hughes <gnu_andrew@member.fsf.org>
* javax/management/openmbean/ArrayType.java:
(getArrayClassName(String, int)): Replaced by...
(getArrayClassName(OpenType, int, boolean)):
Returns appropriate class name for the array.
(getDimensions(OpenType, int)): New method.
(getPrimitiveType(Class<?>)): Likewise.
(getPrimitiveTypeClass(OpenType<?>)): Likewise.
(getElementType(OpenType<?>)): Likewise.
(getElementTypeName(OpenType<?>)): Likewise.
(ArrayType(int, OpenType<?>)): Rewritten
to handle ArrayTypes as input.
(ArrayType(SimpleType<?>, boolean)): New constructor.
(equals(Object)): Handle primitiveArray flag.
(hashCode()): Likewise.
(getArrayType(OpenType<E>)): New method.
(getPrimitiveArrayType(Class<T>)): Likewise.
(isPrimitiveArray()): Likewise.
(toString()): Updated to list primitiveArray
flag.
* javax/management/openmbean/OpenType.java:
(OpenType(String,String,String)): Use Class.forName()
and methods of Class to validate arrays.
* javax/management/openmbean/SimpleType.java:
Include causal exception when creating pre-defined types
throws an exception.
Diffstat (limited to 'javax')
-rw-r--r-- | javax/management/openmbean/ArrayType.java | 405 | ||||
-rw-r--r-- | javax/management/openmbean/OpenType.java | 25 | ||||
-rw-r--r-- | javax/management/openmbean/SimpleType.java | 2 |
3 files changed, 397 insertions, 35 deletions
diff --git a/javax/management/openmbean/ArrayType.java b/javax/management/openmbean/ArrayType.java index 5b9d31416..42f80623d 100644 --- a/javax/management/openmbean/ArrayType.java +++ b/javax/management/openmbean/ArrayType.java @@ -40,6 +40,8 @@ package javax.management.openmbean; import java.lang.reflect.Array; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; /** * The open type descriptor for arrays of open data values. @@ -67,6 +69,11 @@ public class ArrayType<T> private OpenType<?> elementType; /** + * True if this type represents a primitive array. + */ + private boolean primitiveArray; + + /** * The hash code of this instance. */ private transient Integer hashCode; @@ -77,19 +84,183 @@ public class ArrayType<T> private transient String string; /** + * A cache of {@link ArrayType} instances created + * by {@link #getArrayType(OpenType)}. + */ + private static final Map<OpenType<?>,ArrayType<?>> cache = + new HashMap<OpenType<?>,ArrayType<?>>(); + + /** + * A cache of {@link ArrayType} instances created + * by {@link #getPrimitiveArrayType(Class)}. + */ + private static final Map<Class<?>,ArrayType<?>> primCache = + new HashMap<Class<?>,ArrayType<?>>(); + + /** * Returns the class name of the array, given the element * class name and its dimensions. * - * @param className the name of the class used by the - * array's elements. + * @param elementType the type of the array's elements. * @param dim the dimensions of the array. + * @param primitive true if this should be a primitive array. * @return the array's class name. + * @throws OpenDataException if the class name does not reference + * a loadable class. */ - private static String getArrayClassName(String className, int dim) + private static final String getArrayClassName(OpenType<?> elementType, + int dim, + boolean primitive) + throws OpenDataException { - char[] brackets = new char[dim]; - Arrays.fill(brackets, '['); - return String.valueOf(brackets) + "L" + className; + Class<?> type; + if (primitive) + type = getPrimitiveTypeClass((SimpleType<?>) elementType); + else + { + String className = elementType.getClassName(); + try + { + type = Class.forName(className); + } + catch (ClassNotFoundException e) + { + throw new OpenDataException("The class name, " + className + + ", is unavailable."); + } + } + while (type.isArray()) + type = type.getComponentType(); + return + Array.newInstance(type, + new int[getDimensions(elementType, dim)]).getClass().getName(); + } + + /** + * Returns the dimensions of the new {@link ArrayType}, + * based on whether the given element type is already an + * {@link ArrayType} or not. + * + * @param elementType the type of the array. + * @param dim the proposed dimensions. + * @return the resultant dimensions. + * @throws IllegalArgumentException if <code>dim</code> is less than 1. + */ + private static final int getDimensions(OpenType<?> elementType, + int dim) + { + if (dim < 1) + throw new IllegalArgumentException("Dimensions must be greater " + + "than or equal to 1."); + if (elementType instanceof ArrayType) + return dim + ((ArrayType) elementType).getDimension(); + return dim; + } + + /** + * Returns the appropriate primitive type name, given the + * corresponding wrapper class. + * + * @param type the type to convert. + * @return the corresponding primitive type. + * @throws OpenDataException if {@code type} is not a valid + * {@link Class} for a primitive type. + * + */ + private static final SimpleType<?> getPrimitiveType(Class<?> type) + throws OpenDataException + { + if (type.equals(Boolean.TYPE)) + return SimpleType.BOOLEAN; + if (type.equals(Byte.TYPE)) + return SimpleType.BYTE; + if (type.equals(Character.TYPE)) + return SimpleType.CHARACTER; + if (type.equals(Double.TYPE)) + return SimpleType.DOUBLE; + if (type.equals(Float.TYPE)) + return SimpleType.FLOAT; + if (type.equals(Integer.TYPE)) + return SimpleType.INTEGER; + if (type.equals(Long.TYPE)) + return SimpleType.LONG; + if (type.equals(Short.TYPE)) + return SimpleType.SHORT; + if (type.equals(Void.TYPE)) + return SimpleType.VOID; + throw new OpenDataException(type + " is not a primitive type."); + } + + /** + * Returns the appropriate primitive type name, given the + * corresponding wrapper class. + * + * @param type the type to convert. + * @return the corresponding primitive type. + * @throws OpenDataException if {@code type} is not a valid + * {@link SimpleType} for a primitive type. + * + */ + private static final Class<?> getPrimitiveTypeClass(SimpleType<?> type) + throws OpenDataException + { + if (type.equals(SimpleType.BOOLEAN)) + return Boolean.TYPE; + if (type.equals(SimpleType.BYTE)) + return Byte.TYPE; + if (type.equals(SimpleType.CHARACTER)) + return Character.TYPE; + if (type.equals(SimpleType.DOUBLE)) + return Double.TYPE; + if (type.equals(SimpleType.FLOAT)) + return Float.TYPE; + if (type.equals(SimpleType.INTEGER)) + return Integer.TYPE; + if (type.equals(SimpleType.LONG)) + return Long.TYPE; + if (type.equals(SimpleType.SHORT)) + return Short.TYPE; + if (type.equals(SimpleType.VOID)) + return Void.TYPE; + throw new OpenDataException(type + " is not a primitive type."); + } + + /** + * Returns the element type that will actually be used, if the + * specified element type is passed to a constructor. This is + * necessary to ensure that a non-array type is still returned when + * an {@link ArrayType} is constructed from an {@link ArrayType}. + * + * @param elemType the element type that was supplied. + * @return the element type that will be used. + */ + private static final OpenType<?> getElementType(OpenType<?> elemType) + { + if (elemType instanceof ArrayType) + return ((ArrayType) elemType).getElementOpenType(); + return elemType; + } + + /** + * Returns the element type name that will actually be used, if the + * specified element type is passed to a constructor. This is + * necessary to ensure that a non-array type is still returned when + * an {@link ArrayType} is constructed from an {@link ArrayType}, + * and that primitive arrays are described correctly. + * + * @param elemType the element type that was supplied. + * @return the element type name that will be used. + * @throws OpenDataException if the element type is not a valid + * {@link SimpleType} for a primitive type. + */ + private static final String getElementTypeName(OpenType<?> elemType) + throws OpenDataException + { + OpenType<?> trueElemType = getElementType(elemType); + if (elemType instanceof ArrayType && + ((ArrayType) elemType).isPrimitiveArray()) + return getPrimitiveTypeClass((SimpleType<?>) trueElemType).getName(); + return trueElemType.getClassName(); } /** @@ -139,20 +310,81 @@ public class ArrayType<T> public ArrayType(int dim, OpenType<?> elementType) throws OpenDataException { - super(getArrayClassName(elementType.getClassName(), dim), - getArrayClassName(elementType.getClassName(), dim), - dim + "-dimension array of " + elementType.getClassName()); - if (dim < 1) - throw new IllegalArgumentException("Dimensions must be greater " + - "than or equal to 1."); + super(getArrayClassName(elementType, dim, false), + getArrayClassName(elementType, dim, false), + getDimensions(elementType, dim) + "-dimension array of " + + getElementTypeName(elementType)); if (!(elementType instanceof SimpleType || elementType instanceof CompositeType || - elementType instanceof TabularType)) + elementType instanceof TabularType || + elementType instanceof ArrayType)) throw new OpenDataException("The element type must be a simple " + - "type, a composite type or a tabular " + - "type."); - dimension = dim; + "type, an array type, a composite type " + + "or a tabular type."); + dimension = getDimensions(elementType, dim); + this.elementType = getElementType(elementType); + primitiveArray = (elementType instanceof ArrayType && + ((ArrayType) elementType).isPrimitiveArray()); + } + + /** + * <p> + * Constructs a new {@link ArrayType} instance for a unidimensional + * array of the specified {@link SimpleType}. The attributes + * used by the superclass, {@link OpenType}, are automatically defined, + * based on these values. Both the class name and type name are set + * to the value returned by the {@link java.lang.Class#getName()} of + * the array's class. If the array is of a primitive type (indicated + * by giving {@code primitiveArray} the value {@code true}), the + * name will be '[' followed by the appropriate letter for the + * primitive type (see {@link java.lang.Class#getName()}). If the + * array is not of a primitive type, then the name is formed from + * the element type, preceded by '[' and an 'L', in the same way + * as when the multi-dimensional constructor is used. + * </p> + * <p> + * The description is based upon the template <code>1-dimension array + * of e</code>, where e is either the primitive type or a class name, + * depending on whether the array itself is of a primitive type or not. + * The class name of the actual elements is obtainable by calling + * {@link OpenType#getClassName()} on the result of + * {@link #getElementOpenType()}. This will be the appropriate wrapper + * class for a primitive type. + * </p> + * <p> + * As an example, the array type returned by + * <code>new ArrayType(SimpleType.INTEGER, true)</code> has the following + * values: + * </p> + * <table> + * <th><td>Attribute</td><td>Value</td></th> + * <tr><td>Class Name</td><td><code>[I</code> + * </td></tr> + * <tr><td>Type Name</td><td><code>[I</code> + * </td></tr> + * <tr><td>Description</td><td><code>1-dimension array of int</code></td></tr> + * <tr><td>Element Type Class Name</td><td><code>java.lang.Integer</code> + * </td></tr> + * </table> + * + * @param elementType the type of the elements of the array. + * @param primitiveArray true if the array should be of a primitive type. + * @throws OpenDataException if {@code primitiveArray} is {@code true}, + * and {@link elementType} is not a valid + * {@link SimpleType} for a primitive type. + * @since 1.6 + */ + public ArrayType(SimpleType<?> elementType, boolean primitiveArray) + throws OpenDataException + { + super(getArrayClassName(elementType, 1, primitiveArray), + getArrayClassName(elementType, 1, primitiveArray), + "1-dimension array of " + + (primitiveArray ? getPrimitiveTypeClass(elementType).getName() + : elementType.getClassName())); + dimension = 1; this.elementType = elementType; + this.primitiveArray = primitiveArray; } /** @@ -166,6 +398,8 @@ public class ArrayType<T> * {@link ArrayType}.</li> * <li>The dimensions are equal.</li> * <li>The element types are equal.</li> + * <li>The primitive array flag is set the same in both + * instances.</li> * </ul> * * @param obj the object to compare with. @@ -177,7 +411,118 @@ public class ArrayType<T> return false; ArrayType atype = (ArrayType) obj; return (atype.getDimension() == dimension && - atype.getElementOpenType().equals(elementType)); + atype.getElementOpenType().equals(elementType) && + atype.isPrimitiveArray() == primitiveArray); + } + + /** + * <p> + * Returns a new {@link ArrayType} instance in a type-safe + * manner, by ensuring that the type of the given {@link OpenType} + * matches the component type used in the type of the + * returned instance. If the given {@link OpenType} is a + * {@link SimpleType}, {@link CompositeType} or + * {@link TabularType}, then a 1-dimensional array of that + * type is returned. Otherwise, if the type is + * an {@link ArrayType} of n dimensions, the returned + * type is also an {@link ArrayType} but of n+1 dimensions. + * For example, + * {@code ArrayType.getArrayType(ArrayType.getArrayType(SimpleType.STRING))} + * returns a 2-dimensional array of {@link SimpleType#String}. + * </p> + * <p> + * This method caches its results, so that the same instance + * is returned from subsequent calls with the same parameters. + * </p> + * + * @param elementType the element type of the new array type. + * @throws OpenDataException if the class name of {@code elementType} + * is not in {@link OpenType#ALLOWED_CLASSNAMES_LIST}. + * @since 1.6 + */ + public static <E> ArrayType<E[]> getArrayType(OpenType<E> elementType) + throws OpenDataException + { + ArrayType<E[]> arr = (ArrayType<E[]>) cache.get(elementType); + if (arr != null) + return arr; + arr = new ArrayType(1, elementType); + cache.put(elementType, arr); + return arr; + } + + /** + * <p> + * Returns a new {@link ArrayType} instance for the given + * primitive type in a type-safe* manner, by ensuring that + * the type of the given {@link OpenType} matches the type + * used in the returned instance. If the type is + * an array of n dimensions, the returned + * type is also an {@link ArrayType} of n dimensions. + * </p> + * <p> + * As an example, the array type returned by + * <code>getPrimitiveArrayType(Integer.TYPE)</code> has the + * following values: + * </p> + * <table> + * <th><td>Attribute</td><td>Value</td></th> + * <tr><td>Class Name</td><td><code>[I</code> + * </td></tr> + * <tr><td>Type Name</td><td><code>[I</code> + * </td></tr> + * <tr><td>Description</td><td><code>1-dimension array of int</code></td></tr> + * <tr><td>Element Type Class Name</td><td><code>java.lang.Integer</code> + * </td></tr> + * </table> + * <p> + * This method caches its results, so that the same instance + * is returned from subsequent calls with the same parameters. + * </p> + * + * @param type the type of the new {@link ArrayType}. + * @throws IllegalArgumentException if the type is not a primitive + * array. + * @since 1.6 + */ + public static <T> ArrayType<T> getPrimitiveArrayType(Class<T> type) + { + ArrayType<T> arr = (ArrayType<T>) primCache.get(type); + if (arr != null) + return arr; + Class<?> comType = type; + int dim = 0; + do + { + comType = comType.getComponentType(); + ++dim; + if (comType == null) + throw new IllegalArgumentException("The given class is " + + "not an array."); + } while (comType.isArray()); + String className = type.getName(); + try + { + arr = new ArrayType(getPrimitiveType(comType), true); + } + catch (OpenDataException e) + { + throw new IllegalArgumentException("The array is not of a primitive " + + "type", e); + } + while (dim > 1) + try + { + arr = new ArrayType(1, arr); + --dim; + } + catch (OpenDataException e) + { + throw (Error) + new InternalError("Couldn't generate extra dimensions").initCause(e); + } + primCache.put(type, arr); + return arr; } /** @@ -207,11 +552,11 @@ public class ArrayType<T> * Returns the hash code of the array type. * This is computed as the sum of the hash code of the * element type together with the number of dimensions - * the array has. These are the same elements - * of the type that are compared as part of the - * {@link #equals(java.lang.Object)} method, thus ensuring - * that the hashcode is compatible with the equality - * test. + * the array has and the primitive array flag. These + * are the same elements of the type that are compared as + * part of the {@link #equals(java.lang.Object)} method, + * thus ensuring that the hashcode is compatible with the + * equality test. * </p> * <p> * As instances of this class are immutable, the hash code @@ -224,11 +569,24 @@ public class ArrayType<T> public int hashCode() { if (hashCode == null) - hashCode = Integer.valueOf(dimension + elementType.hashCode()); + hashCode = Integer.valueOf(dimension + + elementType.hashCode() + + Boolean.valueOf(primitiveArray).hashCode()); return hashCode.intValue(); } /** + * Returns true if this instance represents an array of + * a primitive type. + * + * @return true if the array is of a primitive type. + */ + public boolean isPrimitiveArray() + { + return primitiveArray; + } + + /** * <p> * Returns true if the specified object is a member of this * array type. The object is judged to be so if it is @@ -306,6 +664,7 @@ public class ArrayType<T> + "[name=" + getTypeName() + ", dimension=" + dimension + ", elementType=" + elementType + + ", primitiveArray=" + primitiveArray + "]"; return string; } diff --git a/javax/management/openmbean/OpenType.java b/javax/management/openmbean/OpenType.java index 62e05b617..f3a97fef3 100644 --- a/javax/management/openmbean/OpenType.java +++ b/javax/management/openmbean/OpenType.java @@ -140,17 +140,20 @@ public abstract class OpenType<T> if (desc == null || desc.equals("")) throw new IllegalArgumentException("The description can not " + "be null or the empty string."); - String testString; - if (className.startsWith("[")) - testString = className.substring(className.indexOf("L") + 1); - else - testString = className; - boolean openTypeFound = false; - for (int a = 0; a < ALLOWED_CLASSNAMES.length; ++a) - if (ALLOWED_CLASSNAMES[a].equals(testString)) - openTypeFound = true; - if (!openTypeFound) - throw new OpenDataException("The class name, " + testString + + Class<?> type; + try + { + type = Class.forName(className); + } + catch (ClassNotFoundException e) + { + throw (OpenDataException) new OpenDataException("The class name, " + className + + ", is unavailable.").initCause(e); + } + while (type.isArray()) + type = type.getComponentType(); + if (!(type.isPrimitive() || ALLOWED_CLASSNAMES_LIST.contains(type.getName()))) + throw new OpenDataException("The class name, " + className + ", does not specify a valid open type."); this.className = className; typeName = name; diff --git a/javax/management/openmbean/SimpleType.java b/javax/management/openmbean/SimpleType.java index faffd3a45..fb3b1bc28 100644 --- a/javax/management/openmbean/SimpleType.java +++ b/javax/management/openmbean/SimpleType.java @@ -192,7 +192,7 @@ public final class SimpleType<T> /* In normal circumstances, this shouldn't be possible. */ throw new IllegalStateException("A invalid class name " + "was passed to the SimpleType " + - "constructor."); + "constructor.", e); } } |