This adds the missing 1.6 methods to ArrayType, along with a few changes to the existing methods to make them work with the new features in 1.6. A batch of Mauve tests will follow for these.
ChangeLog:
2007-03-11 Andrew John Hughes <[EMAIL PROTECTED]>
* 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.
--
Andrew :-)
Escape the Java Trap with GNU Classpath!
http://www.gnu.org/philosophy/java-trap.html
public class gcj extends Freedom implements Java { ... }
Index: javax/management/openmbean/ArrayType.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/management/openmbean/ArrayType.java,v
retrieving revision 1.2
diff -u -3 -p -u -r1.2 ArrayType.java
--- javax/management/openmbean/ArrayType.java 5 Mar 2007 23:19:44 -0000 1.2
+++ javax/management/openmbean/ArrayType.java 11 Mar 2007 22:01:05 -0000
@@ -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 [EMAIL PROTECTED] ArrayType} instances created
+ * by [EMAIL PROTECTED] #getArrayType(OpenType)}.
+ */
+ private static final Map<OpenType<?>,ArrayType<?>> cache =
+ new HashMap<OpenType<?>,ArrayType<?>>();
+
+ /**
+ * A cache of [EMAIL PROTECTED] ArrayType} instances created
+ * by [EMAIL PROTECTED] #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 [EMAIL PROTECTED] ArrayType},
+ * based on whether the given element type is already an
+ * [EMAIL PROTECTED] 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 [EMAIL PROTECTED] type} is not a valid
+ * [EMAIL PROTECTED] 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 [EMAIL PROTECTED] type} is not a valid
+ * [EMAIL PROTECTED] 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 [EMAIL PROTECTED] ArrayType} is constructed from an [EMAIL PROTECTED] 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 [EMAIL PROTECTED] ArrayType} is constructed from an [EMAIL PROTECTED] 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
+ * [EMAIL PROTECTED] 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 [EMAIL PROTECTED] ArrayType} instance for a unidimensional
+ * array of the specified [EMAIL PROTECTED] SimpleType}. The attributes
+ * used by the superclass, [EMAIL PROTECTED] OpenType}, are automatically defined,
+ * based on these values. Both the class name and type name are set
+ * to the value returned by the [EMAIL PROTECTED] java.lang.Class#getName()} of
+ * the array's class. If the array is of a primitive type (indicated
+ * by giving [EMAIL PROTECTED] primitiveArray} the value [EMAIL PROTECTED] true}), the
+ * name will be '[' followed by the appropriate letter for the
+ * primitive type (see [EMAIL PROTECTED] 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
+ * [EMAIL PROTECTED] OpenType#getClassName()} on the result of
+ * [EMAIL PROTECTED] #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 [EMAIL PROTECTED] primitiveArray} is [EMAIL PROTECTED] true},
+ * and [EMAIL PROTECTED] elementType} is not a valid
+ * [EMAIL PROTECTED] 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>
* [EMAIL PROTECTED] 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 [EMAIL PROTECTED] ArrayType} instance in a type-safe
+ * manner, by ensuring that the type of the given [EMAIL PROTECTED] OpenType}
+ * matches the component type used in the type of the
+ * returned instance. If the given [EMAIL PROTECTED] OpenType} is a
+ * [EMAIL PROTECTED] SimpleType}, [EMAIL PROTECTED] CompositeType} or
+ * [EMAIL PROTECTED] TabularType}, then a 1-dimensional array of that
+ * type is returned. Otherwise, if the type is
+ * an [EMAIL PROTECTED] ArrayType} of n dimensions, the returned
+ * type is also an [EMAIL PROTECTED] ArrayType} but of n+1 dimensions.
+ * For example,
+ * [EMAIL PROTECTED] ArrayType.getArrayType(ArrayType.getArrayType(SimpleType.STRING))}
+ * returns a 2-dimensional array of [EMAIL PROTECTED] 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 [EMAIL PROTECTED] elementType}
+ * is not in [EMAIL PROTECTED] 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 [EMAIL PROTECTED] ArrayType} instance for the given
+ * primitive type in a type-safe* manner, by ensuring that
+ * the type of the given [EMAIL PROTECTED] OpenType} matches the type
+ * used in the returned instance. If the type is
+ * an array of n dimensions, the returned
+ * type is also an [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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
- * [EMAIL PROTECTED] #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 [EMAIL PROTECTED] #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;
}
Index: javax/management/openmbean/OpenType.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/management/openmbean/OpenType.java,v
retrieving revision 1.4
diff -u -3 -p -u -r1.4 OpenType.java
--- javax/management/openmbean/OpenType.java 5 Mar 2007 23:19:44 -0000 1.4
+++ javax/management/openmbean/OpenType.java 11 Mar 2007 22:01:05 -0000
@@ -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;
Index: javax/management/openmbean/SimpleType.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/management/openmbean/SimpleType.java,v
retrieving revision 1.3
diff -u -3 -p -u -r1.3 SimpleType.java
--- javax/management/openmbean/SimpleType.java 5 Mar 2007 23:19:44 -0000 1.3
+++ javax/management/openmbean/SimpleType.java 11 Mar 2007 22:01:05 -0000
@@ -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);
}
}
signature.asc
Description: Digital signature
