This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[ecj] Patch: FYI: initial draft of annotation support


I'm checking this in on the gcj-eclipse branch.

In order to build this you will need a new version of gcjh.jar.  This
patch found a bug in the gcjh rewrite.  I've uploaded the new jar to
the usual place:

    http://people.redhat.com/~tromey/gcjh/

This is the initial draft of runtime annotation and "extended"
reflection support.  This draft only covers the runtime side; the
compiler patch is just so that gcj properly initializes the new field
in Class.

See the gcj list for information on how this works.  The code
duplication is a little silly, really, but it does work ok and (IMO)
is not extremely obscure or hard to maintain.

This handles the Signature attribute, the EnclosingMethod attribute,
and annotations, including parameter annotations.

To do:

* Compiler support
* InnerClasses attribute
* Actual instantiation of annotations -- the needed class will appear
  in Classpath 0.92
* Caching of the generated annotations
* A few Classpath bug fixes (PR 28203)
* Change defineclass.cc so that it does not rewrite arbitrary
  utf8consts -- big problem
* Fix handling of 'c' and implement 'e' types for annotation elements

That's a lot unfinished... but I wanted to get this out of my tree
before the weekend.

Tom

Index: gcc/java/ChangeLog
from  Tom Tromey  <tromey@redhat.com>
	* class.c (make_class_data): Set value for reflection_data field.
	* decl.c (java_init_decl_processing): Add reflection_data field.

Index: libjava/ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	* defineclass.cc (input_data, input_offset): New fields.
	(reflection_data, data_stream): Likewise.
	(get_reflection_stream): New method.
	(_Jv_ClassReader): Initialize new fields.
	(parse): Call finish_reflection_data.
	(finish_reflection_data): New method.
	(handleEnclosingMethod): Likewise.
	(handleGenericSignature): Likewise.
	(handleAnnotationElement): Likewise.
	(handleAnnotation): Likewise.
	(handleAnnotations): Likewise.
	(handleMemberAnnotations): Likewise.
	(handleAnnotationDefault): Likewise.
	(handleParameterAnnotations): Likewise.
	(read_one_field_attribute): Handle new attributes.
	(read_one_method_attribute): Likewise.
	(read_one_class_attribute): Likewise.
	* include/jvm.h (resolve_method_entry): New method.
	* java/lang/Class.h (jv_attr_type, jv_attr_kind): New enums.
	(Class): Updated for new methods.  Field, Method, Constructor now
	friends.
	(reflection_data): New field.
	* java/lang/Class.java (asSubclass, cast): New methods.
	(getEnclosingClass, getEnclosingConstructor): Now native.
	(getEnclosingMethod): Likewise.
	(getClassSignature): New method.
	(getGenericInterfaces, getGenericSuperclass, getTypeParameters):
	Likewise.
	(Class): Implements AnnotatedElement.
	(getAnnotation, isAnnotationPresent, getAnnotations): New methods.
	(getDeclaredAnnotations): New method.
	(getDeclaredAnnotationsInternal): Likewise.
	* java/lang/reflect/natConstructor.cc (anno_a_t, anno_aa_t): New
	typedefs.
	(getSignature): New method.
	(getDeclaredAnnotationsInternal): Likewise.
	(getParameterAnnotationsInternal): Likewise.
	* java/lang/reflect/natField.cc (anno_a_t): New typedef.
	(getSignature): New method.
	(getDeclaredAnnotationsInternal): Likewise.
	* java/lang/reflect/natMethod.cc (anno_a_t, anno_aa_t): New
	typedefs.
	(getSignature): New method.
	(getDefaultValue): Likewise.
	(getDeclaredAnnotationsInternal): Likewise.
	(getParameterAnnotationsInternal): Likewise.
	* java/lang/reflect/Constructor.java (addTypeParameters):
	Genericized.
	(getSignature): Now native.
	(getDeclaredAnnotations, getDeclaredAnnotationsInternal,
	getParameterAnnotations, getParameterAnnotationsInternal): New
	methods.
	* java/lang/reflect/Field.java (getDeclaringClass, getType):
	Genericized.
	(getSignature): Now native.
	(getDeclaredAnnotations, getDeclaredAnnotationsInternal): New
	methods.
	* java/lang/reflect/Method.java (getReturnType): Genericized.
	(getParameterTypes, getExceptionTypes, getTypeParameters):
	Likewise.
	(getSignature): Now native.
	(getDefaultValue, getDeclaredAnnotations,
	getParameterAnnotations, getDeclaredAnnotationsInternal,
	getParameterAnnotationsInternal): New methods.
	* java/lang/natClass.cc (read_u1): New functions.
	(read_u2): Likewise.
	(read_4): New function.
	(getReflectionSignature): New methods.
	(getClassSignature): New method.
	(getEnclosingMethodData): Likewise.
	(getEnclosingClass): Likewise.
	(getEnclosingMethod): Likewise.
	(getEnclosingConstructor): Likewise.
	(check_constant): New function.
	(parseAnnotationElement): Likewise.
	(parseAnnotation): Likewise.
	(parseAnnotations): Likewise.
	(parseParameterAnnotations): Likewise.
	(getMethodDefaultValue): New method.
	(getDeclaredAnnotations): New methods.
	(getDeclaredAnnotationsInternal): New method.
	* boehm.cc (_Jv_MarkObj): Mark 'reflection_data' field.
	* link.cc (resolve_method_entry): New method.
	(resolve_pool_entry): Use it.

Index: gcc/java/class.c
===================================================================
--- gcc/java/class.c	(revision 115280)
+++ gcc/java/class.c	(working copy)
@@ -2008,6 +2008,7 @@
   PUSH_FIELD_VALUE (cons, "chain", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "aux_info", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "engine", null_pointer_node);
+  PUSH_FIELD_VALUE (cons, "reflection_data", null_pointer_node);
 
   FINISH_RECORD_CONSTRUCTOR (cons);
 
Index: gcc/java/decl.c
===================================================================
--- gcc/java/decl.c	(revision 115280)
+++ gcc/java/decl.c	(working copy)
@@ -1,6 +1,6 @@
 /* Process declarations and variables for the GNU compiler for the
    Java(TM) language.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -967,6 +967,7 @@
   PUSH_FIELD (class_type_node, field, "chain", ptr_type_node);
   PUSH_FIELD (class_type_node, field, "aux_info", ptr_type_node);
   PUSH_FIELD (class_type_node, field, "engine", ptr_type_node);
+  PUSH_FIELD (class_type_node, field, "reflection_data", ptr_type_node);
   for (t = TYPE_FIELDS (class_type_node);  t != NULL_TREE;  t = TREE_CHAIN (t))
     FIELD_PRIVATE (t) = 1;
   push_super_field (class_type_node, object_type_node);
Index: libjava/link.cc
===================================================================
--- libjava/link.cc	(revision 114871)
+++ libjava/link.cc	(working copy)
@@ -266,6 +266,114 @@
   return the_field;
 }
 
+_Jv_Method *
+_Jv_Linker::resolve_method_entry (jclass klass, jclass &found_class,
+				  int class_index, int name_and_type_index,
+				  bool init, bool is_iface)
+{
+  _Jv_Constants *pool = &klass->constants;
+  jclass owner = resolve_pool_entry (klass, class_index).clazz;
+
+  if (init && owner != klass)
+    _Jv_InitClass (owner);
+
+  _Jv_ushort name_index, type_index;
+  _Jv_loadIndexes (&pool->data[name_and_type_index],
+		   name_index,
+		   type_index);
+
+  _Jv_Utf8Const *method_name = pool->data[name_index].utf8;
+  _Jv_Utf8Const *method_signature = pool->data[type_index].utf8;
+
+  _Jv_Method *the_method = 0;
+  found_class = 0;
+
+  // We're going to cache a pointer to the _Jv_Method object
+  // when we find it.  So, to ensure this doesn't get moved from
+  // beneath us, we first put all the needed Miranda methods
+  // into the target class.
+  wait_for_state (klass, JV_STATE_LOADED);
+
+  // First search the class itself.
+  the_method = search_method_in_class (owner, klass,
+				       method_name, method_signature);
+
+  if (the_method != 0)
+    {
+      found_class = owner;
+      goto end_of_method_search;
+    }
+
+  // If we are resolving an interface method, search the
+  // interface's superinterfaces (A superinterface is not an
+  // interface's superclass - a superinterface is implemented by
+  // the interface).
+  if (is_iface)
+    {
+      _Jv_ifaces ifaces;
+      ifaces.count = 0;
+      ifaces.len = 4;
+      ifaces.list = (jclass *) _Jv_Malloc (ifaces.len
+					   * sizeof (jclass *));
+
+      get_interfaces (owner, &ifaces);
+
+      for (int i = 0; i < ifaces.count; i++)
+	{
+	  jclass cls = ifaces.list[i];
+	  the_method = search_method_in_class (cls, klass, method_name, 
+					       method_signature);
+	  if (the_method != 0)
+	    {
+	      found_class = cls;
+	      break;
+	    }
+	}
+
+      _Jv_Free (ifaces.list);
+
+      if (the_method != 0)
+	goto end_of_method_search;
+    }
+
+  // Finally, search superclasses. 
+  for (jclass cls = owner->getSuperclass (); cls != 0; 
+       cls = cls->getSuperclass ())
+    {
+      the_method = search_method_in_class (cls, klass, method_name,
+					   method_signature);
+      if (the_method != 0)
+	{
+	  found_class = cls;
+	  break;
+	}
+    }
+
+ end_of_method_search:
+
+  // FIXME: if (cls->loader != klass->loader), then we
+  // must actually check that the types of arguments
+  // correspond.  That is, for each argument type, and
+  // the return type, doing _Jv_FindClassFromSignature
+  // with either loader should produce the same result,
+  // i.e., exactly the same jclass object. JVMS 5.4.3.3    
+    
+  if (the_method == 0)
+    {
+      java::lang::StringBuffer *sb = new java::lang::StringBuffer();
+      sb->append(JvNewStringLatin1("method "));
+      sb->append(owner->getName());
+      sb->append(JvNewStringLatin1("."));
+      sb->append(_Jv_NewStringUTF(method_name->chars()));
+      sb->append(JvNewStringLatin1(" with signature "));
+      sb->append(_Jv_NewStringUTF(method_signature->chars()));
+      sb->append(JvNewStringLatin1(" was not found."));
+      throw new java::lang::NoSuchMethodError (sb->toString());
+    }
+
+  return the_method;
+}
+
 _Jv_word
 _Jv_Linker::resolve_pool_entry (jclass klass, int index, bool lazy)
 {
@@ -399,105 +507,14 @@
 	_Jv_loadIndexes (&pool->data[index],
 			 class_index,
 			 name_and_type_index);
-	jclass owner = (resolve_pool_entry (klass, class_index)).clazz;
 
-	if (owner != klass)
-	  _Jv_InitClass (owner);
+	_Jv_Method *the_method;
+	jclass found_class;
+	the_method = resolve_method_entry (klass, found_class,
+					   class_index, name_and_type_index,
+					   true,
+					   pool->tags[index] == JV_CONSTANT_InterfaceMethodref);
 
-	_Jv_ushort name_index, type_index;
-	_Jv_loadIndexes (&pool->data[name_and_type_index],
-			 name_index,
-			 type_index);
-
-	_Jv_Utf8Const *method_name = pool->data[name_index].utf8;
-	_Jv_Utf8Const *method_signature = pool->data[type_index].utf8;
-
-	_Jv_Method *the_method = 0;
-	jclass found_class = 0;
-
-	// We're going to cache a pointer to the _Jv_Method object
-	// when we find it.  So, to ensure this doesn't get moved from
-	// beneath us, we first put all the needed Miranda methods
-	// into the target class.
-	wait_for_state (klass, JV_STATE_LOADED);
-
-	// First search the class itself.
-	the_method = search_method_in_class (owner, klass,
-					     method_name, method_signature);
-
-	if (the_method != 0)
-	  {
-	    found_class = owner;
-	    goto end_of_method_search;
-	  }
-
-	// If we are resolving an interface method, search the
-	// interface's superinterfaces (A superinterface is not an
-	// interface's superclass - a superinterface is implemented by
-	// the interface).
-	if (pool->tags[index] == JV_CONSTANT_InterfaceMethodref)
-	  {
-	    _Jv_ifaces ifaces;
-	    ifaces.count = 0;
-	    ifaces.len = 4;
-	    ifaces.list = (jclass *) _Jv_Malloc (ifaces.len
-						 * sizeof (jclass *));
-
-	    get_interfaces (owner, &ifaces);
-
-	    for (int i = 0; i < ifaces.count; i++)
-	      {
-		jclass cls = ifaces.list[i];
-		the_method = search_method_in_class (cls, klass, method_name, 
-						     method_signature);
-		if (the_method != 0)
-		  {
-		    found_class = cls;
-		    break;
-		  }
-	      }
-
-	    _Jv_Free (ifaces.list);
-
-	    if (the_method != 0)
-	      goto end_of_method_search;
-	  }
-
-	// Finally, search superclasses. 
-	for (jclass cls = owner->getSuperclass (); cls != 0; 
-	     cls = cls->getSuperclass ())
-	  {
-	    the_method = search_method_in_class (cls, klass, method_name,
-						 method_signature);
-	    if (the_method != 0)
-	      {
-		found_class = cls;
-		break;
-	      }
-	  }
-
-      end_of_method_search:
-    
-	// FIXME: if (cls->loader != klass->loader), then we
-	// must actually check that the types of arguments
-	// correspond.  That is, for each argument type, and
-	// the return type, doing _Jv_FindClassFromSignature
-	// with either loader should produce the same result,
-	// i.e., exactly the same jclass object. JVMS 5.4.3.3    
-    
-	if (the_method == 0)
-	  {
-	    java::lang::StringBuffer *sb = new java::lang::StringBuffer();
-	    sb->append(JvNewStringLatin1("method "));
-	    sb->append(owner->getName());
-	    sb->append(JvNewStringLatin1("."));
-	    sb->append(_Jv_NewStringUTF(method_name->chars()));
-	    sb->append(JvNewStringLatin1(" with signature "));
-	    sb->append(_Jv_NewStringUTF(method_signature->chars()));
-	    sb->append(JvNewStringLatin1(" was not found."));
-	    throw new java::lang::NoSuchMethodError (sb->toString());
-	  }
-      
 	pool->data[index].rmethod
 	  = klass->engine->resolve_method(the_method,
 					  found_class,
Index: libjava/boehm.cc
===================================================================
--- libjava/boehm.cc	(revision 114871)
+++ libjava/boehm.cc	(working copy)
@@ -167,6 +167,9 @@
       MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
       p = (GC_PTR) c->aux_info;
       MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
+
+      p = (GC_PTR) c->reflection_data;
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
     }
   else
     {
Index: libjava/java/lang/natClass.cc
===================================================================
--- libjava/java/lang/natClass.cc	(revision 114871)
+++ libjava/java/lang/natClass.cc	(working copy)
@@ -56,6 +56,18 @@
 #include <gcj/method.h>
 #include <gnu/gcj/RawData.h>
 #include <java/lang/VerifyError.h>
+#include <java/lang/InternalError.h>
+#include <java/lang/TypeNotPresentException.h>
+#include <java/lang/Byte.h>
+#include <java/lang/Short.h>
+#include <java/lang/Integer.h>
+#include <java/lang/Float.h>
+#include <java/lang/Double.h>
+#include <java/lang/Long.h>
+#include <java/lang/Character.h>
+#include <java/lang/Boolean.h>
+#include <java/lang/annotation/Annotation.h>
+#include <java/util/HashMap.h>
 
 #include <java-cpool.h>
 #include <java-interp.h>
@@ -851,6 +863,526 @@
 
 
 
+static unsigned char
+read_u1 (unsigned char *&p)
+{
+  return *p++;
+}
+
+static unsigned char
+read_u1 (unsigned char *&p, unsigned char *next)
+{
+  if (next - p < 1)
+    throw new java::lang::InternalError();
+  return *p++;
+}
+
+static unsigned int
+read_u2 (unsigned char *&p)
+{
+  unsigned int b1 = *p++;
+  unsigned int b2 = *p++;
+  return (b1 << 8) | b2;
+}
+
+static unsigned int
+read_u2 (unsigned char *&p, unsigned char *next)
+{
+  if (next - p < 2)
+    throw new java::lang::InternalError();
+  return read_u2 (p);
+}
+
+static int
+read_4 (unsigned char *&p)
+{
+  int b1 = *p++;
+  int b2 = *p++;
+  int b3 = *p++;
+  int b4 = *p++;
+  return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
+}
+
+jstring
+java::lang::Class::getReflectionSignature (jint /*jv_attr_type*/ type,
+					   jint obj_index)
+{
+  // We just re-parse the bytecode for this data each time.  If
+  // necessary we can cache results, but I suspect this is not
+  // performance sensitive.
+  unsigned char *bytes = reflection_data;
+  if (bytes == NULL)
+    return NULL;
+  while (true)
+    {
+      int kind = read_u1 (bytes);
+      if (kind == JV_DONE_ATTR)
+	return NULL;
+      int len = read_4 (bytes);
+      unsigned char *next = bytes + len;
+      if (kind != type)
+	{
+	  bytes = next;
+	  continue;
+	}
+      if (type != JV_CLASS_ATTR)
+	{
+	  unsigned short index = read_u2 (bytes, next);
+	  if (index != obj_index)
+	    {
+	      bytes = next;
+	      continue;
+	    }
+	}
+      int nt = read_u1 (bytes, next);
+      if (nt != JV_SIGNATURE_KIND)
+	{
+	  bytes = next;
+	  continue;
+	}
+      unsigned int cpool_idx = read_u2 (bytes, next);
+      if (cpool_idx >= (unsigned int) constants.size
+	  || constants.tags[cpool_idx] != JV_CONSTANT_Utf8)
+	{
+	  // We just ignore errors for now.  It isn't clear what is
+	  // best to do here, as an encoding error here means a bug
+	  // either in the compiler or in defineclass.cc.
+	  return NULL;
+	}
+      return _Jv_NewStringUtf8Const (constants.data[cpool_idx].utf8);
+    }
+}
+
+jstring
+java::lang::Class::getReflectionSignature (::java::lang::reflect::Constructor *c)
+{
+  _Jv_Method *meth = _Jv_FromReflectedConstructor (c);
+  unsigned short meth_index = meth - methods;
+  return getReflectionSignature (JV_METHOD_ATTR, meth_index);
+}
+
+jstring
+java::lang::Class::getReflectionSignature (::java::lang::reflect::Method *m)
+{
+  _Jv_Method *meth = _Jv_FromReflectedMethod (m);
+  unsigned short meth_index = meth - methods;
+  return getReflectionSignature (JV_METHOD_ATTR, meth_index);
+}
+
+jstring
+java::lang::Class::getReflectionSignature (::java::lang::reflect::Field *f)
+{
+  _Jv_Field *fld = _Jv_FromReflectedField (f);
+  unsigned short fld_index = fld - fields;
+  return getReflectionSignature (JV_FIELD_ATTR, fld_index);
+}
+
+jstring
+java::lang::Class::getClassSignature()
+{
+  return getReflectionSignature (JV_CLASS_ATTR, 0);
+}
+
+jint
+java::lang::Class::getEnclosingMethodData()
+{
+  unsigned char *bytes = reflection_data;
+  if (bytes == NULL)
+    return 0;
+  while (true)
+    {
+      int kind = read_u1 (bytes);
+      if (kind == JV_DONE_ATTR)
+	return 0;
+      int len = read_4 (bytes);
+      unsigned char *next = bytes + len;
+      if (kind != JV_CLASS_ATTR)
+	{
+	  bytes = next;
+	  continue;
+	}
+      int type = read_u1 (bytes, next);
+      if (type != JV_ENCLOSING_METHOD_KIND)
+	{
+	  bytes = next;
+	  continue;
+	}
+      int class_index = read_u2 (bytes, next);
+      int method_index = read_u2 (bytes, next);
+      _Jv_word result;
+      _Jv_storeIndexes (&result, class_index, method_index);
+      return result.i;
+    }
+}
+
+jclass
+java::lang::Class::getEnclosingClass()
+{
+  _Jv_word indexes;
+  indexes.i = getEnclosingMethodData();
+  if (indexes.i == 0)
+    return NULL;
+  _Jv_ushort class_index, method_index;
+  _Jv_loadIndexes (&indexes, class_index, method_index);
+  return _Jv_Linker::resolve_pool_entry (this, class_index).clazz;
+}
+
+::java::lang::reflect::Method *
+java::lang::Class::getEnclosingMethod()
+{
+  _Jv_word indexes;
+  indexes.i = getEnclosingMethodData();
+  if (indexes.i == 0)
+    return NULL;
+  _Jv_ushort class_index, method_index;
+  _Jv_loadIndexes (&indexes, class_index, method_index);
+  jclass found_class;
+  _Jv_Method *method = _Jv_Linker::resolve_method_entry (this, found_class,
+							 class_index,
+							 method_index,
+							 false, false);
+  using namespace java::lang::reflect;
+  Method *rmethod = new Method ();
+  rmethod->offset = (char *) method - (char *) found_class->methods;
+  rmethod->declaringClass = found_class;
+  return rmethod;
+}
+
+::java::lang::reflect::Constructor *
+java::lang::Class::getEnclosingConstructor()
+{
+  _Jv_word indexes;
+  indexes.i = getEnclosingMethodData();
+  if (indexes.i == 0)
+    return NULL;
+  _Jv_ushort class_index, method_index;
+  _Jv_loadIndexes (&indexes, class_index, method_index);
+  jclass found_class;
+  _Jv_Method *method = _Jv_Linker::resolve_method_entry (this, found_class,
+							 class_index,
+							 method_index,
+							 false, false);
+  using namespace java::lang::reflect;
+  Constructor *cons = new Constructor ();
+  cons->offset = (char *) method - (char *) found_class->methods;
+  cons->declaringClass = this;
+  return cons;
+}
+
+static void
+check_constant(_Jv_Constants *pool, jint cpool_index, jint type)
+{
+  if (cpool_index <= 0
+      || cpool_index >= pool->size
+      || pool->tags[cpool_index] != type)
+    throw new InternalError();
+}
+
+// Forward declaration
+static ::java::lang::annotation::Annotation *
+parseAnnotation(jclass klass, _Jv_Constants *pool,
+		unsigned char *&bytes, unsigned char *last);
+
+static jobject
+parseAnnotationElement(jclass klass, _Jv_Constants *pool,
+		       unsigned char *&bytes, unsigned char *last)
+{
+  int tag = read_u1 (bytes, last);
+  jobject result;
+  switch (tag)
+    {
+    case 'B':
+      {
+	int cindex = read_u2 (bytes, last);
+	check_constant (pool, cindex, JV_CONSTANT_Integer);
+	result = Byte::valueOf (pool->data[cindex].i);
+      }
+      break;
+    case 'C':
+      {
+	int cindex = read_u2 (bytes, last);
+	check_constant (pool, cindex, JV_CONSTANT_Integer);
+	result = Character::valueOf (pool->data[cindex].i);
+      }
+      break;
+    case 'S':
+      {
+	int cindex = read_u2 (bytes, last);
+	check_constant (pool, cindex, JV_CONSTANT_Integer);
+	result = Short::valueOf (pool->data[cindex].i);
+      }
+      break;
+    case 'Z':
+      {
+	int cindex = read_u2 (bytes, last);
+	check_constant (pool, cindex, JV_CONSTANT_Integer);
+	result = Boolean::valueOf (jboolean (pool->data[cindex].i));
+      }
+      break;
+    case 'I':
+      {
+	int cindex = read_u2 (bytes, last);
+	check_constant (pool, cindex, JV_CONSTANT_Integer);
+	result = Integer::valueOf (pool->data[cindex].i);
+      }
+      break;
+    case 'D':
+      {
+	int cindex = read_u2 (bytes, last);
+	check_constant (pool, cindex, JV_CONSTANT_Double);
+	_Jv_word2 word;
+	memcpy (&word, &pool->data[cindex], 2 * sizeof (_Jv_word));
+	result = Double::valueOf (word.d);
+      }
+      break;
+    case 'F':
+      {
+	int cindex = read_u2 (bytes, last);
+	check_constant (pool, cindex, JV_CONSTANT_Float);
+	result = Float::valueOf (pool->data[cindex].f);
+      }
+      break;
+    case 'J':
+      {
+	int cindex = read_u2 (bytes, last);
+	check_constant (pool, cindex, JV_CONSTANT_Double);
+	_Jv_word2 word;
+	memcpy (&word, &pool->data[cindex], 2 * sizeof (_Jv_word));
+	result = Long::valueOf (word.l);
+      }
+      break;
+    case 's':
+      {
+	int cindex = read_u2 (bytes, last);
+	check_constant (pool, cindex, JV_CONSTANT_String);
+	result = _Jv_Linker::resolve_pool_entry (klass, cindex).string;
+      }
+      break;
+    case 'e':
+      {
+	// FIXME
+// 	uint16 type_name_index = JCF_readu2 (jcf);
+// 	uint16 const_name_index = JCF_readu2 (jcf);
+      }
+      break;
+    case 'c':
+      {
+	// FIXME: should be a Utf8 here!
+	int cindex = read_u2 (bytes, last);
+	check_constant (pool, cindex, JV_CONSTANT_Class);
+	try
+	  {
+	    result
+	      = _Jv_Linker::resolve_pool_entry (klass, cindex, false).clazz;
+	  }
+	catch (NoClassDefFoundError *err)
+	  {
+	    throw new TypeNotPresentException(err->getMessage(), err);
+	  }
+      }
+      break;
+    case '@':
+      result = parseAnnotation (klass, pool, bytes, last);
+      break;
+    case '[':
+      {
+	int n_array_elts = read_u2 (bytes, last);
+	jobjectArray aresult = _Jv_NewObjectArray (n_array_elts,
+						   &Object::class$, NULL);
+	jobject *elts = elements (aresult);
+	for (int i = 0; i < n_array_elts; ++i)
+	  elts[i] = parseAnnotationElement(klass, pool, bytes, last);
+	result = aresult;
+      }
+      break;
+    default:
+      throw new java::lang::InternalError();
+    }
+  return result;
+}
+
+static ::java::lang::annotation::Annotation *
+parseAnnotation(jclass klass, _Jv_Constants *pool,
+		unsigned char *&bytes, unsigned char *last)
+{
+  int type_index = read_u2 (bytes, last);
+  check_constant (pool, type_index, JV_CONSTANT_Utf8);
+  jclass anno_class = NULL; // FIXME ... and share code with 'c' case
+
+  ::java::util::HashMap *hmap = new ::java::util::HashMap();
+  int npairs = read_u2 (bytes, last);
+  for (int i = 0; i < npairs; ++i)
+    {
+      int name_index = read_u2 (bytes, last);
+      check_constant (pool, name_index, JV_CONSTANT_Utf8);
+      jstring name = _Jv_NewStringUtf8Const (pool->data[name_index].utf8);
+      jobject value = parseAnnotationElement (klass, pool, bytes, last);
+      // FIXME: any checks needed for name?
+      hmap->put(name, value);
+    }
+  // FIXME: use AnnotationInvocationHandler here.
+  // FIXME: add a static method to it for creation, that handles defaults.
+  return NULL;
+}
+
+static jobjectArray
+parseAnnotations(jclass klass, _Jv_Constants *pool,
+		 unsigned char *&bytes, unsigned char *last)
+{
+  int num = read_u2 (bytes, last);
+  jobjectArray result = _Jv_NewObjectArray (num,
+					    &::java::lang::annotation::Annotation::class$,
+					    NULL);
+  jobject *elts = elements (result);
+  for (int i = 0; i < num; ++i)
+    elts[i] = parseAnnotation(klass, pool, bytes, last);
+  return result;
+}
+
+static jobjectArray
+parseParameterAnnotations(jclass klass, _Jv_Constants *pool,
+			  unsigned char *&bytes, unsigned char *last)
+{
+  jclass anno = &::java::lang::annotation::Annotation::class$;
+  jclass annoary = _Jv_GetArrayClass (anno, anno->getClassLoaderInternal());
+
+  // FIXME: something should check the number of params versus the
+  // method
+  int n_params = read_u1 (bytes, last);
+  jobjectArray result = _Jv_NewObjectArray (n_params, annoary, NULL);
+  jobject *elts = elements (result);
+  for (int i = 0; i < n_params; ++i)
+    elts[i] = parseAnnotations(klass, pool, bytes, last);
+  return result;
+}
+
+jobject
+java::lang::Class::getMethodDefaultValue(::java::lang::reflect::Method *meth)
+{
+  // FIXME: could cache the value here...
+
+  unsigned char *bytes = reflection_data;
+  if (bytes == NULL)
+    return 0;
+
+  unsigned short meth_index = _Jv_FromReflectedMethod (meth) - methods;
+
+  while (true)
+    {
+      int kind = read_u1 (bytes);
+      if (kind == JV_DONE_ATTR)
+	return NULL;
+      int len = read_4 (bytes);
+      unsigned char *next = bytes + len;
+      if (kind != JV_METHOD_ATTR)
+	{
+	  bytes = next;
+	  continue;
+	}
+      int type = read_u1 (bytes, next);
+      if (type != JV_ANNOTATION_DEFAULT_KIND)
+	{
+	  bytes = next;
+	  continue;
+	}
+      int index = read_u2 (bytes, next);
+      if (meth_index != index)
+	{
+	  bytes = next;
+	  continue;
+	}
+
+      // FIXME: could cache here.  If we do then we have to clone any
+      // array result.
+      return parseAnnotationElement(this, &this->constants, bytes, next);
+    }
+}
+
+jobjectArray
+java::lang::Class::getDeclaredAnnotations(jint /* jv_attr_type */ member_type,
+					  jint member_index,
+					  jint /* jv_attr_kind */ kind_req)
+{
+  // FIXME: could cache the value here...
+
+  unsigned char *bytes = reflection_data;
+  if (bytes == NULL)
+    return 0;
+
+  while (true)
+    {
+      int type = read_u1 (bytes);
+      if (type == JV_DONE_ATTR)
+	return NULL;
+      int len = read_4 (bytes);
+      unsigned char *next = bytes + len;
+      if (type != member_type)
+	{
+	  bytes = next;
+	  continue;
+	}
+      int kind = read_u1 (bytes, next);
+      if (kind != kind_req)
+	{
+	  bytes = next;
+	  continue;
+	}
+      if (member_type != JV_CLASS_ATTR)
+	{
+	  int index = read_u2 (bytes, next);
+	  if (member_index != index)
+	    {
+	      bytes = next;
+	      continue;
+	    }
+	}
+
+      // FIXME: could cache here.  If we do then we have to clone any
+      // array result.
+      if (kind_req == JV_PARAMETER_ANNOTATIONS_KIND)
+	return parseParameterAnnotations (this, &this->constants, bytes, next);
+      return parseAnnotations (this, &this->constants, bytes, next);
+    }
+}
+
+jobjectArray
+java::lang::Class::getDeclaredAnnotations(::java::lang::reflect::Method *meth,
+					  jboolean is_param)
+{
+  unsigned short meth_index = _Jv_FromReflectedMethod (meth) - methods;
+  return getDeclaredAnnotations(JV_METHOD_ATTR, meth_index,
+				(is_param
+				 ? JV_PARAMETER_ANNOTATIONS_KIND
+				 : JV_ANNOTATIONS_KIND));
+}
+
+jobjectArray
+java::lang::Class::getDeclaredAnnotations(::java::lang::reflect::Constructor *cons,
+					  jboolean is_param)
+{
+  unsigned short meth_index = _Jv_FromReflectedConstructor (cons) - methods;
+  return getDeclaredAnnotations(JV_METHOD_ATTR, meth_index,
+				(is_param
+				 ? JV_PARAMETER_ANNOTATIONS_KIND
+				 : JV_ANNOTATIONS_KIND));
+}
+
+jobjectArray
+java::lang::Class::getDeclaredAnnotations(::java::lang::reflect::Field *fld)
+{
+  unsigned short field_index = _Jv_FromReflectedField (fld) - fields;
+  return getDeclaredAnnotations(JV_FIELD_ATTR, field_index,
+				JV_ANNOTATIONS_KIND);
+}
+
+JArray< ::java::lang::annotation::Annotation *> *
+java::lang::Class::getDeclaredAnnotationsInternal()
+{
+  return (JArray< ::java::lang::annotation::Annotation *> *) getDeclaredAnnotations(JV_CLASS_ATTR, 0, JV_ANNOTATIONS_KIND);
+}
+
+
+
 //
 // Some class-related convenience functions.
 //
Index: libjava/java/lang/reflect/Method.java
===================================================================
--- libjava/java/lang/reflect/Method.java	(revision 114933)
+++ libjava/java/lang/reflect/Method.java	(working copy)
@@ -12,6 +12,7 @@
 
 import gnu.gcj.RawData;
 import gnu.java.lang.reflect.MethodSignatureParser;
+import java.lang.annotation.Annotation;
 
 /**
  * The Method class represents a member method of a class. It also allows
@@ -132,7 +133,7 @@
    * Gets the return type of this method.
    * @return the type of this method
    */
-  public Class getReturnType ()
+  public Class<?> getReturnType ()
   {
     if (return_type == null)
       getType();
@@ -145,11 +146,11 @@
    *
    * @return a list of the types of the method's parameters
    */
-  public Class[] getParameterTypes ()
+  public Class<?>[] getParameterTypes ()
   {
     if (parameter_types == null)
       getType();
-    return (Class[]) parameter_types.clone();
+    return (Class<?>[]) parameter_types.clone();
   }
 
   /**
@@ -159,11 +160,11 @@
    *
    * @return a list of the types in the method's throws clause
    */
-  public Class[] getExceptionTypes ()
+  public Class<?>[] getExceptionTypes ()
   {
     if (exception_types == null)
       getType();
-    return (Class[]) exception_types.clone();
+    return (Class<?>[]) exception_types.clone();
   }
 
   /**
@@ -325,8 +326,7 @@
    *         specification, version 3.
    * @since 1.5
    */
-  /* FIXME[GENERICS]: Should be TypeVariable<Method>[] */
-  public TypeVariable[] getTypeParameters()
+  public TypeVariable<Method>[] getTypeParameters()
   {
     String sig = getSignature();
     if (sig == null)
@@ -339,11 +339,7 @@
    * Return the String in the Signature attribute for this method. If there
    * is no Signature attribute, return null.
    */
-  private String getSignature()
-  {
-    // FIXME: libgcj doesn't record this information yet.
-    return null;
-  }
+  private native String getSignature();
 
   /**
    * Returns an array of <code>Type</code> objects that represents
@@ -405,6 +401,40 @@
     return p.getGenericReturnType();
   }
 
+  /**
+   * If this method is an annotation method, returns the default
+   * value for the method.  If there is no default value, or if the
+   * method is not a member of an annotation type, returns null.
+   * Primitive types are wrapped.
+   *
+   * @throws TypeNotPresentException if the method returns a Class,
+   * and the class cannot be found
+   *
+   * @since 1.5
+   */
+  public native Object getDefaultValue();
+
+  public Annotation[] getDeclaredAnnotations()
+  {
+    Annotation[] result = getDeclaredAnnotationsInternal();
+    if (result == null)
+      result = new Annotation[0];
+    return result;
+  }
+
+  public Annotation[][] getParameterAnnotations()
+  {
+    // FIXME: should check that we have the right number
+    // of parameters ...?
+    Annotation[][] result = getParameterAnnotationsInternal();
+    if (result == null)
+      result = new Annotation[0][0];
+    return result;
+  }
+
+  private native Annotation[] getDeclaredAnnotationsInternal();
+  private native Annotation[][] getParameterAnnotationsInternal();
+
   private native void getType ();
 
   // Append a class name to a string buffer.  We try to print the
Index: libjava/java/lang/reflect/Field.java
===================================================================
--- libjava/java/lang/reflect/Field.java	(revision 114871)
+++ libjava/java/lang/reflect/Field.java	(working copy)
@@ -41,6 +41,7 @@
 import gnu.java.lang.ClassHelper;
 
 import gnu.java.lang.reflect.FieldSignatureParser;
+import java.lang.annotation.Annotation;
 
 /**
  * The Field class represents a member variable of a class. It also allows
@@ -104,7 +105,7 @@
    * is a non-inherited member.
    * @return the class that declared this member
    */
-  public Class getDeclaringClass()
+  public Class<?> getDeclaringClass()
   {
     return declaringClass;
   }
@@ -158,7 +159,7 @@
    * Gets the type of this field.
    * @return the type of this field
    */
-  public native Class getType();
+  public native Class<?> getType();
 
   /**
    * Compare two objects to see if they are semantically equivalent.
@@ -733,15 +734,21 @@
     return p.getFieldType();
   }
 
+  public Annotation[] getDeclaredAnnotations()
+  {
+    Annotation[] result = getDeclaredAnnotationsInternal();
+    if (result == null)
+      result = new Annotation[0];
+    return result;
+  }
+
+  private native Annotation[] getDeclaredAnnotationsInternal();
+
   /**
    * Return the String in the Signature attribute for this field. If there
    * is no Signature attribute, return null.
    */
-  private String getSignature()
-  {
-    // FIXME: libgcj doesn't record Signature attributes yet.
-    return null;
-  }
+  private native String getSignature();
 
   native void setByte (Class caller, Object obj, byte b, boolean checkFinal)
     throws IllegalArgumentException, IllegalAccessException;
Index: libjava/java/lang/reflect/Constructor.java
===================================================================
--- libjava/java/lang/reflect/Constructor.java	(revision 114933)
+++ libjava/java/lang/reflect/Constructor.java	(working copy)
@@ -40,6 +40,7 @@
 package java.lang.reflect;
 
 import gnu.java.lang.reflect.MethodSignatureParser;
+import java.lang.annotation.Annotation;
 
 /**
  * The Constructor class represents a constructor of a class. It also allows
@@ -235,8 +236,8 @@
     return b.toString();
   }
 
-  /* FIXME[GENERICS]: Add X extends GenericDeclaration and TypeVariable<X> */
-  static void addTypeParameters(StringBuilder sb, TypeVariable[] typeArgs)
+  static <X extends GenericDeclaration>
+  void addTypeParameters(StringBuilder sb, TypeVariable<X>[] typeArgs)
   {
     if (typeArgs.length == 0)
       return;
@@ -333,11 +334,7 @@
    * Return the String in the Signature attribute for this constructor. If there
    * is no Signature attribute, return null.
    */
-  private String getSignature()
-  {
-    // FIXME: libgcj doesn't record this information yet.
-    return null;
-  }
+  private native String getSignature();
 
   /**
    * Returns an array of <code>Type</code> objects that represents
@@ -381,6 +378,27 @@
     return p.getGenericParameterTypes();
   }
 
+  public Annotation[] getDeclaredAnnotations()
+  {
+    Annotation[] result = getDeclaredAnnotationsInternal();
+    if (result == null)
+      result = new Annotation[0];
+    return result;
+  }
+
+  public Annotation[][] getParameterAnnotations()
+  {
+    // FIXME: should check that we have the right number
+    // of parameters ...?
+    Annotation[][] result = getParameterAnnotationsInternal();
+    if (result == null)
+      result = new Annotation[0][0];
+    return result;
+  }
+
+  private native Annotation[] getDeclaredAnnotationsInternal();
+  private native Annotation[][] getParameterAnnotationsInternal();
+
   // Update cached values from method descriptor in class.
   private native void getType ();
 
Index: libjava/java/lang/reflect/natMethod.cc
===================================================================
--- libjava/java/lang/reflect/natMethod.cc	(revision 114871)
+++ libjava/java/lang/reflect/natMethod.cc	(working copy)
@@ -48,6 +48,11 @@
 #include <java/lang/UnsupportedOperationException.h>
 #endif
 
+typedef JArray< ::java::lang::annotation::Annotation * > * anno_a_t;
+typedef JArray< JArray< ::java::lang::annotation::Annotation * > *> * anno_aa_t;
+
+
+
 struct cpair
 {
   jclass prim;
@@ -189,6 +194,32 @@
 }
 
 jstring
+java::lang::reflect::Method::getSignature()
+{
+  return declaringClass->getReflectionSignature (this);
+}
+
+jobject
+java::lang::reflect::Method::getDefaultValue()
+{
+  return declaringClass->getMethodDefaultValue(this);
+}
+
+anno_a_t
+java::lang::reflect::Method::getDeclaredAnnotationsInternal()
+{
+  anno_a_t result;
+  return (anno_a_t) declaringClass->getDeclaredAnnotations(this, false);
+}
+
+anno_aa_t
+java::lang::reflect::Method::getParameterAnnotationsInternal()
+{
+  anno_aa_t result;
+  return (anno_aa_t) declaringClass->getDeclaredAnnotations(this, true);
+}
+
+jstring
 java::lang::reflect::Method::getName ()
 {
   if (name == NULL)
Index: libjava/java/lang/reflect/natField.cc
===================================================================
--- libjava/java/lang/reflect/natField.cc	(revision 114871)
+++ libjava/java/lang/reflect/natField.cc	(working copy)
@@ -29,6 +29,8 @@
 #include <java/lang/Boolean.h>
 #include <java/lang/Character.h>
 
+typedef JArray< ::java::lang::annotation::Annotation * > * anno_a_t;
+
 jint
 java::lang::reflect::Field::getModifiersInternal ()
 {
@@ -36,6 +38,19 @@
 }
 
 jstring
+java::lang::reflect::Field::getSignature()
+{
+  return declaringClass->getReflectionSignature (this);
+}
+
+anno_a_t
+java::lang::reflect::Field::getDeclaredAnnotationsInternal()
+{
+  anno_a_t result;
+  return (anno_a_t) declaringClass->getDeclaredAnnotations(this);
+}
+
+jstring
 java::lang::reflect::Field::getName ()
 {
   if (name == NULL)
Index: libjava/java/lang/reflect/natConstructor.cc
===================================================================
--- libjava/java/lang/reflect/natConstructor.cc	(revision 114871)
+++ libjava/java/lang/reflect/natConstructor.cc	(working copy)
@@ -23,12 +23,35 @@
 #include <java/lang/InstantiationException.h>
 #include <gcj/method.h>
 
+typedef JArray< ::java::lang::annotation::Annotation * > * anno_a_t;
+typedef JArray< JArray< ::java::lang::annotation::Annotation * > *> * anno_aa_t;
+
 jint
 java::lang::reflect::Constructor::getModifiersInternal ()
 {
   return _Jv_FromReflectedConstructor (this)->accflags;
 }
 
+jstring
+java::lang::reflect::Constructor::getSignature()
+{
+  return declaringClass->getReflectionSignature (this);
+}
+
+anno_a_t
+java::lang::reflect::Constructor::getDeclaredAnnotationsInternal()
+{
+  anno_a_t result;
+  return (anno_a_t) declaringClass->getDeclaredAnnotations(this, false);
+}
+
+anno_aa_t
+java::lang::reflect::Constructor::getParameterAnnotationsInternal()
+{
+  anno_aa_t result;
+  return (anno_aa_t) declaringClass->getDeclaredAnnotations(this, true);
+}
+
 void
 java::lang::reflect::Constructor::getType ()
 {
Index: libjava/java/lang/Class.java
===================================================================
--- libjava/java/lang/Class.java	(revision 114933)
+++ libjava/java/lang/Class.java	(working copy)
@@ -38,6 +38,7 @@
 
 package java.lang;
 
+import gnu.java.lang.reflect.ClassSignatureParser;
 import java.io.InputStream;
 import java.io.Serializable;
 import java.lang.reflect.Constructor;
@@ -53,6 +54,8 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.annotation.Annotation;
 
 /**
  * A Class represents a Java type.  There will never be multiple Class
@@ -83,7 +86,8 @@
  * @since 1.0
  * @see ClassLoader
  */
-public final class Class<T> implements Type, GenericDeclaration, Serializable
+public final class Class<T>
+  implements Type, AnnotatedElement, GenericDeclaration, Serializable
 {
   /**
    * Class is non-instantiable from Java code; only the VM can create
@@ -932,6 +936,56 @@
 
 
   /**
+   * <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
+   * the class object, and instances of that class, can match the contract
+   * of a more restrictive method.  For example, if this class has the
+   * static type of <code>Class&lt;Object&gt;</code>, and a dynamic type of
+   * <code>Class&lt;Rectangle&gt;</code>, then, assuming <code>Shape</code> is
+   * a superclass of <code>Rectangle</code>, this method can be used on
+   * this class with the parameter, <code>Class&lt;Shape&gt;</code>, to retain
+   * the same instance but with the type
+   * <code>Class&lt;? extends Shape&gt;</code>.
+   * </p>
+   * <p>
+   * If this class can be converted to an instance which is parameterised
+   * over a subtype of the supplied type, <code>U</code>, then this method
+   * returns an appropriately cast reference to this object.  Otherwise,
+   * a <code>ClassCastException</code> is thrown.
+   * </p>
+   * 
+   * @param klass the class object, the parameterized type (<code>U</code>) of
+   *              which should be a superclass of the parameterized type of
+   *              this instance.
+   * @return a reference to this object, appropriately cast.
+   * @throws ClassCastException if this class can not be converted to one
+   *                            which represents a subclass of the specified
+   *                            type, <code>U</code>. 
+   * @since 1.5
+   */
+  public <U> Class<? extends U> asSubclass(Class<U> klass)
+  {
+    if (! klass.isAssignableFrom(this))
+      throw new ClassCastException();
+    return (Class<? extends U>) this;
+  }
+
+  /**
+   * Returns the specified object, cast to this <code>Class</code>' type.
+   *
+   * @param obj the object to cast
+   * @throws ClassCastException  if obj is not an instance of this class
+   * @since 1.5
+   */
+  public T cast(Object obj)
+  {
+    if (obj != null && ! isInstance(obj))
+      throw new ClassCastException();
+    return (T) obj;
+  }
+
+  /**
    * Returns the enumeration constants of this class, or
    * null if this class is not an <code>Enum</code>.
    *
@@ -1039,11 +1093,7 @@
    *         a top-level class.
    * @since 1.5
    */
-  public Class<?> getEnclosingClass()
-  {
-    // FIXME write real implementation
-    return null;
-  }
+  public native Class<?> getEnclosingClass();
 
   /**
    * Returns the constructor which immediately encloses this class.  If
@@ -1056,11 +1106,7 @@
    *         is returned.
    * @since 1.5
    */
-  public Constructor<T> getEnclosingConstructor()
-  {
-    // FIXME write real implementation
-    return null;
-  }
+  public native Constructor<T> getEnclosingConstructor();
 
   /**
    * Returns the method which immediately encloses this class.  If
@@ -1073,19 +1119,109 @@
    *         is returned.
    * @since 1.5
    */
-  public Method getEnclosingMethod()
+  public native Method getEnclosingMethod();
+
+  private native String getClassSignature();
+
+  /**
+   * <p>
+   * Returns an array of <code>Type</code> objects which represent the
+   * interfaces directly implemented by this class or extended by this
+   * interface.
+   * </p>
+   * <p>
+   * If one of the superinterfaces is a parameterized type, then the
+   * object returned for this interface reflects the actual type
+   * parameters used in the source code.  Type parameters are created
+   * using the semantics specified by the <code>ParameterizedType</code>
+   * interface, and only if an instance has not already been created.
+   * </p>
+   * <p>
+   * The order of the interfaces in the array matches the order in which
+   * the interfaces are declared.  For classes which represent an array,
+   * an array of two interfaces, <code>Cloneable</code> and
+   * <code>Serializable</code>, is always returned, with the objects in
+   * that order.  A class representing a primitive type or void always
+   * returns an array of zero size.
+   * </p>
+   *
+   * @return an array of interfaces implemented or extended by this class.
+   * @throws GenericSignatureFormatError if the generic signature of one
+   *         of the interfaces does not comply with that specified by the Java
+   *         Virtual Machine specification, 3rd edition.
+   * @throws TypeNotPresentException if any of the superinterfaces refers
+   *         to a non-existant type.
+   * @throws MalformedParameterizedTypeException if any of the interfaces
+   *         refer to a parameterized type that can not be instantiated for
+   *         some reason.
+   * @since 1.5
+   * @see java.lang.reflect.ParameterizedType
+   */
+  public Type[] getGenericInterfaces()
   {
-    // FIXME write real implementation
-    return null;
+    if (isPrimitive())
+      return new Type[0];
+
+    String sig = getClassSignature();
+    if (sig == null)
+      return getInterfaces();
+
+    ClassSignatureParser p = new ClassSignatureParser(this, sig);
+    return p.getInterfaceTypes();
   }
 
   /**
+   * <p>
+   * Returns a <code>Type</code> object representing the direct superclass,
+   * whether class, interface, primitive type or void, of this class.
+   * If this class is an array class, then a class instance representing
+   * the <code>Object</code> class is returned.  If this class is primitive,
+   * an interface, or a representation of either the <code>Object</code>
+   * class or void, then <code>null</code> is returned.
+   * </p>
+   * <p>
+   * If the superclass is a parameterized type, then the
+   * object returned for this interface reflects the actual type
+   * parameters used in the source code.  Type parameters are created
+   * using the semantics specified by the <code>ParameterizedType</code>
+   * interface, and only if an instance has not already been created.
+   * </p>
+   *
+   * @return the superclass of this class.
+   * @throws GenericSignatureFormatError if the generic signature of the
+   *         class does not comply with that specified by the Java
+   *         Virtual Machine specification, 3rd edition.
+   * @throws TypeNotPresentException if the superclass refers
+   *         to a non-existant type.
+   * @throws MalformedParameterizedTypeException if the superclass
+   *         refers to a parameterized type that can not be instantiated for
+   *         some reason.
+   * @since 1.5
+   * @see java.lang.reflect.ParameterizedType
+   */
+  public Type getGenericSuperclass()
+  {
+    if (isArray())
+      return Object.class;
+
+    if (isPrimitive() || isInterface() || this == Object.class)
+      return null;
+
+    String sig = getClassSignature();
+    if (sig == null)
+      return getSuperclass();
+
+    ClassSignatureParser p = new ClassSignatureParser(this, sig);
+    return p.getSuperclassType();
+  }
+
+  /**
    * Returns an array of <code>TypeVariable</code> objects that represents
    * the type variables declared by this class, in declaration order.
    * An array of size zero is returned if this class has no type
    * variables.
    *
-   * @return the type variables associated with this class.
+   * @return the type variables associated with this class. 
    * @throws GenericSignatureFormatError if the generic signature does
    *         not conform to the format specified in the Virtual Machine
    *         specification, version 3.
@@ -1093,7 +1229,91 @@
    */
   public TypeVariable<Class<T>>[] getTypeParameters()
   {
-    // FIXME - provide real implementation.
-    return new TypeVariable[0];
+    String sig = getClassSignature();
+    if (sig == null)
+      return (TypeVariable<Class<T>>[])new TypeVariable[0];
+
+    ClassSignatureParser p = new ClassSignatureParser(this, sig);
+    return p.getTypeParameters();
   }
+
+  /**
+   * 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
+   */
+  public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
+  {
+    A foundAnnotation = null;
+    Annotation[] annotations = getAnnotations();
+    for (Annotation annotation : annotations)
+      if (annotation.annotationType() == annotationClass)
+	foundAnnotation = (A) annotation;
+    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<Annotation> set = new HashSet<Annotation>();
+    set.addAll(Arrays.asList(getDeclaredAnnotations()));
+    Class[] interfaces = getInterfaces();
+    for (int i = 0; i < interfaces.length; i++)
+      set.addAll(Arrays.asList(interfaces[i].getAnnotations()));
+    Class<? super T> superClass = getSuperclass();
+    if (superClass != null)
+      set.addAll(Arrays.asList(superClass.getAnnotations()));
+    return set.toArray(new Annotation[set.size()]);
+  }
+
+  /**
+   * 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()
+  {
+    Annotation[] result = getDeclaredAnnotationsInternal();
+    if (result == null)
+      result = new Annotation[0];
+    return result;
+  }
+
+  private native Annotation[] getDeclaredAnnotationsInternal();
+
+  /**
+   * 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
+   */
+  public boolean isAnnotationPresent(Class<? extends Annotation> 
+				     annotationClass)
+  {
+    return getAnnotation(annotationClass) != null;
+  }
+
 }
Index: libjava/java/lang/Class.h
===================================================================
--- libjava/java/lang/Class.h	(revision 114871)
+++ libjava/java/lang/Class.h	(working copy)
@@ -192,6 +192,24 @@
   _Jv_Utf8Const *op2;
 };
 
+typedef enum
+{
+  JV_CLASS_ATTR,
+  JV_METHOD_ATTR,
+  JV_FIELD_ATTR,
+  JV_DONE_ATTR
+} jv_attr_type;
+
+typedef enum
+{
+  JV_INNER_CLASSES_KIND,
+  JV_ENCLOSING_METHOD_KIND,
+  JV_SIGNATURE_KIND,
+  JV_ANNOTATIONS_KIND,
+  JV_PARAMETER_ANNOTATIONS_KIND,
+  JV_ANNOTATION_DEFAULT_KIND
+} jv_attr_kind;
+
 #define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1)
 
 #define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas)
@@ -288,7 +306,6 @@
 
 void _Jv_sharedlib_register_hook (jclass klass);
 
-
 class java::lang::Class : public java::lang::Object
 {
 public:
@@ -335,6 +352,15 @@
   java::lang::reflect::Method *_getMethod (jstring, JArray<jclass> *);
   java::lang::reflect::Method *_getDeclaredMethod (jstring, JArray<jclass> *);
 
+  jstring getReflectionSignature (jint /*jv_attr_type*/ type,
+				  jint obj_index);
+  jstring getReflectionSignature (::java::lang::reflect::Method *);
+  jstring getReflectionSignature (::java::lang::reflect::Constructor *);
+  jstring getReflectionSignature (::java::lang::reflect::Field *);
+
+  jstring getClassSignature();
+  jobject getMethodDefaultValue (::java::lang::reflect::Method *);
+
 public:
   JArray<java::lang::reflect::Field *> *getFields (void);
 
@@ -397,9 +423,17 @@
 
   JArray<java::lang::reflect::TypeVariable *> *getTypeParameters (void);
 
+  jint getEnclosingMethodData(void);
   java::lang::Class *getEnclosingClass (void);
   java::lang::reflect::Constructor *getEnclosingConstructor (void);
   java::lang::reflect::Method *getEnclosingMethod (void);
+  jobjectArray getDeclaredAnnotations(jint, jint, jint);
+  jobjectArray getDeclaredAnnotations(::java::lang::reflect::Method *,
+				      jboolean);
+  jobjectArray getDeclaredAnnotations(::java::lang::reflect::Constructor *,
+				      jboolean);
+  jobjectArray getDeclaredAnnotations(::java::lang::reflect::Field *);
+  JArray< ::java::lang::annotation::Annotation *> *getDeclaredAnnotationsInternal();
 
   // FIXME: this probably shouldn't be public.
   jint size (void)
@@ -554,6 +588,10 @@
 
   friend void ::_Jv_CopyClassesToSystemLoader (gnu::gcj::runtime::SystemClassLoader *);
 
+  friend class java::lang::reflect::Field;
+  friend class java::lang::reflect::Method;
+  friend class java::lang::reflect::Constructor;
+
   // Chain for class pool.  This also doubles as the ABI version
   // number.  It is only used for this purpose at class registration
   // time, and only for precompiled classes.
@@ -636,6 +674,8 @@
   void *aux_info;
   // Execution engine.
   _Jv_ExecutionEngine *engine;
+  // Reflection data.
+  unsigned char *reflection_data;
 };
 
 // Inline functions that are friends of java::lang::Class
Index: libjava/include/jvm.h
===================================================================
--- libjava/include/jvm.h	(revision 114871)
+++ libjava/include/jvm.h	(working copy)
@@ -273,6 +273,9 @@
   static void print_class_loaded (jclass);
   static void resolve_class_ref (jclass, jclass *);
   static void wait_for_state(jclass, int);
+  static _Jv_Method *resolve_method_entry (jclass, jclass &,
+					   int, int,
+					   bool, bool);
   static _Jv_word resolve_pool_entry (jclass, int, bool =false);
   static void resolve_field (_Jv_Field *, java::lang::ClassLoader *);
   static void verify_type_assertions (jclass);
Index: libjava/defineclass.cc
===================================================================
--- libjava/defineclass.cc	(revision 114871)
+++ libjava/defineclass.cc	(working copy)
@@ -40,6 +40,8 @@
 #include <java/lang/IncompatibleClassChangeError.h>
 #include <java/lang/reflect/Modifier.h>
 #include <java/security/ProtectionDomain.h>
+#include <java/io/DataOutputStream.h>
+#include <java/io/ByteArrayOutputStream.h>
 
 using namespace gcj;
 
@@ -87,6 +89,10 @@
 
   bool verify;
 
+  // original input data.
+  jbyteArray input_data;
+  jint input_offset;
+
   // input data.
   unsigned char     *bytes;
   int                len;
@@ -111,7 +117,11 @@
   // True if this is a 1.5 class file.
   bool             is_15;
 
+  // Buffer holding extra reflection data.
+  ::java::io::ByteArrayOutputStream *reflection_data;
+  ::java::io::DataOutputStream *data_stream;
 
+
   /* check that the given number of input bytes are available */
   inline void check (int num)
   {
@@ -126,7 +136,7 @@
     pos += num;
   }
   
-  /* read an unsignend 1-byte unit */
+  /* read an unsigned 1-byte unit */
   inline static jint get1u (unsigned char* bytes)
   {
     return bytes[0];
@@ -226,6 +236,16 @@
       throw_class_format_error ("erroneous type descriptor");
   }
 
+  ::java::io::DataOutputStream *get_reflection_stream ()
+  {
+    if (reflection_data == NULL)
+      {
+	reflection_data = new ::java::io::ByteArrayOutputStream();
+	data_stream = new ::java::io::DataOutputStream(reflection_data);
+      }
+    return data_stream;
+  }
+
   _Jv_ClassReader (jclass klass, jbyteArray data, jint offset, jint length,
 		   java::security::ProtectionDomain *pd,
 		   _Jv_Utf8Const **name_result)
@@ -234,6 +254,8 @@
       throw_internal_error ("arguments to _Jv_DefineClass");
 
     verify = true;
+    input_data = data;
+    input_offset = offset;
     bytes  = (unsigned char*) (elements (data)+offset);
     len    = length;
     pos    = 0;
@@ -241,6 +263,8 @@
 
     def    = klass;
     found_name = name_result;
+    reflection_data = NULL;
+    data_stream = NULL;
 
     def->size_in_bytes = -1;
     def->vtable_method_count = -1;
@@ -260,6 +284,16 @@
   void read_one_field_attribute (int field);
   void throw_class_format_error (const char *msg);
 
+  void handleEnclosingMethod(int);
+  void handleGenericSignature(jv_attr_type, unsigned short, int);
+  void handleAnnotationElement();
+  void handleAnnotation();
+  void handleAnnotations();
+  void handleMemberAnnotations(jv_attr_type, int, int);
+  void handleAnnotationDefault(int, int);
+  void handleParameterAnnotations(int, int);
+  void finish_reflection_data ();
+
   /** check an utf8 entry, without creating a Utf8Const object */
   bool is_attribute_name (int index, const char *name);
 
@@ -377,6 +411,8 @@
   if (pos != len)
     throw_class_format_error ("unused data before end of file");
 
+  finish_reflection_data ();
+
   // Tell everyone we're done.
   def->state = JV_STATE_READ;
   if (gcj::verbose_class_flag)
@@ -384,6 +420,229 @@
   def->notifyAll ();
 }
 
+void
+_Jv_ClassReader::finish_reflection_data ()
+{
+  if (data_stream == NULL)
+    return;
+  data_stream->writeByte(JV_DONE_ATTR);
+  data_stream->flush();
+  int nbytes = reflection_data->count;
+  unsigned char *new_bytes = (unsigned char *) _Jv_AllocBytes (nbytes);
+  memcpy (new_bytes, elements (reflection_data->buf), nbytes);
+  def->reflection_data = new_bytes;
+}
+
+void
+_Jv_ClassReader::handleEnclosingMethod (int len)
+{
+  if (len != 4)
+    throw_class_format_error ("invalid EnclosingMethod attribute");
+  // FIXME: only allow one...
+
+  int class_index = read2u();
+  check_tag (class_index, JV_CONSTANT_Class);
+  prepare_pool_entry (class_index, JV_CONSTANT_Class);
+
+  int method_index = read2u();
+  // Zero is ok and means no enclosing method.
+  if (method_index != 0)
+    {
+      check_tag (method_index, JV_CONSTANT_NameAndType);
+      prepare_pool_entry (method_index, JV_CONSTANT_NameAndType);
+    }
+
+  ::java::io::DataOutputStream *stream = get_reflection_stream ();
+  stream->writeByte(JV_CLASS_ATTR);
+  stream->writeInt(5);
+  stream->writeByte(JV_ENCLOSING_METHOD_KIND);
+  stream->writeShort(class_index);
+  stream->writeShort(method_index);
+}
+
+void
+_Jv_ClassReader::handleGenericSignature (jv_attr_type type,
+					 unsigned short index,
+					 int len)
+{
+  if (len != 2)
+    throw_class_format_error ("invalid Signature attribute");
+
+  int cpool_idx = read2u();
+  check_tag (cpool_idx, JV_CONSTANT_Utf8);
+  prepare_pool_entry (cpool_idx, JV_CONSTANT_Utf8);
+
+  ::java::io::DataOutputStream *stream = get_reflection_stream ();
+  stream->writeByte(type);
+  int attrlen = 3;
+  if (type != JV_CLASS_ATTR)
+    attrlen += 2;
+  stream->writeInt(attrlen);
+  if (type != JV_CLASS_ATTR)
+    stream->writeShort(index);
+  stream->writeByte(JV_SIGNATURE_KIND);
+  stream->writeShort(cpool_idx);
+}
+
+void
+_Jv_ClassReader::handleAnnotationElement()
+{
+  int tag = read1u();
+  switch (tag)
+    {
+    case 'B':
+    case 'C':
+    case 'S':
+    case 'Z':
+    case 'I':
+      {
+	int index = read2u();
+	check_tag (index, JV_CONSTANT_Integer);
+	prepare_pool_entry (index, JV_CONSTANT_Integer);
+      }
+      break;
+    case 'D':
+      {
+	int index = read2u();
+	check_tag (index, JV_CONSTANT_Double);
+	prepare_pool_entry (index, JV_CONSTANT_Double);
+      }
+      break;
+    case 'F':
+      {
+	int index = read2u();
+	check_tag (index, JV_CONSTANT_Float);
+	prepare_pool_entry (index, JV_CONSTANT_Float);
+      }
+      break;
+    case 'J':
+      {
+	int index = read2u();
+	check_tag (index, JV_CONSTANT_Long);
+	prepare_pool_entry (index, JV_CONSTANT_Long);
+      }
+      break;
+    case 's':
+      {
+	int index = read2u();
+	check_tag (index, JV_CONSTANT_String);
+	prepare_pool_entry (index, JV_CONSTANT_String);
+      }
+      break;
+
+    case 'e':
+      {
+	int type_name_index = read2u();
+	int const_name_index = read2u ();
+	check_tag (type_name_index, JV_CONSTANT_Utf8);
+	prepare_pool_entry (type_name_index, JV_CONSTANT_Utf8);
+	check_tag (const_name_index, JV_CONSTANT_Utf8);
+	prepare_pool_entry (const_name_index, JV_CONSTANT_Utf8);
+      }
+      break;
+    case 'c':
+      {
+	int index = read2u();
+	check_tag (index, JV_CONSTANT_Utf8);
+	prepare_pool_entry (index, JV_CONSTANT_Utf8);
+      }
+      break;
+    case '@':
+      handleAnnotation();
+      break;
+    case '[':
+      {
+	int n_array_elts = read2u ();
+	for (int i = 0; i < n_array_elts; ++i)
+	  handleAnnotationElement();
+      }
+      break;
+    default:
+      throw_class_format_error ("invalid annotation element");
+    }
+}
+
+void
+_Jv_ClassReader::handleAnnotation()
+{
+  int type_index = read2u();
+  check_tag (type_index, JV_CONSTANT_Utf8);
+  prepare_pool_entry (type_index, JV_CONSTANT_Utf8);
+
+  int npairs = read2u();
+  for (int i = 0; i < npairs; ++i)
+    {
+      int name_index = read2u();
+      check_tag (name_index, JV_CONSTANT_Utf8);
+      handleAnnotationElement();
+    }
+}
+
+void
+_Jv_ClassReader::handleAnnotations()
+{
+  int num = read2u();
+  while (num--)
+    handleAnnotation();
+}
+
+void
+_Jv_ClassReader::handleMemberAnnotations(jv_attr_type member_type,
+					 int member_index,
+					 int len)
+{
+  // We're going to copy the bytes in verbatim.  But first we want to
+  // make sure the attribute is well-formed, and we want to prepare
+  // the constant pool.  So, we save our starting point.
+  int orig_pos = pos;
+
+  handleAnnotations();
+  // FIXME: check that we read all LEN bytes?
+
+  ::java::io::DataOutputStream *stream = get_reflection_stream ();
+  stream->writeByte(member_type);
+  int newLen = len + 1;
+  if (member_type != JV_CLASS_ATTR)
+    newLen += 2;
+  stream->writeInt(newLen);
+  if (member_type != JV_CLASS_ATTR)
+    stream->writeShort(member_index);
+  stream->writeByte(JV_ANNOTATIONS_KIND);
+  // Write the data as-is.
+  stream->write(input_data, input_offset + orig_pos, len);
+}
+
+void
+_Jv_ClassReader::handleAnnotationDefault(int member_index, int len)
+{
+  int orig_pos = pos;
+  handleAnnotationElement();
+
+  ::java::io::DataOutputStream *stream = get_reflection_stream ();
+  stream->writeByte(JV_METHOD_ATTR);
+  stream->writeInt(len + 3);
+  stream->writeByte(JV_ANNOTATION_DEFAULT_KIND);
+  stream->writeShort(member_index);
+  stream->write(input_data, input_offset + orig_pos, len);
+}
+
+void
+_Jv_ClassReader::handleParameterAnnotations(int member_index, int len)
+{
+  int orig_pos = pos;
+
+  int n_params = read1u();
+  for (int i = 0; i < n_params; ++i)
+    handleAnnotations();
+
+  ::java::io::DataOutputStream *stream = get_reflection_stream ();
+  stream->writeByte(JV_METHOD_ATTR);
+  stream->writeByte(len + 3);
+  stream->writeByte(JV_PARAMETER_ANNOTATIONS_KIND);
+  stream->writeShort(member_index);
+  stream->write(input_data, input_offset + orig_pos, len);
+}
+
 void _Jv_ClassReader::read_constpool ()
 {
   tags    = (unsigned char*) _Jv_AllocBytes (pool_count);
@@ -495,22 +754,23 @@
 	      || tags[cv] == JV_CONSTANT_Long
 	      || tags[cv] == JV_CONSTANT_Double
 	      || tags[cv] == JV_CONSTANT_String))
-	  {
-	    handleConstantValueAttribute (field_index, cv);
-	  }
-	else
-	  {
-	    throw_class_format_error ("erroneous ConstantValue attribute");
-	  }
-
-	if (length != 2) 
+	{
+	  handleConstantValueAttribute (field_index, cv);
+	}
+      else
+	{
 	  throw_class_format_error ("erroneous ConstantValue attribute");
-      }
+	}
 
-    else
-      {
-	skip (length);
-      }
+      if (length != 2) 
+	throw_class_format_error ("erroneous ConstantValue attribute");
+    }
+  else if (is_attribute_name (name, "Signature"))
+    handleGenericSignature(JV_FIELD_ATTR, field_index, length);
+  else if (is_attribute_name (name, "RuntimeVisibleAnnotations"))
+    handleMemberAnnotations(JV_FIELD_ATTR, field_index, length);
+  else
+    skip (length);
 }
 
 void _Jv_ClassReader::read_methods ()
@@ -634,7 +894,14 @@
       if ((pos - start_off) != length)
 	throw_class_format_error ("code attribute too short");
     }
-
+  else if (is_attribute_name (name, "Signature"))
+    handleGenericSignature(JV_METHOD_ATTR, method_index, length);
+  else if (is_attribute_name (name, "RuntimeVisibleAnnotations"))
+    handleMemberAnnotations(JV_METHOD_ATTR, method_index, length);
+  else if (is_attribute_name (name, "RuntimeVisibleParameterAnnotations"))
+    handleParameterAnnotations(method_index, length);
+  else if (is_attribute_name (name, "AnnotationDefault"))
+    handleAnnotationDefault(method_index, length);
   else
     {
       /* ignore unknown attributes */
@@ -684,6 +951,12 @@
       def_interp->source_file_name = _Jv_NewStringUtf8Const
 	(def->constants.data[source_index].utf8);
     }
+  else if (is_attribute_name (name, "Signature"))
+    handleGenericSignature(JV_CLASS_ATTR, 0, length);
+  else if (is_attribute_name (name, "EnclosingMethod"))
+    handleEnclosingMethod(length);
+  else if (is_attribute_name (name, "RuntimeVisibleAnnotations"))
+    handleMemberAnnotations(JV_CLASS_ATTR, 0, length);
   else
     {
       /* Currently, we ignore most class attributes.
@@ -775,6 +1048,8 @@
     {
     case JV_CONSTANT_Utf8: 
       {
+	// FIXME: this is very wrong.
+
 	// If we came here, it is because some other tag needs this
 	// utf8-entry for type information!  Thus, we translate /'s to .'s in
 	// order to accomondate gcj's internal representation.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]