summaryrefslogtreecommitdiff
path: root/javax
diff options
context:
space:
mode:
authorAndrew John Hughes <gnu_andrew@member.fsf.org>2007-03-11 22:15:45 +0000
committerAndrew John Hughes <gnu_andrew@member.fsf.org>2007-03-11 22:15:45 +0000
commit49d052d30cc7f5579709b69c5e1064dc102195fe (patch)
treef94e86fc56d27f976d38bfee9bb59977bda6b270 /javax
parent6d5bd4d5458504ff7f228c2902eb0e919f409f66 (diff)
downloadclasspath-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.java405
-rw-r--r--javax/management/openmbean/OpenType.java25
-rw-r--r--javax/management/openmbean/SimpleType.java2
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);
}
}