Hi,

Since we can now support annotations on the trunk I'd like to merge
Class/VMClass with the versions from the generics branch (modulo any 1.5
language feature, of course).

If your VM already supports the generics branch, no changes should be
needed. If you don't yet support it, you need to implement
VMClass.getDeclaredAnnotations, if you use a custom version of VMClass,
you also need to copy VMClass.getEnumConstants.

Unless someone complains, this will go in next week.

Regards,
Jeroen
Index: java/lang/Class.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/lang/Class.java,v
retrieving revision 1.47
diff -u -r1.47 Class.java
--- java/lang/Class.java        7 Apr 2006 19:45:45 -0000       1.47
+++ java/lang/Class.java        21 Apr 2006 13:06:17 -0000
@@ -1,5 +1,5 @@
 /* Class.java -- Representation of a Java class.
-   Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005
+   Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation
 
 This file is part of GNU Classpath.
@@ -44,7 +44,9 @@
 import java.io.InputStream;
 import java.io.ObjectStreamClass;
 import java.io.Serializable;
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Array;
+import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.GenericDeclaration;
@@ -100,7 +102,7 @@
  * @see ClassLoader
  */
 public final class Class 
-  implements Serializable, Type, GenericDeclaration
+  implements Serializable, Type, AnnotatedElement, GenericDeclaration
 {
   /**
    * Compatible with JDK 1.0+.
@@ -640,17 +642,16 @@
     
     public boolean equals(Object o)
     {
-      if(o instanceof MethodKey)
+      if (o instanceof MethodKey)
        {
-         MethodKey m = (MethodKey)o;
-         if(m.name.equals(name) && m.params.length == params.length && 
m.returnType == returnType)
+         MethodKey m = (MethodKey) o;
+         if (m.name.equals(name) && m.params.length == params.length
+              && m.returnType == returnType)
            {
-             for(int i = 0; i < params.length; i++)
+             for (int i = 0; i < params.length; i++)
                {
-                 if(m.params[i] != params[i])
-                   {
-                     return false;
-                   }
+                 if (m.params[i] != params[i])
+                   return false;
                }
              return true;
            }
@@ -1260,7 +1261,7 @@
     return c.defaultAssertionStatus;
   }
 
-  /*
+  /**
    * <p>
    * Casts this class to represent a subclass of the specified class.
    * This method is useful for `narrowing' the type of a class so that
@@ -1369,6 +1370,20 @@
   }
 
   /**
+   * Returns the enumeration constants of this class, or
+   * null if this class is not an <code>Enum</code>.
+   *
+   * @return an array of <code>Enum</code> constants
+   *         associated with this class, or null if this
+   *         class is not an <code>enum</code>.
+   * @since 1.5
+   */
+  public Object[] getEnumConstants()
+  {
+    return VMClass.getEnumConstants(this);
+  }
+
+  /**
    * Returns true if this class is an <code>Enum</code>.
    *
    * @return true if this is an enumeration class.
@@ -1421,6 +1436,50 @@
   }
 
   /**
+   * Returns this class' annotation for the specified annotation type,
+   * or <code>null</code> if no such annotation exists.
+   *
+   * @param annotationClass the type of annotation to look for.
+   * @return this class' annotation for the specified type, or
+   *         <code>null</code> if no such annotation exists.
+   * @since 1.5
+   */
+  /* FIXME[GENERICS]: <T extends Annotation> T getAnnotation(Class <T>) */
+  public Annotation getAnnotation(Class annotationClass)
+  {
+    Annotation foundAnnotation = null;
+    Annotation[] annotations = getAnnotations();
+    for (int i = 0; i < annotations.length; i++)
+      if (annotations[i].annotationType() == annotationClass)
+       foundAnnotation = annotations[i];
+    return foundAnnotation;
+  }
+
+  /**
+   * Returns all annotations associated with this class.  If there are
+   * no annotations associated with this class, then a zero-length array
+   * will be returned.  The returned array may be modified by the client
+   * code, but this will have no effect on the annotation content of this
+   * class, and hence no effect on the return value of this method for
+   * future callers.
+   *
+   * @return this class' annotations.
+   * @since 1.5
+   */
+  public Annotation[] getAnnotations()
+  {
+    HashSet set = new HashSet();
+    set.addAll(Arrays.asList(getDeclaredAnnotations()));
+    Class[] interfaces = getInterfaces();
+    for (int i = 0; i < interfaces.length; i++)
+      set.addAll(Arrays.asList(interfaces[i].getAnnotations()));
+    Class superClass = getSuperclass();
+    if (superClass != null)
+      set.addAll(Arrays.asList(superClass.getAnnotations()));
+    return (Annotation[]) set.toArray(new Annotation[set.size()]);
+  }
+
+  /**
    * <p>
    * Returns the canonical name of this class, as defined by section
    * 6.7 of the Java language specification.  Each package, top-level class,
@@ -1460,6 +1519,22 @@
   }
 
   /**
+   * Returns all annotations directly defined by this class.  If there are
+   * no annotations associated with this class, then a zero-length array
+   * will be returned.  The returned array may be modified by the client
+   * code, but this will have no effect on the annotation content of this
+   * class, and hence no effect on the return value of this method for
+   * future callers.
+   *
+   * @return the annotations directly defined by this class.
+   * @since 1.5
+   */
+  public Annotation[] getDeclaredAnnotations()
+  {
+    return VMClass.getDeclaredAnnotations(this);
+  }
+
+  /**
    * Returns the class which immediately encloses this class.  If this class
    * is a top-level class, this method returns <code>null</code>.
    *
@@ -1622,6 +1697,22 @@
   }
 
   /**
+   * Returns true if an annotation for the specified type is associated
+   * with this class.  This is primarily a short-hand for using marker
+   * annotations.
+   *
+   * @param annotationClass the type of annotation to look for.
+   * @return true if an annotation exists for the specified type.
+   * @since 1.5
+   */
+  /* FIXME[GENERICS]: Should be Class<? extends Annotation> */
+  public boolean isAnnotationPresent(Class
+                                    annotationClass)
+  {
+    return getAnnotation(annotationClass) != null;
+  }
+
+  /**
    * Returns true if this object represents an anonymous class.
    *
    * @return true if this object represents an anonymous class.
Index: vm/reference/java/lang/VMClass.java
===================================================================
RCS file: /cvsroot/classpath/classpath/vm/reference/java/lang/VMClass.java,v
retrieving revision 1.16
diff -u -r1.16 VMClass.java
--- vm/reference/java/lang/VMClass.java 3 Apr 2006 20:09:14 -0000       1.16
+++ vm/reference/java/lang/VMClass.java 21 Apr 2006 13:09:40 -0000
@@ -1,5 +1,5 @@
 /* VMClass.java -- VM Specific Class methods
-   Copyright (C) 2003, 2004, 2005 Free Software Foundation
+   Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation
 
 This file is part of GNU Classpath.
 
@@ -37,9 +37,11 @@
 
 package java.lang;
 
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Array;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
@@ -331,6 +333,60 @@
   }
 
   /**
+   * Returns the enumeration constants of this class, or
+   * null if this class is not an <code>Enum</code>.
+   *
+   * @param klass the class whose enumeration constants should be returned.
+   * @return an array of <code>Enum</code> constants
+   *         associated with this class, or null if this
+   *         class is not an <code>enum</code>.
+   * @since 1.5
+   */
+  static Object[] getEnumConstants(Class klass)
+  {
+    if (isEnum(klass))
+      {
+       try
+         {
+           return (Object[])
+             klass.getMethod("values", new Class[0]).invoke(null, new 
Object[0]);
+         }
+       catch (NoSuchMethodException exception)
+         {
+           throw new Error("Enum lacks values() method");
+         }
+       catch (IllegalAccessException exception)
+         {
+           throw new Error("Unable to access Enum class");
+         }
+       catch (InvocationTargetException exception)
+         {
+           throw new
+             RuntimeException("The values method threw an exception",
+                              exception);
+         }
+      }
+    else
+      {
+       return null;
+      }
+  }
+
+  /**
+   * Returns all annotations directly defined by the specified class.  If
+   * there are no annotations associated with this class, then a zero-length
+   * array will be returned.  The returned array may be modified by the client
+   * code, but this will have no effect on the annotation content of this
+   * class, and hence no effect on the return value of this method for
+   * future callers.
+   *
+   * @param klass the class whose annotations should be returned.
+   * @return the annotations directly defined by the specified class.
+   * @since 1.5
+   */
+  static native Annotation[] getDeclaredAnnotations(Class klass);
+
+  /**
    * <p>
    * Returns the canonical name of the specified class, as defined by section
    * 6.7 of the Java language specification.  Each package, top-level class,

Reply via email to