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