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);
       }
   }
 

Attachment: signature.asc
Description: Digital signature

Reply via email to