re PR libgcj/35020 (Class.getSimpleName() differs from Sun Java)
[gcc.git] / libjava / java / lang / Class.java
index f301f3584271003a5bd8ce2d34536a77fbf53f3a..a4e8ee5929e5a15e8dbec891d875e49ac2172108 100644 (file)
@@ -1,5 +1,5 @@
 /* Class.java -- Representation of a Java class.
-   Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006
+   Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation
 
 This file is part of GNU Classpath.
@@ -38,21 +38,31 @@ exception statement from your version. */
 
 package java.lang;
 
+import gnu.java.lang.reflect.ClassSignatureParser;
 import java.io.InputStream;
 import java.io.Serializable;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.GenericDeclaration;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
 import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.HashMap;
+import java.util.Collection;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Inherited;
+import java.lang.reflect.AccessibleObject;
 
 /**
  * A Class represents a Java type.  There will never be multiple Class
@@ -83,7 +93,8 @@ import java.util.HashSet;
  * @since 1.0
  * @see ClassLoader
  */
-public final class Class 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
@@ -112,7 +123,7 @@ public final class Class implements Type, GenericDeclaration, Serializable
    * @throws ExceptionInInitializerError if the class loads, but an exception
    *         occurs during initialization
    */
-  public static native Class forName (String className)
+  public static native Class<?> forName (String className)
     throws ClassNotFoundException;
 
   // A private internal method that is called by compiler-generated code.
@@ -147,8 +158,8 @@ public final class Class implements Type, GenericDeclaration, Serializable
    * @see ClassLoader
    * @since 1.2
    */
-  public static native Class forName (String className, boolean initialize,
-                                     ClassLoader loader)
+  public static native Class<?> forName (String className, boolean initialize,
+                                        ClassLoader loader)
     throws ClassNotFoundException;
   
   /**
@@ -163,7 +174,7 @@ public final class Class implements Type, GenericDeclaration, Serializable
    * @throws SecurityException if the security check fails
    * @since 1.1
    */
-  public Class[] getClasses()
+  public Class<?>[] getClasses()
   {
     memberAccessCheck(Member.PUBLIC);
     return internalGetClasses();
@@ -172,16 +183,16 @@ public final class Class implements Type, GenericDeclaration, Serializable
   /**
    * Like <code>getClasses()</code> but without the security checks.
    */
-  private Class[] internalGetClasses()
+  private Class<?>[] internalGetClasses()
   {
-    ArrayList list = new ArrayList();
+    ArrayList<Class> list = new ArrayList<Class>();
     list.addAll(Arrays.asList(getDeclaredClasses(true)));
     Class superClass = getSuperclass();
     if (superClass != null)
       list.addAll(Arrays.asList(superClass.internalGetClasses()));
-    return (Class[])list.toArray(new Class[list.size()]);
+    return list.toArray(new Class<?>[list.size()]);
   }
-  
+
   /**
    * Get the ClassLoader that loaded this class.  If the class was loaded
    * by the bootstrap classloader, this method will return null.
@@ -216,7 +227,7 @@ public final class Class implements Type, GenericDeclaration, Serializable
    * @see Array
    * @since 1.1
    */
-  public native Class getComponentType ();
+  public native Class<?> getComponentType ();
 
   /**
    * Get a public constructor declared in this class. If the constructor takes
@@ -232,7 +243,7 @@ public final class Class implements Type, GenericDeclaration, Serializable
    * @see #getConstructors()
    * @since 1.1
    */
-  public native Constructor getConstructor(Class[] args)
+  public native Constructor<T> getConstructor(Class<?>... args)
     throws NoSuchMethodException;
 
   /**
@@ -247,7 +258,7 @@ public final class Class implements Type, GenericDeclaration, Serializable
    * @throws SecurityException if the security check fails
    * @since 1.1
    */
-  public Constructor[] getConstructors()
+  public Constructor<?>[] getConstructors()
   {
     memberAccessCheck(Member.PUBLIC);
     return getDeclaredConstructors(true);
@@ -267,7 +278,7 @@ public final class Class implements Type, GenericDeclaration, Serializable
    * @see #getDeclaredConstructors()
    * @since 1.1
    */
-  public native Constructor getDeclaredConstructor(Class[] args)
+  public native Constructor<T> getDeclaredConstructor(Class<?>... args)
     throws NoSuchMethodException;
 
   /**
@@ -282,13 +293,13 @@ public final class Class implements Type, GenericDeclaration, Serializable
    * @throws SecurityException if the security check fails
    * @since 1.1
    */
-  public Class[] getDeclaredClasses()
+  public Class<?>[] getDeclaredClasses()
   {
     memberAccessCheck(Member.DECLARED);
     return getDeclaredClasses(false);
   }
 
-  native Class[] getDeclaredClasses (boolean publicOnly);
+  native Class<?>[] getDeclaredClasses (boolean publicOnly);
 
   /**
    * Get all the declared constructors of this class. This returns an array of
@@ -302,13 +313,13 @@ public final class Class implements Type, GenericDeclaration, Serializable
    * @throws SecurityException if the security check fails
    * @since 1.1
    */
-  public Constructor[] getDeclaredConstructors()
+  public Constructor<?>[] getDeclaredConstructors()
   {
     memberAccessCheck(Member.DECLARED);
     return getDeclaredConstructors(false);
   }
 
-  native Constructor[] getDeclaredConstructors (boolean publicOnly);
+  native Constructor<?>[] getDeclaredConstructors (boolean publicOnly);
 
   /**
    * Get a field declared in this class, where name is its simple name. The
@@ -369,7 +380,7 @@ public final class Class implements Type, GenericDeclaration, Serializable
    * @see #getDeclaredMethods()
    * @since 1.1
    */
-  public Method getDeclaredMethod(String methodName, Class[] args)
+  public Method getDeclaredMethod(String methodName, Class<?>... args)
     throws NoSuchMethodException
   {
     memberAccessCheck(Member.DECLARED);
@@ -409,7 +420,7 @@ public final class Class implements Type, GenericDeclaration, Serializable
    * @since 1.1
    */
   // This is marked as unimplemented in the JCL book.
-  public native Class getDeclaringClass ();
+  public native Class<?> getDeclaringClass ();
 
   private native Field getField (String fieldName, int hash)
     throws NoSuchFieldException;
@@ -462,7 +473,7 @@ public final class Class implements Type, GenericDeclaration, Serializable
    */
   private Field[] internalGetFields()
   {
-    HashSet set = new HashSet();
+    LinkedHashSet set = new LinkedHashSet();
     set.addAll(Arrays.asList(getDeclaredFields(true)));
     Class[] interfaces = getInterfaces();
     for (int i = 0; i < interfaces.length; i++)
@@ -498,7 +509,7 @@ public final class Class implements Type, GenericDeclaration, Serializable
    *
    * @return the interfaces this class directly implements
    */
-  public native Class[] getInterfaces ();
+  public native Class<?>[] getInterfaces ();
 
   private final native void getSignature(StringBuffer buffer);
   private static final native String getSignature(Class[] args,
@@ -528,7 +539,7 @@ public final class Class implements Type, GenericDeclaration, Serializable
    * @see #getMethods()
    * @since 1.1
    */
-  public Method getMethod(String methodName, Class[] args)
+  public Method getMethod(String methodName, Class<?>... args)
     throws NoSuchMethodException
   {
     memberAccessCheck(Member.PUBLIC);
@@ -701,7 +712,7 @@ public final class Class implements Type, GenericDeclaration, Serializable
    *
    * @return the direct superclass of this class
    */
-  public native Class getSuperclass ();
+  public native Class<? super T> getSuperclass ();
   
   /**
    * Return whether this class is an array type.
@@ -725,7 +736,7 @@ public final class Class implements Type, GenericDeclaration, Serializable
    * @throws NullPointerException if c is null
    * @since 1.1
    */
-  public native boolean isAssignableFrom (Class c);
+  public native boolean isAssignableFrom (Class<?> c);
  
   /**
    * Discover whether an Object is an instance of this Class.  Think of it
@@ -783,7 +794,7 @@ public final class Class implements Type, GenericDeclaration, Serializable
    * @throws ExceptionInInitializerError if class initialization caused by
    *         this call fails with an exception
    */
-  public native Object newInstance ()
+  public native T newInstance ()
     throws InstantiationException, IllegalAccessException;
 
   // We need a native method to retrieve the protection domain, because we
@@ -930,6 +941,125 @@ public final class Class implements Type, GenericDeclaration, Serializable
       }
   }
 
+
+  /**
+   * <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>.
+   *
+   * @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 T[] getEnumConstants()
+  {
+    if (isEnum())
+      {
+       try
+         {
+            Method m = getMethod("values");
+            setAccessible(m);
+           return (T[]) m.invoke(null);
+         }
+       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 true if this class is an <code>Enum</code>.
+   *
+   * @return true if this is an enumeration class.
+   * @since 1.5
+   */
+  public native boolean isEnum();
+
+
+  /**
+   * Returns true if this class is a synthetic class, generated by
+   * the compiler.
+   *
+   * @return true if this is a synthetic class.
+   * @since 1.5
+   */
+  public native boolean isSynthetic();
+
+
+  /**
+   * Returns true if this class is an <code>Annotation</code>.
+   *
+   * @return true if this is an annotation class.
+   * @since 1.5
+   */
+  public native boolean isAnnotation();
+
+
   /**
    * Returns the simple name for this class, as used in the source
    * code.  For normal classes, this is the content returned by
@@ -945,25 +1075,27 @@ public final class Class implements Type, GenericDeclaration, Serializable
    */
   public String getSimpleName()
   {
-    // FIXME write real implementation
-    return "";
-  }
+    if (isAnonymousClass())
+      return "";
+    if (isArray())
+      return getComponentType().getSimpleName() + "[]";
 
-  /**
-   * 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()
-  {
-    // FIXME write real implementation
-    return new Annotation[0];
+    String fullName = getName();
+    Class enclosingClass = getEnclosingClass();
+    if (enclosingClass == null)
+      // It's a top level class.
+      return fullName.substring(fullName.lastIndexOf(".") + 1);
+
+    fullName = fullName.substring(enclosingClass.getName().length());
+
+    // We've carved off the enclosing class name; now we must have '$'
+    // followed optionally by digits, followed by the class name.
+    int pos = 1;
+    while (Character.isDigit(fullName.charAt(pos)))
+      ++pos;
+    fullName = fullName.substring(pos);
+
+    return fullName;
   }
 
   /**
@@ -974,12 +1106,7 @@ public final class Class implements Type, GenericDeclaration, Serializable
    *         a top-level class.
    * @since 1.5
    */
-   /* FIXME[GENERICS]: Should return Class<?> */
-  public Class getEnclosingClass()
-  {
-    // FIXME write real implementation
-    return null;
-  }
+  public native Class<?> getEnclosingClass();
 
   /**
    * Returns the constructor which immediately encloses this class.  If
@@ -992,12 +1119,7 @@ public final class Class implements Type, GenericDeclaration, Serializable
    *         is returned.
    * @since 1.5
    */
-   /* FIXME[GENERICS]: Should return Constructor<?> */
-  public Constructor getEnclosingConstructor()
-  {
-    // FIXME write real implementation
-    return null;
-  }
+  public native Constructor<T> getEnclosingConstructor();
 
   /**
    * Returns the method which immediately encloses this class.  If
@@ -1010,10 +1132,100 @@ public final class Class implements Type, GenericDeclaration, Serializable
    *         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();
   }
 
   /**
@@ -1022,29 +1234,197 @@ public final class Class implements Type, GenericDeclaration, Serializable
    * 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.
    * @since 1.5
    */
-   /* FIXME[GENERICS]: Should return TypeVariable<Class<T>> */
-  public TypeVariable[] getTypeParameters()
+  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 true if this class is an <code>Enum</code>.
+   * Returns this class' annotation for the specified annotation type,
+   * or <code>null</code> if no such annotation exists.
    *
-   * @return true if this is an enumeration class.
+   * @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 boolean isEnum()
+  public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
   {
-    // FIXME - provide real implementation.
-    return false;
+    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()
+  {
+    HashMap<Class, Annotation> map = new HashMap<Class, Annotation>();
+    for (Annotation a : getDeclaredAnnotations())
+      map.put((Class) a.annotationType(), a);
+    for (Class<? super T> s = getSuperclass();
+        s != null;
+        s = s.getSuperclass())
+      {
+       for (Annotation a : s.getDeclaredAnnotations())
+         {
+           Class k = (Class) a.annotationType();
+           if (! map.containsKey(k) && k.isAnnotationPresent(Inherited.class))
+             map.put(k, a);
+         }
+      }
+    Collection<Annotation> v = map.values();
+    return v.toArray(new Annotation[v.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,
+   * top-level interface and primitive type has a canonical name.  A member
+   * class has a canonical name, if its parent class has one.  Likewise,
+   * an array type has a canonical name, if its component type does.
+   * Local or anonymous classes do not have canonical names.
+   * </p>
+   * <p>
+   * The canonical name for top-level classes, top-level interfaces and
+   * primitive types is always the same as the fully-qualified name.
+   * For array types, the canonical name is the canonical name of its
+   * component type with `[]' appended.  
+   * </p>
+   * <p>
+   * The canonical name of a member class always refers to the place where
+   * the class was defined, and is composed of the canonical name of the
+   * defining class and the simple name of the member class, joined by `.'.
+   *  For example, if a <code>Person</code> class has an inner class,
+   * <code>M</code>, then both its fully-qualified name and canonical name
+   * is <code>Person.M</code>.  A subclass, <code>Staff</code>, of
+   * <code>Person</code> refers to the same inner class by the fully-qualified
+   * name of <code>Staff.M</code>, but its canonical name is still
+   * <code>Person.M</code>.
+   * </p>
+   * <p>
+   * Where no canonical name is present, <code>null</code> is returned.
+   * </p>
+   *
+   * @return the canonical name of the class, or <code>null</code> if the
+   *         class doesn't have a canonical name.
+   * @since 1.5
+   */
+  public String getCanonicalName()
+  {
+    if (isArray())
+      {
+       String componentName = getComponentType().getCanonicalName();
+       if (componentName != null)
+         return componentName + "[]";
+      }
+    if (isMemberClass())
+      {
+       String memberName = getDeclaringClass().getCanonicalName();
+       if (memberName != null)
+         return memberName + "." + getSimpleName();
+      }
+    if (isLocalClass() || isAnonymousClass())
+      return null;
+    return getName();
+  }
+
+  /**
+   * 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;
+  }
+
+  /**
+   * Returns true if this object represents an anonymous class.
+   *
+   * @return true if this object represents an anonymous class.
+   * @since 1.5
+   */
+  public native boolean isAnonymousClass();
+
+  /**
+   * Returns true if this object represents an local class.
+   *
+   * @return true if this object represents an local class.
+   * @since 1.5
+   */
+  public native boolean isLocalClass();
+
+  /**
+   * Returns true if this object represents an member class.
+   *
+   * @return true if this object represents an member class.
+   * @since 1.5
+   */
+  public native boolean isMemberClass();
+
+  /**
+   * Utility method for use by classes in this package.
+   */
+  static void setAccessible(final AccessibleObject obj)
+  {
+    AccessController.doPrivileged(new PrivilegedAction()
+      {
+        public Object run()
+          {
+            obj.setAccessible(true);
+            return null;
+          }
+      });
+  }
 }