GNU Classpath (0.95) | |
Frames | No Frames |
1: /* ClassLoader.java -- responsible for loading classes into the VM 2: Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.lang; 40: 41: import gnu.classpath.SystemProperties; 42: import gnu.classpath.VMStackWalker; 43: import gnu.java.util.DoubleEnumeration; 44: import gnu.java.util.EmptyEnumeration; 45: 46: import java.io.File; 47: import java.io.IOException; 48: import java.io.InputStream; 49: import java.lang.reflect.Constructor; 50: import java.net.URL; 51: import java.net.URLClassLoader; 52: import java.nio.ByteBuffer; 53: import java.security.CodeSource; 54: import java.security.PermissionCollection; 55: import java.security.Policy; 56: import java.security.ProtectionDomain; 57: import java.util.ArrayList; 58: import java.util.Enumeration; 59: import java.util.HashMap; 60: import java.util.Map; 61: import java.util.StringTokenizer; 62: 63: /** 64: * The ClassLoader is a way of customizing the way Java gets its classes 65: * and loads them into memory. The verifier and other standard Java things 66: * still run, but the ClassLoader is allowed great flexibility in determining 67: * where to get the classfiles and when to load and resolve them. For that 68: * matter, a custom ClassLoader can perform on-the-fly code generation or 69: * modification! 70: * 71: * <p>Every classloader has a parent classloader that is consulted before 72: * the 'child' classloader when classes or resources should be loaded. 73: * This is done to make sure that classes can be loaded from an hierarchy of 74: * multiple classloaders and classloaders do not accidentially redefine 75: * already loaded classes by classloaders higher in the hierarchy. 76: * 77: * <p>The grandparent of all classloaders is the bootstrap classloader, which 78: * loads all the standard system classes as implemented by GNU Classpath. The 79: * other special classloader is the system classloader (also called 80: * application classloader) that loads all classes from the CLASSPATH 81: * (<code>java.class.path</code> system property). The system classloader 82: * is responsible for finding the application classes from the classpath, 83: * and delegates all requests for the standard library classes to its parent 84: * the bootstrap classloader. Most programs will load all their classes 85: * through the system classloaders. 86: * 87: * <p>The bootstrap classloader in GNU Classpath is implemented as a couple of 88: * static (native) methods on the package private class 89: * <code>java.lang.VMClassLoader</code>, the system classloader is an 90: * anonymous inner class of ClassLoader and a subclass of 91: * <code>java.net.URLClassLoader</code>. 92: * 93: * <p>Users of a <code>ClassLoader</code> will normally just use the methods 94: * <ul> 95: * <li> <code>loadClass()</code> to load a class.</li> 96: * <li> <code>getResource()</code> or <code>getResourceAsStream()</code> 97: * to access a resource.</li> 98: * <li> <code>getResources()</code> to get an Enumeration of URLs to all 99: * the resources provided by the classloader and its parents with the 100: * same name.</li> 101: * </ul> 102: * 103: * <p>Subclasses should implement the methods 104: * <ul> 105: * <li> <code>findClass()</code> which is called by <code>loadClass()</code> 106: * when the parent classloader cannot provide a named class.</li> 107: * <li> <code>findResource()</code> which is called by 108: * <code>getResource()</code> when the parent classloader cannot provide 109: * a named resource.</li> 110: * <li> <code>findResources()</code> which is called by 111: * <code>getResource()</code> to combine all the resources with the 112: * same name from the classloader and its parents.</li> 113: * <li> <code>findLibrary()</code> which is called by 114: * <code>Runtime.loadLibrary()</code> when a class defined by the 115: * classloader wants to load a native library.</li> 116: * </ul> 117: * 118: * @author John Keiser 119: * @author Mark Wielaard 120: * @author Eric Blake (ebb9@email.byu.edu) 121: * @see Class 122: * @since 1.0 123: */ 124: public abstract class ClassLoader 125: { 126: /** 127: * All packages defined by this classloader. It is not private in order to 128: * allow native code (and trusted subclasses) access to this field. 129: */ 130: final HashMap<String, Package> definedPackages = new HashMap<String, Package>(); 131: 132: /** 133: * The classloader that is consulted before this classloader. 134: * If null then the parent is the bootstrap classloader. 135: */ 136: private final ClassLoader parent; 137: 138: /** 139: * This is true if this classloader was successfully initialized. 140: * This flag is needed to avoid a class loader attack: even if the 141: * security manager rejects an attempt to create a class loader, the 142: * malicious class could have a finalize method which proceeds to 143: * define classes. 144: */ 145: private final boolean initialized; 146: 147: static class StaticData 148: { 149: /** 150: * The System Class Loader (a.k.a. Application Class Loader). The one 151: * returned by ClassLoader.getSystemClassLoader. 152: */ 153: static final ClassLoader systemClassLoader = 154: VMClassLoader.getSystemClassLoader(); 155: static 156: { 157: // Find out if we have to install a default security manager. Note that 158: // this is done here because we potentially need the system class loader 159: // to load the security manager and note also that we don't need the 160: // security manager until the system class loader is created. 161: // If the runtime chooses to use a class loader that doesn't have the 162: // system class loader as its parent, it is responsible for setting 163: // up a security manager before doing so. 164: String secman = SystemProperties.getProperty("java.security.manager"); 165: if (secman != null && SecurityManager.current == null) 166: { 167: if (secman.equals("") || secman.equals("default")) 168: { 169: SecurityManager.current = new SecurityManager(); 170: } 171: else 172: { 173: try 174: { 175: Class cl = Class.forName(secman, false, StaticData.systemClassLoader); 176: SecurityManager.current = (SecurityManager)cl.newInstance(); 177: } 178: catch (Exception x) 179: { 180: throw (InternalError) 181: new InternalError("Unable to create SecurityManager") 182: .initCause(x); 183: } 184: } 185: } 186: } 187: 188: /** 189: * The default protection domain, used when defining a class with a null 190: * parameter for the domain. 191: */ 192: static final ProtectionDomain defaultProtectionDomain; 193: static 194: { 195: CodeSource cs = new CodeSource(null, null); 196: PermissionCollection perm = Policy.getPolicy().getPermissions(cs); 197: defaultProtectionDomain = new ProtectionDomain(cs, perm); 198: } 199: /** 200: * The command-line state of the package assertion status overrides. This 201: * map is never modified, so it does not need to be synchronized. 202: */ 203: // Package visible for use by Class. 204: static final Map systemPackageAssertionStatus 205: = VMClassLoader.packageAssertionStatus(); 206: /** 207: * The command-line state of the class assertion status overrides. This 208: * map is never modified, so it does not need to be synchronized. 209: */ 210: // Package visible for use by Class. 211: static final Map systemClassAssertionStatus 212: = VMClassLoader.classAssertionStatus(); 213: } 214: 215: /** 216: * The desired assertion status of classes loaded by this loader, if not 217: * overridden by package or class instructions. 218: */ 219: // Package visible for use by Class. 220: boolean defaultAssertionStatus = VMClassLoader.defaultAssertionStatus(); 221: 222: /** 223: * The map of package assertion status overrides, or null if no package 224: * overrides have been specified yet. The values of the map should be 225: * Boolean.TRUE or Boolean.FALSE, and the unnamed package is represented 226: * by the null key. This map must be synchronized on this instance. 227: */ 228: // Package visible for use by Class. 229: Map<String, Boolean> packageAssertionStatus; 230: 231: /** 232: * The map of class assertion status overrides, or null if no class 233: * overrides have been specified yet. The values of the map should be 234: * Boolean.TRUE or Boolean.FALSE. This map must be synchronized on this 235: * instance. 236: */ 237: // Package visible for use by Class. 238: Map<String, Boolean> classAssertionStatus; 239: 240: /** 241: * VM private data. 242: */ 243: transient Object vmdata; 244: 245: /** 246: * Create a new ClassLoader with as parent the system classloader. There 247: * may be a security check for <code>checkCreateClassLoader</code>. 248: * 249: * @throws SecurityException if the security check fails 250: */ 251: protected ClassLoader() throws SecurityException 252: { 253: this(StaticData.systemClassLoader); 254: } 255: 256: /** 257: * Create a new ClassLoader with the specified parent. The parent will 258: * be consulted when a class or resource is requested through 259: * <code>loadClass()</code> or <code>getResource()</code>. Only when the 260: * parent classloader cannot provide the requested class or resource the 261: * <code>findClass()</code> or <code>findResource()</code> method 262: * of this classloader will be called. There may be a security check for 263: * <code>checkCreateClassLoader</code>. 264: * 265: * @param parent the classloader's parent, or null for the bootstrap 266: * classloader 267: * @throws SecurityException if the security check fails 268: * @since 1.2 269: */ 270: protected ClassLoader(ClassLoader parent) 271: { 272: // May we create a new classloader? 273: SecurityManager sm = SecurityManager.current; 274: if (sm != null) 275: sm.checkCreateClassLoader(); 276: this.parent = parent; 277: this.initialized = true; 278: } 279: 280: /** 281: * Load a class using this ClassLoader or its parent, without resolving 282: * it. Calls <code>loadClass(name, false)</code>. 283: * 284: * <p>Subclasses should not override this method but should override 285: * <code>findClass()</code> which is called by this method.</p> 286: * 287: * @param name the name of the class relative to this ClassLoader 288: * @return the loaded class 289: * @throws ClassNotFoundException if the class cannot be found 290: */ 291: public Class<?> loadClass(String name) throws ClassNotFoundException 292: { 293: return loadClass(name, false); 294: } 295: 296: /** 297: * Load a class using this ClassLoader or its parent, possibly resolving 298: * it as well using <code>resolveClass()</code>. It first tries to find 299: * out if the class has already been loaded through this classloader by 300: * calling <code>findLoadedClass()</code>. Then it calls 301: * <code>loadClass()</code> on the parent classloader (or when there is 302: * no parent it uses the VM bootclassloader). If the class is still 303: * not loaded it tries to create a new class by calling 304: * <code>findClass()</code>. Finally when <code>resolve</code> is 305: * <code>true</code> it also calls <code>resolveClass()</code> on the 306: * newly loaded class. 307: * 308: * <p>Subclasses should not override this method but should override 309: * <code>findClass()</code> which is called by this method.</p> 310: * 311: * @param name the fully qualified name of the class to load 312: * @param resolve whether or not to resolve the class 313: * @return the loaded class 314: * @throws ClassNotFoundException if the class cannot be found 315: */ 316: protected synchronized Class<?> loadClass(String name, boolean resolve) 317: throws ClassNotFoundException 318: { 319: // Have we already loaded this class? 320: Class<?> c = findLoadedClass(name); 321: if (c == null) 322: { 323: // Can the class be loaded by a parent? 324: try 325: { 326: if (parent == null) 327: { 328: c = VMClassLoader.loadClass(name, resolve); 329: if (c != null) 330: return c; 331: } 332: else 333: { 334: return parent.loadClass(name, resolve); 335: } 336: } 337: catch (ClassNotFoundException e) 338: { 339: } 340: // Still not found, we have to do it ourself. 341: c = findClass(name); 342: } 343: if (resolve) 344: resolveClass(c); 345: return c; 346: } 347: 348: /** 349: * Called for every class name that is needed but has not yet been 350: * defined by this classloader or one of its parents. It is called by 351: * <code>loadClass()</code> after both <code>findLoadedClass()</code> and 352: * <code>parent.loadClass()</code> couldn't provide the requested class. 353: * 354: * <p>The default implementation throws a 355: * <code>ClassNotFoundException</code>. Subclasses should override this 356: * method. An implementation of this method in a subclass should get the 357: * class bytes of the class (if it can find them), if the package of the 358: * requested class doesn't exist it should define the package and finally 359: * it should call define the actual class. It does not have to resolve the 360: * class. It should look something like the following:<br> 361: * 362: * <pre> 363: * // Get the bytes that describe the requested class 364: * byte[] classBytes = classLoaderSpecificWayToFindClassBytes(name); 365: * // Get the package name 366: * int lastDot = name.lastIndexOf('.'); 367: * if (lastDot != -1) 368: * { 369: * String packageName = name.substring(0, lastDot); 370: * // Look if the package already exists 371: * if (getPackage(packageName) == null) 372: * { 373: * // define the package 374: * definePackage(packageName, ...); 375: * } 376: * } 377: * // Define and return the class 378: * return defineClass(name, classBytes, 0, classBytes.length); 379: * </pre> 380: * 381: * <p><code>loadClass()</code> makes sure that the <code>Class</code> 382: * returned by <code>findClass()</code> will later be returned by 383: * <code>findLoadedClass()</code> when the same class name is requested. 384: * 385: * @param name class name to find (including the package name) 386: * @return the requested Class 387: * @throws ClassNotFoundException when the class can not be found 388: * @since 1.2 389: */ 390: protected Class<?> findClass(String name) throws ClassNotFoundException 391: { 392: throw new ClassNotFoundException(name); 393: } 394: 395: /** 396: * Helper to define a class using a string of bytes. This version is not 397: * secure. 398: * 399: * @param data the data representing the classfile, in classfile format 400: * @param offset the offset into the data where the classfile starts 401: * @param len the length of the classfile data in the array 402: * @return the class that was defined 403: * @throws ClassFormatError if data is not in proper classfile format 404: * @throws IndexOutOfBoundsException if offset or len is negative, or 405: * offset + len exceeds data 406: * @deprecated use {@link #defineClass(String, byte[], int, int)} instead 407: */ 408: protected final Class<?> defineClass(byte[] data, int offset, int len) 409: throws ClassFormatError 410: { 411: return defineClass(null, data, offset, len); 412: } 413: 414: /** 415: * Helper to define a class using a string of bytes without a 416: * ProtectionDomain. Subclasses should call this method from their 417: * <code>findClass()</code> implementation. The name should use '.' 418: * separators, and discard the trailing ".class". The default protection 419: * domain has the permissions of 420: * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))</code>. 421: * 422: * @param name the name to give the class, or null if unknown 423: * @param data the data representing the classfile, in classfile format 424: * @param offset the offset into the data where the classfile starts 425: * @param len the length of the classfile data in the array 426: * @return the class that was defined 427: * @throws ClassFormatError if data is not in proper classfile format 428: * @throws IndexOutOfBoundsException if offset or len is negative, or 429: * offset + len exceeds data 430: * @throws SecurityException if name starts with "java." 431: * @since 1.1 432: */ 433: protected final Class<?> defineClass(String name, byte[] data, int offset, 434: int len) throws ClassFormatError 435: { 436: return defineClass(name, data, offset, len, null); 437: } 438: 439: /** 440: * Helper to define a class using a string of bytes. Subclasses should call 441: * this method from their <code>findClass()</code> implementation. If the 442: * domain is null, the default of 443: * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))</code> 444: * is used. Once a class has been defined in a package, all further classes 445: * in that package must have the same set of certificates or a 446: * SecurityException is thrown. 447: * 448: * @param name the name to give the class. null if unknown 449: * @param data the data representing the classfile, in classfile format 450: * @param offset the offset into the data where the classfile starts 451: * @param len the length of the classfile data in the array 452: * @param domain the ProtectionDomain to give to the class, null for the 453: * default protection domain 454: * @return the class that was defined 455: * @throws ClassFormatError if data is not in proper classfile format 456: * @throws IndexOutOfBoundsException if offset or len is negative, or 457: * offset + len exceeds data 458: * @throws SecurityException if name starts with "java.", or if certificates 459: * do not match up 460: * @since 1.2 461: */ 462: protected final synchronized Class<?> defineClass(String name, byte[] data, 463: int offset, int len, 464: ProtectionDomain domain) 465: throws ClassFormatError 466: { 467: checkInitialized(); 468: if (domain == null) 469: domain = StaticData.defaultProtectionDomain; 470: 471: return VMClassLoader.defineClassWithTransformers(this, name, data, offset, 472: len, domain); 473: } 474: 475: /** 476: * Helper to define a class using the contents of a byte buffer. If 477: * the domain is null, the default of 478: * <code>Policy.getPolicy().getPermissions(new CodeSource(null, 479: * null))</code> is used. Once a class has been defined in a 480: * package, all further classes in that package must have the same 481: * set of certificates or a SecurityException is thrown. 482: * 483: * @param name the name to give the class. null if unknown 484: * @param buf a byte buffer containing bytes that form a class. 485: * @param domain the ProtectionDomain to give to the class, null for the 486: * default protection domain 487: * @return the class that was defined 488: * @throws ClassFormatError if data is not in proper classfile format 489: * @throws NoClassDefFoundError if the supplied name is not the same as 490: * the one specified by the byte buffer. 491: * @throws SecurityException if name starts with "java.", or if certificates 492: * do not match up 493: * @since 1.5 494: */ 495: protected final Class<?> defineClass(String name, ByteBuffer buf, 496: ProtectionDomain domain) 497: throws ClassFormatError 498: { 499: byte[] data = new byte[buf.remaining()]; 500: buf.get(data); 501: return defineClass(name, data, 0, data.length, domain); 502: } 503: 504: /** 505: * Links the class, if that has not already been done. Linking basically 506: * resolves all references to other classes made by this class. 507: * 508: * @param c the class to resolve 509: * @throws NullPointerException if c is null 510: * @throws LinkageError if linking fails 511: */ 512: protected final void resolveClass(Class<?> c) 513: { 514: checkInitialized(); 515: VMClassLoader.resolveClass(c); 516: } 517: 518: /** 519: * Helper to find a Class using the system classloader, possibly loading it. 520: * A subclass usually does not need to call this, if it correctly 521: * overrides <code>findClass(String)</code>. 522: * 523: * @param name the name of the class to find 524: * @return the found class 525: * @throws ClassNotFoundException if the class cannot be found 526: */ 527: protected final Class<?> findSystemClass(String name) 528: throws ClassNotFoundException 529: { 530: checkInitialized(); 531: return Class.forName(name, false, StaticData.systemClassLoader); 532: } 533: 534: /** 535: * Returns the parent of this classloader. If the parent of this 536: * classloader is the bootstrap classloader then this method returns 537: * <code>null</code>. A security check may be performed on 538: * <code>RuntimePermission("getClassLoader")</code>. 539: * 540: * @return the parent <code>ClassLoader</code> 541: * @throws SecurityException if the security check fails 542: * @since 1.2 543: */ 544: public final ClassLoader getParent() 545: { 546: // Check if we may return the parent classloader. 547: SecurityManager sm = SecurityManager.current; 548: if (sm != null) 549: { 550: ClassLoader cl = VMStackWalker.getCallingClassLoader(); 551: if (cl != null && ! cl.isAncestorOf(this)) 552: sm.checkPermission(new RuntimePermission("getClassLoader")); 553: } 554: return parent; 555: } 556: 557: /** 558: * Helper to set the signers of a class. This should be called after 559: * defining the class. 560: * 561: * @param c the Class to set signers of 562: * @param signers the signers to set 563: * @since 1.1 564: */ 565: protected final void setSigners(Class<?> c, Object[] signers) 566: { 567: checkInitialized(); 568: c.setSigners(signers); 569: } 570: 571: /** 572: * Helper to find an already-loaded class in this ClassLoader. 573: * 574: * @param name the name of the class to find 575: * @return the found Class, or null if it is not found 576: * @since 1.1 577: */ 578: protected final synchronized Class<?> findLoadedClass(String name) 579: { 580: checkInitialized(); 581: return VMClassLoader.findLoadedClass(this, name); 582: } 583: 584: /** 585: * Get the URL to a resource using this classloader or one of its parents. 586: * First tries to get the resource by calling <code>getResource()</code> 587: * on the parent classloader. If the parent classloader returns null then 588: * it tries finding the resource by calling <code>findResource()</code> on 589: * this classloader. The resource name should be separated by '/' for path 590: * elements. 591: * 592: * <p>Subclasses should not override this method but should override 593: * <code>findResource()</code> which is called by this method. 594: * 595: * @param name the name of the resource relative to this classloader 596: * @return the URL to the resource or null when not found 597: */ 598: public URL getResource(String name) 599: { 600: URL result; 601: 602: if (parent == null) 603: result = VMClassLoader.getResource(name); 604: else 605: result = parent.getResource(name); 606: 607: if (result == null) 608: result = findResource(name); 609: return result; 610: } 611: 612: /** 613: * Returns an Enumeration of all resources with a given name that can 614: * be found by this classloader and its parents. Certain classloaders 615: * (such as the URLClassLoader when given multiple jar files) can have 616: * multiple resources with the same name that come from multiple locations. 617: * It can also occur that a parent classloader offers a resource with a 618: * certain name and the child classloader also offers a resource with that 619: * same name. <code>getResource()</code> only offers the first resource (of the 620: * parent) with a given name. This method lists all resources with the 621: * same name. The name should use '/' as path separators. 622: * 623: * <p>The Enumeration is created by first calling <code>getResources()</code> 624: * on the parent classloader and then calling <code>findResources()</code> 625: * on this classloader.</p> 626: * 627: * @param name the resource name 628: * @return an enumaration of all resources found 629: * @throws IOException if I/O errors occur in the process 630: * @since 1.2 631: * @specnote this was <code>final</code> prior to 1.5 632: */ 633: public Enumeration<URL> getResources(String name) throws IOException 634: { 635: Enumeration<URL> parentResources; 636: if (parent == null) 637: parentResources = VMClassLoader.getResources(name); 638: else 639: parentResources = parent.getResources(name); 640: return new DoubleEnumeration<URL>(parentResources, findResources(name)); 641: } 642: 643: /** 644: * Called whenever all locations of a named resource are needed. 645: * It is called by <code>getResources()</code> after it has called 646: * <code>parent.getResources()</code>. The results are combined by 647: * the <code>getResources()</code> method. 648: * 649: * <p>The default implementation always returns an empty Enumeration. 650: * Subclasses should override it when they can provide an Enumeration of 651: * URLs (possibly just one element) to the named resource. 652: * The first URL of the Enumeration should be the same as the one 653: * returned by <code>findResource</code>. 654: * 655: * @param name the name of the resource to be found 656: * @return a possibly empty Enumeration of URLs to the named resource 657: * @throws IOException if I/O errors occur in the process 658: * @since 1.2 659: */ 660: protected Enumeration<URL> findResources(String name) throws IOException 661: { 662: return (Enumeration<URL>) EmptyEnumeration.getInstance(); 663: } 664: 665: /** 666: * Called whenever a resource is needed that could not be provided by 667: * one of the parents of this classloader. It is called by 668: * <code>getResource()</code> after <code>parent.getResource()</code> 669: * couldn't provide the requested resource. 670: * 671: * <p>The default implementation always returns null. Subclasses should 672: * override this method when they can provide a way to return a URL 673: * to a named resource. 674: * 675: * @param name the name of the resource to be found 676: * @return a URL to the named resource or null when not found 677: * @since 1.2 678: */ 679: protected URL findResource(String name) 680: { 681: return null; 682: } 683: 684: /** 685: * Get the URL to a resource using the system classloader. 686: * 687: * @param name the name of the resource relative to the system classloader 688: * @return the URL to the resource 689: * @since 1.1 690: */ 691: public static final URL getSystemResource(String name) 692: { 693: return StaticData.systemClassLoader.getResource(name); 694: } 695: 696: /** 697: * Get an Enumeration of URLs to resources with a given name using the 698: * the system classloader. The enumeration firsts lists the resources with 699: * the given name that can be found by the bootstrap classloader followed 700: * by the resources with the given name that can be found on the classpath. 701: * 702: * @param name the name of the resource relative to the system classloader 703: * @return an Enumeration of URLs to the resources 704: * @throws IOException if I/O errors occur in the process 705: * @since 1.2 706: */ 707: public static Enumeration<URL> getSystemResources(String name) 708: throws IOException 709: { 710: return StaticData.systemClassLoader.getResources(name); 711: } 712: 713: /** 714: * Get a resource as stream using this classloader or one of its parents. 715: * First calls <code>getResource()</code> and if that returns a URL to 716: * the resource then it calls and returns the InputStream given by 717: * <code>URL.openStream()</code>. 718: * 719: * <p>Subclasses should not override this method but should override 720: * <code>findResource()</code> which is called by this method. 721: * 722: * @param name the name of the resource relative to this classloader 723: * @return an InputStream to the resource, or null 724: * @since 1.1 725: */ 726: public InputStream getResourceAsStream(String name) 727: { 728: try 729: { 730: URL url = getResource(name); 731: if (url == null) 732: return null; 733: return url.openStream(); 734: } 735: catch (IOException e) 736: { 737: return null; 738: } 739: } 740: 741: /** 742: * Get a resource using the system classloader. 743: * 744: * @param name the name of the resource relative to the system classloader 745: * @return an input stream for the resource, or null 746: * @since 1.1 747: */ 748: public static final InputStream getSystemResourceAsStream(String name) 749: { 750: try 751: { 752: URL url = getSystemResource(name); 753: if (url == null) 754: return null; 755: return url.openStream(); 756: } 757: catch (IOException e) 758: { 759: return null; 760: } 761: } 762: 763: /** 764: * Returns the system classloader. The system classloader (also called 765: * the application classloader) is the classloader that is used to 766: * load the application classes on the classpath (given by the system 767: * property <code>java.class.path</code>. This is set as the context 768: * class loader for a thread. The system property 769: * <code>java.system.class.loader</code>, if defined, is taken to be the 770: * name of the class to use as the system class loader, which must have 771: * a public constructor which takes a ClassLoader as a parent. The parent 772: * class loader passed in the constructor is the default system class 773: * loader. 774: * 775: * <p>Note that this is different from the bootstrap classloader that 776: * actually loads all the real "system" classes. 777: * 778: * <p>A security check will be performed for 779: * <code>RuntimePermission("getClassLoader")</code> if the calling class 780: * is not a parent of the system class loader. 781: * 782: * @return the system class loader 783: * @throws SecurityException if the security check fails 784: * @throws IllegalStateException if this is called recursively 785: * @throws Error if <code>java.system.class.loader</code> fails to load 786: * @since 1.2 787: */ 788: public static ClassLoader getSystemClassLoader() 789: { 790: // Check if we may return the system classloader 791: SecurityManager sm = SecurityManager.current; 792: if (sm != null) 793: { 794: ClassLoader cl = VMStackWalker.getCallingClassLoader(); 795: if (cl != null && cl != StaticData.systemClassLoader) 796: sm.checkPermission(new RuntimePermission("getClassLoader")); 797: } 798: 799: return StaticData.systemClassLoader; 800: } 801: 802: /** 803: * Defines a new package and creates a Package object. The package should 804: * be defined before any class in the package is defined with 805: * <code>defineClass()</code>. The package should not yet be defined 806: * before in this classloader or in one of its parents (which means that 807: * <code>getPackage()</code> should return <code>null</code>). All 808: * parameters except the <code>name</code> of the package may be 809: * <code>null</code>. 810: * 811: * <p>Subclasses should call this method from their <code>findClass()</code> 812: * implementation before calling <code>defineClass()</code> on a Class 813: * in a not yet defined Package (which can be checked by calling 814: * <code>getPackage()</code>). 815: * 816: * @param name the name of the Package 817: * @param specTitle the name of the specification 818: * @param specVendor the name of the specification designer 819: * @param specVersion the version of this specification 820: * @param implTitle the name of the implementation 821: * @param implVendor the vendor that wrote this implementation 822: * @param implVersion the version of this implementation 823: * @param sealed if sealed the origin of the package classes 824: * @return the Package object for the specified package 825: * @throws IllegalArgumentException if the package name is null or it 826: * was already defined by this classloader or one of its parents 827: * @see Package 828: * @since 1.2 829: */ 830: protected Package definePackage(String name, String specTitle, 831: String specVendor, String specVersion, 832: String implTitle, String implVendor, 833: String implVersion, URL sealed) 834: { 835: if (getPackage(name) != null) 836: throw new IllegalArgumentException("Package " + name 837: + " already defined"); 838: Package p = new Package(name, specTitle, specVendor, specVersion, 839: implTitle, implVendor, implVersion, sealed, this); 840: synchronized (definedPackages) 841: { 842: definedPackages.put(name, p); 843: } 844: return p; 845: } 846: 847: /** 848: * Returns the Package object for the requested package name. It returns 849: * null when the package is not defined by this classloader or one of its 850: * parents. 851: * 852: * @param name the package name to find 853: * @return the package, if defined 854: * @since 1.2 855: */ 856: protected Package getPackage(String name) 857: { 858: Package p; 859: if (parent == null) 860: p = VMClassLoader.getPackage(name); 861: else 862: p = parent.getPackage(name); 863: 864: if (p == null) 865: { 866: synchronized (definedPackages) 867: { 868: p = definedPackages.get(name); 869: } 870: } 871: return p; 872: } 873: 874: /** 875: * Returns all Package objects defined by this classloader and its parents. 876: * 877: * @return an array of all defined packages 878: * @since 1.2 879: */ 880: protected Package[] getPackages() 881: { 882: // Get all our packages. 883: Package[] packages; 884: synchronized(definedPackages) 885: { 886: packages = new Package[definedPackages.size()]; 887: definedPackages.values().toArray(packages); 888: } 889: 890: // If we have a parent get all packages defined by our parents. 891: Package[] parentPackages; 892: if (parent == null) 893: parentPackages = VMClassLoader.getPackages(); 894: else 895: parentPackages = parent.getPackages(); 896: 897: Package[] allPackages = new Package[parentPackages.length 898: + packages.length]; 899: System.arraycopy(parentPackages, 0, allPackages, 0, 900: parentPackages.length); 901: System.arraycopy(packages, 0, allPackages, parentPackages.length, 902: packages.length); 903: return allPackages; 904: } 905: 906: /** 907: * Called by <code>Runtime.loadLibrary()</code> to get an absolute path 908: * to a (system specific) library that was requested by a class loaded 909: * by this classloader. The default implementation returns 910: * <code>null</code>. It should be implemented by subclasses when they 911: * have a way to find the absolute path to a library. If this method 912: * returns null the library is searched for in the default locations 913: * (the directories listed in the <code>java.library.path</code> system 914: * property). 915: * 916: * @param name the (system specific) name of the requested library 917: * @return the full pathname to the requested library, or null 918: * @see Runtime#loadLibrary(String) 919: * @since 1.2 920: */ 921: protected String findLibrary(String name) 922: { 923: return null; 924: } 925: 926: /** 927: * Set the default assertion status for classes loaded by this classloader, 928: * used unless overridden by a package or class request. 929: * 930: * @param enabled true to set the default to enabled 931: * @see #setClassAssertionStatus(String, boolean) 932: * @see #setPackageAssertionStatus(String, boolean) 933: * @see #clearAssertionStatus() 934: * @since 1.4 935: */ 936: public void setDefaultAssertionStatus(boolean enabled) 937: { 938: defaultAssertionStatus = enabled; 939: } 940: 941: /** 942: * Set the default assertion status for packages, used unless overridden 943: * by a class request. This default also covers subpackages, unless they 944: * are also specified. The unnamed package should use null for the name. 945: * 946: * @param name the package (and subpackages) to affect 947: * @param enabled true to set the default to enabled 948: * @see #setDefaultAssertionStatus(boolean) 949: * @see #setClassAssertionStatus(String, boolean) 950: * @see #clearAssertionStatus() 951: * @since 1.4 952: */ 953: public synchronized void setPackageAssertionStatus(String name, 954: boolean enabled) 955: { 956: if (packageAssertionStatus == null) 957: packageAssertionStatus 958: = new HashMap<String, Boolean>(StaticData.systemPackageAssertionStatus); 959: packageAssertionStatus.put(name, Boolean.valueOf(enabled)); 960: } 961: 962: /** 963: * Set the default assertion status for a class. This only affects the 964: * status of top-level classes, any other string is harmless. 965: * 966: * @param name the class to affect 967: * @param enabled true to set the default to enabled 968: * @throws NullPointerException if name is null 969: * @see #setDefaultAssertionStatus(boolean) 970: * @see #setPackageAssertionStatus(String, boolean) 971: * @see #clearAssertionStatus() 972: * @since 1.4 973: */ 974: public synchronized void setClassAssertionStatus(String name, 975: boolean enabled) 976: { 977: if (classAssertionStatus == null) 978: classAssertionStatus 979: = new HashMap<String, Boolean>(StaticData.systemClassAssertionStatus); 980: // The toString() hack catches null, as required. 981: classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled)); 982: } 983: 984: /** 985: * Resets the default assertion status of this classloader, its packages 986: * and classes, all to false. This allows overriding defaults inherited 987: * from the command line. 988: * 989: * @see #setDefaultAssertionStatus(boolean) 990: * @see #setClassAssertionStatus(String, boolean) 991: * @see #setPackageAssertionStatus(String, boolean) 992: * @since 1.4 993: */ 994: public synchronized void clearAssertionStatus() 995: { 996: defaultAssertionStatus = false; 997: packageAssertionStatus = null; 998: classAssertionStatus = null; 999: } 1000: 1001: /** 1002: * Return true if this loader is either the specified class loader 1003: * or an ancestor thereof. 1004: * @param loader the class loader to check 1005: */ 1006: final boolean isAncestorOf(ClassLoader loader) 1007: { 1008: while (loader != null) 1009: { 1010: if (this == loader) 1011: return true; 1012: loader = loader.parent; 1013: } 1014: return false; 1015: } 1016: 1017: private static URL[] getExtClassLoaderUrls() 1018: { 1019: String classpath = SystemProperties.getProperty("java.ext.dirs", ""); 1020: StringTokenizer tok = new StringTokenizer(classpath, File.pathSeparator); 1021: ArrayList list = new ArrayList(); 1022: while (tok.hasMoreTokens()) 1023: { 1024: try 1025: { 1026: File f = new File(tok.nextToken()); 1027: File[] files = f.listFiles(); 1028: if (files != null) 1029: for (int i = 0; i < files.length; i++) 1030: list.add(files[i].toURL()); 1031: } 1032: catch(Exception x) 1033: { 1034: } 1035: } 1036: URL[] urls = new URL[list.size()]; 1037: list.toArray(urls); 1038: return urls; 1039: } 1040: 1041: private static void addFileURL(ArrayList list, String file) 1042: { 1043: try 1044: { 1045: list.add(new File(file).toURL()); 1046: } 1047: catch(java.net.MalformedURLException x) 1048: { 1049: } 1050: } 1051: 1052: private static URL[] getSystemClassLoaderUrls() 1053: { 1054: String classpath = SystemProperties.getProperty("java.class.path", "."); 1055: StringTokenizer tok = new StringTokenizer(classpath, File.pathSeparator, true); 1056: ArrayList list = new ArrayList(); 1057: while (tok.hasMoreTokens()) 1058: { 1059: String s = tok.nextToken(); 1060: if (s.equals(File.pathSeparator)) 1061: addFileURL(list, "."); 1062: else 1063: { 1064: addFileURL(list, s); 1065: if (tok.hasMoreTokens()) 1066: { 1067: // Skip the separator. 1068: tok.nextToken(); 1069: // If the classpath ended with a separator, 1070: // append the current directory. 1071: if (!tok.hasMoreTokens()) 1072: addFileURL(list, "."); 1073: } 1074: } 1075: } 1076: URL[] urls = new URL[list.size()]; 1077: list.toArray(urls); 1078: return urls; 1079: } 1080: 1081: static ClassLoader defaultGetSystemClassLoader() 1082: { 1083: return createAuxiliarySystemClassLoader( 1084: createSystemClassLoader(getSystemClassLoaderUrls(), 1085: createExtClassLoader(getExtClassLoaderUrls(), null))); 1086: } 1087: 1088: static ClassLoader createExtClassLoader(URL[] urls, ClassLoader parent) 1089: { 1090: if (urls.length > 0) 1091: return new URLClassLoader(urls, parent); 1092: else 1093: return parent; 1094: } 1095: 1096: static ClassLoader createSystemClassLoader(URL[] urls, ClassLoader parent) 1097: { 1098: return 1099: new URLClassLoader(urls, parent) 1100: { 1101: protected synchronized Class loadClass(String name, 1102: boolean resolve) 1103: throws ClassNotFoundException 1104: { 1105: SecurityManager sm = SecurityManager.current; 1106: if (sm != null) 1107: { 1108: int lastDot = name.lastIndexOf('.'); 1109: if (lastDot != -1) 1110: sm.checkPackageAccess(name.substring(0, lastDot)); 1111: } 1112: return super.loadClass(name, resolve); 1113: } 1114: }; 1115: } 1116: 1117: static ClassLoader createAuxiliarySystemClassLoader(ClassLoader parent) 1118: { 1119: String loader = SystemProperties.getProperty("java.system.class.loader", null); 1120: if (loader == null) 1121: { 1122: return parent; 1123: } 1124: try 1125: { 1126: Constructor c = Class.forName(loader, false, parent) 1127: .getConstructor(new Class[] { ClassLoader.class }); 1128: return (ClassLoader)c.newInstance(new Object[] { parent }); 1129: } 1130: catch (Exception e) 1131: { 1132: System.err.println("Requested system classloader " + loader + " failed."); 1133: throw (Error) 1134: new Error("Requested system classloader " + loader + " failed.") 1135: .initCause(e); 1136: } 1137: } 1138: 1139: /** 1140: * Before doing anything "dangerous" please call this method to make sure 1141: * this class loader instance was properly constructed (and not obtained 1142: * by exploiting the finalizer attack) 1143: * @see #initialized 1144: */ 1145: private void checkInitialized() 1146: { 1147: if (! initialized) 1148: throw new SecurityException("attempt to use uninitialized class loader"); 1149: } 1150: 1151: }
GNU Classpath (0.95) |