OSDN Git Service

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