1 // Class.java - Representation of a Java class.
2 
3 /* Copyright (C) 1998, 1999, 2000, 2002, 2003  Free Software Foundation
4 
5    This file is part of libgcj.
6 
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10 
11 package java.lang;
12 import java.io.Serializable;
13 import java.io.InputStream;
14 import java.lang.reflect.*;
15 import java.security.*;
16 import java.util.Arrays;
17 import java.util.HashSet;
18 
19 /**
20  * @author Tom Tromey <tromey@cygnus.com>
21  * @date October 1, 1998
22  */
23 
24 /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
25  * "The Java Language Specification", ISBN 0-201-63451-1
26  * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
27  * plus gcj compiler sources (to determine object layout)
28  * Status:  Sufficient for our purposes, but some methods missing
29  * and some not implemented.
30  */
31 
32 public final class Class implements Serializable
33 {
forName(String className)34   public static native Class forName (String className)
35     throws ClassNotFoundException;
36   /** @since 1.2 */
forName(String className, boolean initialize, ClassLoader loader)37   public static native Class forName (String className, boolean initialize,
38 				      ClassLoader loader)
39     throws ClassNotFoundException;
getClasses()40   public native Class[] getClasses ();
getClassLoader()41   public native ClassLoader getClassLoader ();
getComponentType()42   public native Class getComponentType ();
43 
getConstructor(Class[] parameterTypes)44   public native Constructor getConstructor (Class[] parameterTypes)
45     throws NoSuchMethodException, SecurityException;
46 
47   // This is used to implement getConstructors and
48   // getDeclaredConstructors.
_getConstructors(boolean declared)49   private native Constructor[] _getConstructors (boolean declared)
50     throws SecurityException;
51 
getConstructors()52   public Constructor[] getConstructors () throws SecurityException
53   {
54     return _getConstructors (false);
55   }
56 
getDeclaredConstructor(Class[] parameterTypes)57   public native Constructor getDeclaredConstructor (Class[] parameterTypes)
58     throws NoSuchMethodException, SecurityException;
59 
getDeclaredClasses()60   public native Class[] getDeclaredClasses () throws SecurityException;
61 
getDeclaredConstructors()62   public Constructor[] getDeclaredConstructors () throws SecurityException
63   {
64     return _getConstructors (true);
65   }
66 
getDeclaredField(String fieldName)67   public native Field getDeclaredField (String fieldName)
68     throws NoSuchFieldException, SecurityException;
69 
70   /**
71    * Get all the declared fields in this class, but not those inherited from
72    * superclasses. This returns an array of length 0 if there are no fields,
73    * including for primitive types. This does not return the implicit length
74    * field of arrays. A security check may be performed, with
75    * <code>checkMemberAccess(this, Member.DECLARED)</code> as well as
76    * <code>checkPackageAccess</code> both having to succeed.
77    *
78    * @return all declared fields in this class
79    * @throws SecurityException if the security check fails
80    * @since 1.1
81    */
getDeclaredFields()82   public Field[] getDeclaredFields()
83   {
84     memberAccessCheck(Member.DECLARED);
85     return getDeclaredFields(false);
86   }
87 
getDeclaredFields(boolean publicOnly)88   native Field[] getDeclaredFields (boolean publicOnly);
89 
_getDeclaredMethod(String methodName, Class[] parameterTypes)90   private native Method _getDeclaredMethod (String methodName,
91 					    Class[] parameterTypes);
92 
getDeclaredMethod(String methodName, Class[] parameterTypes)93   public Method getDeclaredMethod (String methodName, Class[] parameterTypes)
94     throws NoSuchMethodException, SecurityException
95   {
96     memberAccessCheck(Member.DECLARED);
97 
98     if ("<init>".equals(methodName) || "<clinit>".equals(methodName))
99       throw new NoSuchMethodException(methodName);
100 
101     Method m = _getDeclaredMethod(methodName, parameterTypes);
102     if (m == null)
103       throw new NoSuchMethodException (methodName);
104     return m;
105   }
106 
getDeclaredMethods()107   public native Method[] getDeclaredMethods () throws SecurityException;
108 
109   // This is marked as unimplemented in the JCL book.
getDeclaringClass()110   public native Class getDeclaringClass ();
111 
getField(String fieldName, int hash)112   private native Field getField (String fieldName, int hash)
113     throws NoSuchFieldException, SecurityException;
114 
getField(String fieldName)115   public Field getField (String fieldName)
116     throws NoSuchFieldException, SecurityException
117   {
118     memberAccessCheck (Member.PUBLIC);
119     Field fld = getField(fieldName, fieldName.hashCode());
120     if (fld == null)
121       throw new NoSuchFieldException(fieldName);
122     return fld;
123   }
124 
125   /**
126    * Get all the public fields declared in this class or inherited from
127    * superclasses. This returns an array of length 0 if there are no fields,
128    * including for primitive types. This does not return the implicit length
129    * field of arrays. A security check may be performed, with
130    * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as
131    * <code>checkPackageAccess</code> both having to succeed.
132    *
133    * @return all public fields in this class
134    * @throws SecurityException if the security check fails
135    * @since 1.1
136    */
getFields()137   public Field[] getFields()
138   {
139     memberAccessCheck(Member.PUBLIC);
140     return internalGetFields();
141   }
142 
143   /**
144    * Like <code>getFields()</code> but without the security checks.
145    */
internalGetFields()146   private Field[] internalGetFields()
147   {
148     HashSet set = new HashSet();
149     set.addAll(Arrays.asList(getDeclaredFields(true)));
150     Class[] interfaces = getInterfaces();
151     for (int i = 0; i < interfaces.length; i++)
152       set.addAll(Arrays.asList(interfaces[i].internalGetFields()));
153     Class superClass = getSuperclass();
154     if (superClass != null)
155       set.addAll(Arrays.asList(superClass.internalGetFields()));
156     return (Field[])set.toArray(new Field[set.size()]);
157   }
158 
159   /**
160    * Returns the <code>Package</code> in which this class is defined
161    * Returns null when this information is not available from the
162    * classloader of this class or when the classloader of this class
163    * is null.
164    *
165    * @since 1.2
166    */
getPackage()167   public Package getPackage()
168   {
169     ClassLoader cl = getClassLoader();
170     if (cl != null)
171       {
172         String name = getName();
173 	String pkg = "";
174 	int idx = name.lastIndexOf('.');
175 	if (idx >= 0)
176 	  pkg = name.substring(0, idx);
177 	return cl.getPackage(pkg);
178       }
179     else
180       return null;
181   }
182 
getInterfaces()183   public native Class[] getInterfaces ();
184 
getSignature(StringBuffer buffer)185   private final native void getSignature (StringBuffer buffer);
getSignature(Class[] parameterTypes, boolean is_construtor)186   private static final native String getSignature (Class[] parameterTypes,
187 						   boolean is_construtor);
188 
_getMethod(String methodName, Class[] parameterTypes)189   public native Method _getMethod (String methodName, Class[] parameterTypes);
190 
getMethod(String methodName, Class[] parameterTypes)191   public Method getMethod (String methodName, Class[] parameterTypes)
192     throws NoSuchMethodException, SecurityException
193   {
194     memberAccessCheck(Member.PUBLIC);
195 
196     if ("<init>".equals(methodName) || "<clinit>".equals(methodName))
197       throw new NoSuchMethodException(methodName);
198 
199     Method m = _getMethod(methodName, parameterTypes);
200     if (m == null)
201       throw new NoSuchMethodException (methodName);
202     return m;
203   }
204 
_getMethods(Method[] result, int offset)205   private native int _getMethods (Method[] result, int offset);
getMethods()206   public native Method[] getMethods () throws SecurityException;
207 
getModifiers()208   public native int getModifiers ();
getName()209   public native String getName ();
210 
getResource(String resourceName)211   public java.net.URL getResource (String resourceName)
212   {
213     String name = resourcePath (resourceName);
214     ClassLoader loader = getClassLoader ();
215     if (loader == null)
216       return ClassLoader.getSystemResource (name);
217     else
218       return loader.getResource (name);
219   }
220 
getResourceAsStream(String resourceName)221   public java.io.InputStream getResourceAsStream (String resourceName)
222   {
223     String name = resourcePath (resourceName);
224     ClassLoader loader = getClassLoader ();
225     if (loader == null)
226       return ClassLoader.getSystemResourceAsStream (name);
227     else
228       return loader.getResourceAsStream (name);
229   }
230 
resourcePath(String resourceName)231   private String resourcePath (String resourceName)
232   {
233     if (resourceName.startsWith ("/"))
234       return resourceName.substring (1);
235 
236     Class c = this;
237     while (c.isArray ())
238       c = c.getComponentType ();
239 
240     String packageName = c.getName ().replace ('.', '/');
241     int end = packageName.lastIndexOf ('/');
242     if (end == -1)
243       return resourceName;
244     else
245       return packageName.substring (0, end+1) + resourceName;
246   }
247 
getSigners()248   public native Object[] getSigners ();
setSigners(Object[] signers)249   native void setSigners(Object[] signers);
250 
getSuperclass()251   public native Class getSuperclass ();
isArray()252   public native boolean isArray ();
isAssignableFrom(Class cls)253   public native boolean isAssignableFrom (Class cls);
isInstance(Object obj)254   public native boolean isInstance (Object obj);
isInterface()255   public native boolean isInterface ();
isPrimitive()256   public native boolean isPrimitive ();
newInstance()257   public native Object newInstance ()
258     throws InstantiationException, IllegalAccessException;
259 
260   // We need a native method to retrieve the protection domain, because we
261   // can't add fields to java.lang.Class that are accessible from Java.
getProtectionDomain0()262   private native ProtectionDomain getProtectionDomain0();
263 
264   /**
265    * Returns the protection domain of this class. If the classloader
266    * did not record the protection domain when creating this class
267    * the unknown protection domain is returned which has a <code>null</code>
268    * code source and all permissions.
269    *
270    * @exception SecurityException if a security manager exists and the caller
271    * does not have <code>RuntimePermission("getProtectionDomain")</code>.
272    *
273    * @since 1.2
274    */
getProtectionDomain()275   public ProtectionDomain getProtectionDomain()
276   {
277     SecurityManager sm = System.getSecurityManager();
278     if (sm != null)
279       sm.checkPermission(VMClassLoader.protectionDomainPermission);
280 
281     ProtectionDomain protectionDomain = getProtectionDomain0();
282 
283     if (protectionDomain == null)
284       return VMClassLoader.unknownProtectionDomain;
285     else
286       return protectionDomain;
287   }
288 
toString()289   public String toString ()
290   {
291     if (isPrimitive ())
292       return getName ();
293     return (isInterface () ? "interface " : "class ") + getName ();
294   }
295 
296   /**
297    * Returns the desired assertion status of this class, if it were to be
298    * initialized at this moment. The class assertion status, if set, is
299    * returned; the backup is the default package status; then if there is
300    * a class loader, that default is returned; and finally the system default
301    * is returned. This method seldom needs calling in user code, but exists
302    * for compilers to implement the assert statement. Note that there is no
303    * guarantee that the result of this method matches the class's actual
304    * assertion status.
305    *
306    * @return the desired assertion status
307    * @see ClassLoader#setClassAssertionStatus(String, boolean)
308    * @see ClassLoader#setPackageAssertionStatus(String, boolean)
309    * @see ClassLoader#setDefaultAssertionStatus(boolean)
310    * @since 1.4
311    */
desiredAssertionStatus()312   public boolean desiredAssertionStatus()
313   {
314     ClassLoader c = getClassLoader();
315     Object status;
316     if (c == null)
317       return VMClassLoader.defaultAssertionStatus();
318     if (c.classAssertionStatus != null)
319       synchronized (c)
320         {
321           status = c.classAssertionStatus.get(getName());
322           if (status != null)
323             return status.equals(Boolean.TRUE);
324         }
325     else
326       {
327         status = ClassLoader.systemClassAssertionStatus.get(getName());
328         if (status != null)
329           return status.equals(Boolean.TRUE);
330       }
331     if (c.packageAssertionStatus != null)
332       synchronized (c)
333         {
334           String name = getPackagePortion(getName());
335           if ("".equals(name))
336             status = c.packageAssertionStatus.get(null);
337           else
338             do
339               {
340                 status = c.packageAssertionStatus.get(name);
341                 name = getPackagePortion(name);
342               }
343             while (! "".equals(name) && status == null);
344           if (status != null)
345             return status.equals(Boolean.TRUE);
346         }
347     else
348       {
349         String name = getPackagePortion(getName());
350         if ("".equals(name))
351           status = ClassLoader.systemPackageAssertionStatus.get(null);
352         else
353           do
354             {
355               status = ClassLoader.systemPackageAssertionStatus.get(name);
356               name = getPackagePortion(name);
357             }
358           while (! "".equals(name) && status == null);
359         if (status != null)
360           return status.equals(Boolean.TRUE);
361       }
362     return c.defaultAssertionStatus;
363   }
364 
365   // Don't allow new classes to be made.
Class()366   private Class ()
367   {
368   }
369 
370   // Initialize the class.
initializeClass()371   private native void initializeClass ();
372 
373   // finalization
finalize()374   protected native void finalize () throws Throwable;
375 
376   /**
377    * Strip the last portion of the name (after the last dot).
378    *
379    * @param name the name to get package of
380    * @return the package name, or "" if no package
381    */
getPackagePortion(String name)382   private static String getPackagePortion(String name)
383   {
384     int lastInd = name.lastIndexOf('.');
385     if (lastInd == -1)
386       return "";
387     return name.substring(0, lastInd);
388   }
389 
390   /**
391    * Perform security checks common to all of the methods that
392    * get members of this Class.
393    */
memberAccessCheck(int which)394   private void memberAccessCheck(int which)
395   {
396     SecurityManager sm = System.getSecurityManager();
397     if (sm != null)
398       {
399 	sm.checkMemberAccess(this, which);
400 	Package pkg = getPackage();
401 	if (pkg != null)
402 	  sm.checkPackageAccess(pkg.getName());
403       }
404   }
405 }
406