| /* Class.java -- Representation of a Java class. | |
| Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006 | |
| Free Software Foundation | |
| This file is part of GNU Classpath. | |
| GNU Classpath is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 2, or (at your option) | |
| any later version. | |
| GNU Classpath is distributed in the hope that it will be useful, but | |
| WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| General Public License for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with GNU Classpath; see the file COPYING. If not, write to the | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| 02110-1301 USA. | |
| Linking this library statically or dynamically with other modules is | |
| making a combined work based on this library. Thus, the terms and | |
| conditions of the GNU General Public License cover the whole | |
| combination. | |
| As a special exception, the copyright holders of this library give you | |
| permission to link this library with independent modules to produce an | |
| executable, regardless of the license terms of these independent | |
| modules, and to copy and distribute the resulting executable under | |
| terms of your choice, provided that you also meet, for each linked | |
| independent module, the terms and conditions of the license of that | |
| module. An independent module is a module which is not derived from | |
| or based on this library. If you modify this library, you may extend | |
| this exception to your version of the library, but you are not | |
| obligated to do so. If you do not wish to do so, delete this | |
| exception statement from your version. */ | |
| package java.lang; | |
| import gnu.classpath.VMStackWalker; | |
| import gnu.java.lang.reflect.ClassSignatureParser; | |
| import java.io.InputStream; | |
| import java.io.ObjectStreamClass; | |
| import java.io.Serializable; | |
| import java.lang.annotation.Annotation; | |
| import java.lang.reflect.Array; | |
| import java.lang.reflect.AnnotatedElement; | |
| import java.lang.reflect.Constructor; | |
| import java.lang.reflect.Field; | |
| import java.lang.reflect.GenericDeclaration; | |
| import java.lang.reflect.GenericSignatureFormatError; | |
| import java.lang.reflect.InvocationTargetException; | |
| import java.lang.reflect.MalformedParameterizedTypeException; | |
| import java.lang.reflect.Member; | |
| import java.lang.reflect.Method; | |
| import java.lang.reflect.Modifier; | |
| import java.lang.reflect.Type; | |
| import java.lang.reflect.TypeVariable; | |
| import java.net.URL; | |
| import java.security.AccessController; | |
| import java.security.AllPermission; | |
| import java.security.Permissions; | |
| import java.security.PrivilegedAction; | |
| import java.security.ProtectionDomain; | |
| import java.util.ArrayList; | |
| import java.util.Arrays; | |
| import java.util.HashMap; | |
| import java.util.HashSet; | |
| /** | |
| * A Class represents a Java type. There will never be multiple Class | |
| * objects with identical names and ClassLoaders. Primitive types, array | |
| * types, and void also have a Class object. | |
| * | |
| * <p>Arrays with identical type and number of dimensions share the same class. | |
| * The array class ClassLoader is the same as the ClassLoader of the element | |
| * type of the array (which can be null to indicate the bootstrap classloader). | |
| * The name of an array class is <code>[<signature format>;</code>. | |
| * <p> For example, | |
| * String[]'s class is <code>[Ljava.lang.String;</code>. boolean, byte, | |
| * short, char, int, long, float and double have the "type name" of | |
| * Z,B,S,C,I,J,F,D for the purposes of array classes. If it's a | |
| * multidimensioned array, the same principle applies: | |
| * <code>int[][][]</code> == <code>[[[I</code>. | |
| * | |
| * <p>There is no public constructor - Class objects are obtained only through | |
| * the virtual machine, as defined in ClassLoaders. | |
| * | |
| * @serialData Class objects serialize specially: | |
| * <code>TC_CLASS ClassDescriptor</code>. For more serialization information, | |
| * see {@link ObjectStreamClass}. | |
| * | |
| * @author John Keiser | |
| * @author Eric Blake (ebb9@email.byu.edu) | |
| * @author Tom Tromey (tromey@redhat.com) | |
| * @author Andrew John Hughes (gnu_andrew@member.fsf.org) | |
| * @author Tom Tromey (tromey@cygnus.com) | |
| * @since 1.0 | |
| * @see ClassLoader | |
| */ | |
| public final class Class | |
| implements Serializable, Type, AnnotatedElement, GenericDeclaration | |
| { | |
| /** | |
| * Compatible with JDK 1.0+. | |
| */ | |
| private static final long serialVersionUID = 3206093459760846163L; | |
| /** | |
| * Flag indicating a synthetic member. | |
| * Note that this duplicates a constant in Modifier. | |
| */ | |
| private static final int SYNTHETIC = 0x1000; | |
| /** | |
| * Flag indiciating an annotation class. | |
| */ | |
| private static final int ANNOTATION = 0x2000; | |
| /** | |
| * Flag indicating an enum constant or an enum class. | |
| * Note that this duplicates a constant in Modifier. | |
| */ | |
| private static final int ENUM = 0x4000; | |
| /** The class signers. */ | |
| private Object[] signers = null; | |
| /** The class protection domain. */ | |
| private final transient ProtectionDomain pd; | |
| /* We use an inner class, so that Class doesn't have a static initializer */ | |
| private static final class StaticData | |
| { | |
| static final ProtectionDomain unknownProtectionDomain; | |
| static | |
| { | |
| Permissions permissions = new Permissions(); | |
| permissions.add(new AllPermission()); | |
| unknownProtectionDomain = new ProtectionDomain(null, permissions); | |
| } | |
| } | |
| final transient Object vmdata; | |
| /** newInstance() caches the default constructor */ | |
| private transient Constructor constructor; | |
| /** | |
| * Class is non-instantiable from Java code; only the VM can create | |
| * instances of this class. | |
| */ | |
| Class(Object vmdata) | |
| { | |
| this(vmdata, null); | |
| } | |
| Class(Object vmdata, ProtectionDomain pd) | |
| { | |
| this.vmdata = vmdata; | |
| // If the VM didn't supply a protection domain and the class is an array, | |
| // we "inherit" the protection domain from the component type class. This | |
| // saves the VM from having to worry about protection domains for array | |
| // classes. | |
| if (pd == null && isArray()) | |
| this.pd = getComponentType().pd; | |
| else | |
| this.pd = pd; | |
| } | |
| /** | |
| * Use the classloader of the current class to load, link, and initialize | |
| * a class. This is equivalent to your code calling | |
| * <code>Class.forName(name, true, getClass().getClassLoader())</code>. | |
| * | |
| * @param name the name of the class to find | |
| * @return the Class object representing the class | |
| * @throws ClassNotFoundException if the class was not found by the | |
| * classloader | |
| * @throws LinkageError if linking the class fails | |
| * @throws ExceptionInInitializerError if the class loads, but an exception | |
| * occurs during initialization | |
| */ | |
| public static Class forName(String name) throws ClassNotFoundException | |
| { | |
| return VMClass.forName(name, true, VMStackWalker.getCallingClassLoader()); | |
| } | |
| /** | |
| * Use the specified classloader to load and link a class. If the loader | |
| * is null, this uses the bootstrap class loader (provide the security | |
| * check succeeds). Unfortunately, this method cannot be used to obtain | |
| * the Class objects for primitive types or for void, you have to use | |
| * the fields in the appropriate java.lang wrapper classes. | |
| * | |
| * <p>Calls <code>classloader.loadclass(name, initialize)</code>. | |
| * | |
| * @param name the name of the class to find | |
| * @param initialize whether or not to initialize the class at this time | |
| * @param classloader the classloader to use to find the class; null means | |
| * to use the bootstrap class loader | |
| * | |
| * @return the class object for the given class | |
| * | |
| * @throws ClassNotFoundException if the class was not found by the | |
| * classloader | |
| * @throws LinkageError if linking the class fails | |
| * @throws ExceptionInInitializerError if the class loads, but an exception | |
| * occurs during initialization | |
| * @throws SecurityException if the <code>classloader</code> argument | |
| * is <code>null</code> and the caller does not have the | |
| * <code>RuntimePermission("getClassLoader")</code> permission | |
| * @see ClassLoader | |
| * @since 1.2 | |
| */ | |
| public static Class forName(String name, boolean initialize, | |
| ClassLoader classloader) | |
| throws ClassNotFoundException | |
| { | |
| if (classloader == null) | |
| { | |
| // Check if we may access the bootstrap classloader | |
| SecurityManager sm = SecurityManager.current; | |
| if (sm != null) | |
| { | |
| // Get the calling classloader | |
| ClassLoader cl = VMStackWalker.getCallingClassLoader(); | |
| if (cl != null) | |
| sm.checkPermission(new RuntimePermission("getClassLoader")); | |
| } | |
| } | |
| return VMClass.forName(name, initialize, classloader); | |
| } | |
| /** | |
| * Get all the public member classes and interfaces declared in this | |
| * class or inherited from superclasses. This returns an array of length | |
| * 0 if there are no member classes, including for primitive types. A | |
| * security check may be performed, with | |
| * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as | |
| * <code>checkPackageAccess</code> both having to succeed. | |
| * | |
| * @return all public member classes in this class | |
| * @throws SecurityException if the security check fails | |
| * @since 1.1 | |
| */ | |
| public Class[] getClasses() | |
| { | |
| memberAccessCheck(Member.PUBLIC); | |
| return internalGetClasses(); | |
| } | |
| /** | |
| * Like <code>getClasses()</code> but without the security checks. | |
| */ | |
| private Class[] internalGetClasses() | |
| { | |
| ArrayList list = new ArrayList(); | |
| 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()]); | |
| } | |
| /** | |
| * Get the ClassLoader that loaded this class. If the class was loaded | |
| * by the bootstrap classloader, this method will return null. | |
| * If there is a security manager, and the caller's class loader is not | |
| * an ancestor of the requested one, a security check of | |
| * <code>RuntimePermission("getClassLoader")</code> | |
| * must first succeed. Primitive types and void return null. | |
| * | |
| * @return the ClassLoader that loaded this class | |
| * @throws SecurityException if the security check fails | |
| * @see ClassLoader | |
| * @see RuntimePermission | |
| */ | |
| public ClassLoader getClassLoader() | |
| { | |
| if (isPrimitive()) | |
| return null; | |
| ClassLoader loader = VMClass.getClassLoader(this); | |
| // Check if we may get the classloader | |
| SecurityManager sm = SecurityManager.current; | |
| if (loader != null && sm != null) | |
| { | |
| // Get the calling classloader | |
| ClassLoader cl = VMStackWalker.getCallingClassLoader(); | |
| if (cl != null && !cl.isAncestorOf(loader)) | |
| sm.checkPermission(new RuntimePermission("getClassLoader")); | |
| } | |
| return loader; | |
| } | |
| /** | |
| * If this is an array, get the Class representing the type of array. | |
| * Examples: "[[Ljava.lang.String;" would return "[Ljava.lang.String;", and | |
| * calling getComponentType on that would give "java.lang.String". If | |
| * this is not an array, returns null. | |
| * | |
| * @return the array type of this class, or null | |
| * @see Array | |
| * @since 1.1 | |
| */ | |
| public Class getComponentType() | |
| { | |
| return VMClass.getComponentType (this); | |
| } | |
| /** | |
| * Get a public constructor declared in this class. If the constructor takes | |
| * no argument, an array of zero elements and null are equivalent for the | |
| * types argument. A security check may be performed, with | |
| * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as | |
| * <code>checkPackageAccess</code> both having to succeed. | |
| * | |
| * @param types the type of each parameter | |
| * @return the constructor | |
| * @throws NoSuchMethodException if the constructor does not exist | |
| * @throws SecurityException if the security check fails | |
| * @see #getConstructors() | |
| * @since 1.1 | |
| */ | |
| public Constructor getConstructor(Class[] types) throws NoSuchMethodException | |
| { | |
| memberAccessCheck(Member.PUBLIC); | |
| Constructor[] constructors = getDeclaredConstructors(true); | |
| for (int i = 0; i < constructors.length; i++) | |
| { | |
| Constructor constructor = constructors[i]; | |
| if (matchParameters(types, constructor.getParameterTypes())) | |
| return constructor; | |
| } | |
| throw new NoSuchMethodException(); | |
| } | |
| /** | |
| * Get all the public constructors of this class. This returns an array of | |
| * length 0 if there are no constructors, including for primitive types, | |
| * arrays, and interfaces. It does, however, include the default | |
| * constructor if one was supplied by the compiler. A security check may | |
| * be performed, with <code>checkMemberAccess(this, Member.PUBLIC)</code> | |
| * as well as <code>checkPackageAccess</code> both having to succeed. | |
| * | |
| * @return all public constructors in this class | |
| * @throws SecurityException if the security check fails | |
| * @since 1.1 | |
| */ | |
| public Constructor[] getConstructors() | |
| { | |
| memberAccessCheck(Member.PUBLIC); | |
| return getDeclaredConstructors(true); | |
| } | |
| /** | |
| * Get a constructor declared in this class. If the constructor takes no | |
| * argument, an array of zero elements and null are equivalent for the | |
| * types argument. A security check may be performed, with | |
| * <code>checkMemberAccess(this, Member.DECLARED)</code> as well as | |
| * <code>checkPackageAccess</code> both having to succeed. | |
| * | |
| * @param types the type of each parameter | |
| * @return the constructor | |
| * @throws NoSuchMethodException if the constructor does not exist | |
| * @throws SecurityException if the security check fails | |
| * @see #getDeclaredConstructors() | |
| * @since 1.1 | |
| */ | |
| public Constructor getDeclaredConstructor(Class[] types) | |
| throws NoSuchMethodException | |
| { | |
| memberAccessCheck(Member.DECLARED); | |
| Constructor[] constructors = getDeclaredConstructors(false); | |
| for (int i = 0; i < constructors.length; i++) | |
| { | |
| Constructor constructor = constructors[i]; | |
| if (matchParameters(types, constructor.getParameterTypes())) | |
| return constructor; | |
| } | |
| throw new NoSuchMethodException(); | |
| } | |
| /** | |
| * Get all the declared member classes and interfaces in this class, but | |
| * not those inherited from superclasses. This returns an array of length | |
| * 0 if there are no member classes, including for primitive types. A | |
| * security check may be performed, with | |
| * <code>checkMemberAccess(this, Member.DECLARED)</code> as well as | |
| * <code>checkPackageAccess</code> both having to succeed. | |
| * | |
| * @return all declared member classes in this class | |
| * @throws SecurityException if the security check fails | |
| * @since 1.1 | |
| */ | |
| public Class[] getDeclaredClasses() | |
| { | |
| memberAccessCheck(Member.DECLARED); | |
| return getDeclaredClasses(false); | |
| } | |
| Class[] getDeclaredClasses (boolean publicOnly) | |
| { | |
| return VMClass.getDeclaredClasses (this, publicOnly); | |
| } | |
| /** | |
| * Get all the declared constructors of this class. This returns an array of | |
| * length 0 if there are no constructors, including for primitive types, | |
| * arrays, and interfaces. It does, however, include the default | |
| * constructor if one was supplied by the compiler. A security check may | |
| * be performed, with <code>checkMemberAccess(this, Member.DECLARED)</code> | |
| * as well as <code>checkPackageAccess</code> both having to succeed. | |
| * | |
| * @return all constructors in this class | |
| * @throws SecurityException if the security check fails | |
| * @since 1.1 | |
| */ | |
| public Constructor[] getDeclaredConstructors() | |
| { | |
| memberAccessCheck(Member.DECLARED); | |
| return getDeclaredConstructors(false); | |
| } | |
| Constructor[] getDeclaredConstructors (boolean publicOnly) | |
| { | |
| return VMClass.getDeclaredConstructors (this, publicOnly); | |
| } | |
| /** | |
| * Get a field declared in this class, where name is its simple name. The | |
| * implicit length field of arrays is not available. A security check may | |
| * be performed, with <code>checkMemberAccess(this, Member.DECLARED)</code> | |
| * as well as <code>checkPackageAccess</code> both having to succeed. | |
| * | |
| * @param name the name of the field | |
| * @return the field | |
| * @throws NoSuchFieldException if the field does not exist | |
| * @throws SecurityException if the security check fails | |
| * @see #getDeclaredFields() | |
| * @since 1.1 | |
| */ | |
| public Field getDeclaredField(String name) throws NoSuchFieldException | |
| { | |
| memberAccessCheck(Member.DECLARED); | |
| Field[] fields = getDeclaredFields(false); | |
| for (int i = 0; i < fields.length; i++) | |
| { | |
| if (fields[i].getName().equals(name)) | |
| return fields[i]; | |
| } | |
| throw new NoSuchFieldException(); | |
| } | |
| /** | |
| * Get all the declared fields in this class, but not those inherited from | |
| * superclasses. This returns an array of length 0 if there are no fields, | |
| * including for primitive types. This does not return the implicit length | |
| * field of arrays. A security check may be performed, with | |
| * <code>checkMemberAccess(this, Member.DECLARED)</code> as well as | |
| * <code>checkPackageAccess</code> both having to succeed. | |
| * | |
| * @return all declared fields in this class | |
| * @throws SecurityException if the security check fails | |
| * @since 1.1 | |
| */ | |
| public Field[] getDeclaredFields() | |
| { | |
| memberAccessCheck(Member.DECLARED); | |
| return getDeclaredFields(false); | |
| } | |
| Field[] getDeclaredFields (boolean publicOnly) | |
| { | |
| return VMClass.getDeclaredFields (this, publicOnly); | |
| } | |
| /** | |
| * Get a method declared in this class, where name is its simple name. The | |
| * implicit methods of Object are not available from arrays or interfaces. | |
| * Constructors (named "<init>" in the class file) and class initializers | |
| * (name "<clinit>") are not available. The Virtual Machine allows | |
| * multiple methods with the same signature but differing return types; in | |
| * such a case the most specific return types are favored, then the final | |
| * choice is arbitrary. If the method takes no argument, an array of zero | |
| * elements and null are equivalent for the types argument. A security | |
| * check may be performed, with | |
| * <code>checkMemberAccess(this, Member.DECLARED)</code> as well as | |
| * <code>checkPackageAccess</code> both having to succeed. | |
| * | |
| * @param methodName the name of the method | |
| * @param types the type of each parameter | |
| * @return the method | |
| * @throws NoSuchMethodException if the method does not exist | |
| * @throws SecurityException if the security check fails | |
| * @see #getDeclaredMethods() | |
| * @since 1.1 | |
| */ | |
| public Method getDeclaredMethod(String methodName, Class[] types) | |
| throws NoSuchMethodException | |
| { | |
| memberAccessCheck(Member.DECLARED); | |
| Method match = matchMethod(getDeclaredMethods(false), methodName, types); | |
| if (match == null) | |
| throw new NoSuchMethodException(methodName); | |
| return match; | |
| } | |
| /** | |
| * Get all the declared methods in this class, but not those inherited from | |
| * superclasses. This returns an array of length 0 if there are no methods, | |
| * including for primitive types. This does include the implicit methods of | |
| * arrays and interfaces which mirror methods of Object, nor does it | |
| * include constructors or the class initialization methods. The Virtual | |
| * Machine allows multiple methods with the same signature but differing | |
| * return types; all such methods are in the returned array. A security | |
| * check may be performed, with | |
| * <code>checkMemberAccess(this, Member.DECLARED)</code> as well as | |
| * <code>checkPackageAccess</code> both having to succeed. | |
| * | |
| * @return all declared methods in this class | |
| * @throws SecurityException if the security check fails | |
| * @since 1.1 | |
| */ | |
| public Method[] getDeclaredMethods() | |
| { | |
| memberAccessCheck(Member.DECLARED); | |
| return getDeclaredMethods(false); | |
| } | |
| Method[] getDeclaredMethods (boolean publicOnly) | |
| { | |
| return VMClass.getDeclaredMethods (this, publicOnly); | |
| } | |
| /** | |
| * If this is a nested or inner class, return the class that declared it. | |
| * If not, return null. | |
| * | |
| * @return the declaring class of this class | |
| * @since 1.1 | |
| */ | |
| public Class getDeclaringClass() | |
| { | |
| return VMClass.getDeclaringClass (this); | |
| } | |
| /** | |
| * Get a public field declared or inherited in this class, where name is | |
| * its simple name. If the class contains multiple accessible fields by | |
| * that name, an arbitrary one is returned. The implicit length field of | |
| * arrays is not available. A security check may be performed, with | |
| * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as | |
| * <code>checkPackageAccess</code> both having to succeed. | |
| * | |
| * @param fieldName the name of the field | |
| * @return the field | |
| * @throws NoSuchFieldException if the field does not exist | |
| * @throws SecurityException if the security check fails | |
| * @see #getFields() | |
| * @since 1.1 | |
| */ | |
| public Field getField(String fieldName) | |
| throws NoSuchFieldException | |
| { | |
| memberAccessCheck(Member.PUBLIC); | |
| Field field = internalGetField(fieldName); | |
| if (field == null) | |
| throw new NoSuchFieldException(fieldName); | |
| return field; | |
| } | |
| /** | |
| * Get all the public fields declared in this class or inherited from | |
| * superclasses. This returns an array of length 0 if there are no fields, | |
| * including for primitive types. This does not return the implicit length | |
| * field of arrays. A security check may be performed, with | |
| * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as | |
| * <code>checkPackageAccess</code> both having to succeed. | |
| * | |
| * @return all public fields in this class | |
| * @throws SecurityException if the security check fails | |
| * @since 1.1 | |
| */ | |
| public Field[] getFields() | |
| { | |
| memberAccessCheck(Member.PUBLIC); | |
| return internalGetFields(); | |
| } | |
| /** | |
| * Like <code>getFields()</code> but without the security checks. | |
| */ | |
| private Field[] internalGetFields() | |
| { | |
| HashSet set = new HashSet(); | |
| set.addAll(Arrays.asList(getDeclaredFields(true))); | |
| Class[] interfaces = getInterfaces(); | |
| for (int i = 0; i < interfaces.length; i++) | |
| set.addAll(Arrays.asList(interfaces[i].internalGetFields())); | |
| Class superClass = getSuperclass(); | |
| if (superClass != null) | |
| set.addAll(Arrays.asList(superClass.internalGetFields())); | |
| return (Field[])set.toArray(new Field[set.size()]); | |
| } | |
| /** | |
| * Returns the <code>Package</code> in which this class is defined | |
| * Returns null when this information is not available from the | |
| * classloader of this class. | |
| * | |
| * @return the package for this class, if it is available | |
| * @since 1.2 | |
| */ | |
| public Package getPackage() | |
| { | |
| ClassLoader cl = getClassLoader(); | |
| if (cl != null) | |
| return cl.getPackage(getPackagePortion(getName())); | |
| else | |
| return VMClassLoader.getPackage(getPackagePortion(getName())); | |
| } | |
| /** | |
| * Get the interfaces this class <em>directly</em> implements, in the | |
| * order that they were declared. This returns an empty array, not null, | |
| * for Object, primitives, void, and classes or interfaces with no direct | |
| * superinterface. Array types return Cloneable and Serializable. | |
| * | |
| * @return the interfaces this class directly implements | |
| */ | |
| public Class[] getInterfaces() | |
| { | |
| return VMClass.getInterfaces (this); | |
| } | |
| private static final class MethodKey | |
| { | |
| private String name; | |
| private Class[] params; | |
| private Class returnType; | |
| private int hash; | |
| MethodKey(Method m) | |
| { | |
| name = m.getName(); | |
| params = m.getParameterTypes(); | |
| returnType = m.getReturnType(); | |
| hash = name.hashCode() ^ returnType.hashCode(); | |
| for(int i = 0; i < params.length; i++) | |
| { | |
| hash ^= params[i].hashCode(); | |
| } | |
| } | |
| public boolean equals(Object o) | |
| { | |
| if (o instanceof MethodKey) | |
| { | |
| MethodKey m = (MethodKey) o; | |
| if (m.name.equals(name) && m.params.length == params.length | |
| && m.returnType == returnType) | |
| { | |
| for (int i = 0; i < params.length; i++) | |
| { | |
| if (m.params[i] != params[i]) | |
| return false; | |
| } | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| public int hashCode() | |
| { | |
| return hash; | |
| } | |
| } | |
| /** | |
| * Get a public method declared or inherited in this class, where name is | |
| * its simple name. The implicit methods of Object are not available from | |
| * interfaces. Constructors (named "<init>" in the class file) and class | |
| * initializers (name "<clinit>") are not available. The Virtual | |
| * Machine allows multiple methods with the same signature but differing | |
| * return types, and the class can inherit multiple methods of the same | |
| * return type; in such a case the most specific return types are favored, | |
| * then the final choice is arbitrary. If the method takes no argument, an | |
| * array of zero elements and null are equivalent for the types argument. | |
| * A security check may be performed, with | |
| * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as | |
| * <code>checkPackageAccess</code> both having to succeed. | |
| * | |
| * @param methodName the name of the method | |
| * @param types the type of each parameter | |
| * @return the method | |
| * @throws NoSuchMethodException if the method does not exist | |
| * @throws SecurityException if the security check fails | |
| * @see #getMethods() | |
| * @since 1.1 | |
| */ | |
| public Method getMethod(String methodName, Class[] types) | |
| throws NoSuchMethodException | |
| { | |
| memberAccessCheck(Member.PUBLIC); | |
| Method method = internalGetMethod(methodName, types); | |
| if (method == null) | |
| throw new NoSuchMethodException(methodName); | |
| return method; | |
| } | |
| /** | |
| * Like <code>getMethod(String,Class[])</code> but without the security | |
| * checks and returns null instead of throwing NoSuchMethodException. | |
| */ | |
| private Method internalGetMethod(String methodName, Class[] args) | |
| { | |
| Method match = matchMethod(getDeclaredMethods(true), methodName, args); | |
| if (match != null) | |
| return match; | |
| Class superClass = getSuperclass(); | |
| if (superClass != null) | |
| { | |
| match = superClass.internalGetMethod(methodName, args); | |
| if(match != null) | |
| return match; | |
| } | |
| Class[] interfaces = getInterfaces(); | |
| for (int i = 0; i < interfaces.length; i++) | |
| { | |
| match = interfaces[i].internalGetMethod(methodName, args); | |
| if (match != null) | |
| return match; | |
| } | |
| return null; | |
| } | |
| /** | |
| * Find the best matching method in <code>list</code> according to | |
| * the definition of ``best matching'' used by <code>getMethod()</code> | |
| * | |
| * <p> | |
| * Returns the method if any, otherwise <code>null</code>. | |
| * | |
| * @param list List of methods to search | |
| * @param name Name of method | |
| * @param args Method parameter types | |
| * @see #getMethod(String, Class[]) | |
| */ | |
| private static Method matchMethod(Method[] list, String name, Class[] args) | |
| { | |
| Method match = null; | |
| for (int i = 0; i < list.length; i++) | |
| { | |
| Method method = list[i]; | |
| if (!method.getName().equals(name)) | |
| continue; | |
| if (!matchParameters(args, method.getParameterTypes())) | |
| continue; | |
| if (match == null | |
| || match.getReturnType().isAssignableFrom(method.getReturnType())) | |
| match = method; | |
| } | |
| return match; | |
| } | |
| /** | |
| * Check for an exact match between parameter type lists. | |
| * Either list may be <code>null</code> to mean a list of | |
| * length zero. | |
| */ | |
| private static boolean matchParameters(Class[] types1, Class[] types2) | |
| { | |
| if (types1 == null) | |
| return types2 == null || types2.length == 0; | |
| if (types2 == null) | |
| return types1 == null || types1.length == 0; | |
| if (types1.length != types2.length) | |
| return false; | |
| for (int i = 0; i < types1.length; i++) | |
| { | |
| if (types1[i] != types2[i]) | |
| return false; | |
| } | |
| return true; | |
| } | |
| /** | |
| * Get all the public methods declared in this class or inherited from | |
| * superclasses. This returns an array of length 0 if there are no methods, | |
| * including for primitive types. This does not include the implicit | |
| * methods of interfaces which mirror methods of Object, nor does it | |
| * include constructors or the class initialization methods. The Virtual | |
| * Machine allows multiple methods with the same signature but differing | |
| * return types; all such methods are in the returned array. A security | |
| * check may be performed, with | |
| * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as | |
| * <code>checkPackageAccess</code> both having to succeed. | |
| * | |
| * @return all public methods in this class | |
| * @throws SecurityException if the security check fails | |
| * @since 1.1 | |
| */ | |
| public Method[] getMethods() | |
| { | |
| memberAccessCheck(Member.PUBLIC); | |
| // NOTE the API docs claim that no methods are returned for arrays, | |
| // but Sun's implementation *does* return the public methods of Object | |
| // (as would be expected), so we follow their implementation instead | |
| // of their documentation. | |
| return internalGetMethods(); | |
| } | |
| /** | |
| * Like <code>getMethods()</code> but without the security checks. | |
| */ | |
| private Method[] internalGetMethods() | |
| { | |
| HashMap map = new HashMap(); | |
| Method[] methods; | |
| Class[] interfaces = getInterfaces(); | |
| for(int i = 0; i < interfaces.length; i++) | |
| { | |
| methods = interfaces[i].internalGetMethods(); | |
| for(int j = 0; j < methods.length; j++) | |
| { | |
| map.put(new MethodKey(methods[j]), methods[j]); | |
| } | |
| } | |
| Class superClass = getSuperclass(); | |
| if(superClass != null) | |
| { | |
| methods = superClass.internalGetMethods(); | |
| for(int i = 0; i < methods.length; i++) | |
| { | |
| map.put(new MethodKey(methods[i]), methods[i]); | |
| } | |
| } | |
| methods = getDeclaredMethods(true); | |
| for(int i = 0; i < methods.length; i++) | |
| { | |
| map.put(new MethodKey(methods[i]), methods[i]); | |
| } | |
| return (Method[])map.values().toArray(new Method[map.size()]); | |
| } | |
| /** | |
| * Get the modifiers of this class. These can be decoded using Modifier, | |
| * and is limited to one of public, protected, or private, and any of | |
| * final, static, abstract, or interface. An array class has the same | |
| * public, protected, or private modifier as its component type, and is | |
| * marked final but not an interface. Primitive types and void are marked | |
| * public and final, but not an interface. | |
| * | |
| * @return the modifiers of this class | |
| * @see Modifier | |
| * @since 1.1 | |
| */ | |
| public int getModifiers() | |
| { | |
| int mod = VMClass.getModifiers (this, false); | |
| return (mod & (Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | | |
| Modifier.FINAL | Modifier.STATIC | Modifier.ABSTRACT | | |
| Modifier.INTERFACE)); | |
| } | |
| /** | |
| * Get the name of this class, separated by dots for package separators. | |
| * If the class represents a primitive type, or void, then the | |
| * name of the type as it appears in the Java programming language | |
| * is returned. For instance, <code>Byte.TYPE.getName()</code> | |
| * returns "byte". | |
| * | |
| * Arrays are specially encoded as shown on this table. | |
| * <pre> | |
| * array type [<em>element type</em> | |
| * (note that the element type is encoded per | |
| * this table) | |
| * boolean Z | |
| * byte B | |
| * char C | |
| * short S | |
| * int I | |
| * long J | |
| * float F | |
| * double D | |
| * void V | |
| * class or interface, alone: <dotted name> | |
| * class or interface, as element type: L<dotted name>; | |
| * </pre> | |
| * | |
| * @return the name of this class | |
| */ | |
| public String getName() | |
| { | |
| return VMClass.getName (this); | |
| } | |
| /** | |
| * Get a resource URL using this class's package using the | |
| * getClassLoader().getResource() method. If this class was loaded using | |
| * the system classloader, ClassLoader.getSystemResource() is used instead. | |
| * | |
| * <p>If the name you supply is absolute (it starts with a <code>/</code>), | |
| * then the leading <code>/</code> is removed and it is passed on to | |
| * getResource(). If it is relative, the package name is prepended, and | |
| * <code>.</code>'s are replaced with <code>/</code>. | |
| * | |
| * <p>The URL returned is system- and classloader-dependent, and could | |
| * change across implementations. | |
| * | |
| * @param resourceName the name of the resource, generally a path | |
| * @return the URL to the resource | |
| * @throws NullPointerException if name is null | |
| * @since 1.1 | |
| */ | |
| public URL getResource(String resourceName) | |
| { | |
| String name = resourcePath(resourceName); | |
| ClassLoader loader = getClassLoader(); | |
| if (loader == null) | |
| return ClassLoader.getSystemResource(name); | |
| return loader.getResource(name); | |
| } | |
| /** | |
| * Get a resource using this class's package using the | |
| * getClassLoader().getResourceAsStream() method. If this class was loaded | |
| * using the system classloader, ClassLoader.getSystemResource() is used | |
| * instead. | |
| * | |
| * <p>If the name you supply is absolute (it starts with a <code>/</code>), | |
| * then the leading <code>/</code> is removed and it is passed on to | |
| * getResource(). If it is relative, the package name is prepended, and | |
| * <code>.</code>'s are replaced with <code>/</code>. | |
| * | |
| * <p>The URL returned is system- and classloader-dependent, and could | |
| * change across implementations. | |
| * | |
| * @param resourceName the name of the resource, generally a path | |
| * @return an InputStream with the contents of the resource in it, or null | |
| * @throws NullPointerException if name is null | |
| * @since 1.1 | |
| */ | |
| public InputStream getResourceAsStream(String resourceName) | |
| { | |
| String name = resourcePath(resourceName); | |
| ClassLoader loader = getClassLoader(); | |
| if (loader == null) | |
| return ClassLoader.getSystemResourceAsStream(name); | |
| return loader.getResourceAsStream(name); | |
| } | |
| private String resourcePath(String resourceName) | |
| { | |
| if (resourceName.length() > 0) | |
| { | |
| if (resourceName.charAt(0) != '/') | |
| { | |
| String pkg = getPackagePortion(getName()); | |
| if (pkg.length() > 0) | |
| resourceName = pkg.replace('.','/') + '/' + resourceName; | |
| } | |
| else | |
| { | |
| resourceName = resourceName.substring(1); | |
| } | |
| } | |
| return resourceName; | |
| } | |
| /** | |
| * Get the signers of this class. This returns null if there are no signers, | |
| * such as for primitive types or void. | |
| * | |
| * @return the signers of this class | |
| * @since 1.1 | |
| */ | |
| public Object[] getSigners() | |
| { | |
| return signers == null ? null : (Object[]) signers.clone (); | |
| } | |
| /** | |
| * Set the signers of this class. | |
| * | |
| * @param signers the signers of this class | |
| */ | |
| void setSigners(Object[] signers) | |
| { | |
| this.signers = signers; | |
| } | |
| /** | |
| * Get the direct superclass of this class. If this is an interface, | |
| * Object, a primitive type, or void, it will return null. If this is an | |
| * array type, it will return Object. | |
| * | |
| * @return the direct superclass of this class | |
| */ | |
| public Class getSuperclass() | |
| { | |
| return VMClass.getSuperclass (this); | |
| } | |
| /** | |
| * Return whether this class is an array type. | |
| * | |
| * @return whether this class is an array type | |
| * @since 1.1 | |
| */ | |
| public boolean isArray() | |
| { | |
| return VMClass.isArray (this); | |
| } | |
| /** | |
| * Discover whether an instance of the Class parameter would be an | |
| * instance of this Class as well. Think of doing | |
| * <code>isInstance(c.newInstance())</code> or even | |
| * <code>c.newInstance() instanceof (this class)</code>. While this | |
| * checks widening conversions for objects, it must be exact for primitive | |
| * types. | |
| * | |
| * @param c the class to check | |
| * @return whether an instance of c would be an instance of this class | |
| * as well | |
| * @throws NullPointerException if c is null | |
| * @since 1.1 | |
| */ | |
| public boolean isAssignableFrom(Class c) | |
| { | |
| return VMClass.isAssignableFrom (this, c); | |
| } | |
| /** | |
| * Discover whether an Object is an instance of this Class. Think of it | |
| * as almost like <code>o instanceof (this class)</code>. | |
| * | |
| * @param o the Object to check | |
| * @return whether o is an instance of this class | |
| * @since 1.1 | |
| */ | |
| public boolean isInstance(Object o) | |
| { | |
| return VMClass.isInstance (this, o); | |
| } | |
| /** | |
| * Check whether this class is an interface or not. Array types are not | |
| * interfaces. | |
| * | |
| * @return whether this class is an interface or not | |
| */ | |
| public boolean isInterface() | |
| { | |
| return VMClass.isInterface (this); | |
| } | |
| /** | |
| * Return whether this class is a primitive type. A primitive type class | |
| * is a class representing a kind of "placeholder" for the various | |
| * primitive types, or void. You can access the various primitive type | |
| * classes through java.lang.Boolean.TYPE, java.lang.Integer.TYPE, etc., | |
| * or through boolean.class, int.class, etc. | |
| * | |
| * @return whether this class is a primitive type | |
| * @see Boolean#TYPE | |
| * @see Byte#TYPE | |
| * @see Character#TYPE | |
| * @see Short#TYPE | |
| * @see Integer#TYPE | |
| * @see Long#TYPE | |
| * @see Float#TYPE | |
| * @see Double#TYPE | |
| * @see Void#TYPE | |
| * @since 1.1 | |
| */ | |
| public boolean isPrimitive() | |
| { | |
| return VMClass.isPrimitive (this); | |
| } | |
| /** | |
| * Get a new instance of this class by calling the no-argument constructor. | |
| * The class is initialized if it has not been already. A security check | |
| * may be performed, with <code>checkMemberAccess(this, Member.PUBLIC)</code> | |
| * as well as <code>checkPackageAccess</code> both having to succeed. | |
| * | |
| * @return a new instance of this class | |
| * @throws InstantiationException if there is not a no-arg constructor | |
| * for this class, including interfaces, abstract classes, arrays, | |
| * primitive types, and void; or if an exception occurred during | |
| * the constructor | |
| * @throws IllegalAccessException if you are not allowed to access the | |
| * no-arg constructor because of scoping reasons | |
| * @throws SecurityException if the security check fails | |
| * @throws ExceptionInInitializerError if class initialization caused by | |
| * this call fails with an exception | |
| */ | |
| public Object newInstance() | |
| throws InstantiationException, IllegalAccessException | |
| { | |
| memberAccessCheck(Member.PUBLIC); | |
| Constructor constructor; | |
| synchronized(this) | |
| { | |
| constructor = this.constructor; | |
| } | |
| if (constructor == null) | |
| { | |
| Constructor[] constructors = getDeclaredConstructors(false); | |
| for (int i = 0; i < constructors.length; i++) | |
| { | |
| if (constructors[i].getParameterTypes().length == 0) | |
| { | |
| constructor = constructors[i]; | |
| break; | |
| } | |
| } | |
| if (constructor == null) | |
| throw new InstantiationException(getName()); | |
| if (!Modifier.isPublic(constructor.getModifiers()) | |
| || !Modifier.isPublic(VMClass.getModifiers(this, true))) | |
| { | |
| final Constructor finalConstructor = constructor; | |
| AccessController.doPrivileged(new PrivilegedAction() | |
| { | |
| public Object run() | |
| { | |
| finalConstructor.setAccessible(true); | |
| return null; | |
| } | |
| }); | |
| } | |
| synchronized(this) | |
| { | |
| if (this.constructor == null) | |
| this.constructor = constructor; | |
| } | |
| } | |
| int modifiers = constructor.getModifiers(); | |
| if (!Modifier.isPublic(modifiers) | |
| || !Modifier.isPublic(VMClass.getModifiers(this, true))) | |
| { | |
| Class caller = VMStackWalker.getCallingClass(); | |
| if (caller != null && | |
| caller != this && | |
| (Modifier.isPrivate(modifiers) | |
| || getClassLoader() != caller.getClassLoader() | |
| || !getPackagePortion(getName()) | |
| .equals(getPackagePortion(caller.getName())))) | |
| throw new IllegalAccessException(getName() | |
| + " has an inaccessible constructor"); | |
| } | |
| try | |
| { | |
| return constructor.newInstance(null); | |
| } | |
| catch (InvocationTargetException e) | |
| { | |
| VMClass.throwException(e.getTargetException()); | |
| throw (InternalError) new InternalError | |
| ("VMClass.throwException returned").initCause(e); | |
| } | |
| } | |
| /** | |
| * Returns the protection domain of this class. If the classloader did not | |
| * record the protection domain when creating this class the unknown | |
| * protection domain is returned which has a <code>null</code> code source | |
| * and all permissions. A security check may be performed, with | |
| * <code>RuntimePermission("getProtectionDomain")</code>. | |
| * | |
| * @return the protection domain | |
| * @throws SecurityException if the security manager exists and the caller | |
| * does not have <code>RuntimePermission("getProtectionDomain")</code>. | |
| * @see RuntimePermission | |
| * @since 1.2 | |
| */ | |
| public ProtectionDomain getProtectionDomain() | |
| { | |
| SecurityManager sm = SecurityManager.current; | |
| if (sm != null) | |
| sm.checkPermission(new RuntimePermission("getProtectionDomain")); | |
| return pd == null ? StaticData.unknownProtectionDomain : pd; | |
| } | |
| /** | |
| * Return the human-readable form of this Object. For an object, this | |
| * is either "interface " or "class " followed by <code>getName()</code>, | |
| * for primitive types and void it is just <code>getName()</code>. | |
| * | |
| * @return the human-readable form of this Object | |
| */ | |
| public String toString() | |
| { | |
| if (isPrimitive()) | |
| return getName(); | |
| return (isInterface() ? "interface " : "class ") + getName(); | |
| } | |
| /** | |
| * Returns the desired assertion status of this class, if it were to be | |
| * initialized at this moment. The class assertion status, if set, is | |
| * returned; the backup is the default package status; then if there is | |
| * a class loader, that default is returned; and finally the system default | |
| * is returned. This method seldom needs calling in user code, but exists | |
| * for compilers to implement the assert statement. Note that there is no | |
| * guarantee that the result of this method matches the class's actual | |
| * assertion status. | |
| * | |
| * @return the desired assertion status | |
| * @see ClassLoader#setClassAssertionStatus(String, boolean) | |
| * @see ClassLoader#setPackageAssertionStatus(String, boolean) | |
| * @see ClassLoader#setDefaultAssertionStatus(boolean) | |
| * @since 1.4 | |
| */ | |
| public boolean desiredAssertionStatus() | |
| { | |
| ClassLoader c = getClassLoader(); | |
| Object status; | |
| if (c == null) | |
| return VMClassLoader.defaultAssertionStatus(); | |
| if (c.classAssertionStatus != null) | |
| synchronized (c) | |
| { | |
| status = c.classAssertionStatus.get(getName()); | |
| if (status != null) | |
| return status.equals(Boolean.TRUE); | |
| } | |
| else | |
| { | |
| status = ClassLoader.StaticData. | |
| systemClassAssertionStatus.get(getName()); | |
| if (status != null) | |
| return status.equals(Boolean.TRUE); | |
| } | |
| if (c.packageAssertionStatus != null) | |
| synchronized (c) | |
| { | |
| String name = getPackagePortion(getName()); | |
| if ("".equals(name)) | |
| status = c.packageAssertionStatus.get(null); | |
| else | |
| do | |
| { | |
| status = c.packageAssertionStatus.get(name); | |
| name = getPackagePortion(name); | |
| } | |
| while (! "".equals(name) && status == null); | |
| if (status != null) | |
| return status.equals(Boolean.TRUE); | |
| } | |
| else | |
| { | |
| String name = getPackagePortion(getName()); | |
| if ("".equals(name)) | |
| status = ClassLoader.StaticData. | |
| systemPackageAssertionStatus.get(null); | |
| else | |
| do | |
| { | |
| status = ClassLoader.StaticData. | |
| systemPackageAssertionStatus.get(name); | |
| name = getPackagePortion(name); | |
| } | |
| while (! "".equals(name) && status == null); | |
| if (status != null) | |
| return status.equals(Boolean.TRUE); | |
| } | |
| return c.defaultAssertionStatus; | |
| } | |
| /** | |
| * <p> | |
| * Casts this class to represent a subclass of the specified class. | |
| * This method is useful for `narrowing' the type of a class so that | |
| * 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<Object></code>, and a dynamic type of | |
| * <code>Class<Rectangle></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<Shape></code>, to retain | |
| * the same instance but with the type | |
| * <code>Class<? extends Shape></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 | |
| */ | |
| /* FIXME[GENERICS]: Should be <U> Class<? extends U> asSubClass(Class<U> klass */ | |
| public Class asSubclass(Class klass) | |
| { | |
| if (! klass.isAssignableFrom(this)) | |
| throw new ClassCastException(); | |
| return this; /* FIXME[GENERICS]: Should cast to Class<? extends U> */ | |
| } | |
| /** | |
| * 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 | |
| */ | |
| /* FIXME[GENERICS]: Should be T cast(Object obj) */ | |
| public Object cast(Object obj) | |
| { | |
| if (obj != null && ! isInstance(obj)) | |
| throw new ClassCastException(); | |
| return obj; /* FIXME[GENERICS]: Should be cast to T */ | |
| } | |
| /** | |
| * Like <code>getField(String)</code> but without the security checks and | |
| * returns null instead of throwing NoSuchFieldException. | |
| */ | |
| private Field internalGetField(String name) | |
| { | |
| Field[] fields = getDeclaredFields(true); | |
| for (int i = 0; i < fields.length; i++) | |
| { | |
| Field field = fields[i]; | |
| if (field.getName().equals(name)) | |
| return field; | |
| } | |
| Class[] interfaces = getInterfaces(); | |
| for (int i = 0; i < interfaces.length; i++) | |
| { | |
| Field field = interfaces[i].internalGetField(name); | |
| if(field != null) | |
| return field; | |
| } | |
| Class superClass = getSuperclass(); | |
| if (superClass != null) | |
| return superClass.internalGetField(name); | |
| return null; | |
| } | |
| /** | |
| * Strip the last portion of the name (after the last dot). | |
| * | |
| * @param name the name to get package of | |
| * @return the package name, or "" if no package | |
| */ | |
| private static String getPackagePortion(String name) | |
| { | |
| int lastInd = name.lastIndexOf('.'); | |
| if (lastInd == -1) | |
| return ""; | |
| return name.substring(0, lastInd); | |
| } | |
| /** | |
| * Perform security checks common to all of the methods that | |
| * get members of this Class. | |
| */ | |
| private void memberAccessCheck(int which) | |
| { | |
| SecurityManager sm = SecurityManager.current; | |
| if (sm != null) | |
| { | |
| sm.checkMemberAccess(this, which); | |
| Package pkg = getPackage(); | |
| if (pkg != null) | |
| sm.checkPackageAccess(pkg.getName()); | |
| } | |
| } | |
| /** | |
| * 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 | |
| */ | |
| /* FIXME[GENERICS]: T[] getEnumConstants() */ | |
| public Object[] getEnumConstants() | |
| { | |
| if (isEnum()) | |
| { | |
| try | |
| { | |
| return (Object[]) | |
| getMethod("values", new Class[0]).invoke(null, new Object[0]); | |
| } | |
| catch (NoSuchMethodException exception) | |
| { | |
| throw new Error("Enum lacks values() method"); | |
| } | |
| catch (IllegalAccessException exception) | |
| { | |
| throw new Error("Unable to access Enum class"); | |
| } | |
| catch (InvocationTargetException exception) | |
| { | |
| throw new | |
| RuntimeException("The values method threw an exception", | |
| exception); | |
| } | |
| } | |
| else | |
| { | |
| return null; | |
| } | |
| } | |
| /** | |
| * Returns true if this class is an <code>Enum</code>. | |
| * | |
| * @return true if this is an enumeration class. | |
| * @since 1.5 | |
| */ | |
| public boolean isEnum() | |
| { | |
| int mod = VMClass.getModifiers (this, true); | |
| return (mod & ENUM) != 0; | |
| } | |
| /** | |
| * 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 boolean isSynthetic() | |
| { | |
| int mod = VMClass.getModifiers (this, true); | |
| return (mod & SYNTHETIC) != 0; | |
| } | |
| /** | |
| * Returns true if this class is an <code>Annotation</code>. | |
| * | |
| * @return true if this is an annotation class. | |
| * @since 1.5 | |
| */ | |
| public boolean isAnnotation() | |
| { | |
| int mod = VMClass.getModifiers (this, true); | |
| return (mod & ANNOTATION) != 0; | |
| } | |
| /** | |
| * Returns the simple name for this class, as used in the source | |
| * code. For normal classes, this is the content returned by | |
| * <code>getName()</code> which follows the last ".". Anonymous | |
| * classes have no name, and so the result of calling this method is | |
| * "". The simple name of an array consists of the simple name of | |
| * its component type, followed by "[]". Thus, an array with the | |
| * component type of an anonymous class has a simple name of simply | |
| * "[]". | |
| * | |
| * @return the simple name for this class. | |
| * @since 1.5 | |
| */ | |
| public String getSimpleName() | |
| { | |
| return VMClass.getSimpleName(this); | |
| } | |
| /** | |
| * Returns this class' annotation for the specified annotation type, | |
| * or <code>null</code> if no such annotation exists. | |
| * | |
| * @param annotationClass the type of annotation to look for. | |
| * @return this class' annotation for the specified type, or | |
| * <code>null</code> if no such annotation exists. | |
| * @since 1.5 | |
| */ | |
| /* FIXME[GENERICS]: <T extends Annotation> T getAnnotation(Class <T>) */ | |
| public Annotation getAnnotation(Class annotationClass) | |
| { | |
| Annotation foundAnnotation = null; | |
| Annotation[] annotations = getAnnotations(); | |
| for (int i = 0; i < annotations.length; i++) | |
| if (annotations[i].annotationType() == annotationClass) | |
| foundAnnotation = annotations[i]; | |
| return foundAnnotation; | |
| } | |
| /** | |
| * Returns all annotations associated with this class. If there are | |
| * no annotations associated with this class, then a zero-length array | |
| * will be returned. The returned array may be modified by the client | |
| * code, but this will have no effect on the annotation content of this | |
| * class, and hence no effect on the return value of this method for | |
| * future callers. | |
| * | |
| * @return this class' annotations. | |
| * @since 1.5 | |
| */ | |
| public Annotation[] getAnnotations() | |
| { | |
| HashSet set = new HashSet(); | |
| set.addAll(Arrays.asList(getDeclaredAnnotations())); | |
| Class[] interfaces = getInterfaces(); | |
| for (int i = 0; i < interfaces.length; i++) | |
| set.addAll(Arrays.asList(interfaces[i].getAnnotations())); | |
| Class superClass = getSuperclass(); | |
| if (superClass != null) | |
| set.addAll(Arrays.asList(superClass.getAnnotations())); | |
| return (Annotation[]) set.toArray(new Annotation[set.size()]); | |
| } | |
| /** | |
| * <p> | |
| * Returns the canonical name of this class, as defined by section | |
| * 6.7 of the Java language specification. Each package, top-level class, | |
| * 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() | |
| { | |
| return VMClass.getCanonicalName(this); | |
| } | |
| /** | |
| * Returns all annotations directly defined by this class. If there are | |
| * no annotations associated with this class, then a zero-length array | |
| * will be returned. The returned array may be modified by the client | |
| * code, but this will have no effect on the annotation content of this | |
| * class, and hence no effect on the return value of this method for | |
| * future callers. | |
| * | |
| * @return the annotations directly defined by this class. | |
| * @since 1.5 | |
| */ | |
| public Annotation[] getDeclaredAnnotations() | |
| { | |
| return VMClass.getDeclaredAnnotations(this); | |
| } | |
| /** | |
| * Returns the class which immediately encloses this class. If this class | |
| * is a top-level class, this method returns <code>null</code>. | |
| * | |
| * @return the immediate enclosing class, or <code>null</code> if this is | |
| * a top-level class. | |
| * @since 1.5 | |
| */ | |
| /* FIXME[GENERICS]: Should return Class<?> */ | |
| public Class getEnclosingClass() | |
| { | |
| return VMClass.getEnclosingClass(this); | |
| } | |
| /** | |
| * Returns the constructor which immediately encloses this class. If | |
| * this class is a top-level class, or a local or anonymous class | |
| * immediately enclosed by a type definition, instance initializer | |
| * or static initializer, then <code>null</code> is returned. | |
| * | |
| * @return the immediate enclosing constructor if this class is | |
| * declared within a constructor. Otherwise, <code>null</code> | |
| * is returned. | |
| * @since 1.5 | |
| */ | |
| /* FIXME[GENERICS]: Should return Constructor<?> */ | |
| public Constructor getEnclosingConstructor() | |
| { | |
| return VMClass.getEnclosingConstructor(this); | |
| } | |
| /** | |
| * Returns the method which immediately encloses this class. If | |
| * this class is a top-level class, or a local or anonymous class | |
| * immediately enclosed by a type definition, instance initializer | |
| * or static initializer, then <code>null</code> is returned. | |
| * | |
| * @return the immediate enclosing method if this class is | |
| * declared within a method. Otherwise, <code>null</code> | |
| * is returned. | |
| * @since 1.5 | |
| */ | |
| public Method getEnclosingMethod() | |
| { | |
| return VMClass.getEnclosingMethod(this); | |
| } | |
| /** | |
| * <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() | |
| { | |
| if (isPrimitive()) | |
| return new Type[0]; | |
| String sig = VMClass.getClassSignature(this); | |
| 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 = VMClass.getClassSignature(this); | |
| 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. | |
| * @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() | |
| { | |
| String sig = VMClass.getClassSignature(this); | |
| if (sig == null) | |
| return new TypeVariable[0]; | |
| ClassSignatureParser p = new ClassSignatureParser(this, sig); | |
| return p.getTypeParameters(); | |
| } | |
| /** | |
| * Returns true if an annotation for the specified type is associated | |
| * with this class. This is primarily a short-hand for using marker | |
| * annotations. | |
| * | |
| * @param annotationClass the type of annotation to look for. | |
| * @return true if an annotation exists for the specified type. | |
| * @since 1.5 | |
| */ | |
| /* FIXME[GENERICS]: Should be Class<? extends Annotation> */ | |
| public boolean isAnnotationPresent(Class | |
| annotationClass) | |
| { | |
| return getAnnotation(annotationClass) != null; | |
| } | |
| /** | |
| * Returns true if this object represents an anonymous class. | |
| * | |
| * @return true if this object represents an anonymous class. | |
| * @since 1.5 | |
| */ | |
| public boolean isAnonymousClass() | |
| { | |
| return VMClass.isAnonymousClass(this); | |
| } | |
| /** | |
| * Returns true if this object represents an local class. | |
| * | |
| * @return true if this object represents an local class. | |
| * @since 1.5 | |
| */ | |
| public boolean isLocalClass() | |
| { | |
| return VMClass.isLocalClass(this); | |
| } | |
| /** | |
| * Returns true if this object represents an member class. | |
| * | |
| * @return true if this object represents an member class. | |
| * @since 1.5 | |
| */ | |
| public boolean isMemberClass() | |
| { | |
| return VMClass.isMemberClass(this); | |
| } | |
| } |