eab09cdf1a
PR libgcj/12416: * java/lang/Class.h: Updated. * java/lang/natClass.cc (_getFields): Removed. (getFields): Likewise. (getDeclaredFields): Added `public_only' parameter. * java/lang/Class.java (getFields): Now implemented in java; from Classpath. (getDeclaredFields): Likewise. (getDeclaredFields(boolean)): Declare. (_getFields): Removed. (internalGetFields): New method, from Classpath. From-SVN: r72818
406 lines
12 KiB
Java
406 lines
12 KiB
Java
// Class.java - Representation of a Java class.
|
|
|
|
/* Copyright (C) 1998, 1999, 2000, 2002, 2003 Free Software Foundation
|
|
|
|
This file is part of libgcj.
|
|
|
|
This software is copyrighted work licensed under the terms of the
|
|
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
|
details. */
|
|
|
|
package java.lang;
|
|
import java.io.Serializable;
|
|
import java.io.InputStream;
|
|
import java.lang.reflect.*;
|
|
import java.security.*;
|
|
import java.util.Arrays;
|
|
import java.util.HashSet;
|
|
|
|
/**
|
|
* @author Tom Tromey <tromey@cygnus.com>
|
|
* @date October 1, 1998
|
|
*/
|
|
|
|
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
|
|
* "The Java Language Specification", ISBN 0-201-63451-1
|
|
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
|
|
* plus gcj compiler sources (to determine object layout)
|
|
* Status: Sufficient for our purposes, but some methods missing
|
|
* and some not implemented.
|
|
*/
|
|
|
|
public final class Class implements Serializable
|
|
{
|
|
public static native Class forName (String className)
|
|
throws ClassNotFoundException;
|
|
/** @since 1.2 */
|
|
public static native Class forName (String className, boolean initialize,
|
|
ClassLoader loader)
|
|
throws ClassNotFoundException;
|
|
public native Class[] getClasses ();
|
|
public native ClassLoader getClassLoader ();
|
|
public native Class getComponentType ();
|
|
|
|
public native Constructor getConstructor (Class[] parameterTypes)
|
|
throws NoSuchMethodException, SecurityException;
|
|
|
|
// This is used to implement getConstructors and
|
|
// getDeclaredConstructors.
|
|
private native Constructor[] _getConstructors (boolean declared)
|
|
throws SecurityException;
|
|
|
|
public Constructor[] getConstructors () throws SecurityException
|
|
{
|
|
return _getConstructors (false);
|
|
}
|
|
|
|
public native Constructor getDeclaredConstructor (Class[] parameterTypes)
|
|
throws NoSuchMethodException, SecurityException;
|
|
|
|
public native Class[] getDeclaredClasses () throws SecurityException;
|
|
|
|
public Constructor[] getDeclaredConstructors () throws SecurityException
|
|
{
|
|
return _getConstructors (true);
|
|
}
|
|
|
|
public native Field getDeclaredField (String fieldName)
|
|
throws NoSuchFieldException, SecurityException;
|
|
|
|
/**
|
|
* 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);
|
|
}
|
|
|
|
native Field[] getDeclaredFields (boolean publicOnly);
|
|
|
|
private native Method _getDeclaredMethod (String methodName,
|
|
Class[] parameterTypes);
|
|
|
|
public Method getDeclaredMethod (String methodName, Class[] parameterTypes)
|
|
throws NoSuchMethodException, SecurityException
|
|
{
|
|
memberAccessCheck(Member.DECLARED);
|
|
|
|
if ("<init>".equals(methodName) || "<clinit>".equals(methodName))
|
|
throw new NoSuchMethodException(methodName);
|
|
|
|
Method m = _getDeclaredMethod(methodName, parameterTypes);
|
|
if (m == null)
|
|
throw new NoSuchMethodException (methodName);
|
|
return m;
|
|
}
|
|
|
|
public native Method[] getDeclaredMethods () throws SecurityException;
|
|
|
|
// This is marked as unimplemented in the JCL book.
|
|
public native Class getDeclaringClass ();
|
|
|
|
private native Field getField (String fieldName, int hash)
|
|
throws NoSuchFieldException, SecurityException;
|
|
|
|
public Field getField (String fieldName)
|
|
throws NoSuchFieldException, SecurityException
|
|
{
|
|
memberAccessCheck (Member.PUBLIC);
|
|
Field fld = getField(fieldName, fieldName.hashCode());
|
|
if (fld == null)
|
|
throw new NoSuchFieldException(fieldName);
|
|
return fld;
|
|
}
|
|
|
|
/**
|
|
* 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 or when the classloader of this class
|
|
* is null.
|
|
*
|
|
* @since 1.2
|
|
*/
|
|
public Package getPackage()
|
|
{
|
|
ClassLoader cl = getClassLoader();
|
|
if (cl != null)
|
|
{
|
|
String name = getName();
|
|
String pkg = "";
|
|
int idx = name.lastIndexOf('.');
|
|
if (idx >= 0)
|
|
pkg = name.substring(0, idx);
|
|
return cl.getPackage(pkg);
|
|
}
|
|
else
|
|
return null;
|
|
}
|
|
|
|
public native Class[] getInterfaces ();
|
|
|
|
private final native void getSignature (StringBuffer buffer);
|
|
private static final native String getSignature (Class[] parameterTypes,
|
|
boolean is_construtor);
|
|
|
|
public native Method _getMethod (String methodName, Class[] parameterTypes);
|
|
|
|
public Method getMethod (String methodName, Class[] parameterTypes)
|
|
throws NoSuchMethodException, SecurityException
|
|
{
|
|
memberAccessCheck(Member.PUBLIC);
|
|
|
|
if ("<init>".equals(methodName) || "<clinit>".equals(methodName))
|
|
throw new NoSuchMethodException(methodName);
|
|
|
|
Method m = _getMethod(methodName, parameterTypes);
|
|
if (m == null)
|
|
throw new NoSuchMethodException (methodName);
|
|
return m;
|
|
}
|
|
|
|
private native int _getMethods (Method[] result, int offset);
|
|
public native Method[] getMethods () throws SecurityException;
|
|
|
|
public native int getModifiers ();
|
|
public native String getName ();
|
|
|
|
public java.net.URL getResource (String resourceName)
|
|
{
|
|
String name = resourcePath (resourceName);
|
|
ClassLoader loader = getClassLoader ();
|
|
if (loader == null)
|
|
return ClassLoader.getSystemResource (name);
|
|
else
|
|
return loader.getResource (name);
|
|
}
|
|
|
|
public java.io.InputStream getResourceAsStream (String resourceName)
|
|
{
|
|
String name = resourcePath (resourceName);
|
|
ClassLoader loader = getClassLoader ();
|
|
if (loader == null)
|
|
return ClassLoader.getSystemResourceAsStream (name);
|
|
else
|
|
return loader.getResourceAsStream (name);
|
|
}
|
|
|
|
private String resourcePath (String resourceName)
|
|
{
|
|
if (resourceName.startsWith ("/"))
|
|
return resourceName.substring (1);
|
|
|
|
Class c = this;
|
|
while (c.isArray ())
|
|
c = c.getComponentType ();
|
|
|
|
String packageName = c.getName ().replace ('.', '/');
|
|
int end = packageName.lastIndexOf ('/');
|
|
if (end == -1)
|
|
return resourceName;
|
|
else
|
|
return packageName.substring (0, end+1) + resourceName;
|
|
}
|
|
|
|
public native Object[] getSigners ();
|
|
native void setSigners(Object[] signers);
|
|
|
|
public native Class getSuperclass ();
|
|
public native boolean isArray ();
|
|
public native boolean isAssignableFrom (Class cls);
|
|
public native boolean isInstance (Object obj);
|
|
public native boolean isInterface ();
|
|
public native boolean isPrimitive ();
|
|
public native Object newInstance ()
|
|
throws InstantiationException, IllegalAccessException;
|
|
|
|
// We need a native method to retrieve the protection domain, because we
|
|
// can't add fields to java.lang.Class that are accessible from Java.
|
|
private native ProtectionDomain getProtectionDomain0();
|
|
|
|
/**
|
|
* 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.
|
|
*
|
|
* @exception SecurityException if a security manager exists and the caller
|
|
* does not have <code>RuntimePermission("getProtectionDomain")</code>.
|
|
*
|
|
* @since 1.2
|
|
*/
|
|
public ProtectionDomain getProtectionDomain()
|
|
{
|
|
SecurityManager sm = System.getSecurityManager();
|
|
if (sm != null)
|
|
sm.checkPermission(VMClassLoader.protectionDomainPermission);
|
|
|
|
ProtectionDomain protectionDomain = getProtectionDomain0();
|
|
|
|
if (protectionDomain == null)
|
|
return VMClassLoader.unknownProtectionDomain;
|
|
else
|
|
return protectionDomain;
|
|
}
|
|
|
|
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.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.systemPackageAssertionStatus.get(null);
|
|
else
|
|
do
|
|
{
|
|
status = ClassLoader.systemPackageAssertionStatus.get(name);
|
|
name = getPackagePortion(name);
|
|
}
|
|
while (! "".equals(name) && status == null);
|
|
if (status != null)
|
|
return status.equals(Boolean.TRUE);
|
|
}
|
|
return c.defaultAssertionStatus;
|
|
}
|
|
|
|
// Don't allow new classes to be made.
|
|
private Class ()
|
|
{
|
|
}
|
|
|
|
// Initialize the class.
|
|
private native void initializeClass ();
|
|
|
|
// finalization
|
|
protected native void finalize () throws Throwable;
|
|
|
|
/**
|
|
* 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 = System.getSecurityManager();
|
|
if (sm != null)
|
|
{
|
|
sm.checkMemberAccess(this, which);
|
|
Package pkg = getPackage();
|
|
if (pkg != null)
|
|
sm.checkPackageAccess(pkg.getName());
|
|
}
|
|
}
|
|
}
|