GNU Classpath (0.20) | |
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: * @status still missing 1.4 functionality 124: */ 125: public abstract class ClassLoader 126: { 127: /** 128: * All packages defined by this classloader. It is not private in order to 129: * allow native code (and trusted subclasses) access to this field. 130: */ 131: final HashMap definedPackages = new HashMap(); 132: 133: /** 134: * The classloader that is consulted before this classloader. 135: * If null then the parent is the bootstrap classloader. 136: */ 137: private final ClassLoader parent; 138: 139: /** 140: * This is true if this classloader was successfully initialized. 141: * This flag is needed to avoid a class loader attack: even if the 142: * security manager rejects an attempt to create a class loader, the 143: * malicious class could have a finalize method which proceeds to 144: * define classes. 145: */ 146: private final boolean initialized; 147: 148: static class StaticData 149: { 150: /** 151: * The System Class Loader (a.k.a. Application Class Loader). The one 152: * returned by ClassLoader.getSystemClassLoader. 153: */ 154: static final ClassLoader systemClassLoader = 155: VMClassLoader.getSystemClassLoader(); 156: static 157: { 158: // Find out if we have to install a default security manager. Note that 159: // this is done here because we potentially need the system class loader 160: // to load the security manager and note also that we don't need the 161: // security manager until the system class loader is created. 162: // If the runtime chooses to use a class loader that doesn't have the 163: // system class loader as its parent, it is responsible for setting 164: // up a security manager before doing so. 165: String secman = SystemProperties.getProperty("java.security.manager"); 166: if (secman != null && SecurityManager.current == null) 167: { 168: if (secman.equals("") || secman.equals("default")) 169: { 170: SecurityManager.current = new SecurityManager(); 171: } 172: else 173: { 174: try 175: { 176: Class cl = Class.forName(secman, false, StaticData.systemClassLoader); 177: SecurityManager.current = (SecurityManager)cl.newInstance(); 178: } 179: catch (Exception x) 180: { 181: throw (InternalError) 182: new InternalError("Unable to create SecurityManager") 183: .initCause(x); 184: } 185: } 186: } 187: } 188: 189: /** 190: * The default protection domain, used when defining a class with a null 191: * parameter for the domain. 192: */ 193: static final ProtectionDomain defaultProtectionDomain; 194: static 195: { 196: CodeSource cs = new CodeSource(null, null); 197: PermissionCollection perm = Policy.getPolicy().getPermissions(cs); 198: defaultProtectionDomain = new ProtectionDomain(cs, perm); 199: } 200: /** 201: * The command-line state of the package assertion status overrides. This 202: * map is never modified, so it does not need to be synchronized. 203: */ 204: // Package visible for use by Class. 205: static final Map systemPackageAssertionStatus 206: = VMClassLoader.packageAssertionStatus(); 207: /** 208: * The command-line state of the class assertion status overrides. This 209: * map is never modified, so it does not need to be synchronized. 210: */ 211: // Package visible for use by Class. 212: static final Map systemClassAssertionStatus 213: = VMClassLoader.classAssertionStatus(); 214: } 215: 216: /** 217: * The desired assertion status of classes loaded by this loader, if not 218: * overridden by package or class instructions. 219: */ 220: // Package visible for use by Class. 221: boolean defaultAssertionStatus = VMClassLoader.defaultAssertionStatus(); 222: 223: /** 224: * The map of package assertion status overrides, or null if no package 225: * overrides have been specified yet. The values of the map should be 226: * Boolean.TRUE or Boolean.FALSE, and the unnamed package is represented 227: * by the null key. This map must be synchronized on this instance. 228: */ 229: // Package visible for use by Class. 230: Map packageAssertionStatus; 231: 232: /** 233: * The map of class assertion status overrides, or null if no class 234: * overrides have been specified yet. The values of the map should be 235: * Boolean.TRUE or Boolean.FALSE. This map must be synchronized on this 236: * instance. 237: */ 238: // Package visible for use by Class. 239: Map classAssertionStatus; 240: 241: /** 242: * VM private data. 243: */ 244: transient Object vmdata; 245: 246: /** 247: * Create a new ClassLoader with as parent the system classloader. There 248: * may be a security check for <code>checkCreateClassLoader</code>. 249: * 250: * @throws SecurityException if the security check fails 251: */ 252: protected ClassLoader() throws SecurityException 253: { 254: this(StaticData.systemClassLoader); 255: } 256: 257: /** 258: * Create a new ClassLoader with the specified parent. The parent will 259: * be consulted when a class or resource is requested through 260: * <code>loadClass()</code> or <code>getResource()</code>. Only when the 261: * parent classloader cannot provide the requested class or resource the 262: * <code>findClass()</code> or <code>findResource()</code> method 263: * of this classloader will be called. There may be a security check for 264: * <code>checkCreateClassLoader</code>. 265: * 266: * @param parent the classloader's parent, or null for the bootstrap 267: * classloader 268: * @throws SecurityException if the security check fails 269: * @since 1.2 270: */ 271: protected ClassLoader(ClassLoader parent) 272: { 273: // May we create a new classloader? 274: SecurityManager sm = SecurityManager.current; 275: if (sm != null) 276: sm.checkCreateClassLoader(); 277: this.parent = parent; 278: this.initialized = true; 279: } 280: 281: /** 282: * Load a class using this ClassLoader or its parent, without resolving 283: * it. Calls <code>loadClass(name, false)</code>. 284: * 285: * <p>Subclasses should not override this method but should override 286: * <code>findClass()</code> which is called by this method.</p> 287: * 288: * @param name the name of the class relative to this ClassLoader 289: * @return the loaded class 290: * @throws ClassNotFoundException if the class cannot be found 291: */ 292: public Class loadClass(String name) throws ClassNotFoundException 293: { 294: return loadClass(name, false); 295: } 296: 297: /** 298: * Load a class using this ClassLoader or its parent, possibly resolving 299: * it as well using <code>resolveClass()</code>. It first tries to find 300: * out if the class has already been loaded through this classloader by 301: * calling <code>findLoadedClass()</code>. Then it calls 302: * <code>loadClass()</code> on the parent classloader (or when there is 303: * no parent it uses the VM bootclassloader). If the class is still 304: * not loaded it tries to create a new class by calling 305: * <code>findClass()</code>. Finally when <code>resolve</code> is 306: * <code>true</code> it also calls <code>resolveClass()</code> on the 307: * newly loaded class. 308: * 309: * <p>Subclasses should not override this method but should override 310: * <code>findClass()</code> which is called by this method.</p> 311: * 312: * @param name the fully qualified name of the class to load 313: * @param resolve whether or not to resolve the class 314: * @return the loaded class 315: * @throws ClassNotFoundException if the class cannot be found 316: */ 317: protected synchronized Class loadClass(String name, boolean resolve) 318: throws ClassNotFoundException 319: { 320: // Have we already loaded this class? 321: Class c = findLoadedClass(name); 322: if (c == null) 323: { 324: // Can the class be loaded by a parent? 325: try 326: { 327: if (parent == null) 328: { 329: c = VMClassLoader.loadClass(name, resolve); 330: if (c != null) 331: return c; 332: } 333: else 334: { 335: return parent.loadClass(name, resolve); 336: } 337: } 338: catch (ClassNotFoundException e) 339: { 340: } 341: // Still not found, we have to do it ourself. 342: c = findClass(name); 343: } 344: if (resolve) 345: resolveClass(c); 346: return c; 347: } 348: 349: /** 350: * Called for every class name that is needed but has not yet been 351: * defined by this classloader or one of its parents. It is called by 352: * <code>loadClass()</code> after both <code>findLoadedClass()</code> and 353: * <code>parent.loadClass()</code> couldn't provide the requested class. 354: * 355: * <p>The default implementation throws a 356: * <code>ClassNotFoundException</code>. Subclasses should override this 357: * method. An implementation of this method in a subclass should get the 358: * class bytes of the class (if it can find them), if the package of the 359: * requested class doesn't exist it should define the package and finally 360: * it should call define the actual class. It does not have to resolve the 361: * class. It should look something like the following:<br> 362: * 363: * <pre> 364: * // Get the bytes that describe the requested class 365: * byte[] classBytes = classLoaderSpecificWayToFindClassBytes(name); 366: * // Get the package name 367: * int lastDot = name.lastIndexOf('.'); 368: * if (lastDot != -1) 369: * { 370: * String packageName = name.substring(0, lastDot); 371: * // Look if the package already exists 372: * if (getPackage(packageName) == null) 373: * { 374: * // define the package 375: * definePackage(packageName, ...); 376: * } 377: * } 378: * // Define and return the class 379: * return defineClass(name, classBytes, 0, classBytes.length); 380: * </pre> 381: * 382: * <p><code>loadClass()</code> makes sure that the <code>Class</code> 383: * returned by <code>findClass()</code> will later be returned by 384: * <code>findLoadedClass()</code> when the same class name is requested. 385: * 386: * @param name class name to find (including the package name) 387: * @return the requested Class 388: * @throws ClassNotFoundException when the class can not be found 389: * @since 1.2 390: */ 391: protected Class findClass(String name) throws ClassNotFoundException 392: { 393: throw new ClassNotFoundException(name); 394: } 395: 396: /** 397: * Helper to define a class using a string of bytes. This version is not 398: * secure. 399: * 400: * @param data the data representing the classfile, in classfile format 401: * @param offset the offset into the data where the classfile starts 402: * @param len the length of the classfile data in the array 403: * @return the class that was defined 404: * @throws ClassFormatError if data is not in proper classfile format 405: * @throws IndexOutOfBoundsException if offset or len is negative, or 406: * offset + len exceeds data 407: * @deprecated use {@link #defineClass(String, byte[], int, int)} instead 408: */ 409: protected final Class defineClass(byte[] data, int offset, int len) 410: throws ClassFormatError 411: { 412: return defineClass(null, data, offset, len); 413: } 414: 415: /** 416: * Helper to define a class using a string of bytes without a 417: * ProtectionDomain. Subclasses should call this method from their 418: * <code>findClass()</code> implementation. The name should use '.' 419: * separators, and discard the trailing ".class". The default protection 420: * domain has the permissions of 421: * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))</code>. 422: * 423: * @param name the name to give the class, or null if unknown 424: * @param data the data representing the classfile, in classfile format 425: * @param offset the offset into the data where the classfile starts 426: * @param len the length of the classfile data in the array 427: * @return the class that was defined 428: * @throws ClassFormatError if data is not in proper classfile format 429: * @throws IndexOutOfBoundsException if offset or len is negative, or 430: * offset + len exceeds data 431: * @throws SecurityException if name starts with "java." 432: * @since 1.1 433: */ 434: protected final Class defineClass(String name, byte[] data, int offset, 435: int len) throws ClassFormatError 436: { 437: return defineClass(name, data, offset, len, null); 438: } 439: 440: /** 441: * Helper to define a class using a string of bytes. Subclasses should call 442: * this method from their <code>findClass()</code> implementation. If the 443: * domain is null, the default of 444: * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))</code> 445: * is used. Once a class has been defined in a package, all further classes 446: * in that package must have the same set of certificates or a 447: * SecurityException is thrown. 448: * 449: * @param name the name to give the class. null if unknown 450: * @param data the data representing the classfile, in classfile format 451: * @param offset the offset into the data where the classfile starts 452: * @param len the length of the classfile data in the array 453: * @param domain the ProtectionDomain to give to the class, null for the 454: * default protection domain 455: * @return the class that was defined 456: * @throws ClassFormatError if data is not in proper classfile format 457: * @throws IndexOutOfBoundsException if offset or len is negative, or 458: * offset + len exceeds data 459: * @throws SecurityException if name starts with "java.", or if certificates 460: * do not match up 461: * @since 1.2 462: */ 463: protected final synchronized Class defineClass(String name, byte[] data, 464: int offset, int len, 465: ProtectionDomain domain) 466: throws ClassFormatError 467: { 468: checkInitialized(); 469: if (domain == null) 470: domain = StaticData.defaultProtectionDomain; 471: 472: return VMClassLoader.defineClass(this, name, data, offset, 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: */ 632: public final Enumeration getResources(String name) throws IOException 633: { 634: Enumeration parentResources; 635: if (parent == null) 636: parentResources = VMClassLoader.getResources(name); 637: else 638: parentResources = parent.getResources(name); 639: return new DoubleEnumeration(parentResources, findResources(name)); 640: } 641: 642: /** 643: * Called whenever all locations of a named resource are needed. 644: * It is called by <code>getResources()</code> after it has called 645: * <code>parent.getResources()</code>. The results are combined by 646: * the <code>getResources()</code> method. 647: * 648: * <p>The default implementation always returns an empty Enumeration. 649: * Subclasses should override it when they can provide an Enumeration of 650: * URLs (possibly just one element) to the named resource. 651: * The first URL of the Enumeration should be the same as the one 652: * returned by <code>findResource</code>. 653: * 654: * @param name the name of the resource to be found 655: * @return a possibly empty Enumeration of URLs to the named resource 656: * @throws IOException if I/O errors occur in the process 657: * @since 1.2 658: */ 659: protected Enumeration findResources(String name) throws IOException 660: { 661: return EmptyEnumeration.getInstance(); 662: } 663: 664: /** 665: * Called whenever a resource is needed that could not be provided by 666: * one of the parents of this classloader. It is called by 667: * <code>getResource()</code> after <code>parent.getResource()</code> 668: * couldn't provide the requested resource. 669: * 670: * <p>The default implementation always returns null. Subclasses should 671: * override this method when they can provide a way to return a URL 672: * to a named resource. 673: * 674: * @param name the name of the resource to be found 675: * @return a URL to the named resource or null when not found 676: * @since 1.2 677: */ 678: protected URL findResource(String name) 679: { 680: return null; 681: } 682: 683: /** 684: * Get the URL to a resource using the system classloader. 685: * 686: * @param name the name of the resource relative to the system classloader 687: * @return the URL to the resource 688: * @since 1.1 689: */ 690: public static final URL getSystemResource(String name) 691: { 692: return StaticData.systemClassLoader.getResource(name); 693: } 694: 695: /** 696: * Get an Enumeration of URLs to resources with a given name using the 697: * the system classloader. The enumeration firsts lists the resources with 698: * the given name that can be found by the bootstrap classloader followed 699: * by the resources with the given name that can be found on the classpath. 700: * 701: * @param name the name of the resource relative to the system classloader 702: * @return an Enumeration of URLs to the resources 703: * @throws IOException if I/O errors occur in the process 704: * @since 1.2 705: */ 706: public static Enumeration getSystemResources(String name) throws IOException 707: { 708: return StaticData.systemClassLoader.getResources(name); 709: } 710: 711: /** 712: * Get a resource as stream using this classloader or one of its parents. 713: * First calls <code>getResource()</code> and if that returns a URL to 714: * the resource then it calls and returns the InputStream given by 715: * <code>URL.openStream()</code>. 716: * 717: * <p>Subclasses should not override this method but should override 718: * <code>findResource()</code> which is called by this method. 719: * 720: * @param name the name of the resource relative to this classloader 721: * @return an InputStream to the resource, or null 722: * @since 1.1 723: */ 724: public InputStream getResourceAsStream(String name) 725: { 726: try 727: { 728: URL url = getResource(name); 729: if (url == null) 730: return null; 731: return url.openStream(); 732: } 733: catch (IOException e) 734: { 735: return null; 736: } 737: } 738: 739: /** 740: * Get a resource using the system classloader. 741: * 742: * @param name the name of the resource relative to the system classloader 743: * @return an input stream for the resource, or null 744: * @since 1.1 745: */ 746: public static final InputStream getSystemResourceAsStream(String name) 747: { 748: try 749: { 750: URL url = getSystemResource(name); 751: if (url == null) 752: return null; 753: return url.openStream(); 754: } 755: catch (IOException e) 756: { 757: return null; 758: } 759: } 760: 761: /** 762: * Returns the system classloader. The system classloader (also called 763: * the application classloader) is the classloader that is used to 764: * load the application classes on the classpath (given by the system 765: * property <code>java.class.path</code>. This is set as the context 766: * class loader for a thread. The system property 767: * <code>java.system.class.loader</code>, if defined, is taken to be the 768: * name of the class to use as the system class loader, which must have 769: * a public constructor which takes a ClassLoader as a parent. The parent 770: * class loader passed in the constructor is the default system class 771: * loader. 772: * 773: * <p>Note that this is different from the bootstrap classloader that 774: * actually loads all the real "system" classes. 775: * 776: * <p>A security check will be performed for 777: * <code>RuntimePermission("getClassLoader")</code> if the calling class 778: * is not a parent of the system class loader. 779: * 780: * @return the system class loader 781: * @throws SecurityException if the security check fails 782: * @throws IllegalStateException if this is called recursively 783: * @throws Error if <code>java.system.class.loader</code> fails to load 784: * @since 1.2 785: */ 786: public static ClassLoader getSystemClassLoader() 787: { 788: // Check if we may return the system classloader 789: SecurityManager sm = SecurityManager.current; 790: if (sm != null) 791: { 792: ClassLoader cl = VMStackWalker.getCallingClassLoader(); 793: if (cl != null && cl != StaticData.systemClassLoader) 794: sm.checkPermission(new RuntimePermission("getClassLoader")); 795: } 796: 797: return StaticData.systemClassLoader; 798: } 799: 800: /** 801: * Defines a new package and creates a Package object. The package should 802: * be defined before any class in the package is defined with 803: * <code>defineClass()</code>. The package should not yet be defined 804: * before in this classloader or in one of its parents (which means that 805: * <code>getPackage()</code> should return <code>null</code>). All 806: * parameters except the <code>name</code> of the package may be 807: * <code>null</code>. 808: * 809: * <p>Subclasses should call this method from their <code>findClass()</code> 810: * implementation before calling <code>defineClass()</code> on a Class 811: * in a not yet defined Package (which can be checked by calling 812: * <code>getPackage()</code>). 813: * 814: * @param name the name of the Package 815: * @param specTitle the name of the specification 816: * @param specVendor the name of the specification designer 817: * @param specVersion the version of this specification 818: * @param implTitle the name of the implementation 819: * @param implVendor the vendor that wrote this implementation 820: * @param implVersion the version of this implementation 821: * @param sealed if sealed the origin of the package classes 822: * @return the Package object for the specified package 823: * @throws IllegalArgumentException if the package name is null or it 824: * was already defined by this classloader or one of its parents 825: * @see Package 826: * @since 1.2 827: */ 828: protected Package definePackage(String name, String specTitle, 829: String specVendor, String specVersion, 830: String implTitle, String implVendor, 831: String implVersion, URL sealed) 832: { 833: if (getPackage(name) != null) 834: throw new IllegalArgumentException("Package " + name 835: + " already defined"); 836: Package p = new Package(name, specTitle, specVendor, specVersion, 837: implTitle, implVendor, implVersion, sealed); 838: synchronized (definedPackages) 839: { 840: definedPackages.put(name, p); 841: } 842: return p; 843: } 844: 845: /** 846: * Returns the Package object for the requested package name. It returns 847: * null when the package is not defined by this classloader or one of its 848: * parents. 849: * 850: * @param name the package name to find 851: * @return the package, if defined 852: * @since 1.2 853: */ 854: protected Package getPackage(String name) 855: { 856: Package p; 857: if (parent == null) 858: p = VMClassLoader.getPackage(name); 859: else 860: p = parent.getPackage(name); 861: 862: if (p == null) 863: { 864: synchronized (definedPackages) 865: { 866: p = (Package) definedPackages.get(name); 867: } 868: } 869: return p; 870: } 871: 872: /** 873: * Returns all Package objects defined by this classloader and its parents. 874: * 875: * @return an array of all defined packages 876: * @since 1.2 877: */ 878: protected Package[] getPackages() 879: { 880: // Get all our packages. 881: Package[] packages; 882: synchronized(definedPackages) 883: { 884: packages = new Package[definedPackages.size()]; 885: definedPackages.values().toArray(packages); 886: } 887: 888: // If we have a parent get all packages defined by our parents. 889: Package[] parentPackages; 890: if (parent == null) 891: parentPackages = VMClassLoader.getPackages(); 892: else 893: parentPackages = parent.getPackages(); 894: 895: Package[] allPackages = new Package[parentPackages.length 896: + packages.length]; 897: System.arraycopy(parentPackages, 0, allPackages, 0, 898: parentPackages.length); 899: System.arraycopy(packages, 0, allPackages, parentPackages.length, 900: packages.length); 901: return allPackages; 902: } 903: 904: /** 905: * Called by <code>Runtime.loadLibrary()</code> to get an absolute path 906: * to a (system specific) library that was requested by a class loaded 907: * by this classloader. The default implementation returns 908: * <code>null</code>. It should be implemented by subclasses when they 909: * have a way to find the absolute path to a library. If this method 910: * returns null the library is searched for in the default locations 911: * (the directories listed in the <code>java.library.path</code> system 912: * property). 913: * 914: * @param name the (system specific) name of the requested library 915: * @return the full pathname to the requested library, or null 916: * @see Runtime#loadLibrary(String) 917: * @since 1.2 918: */ 919: protected String findLibrary(String name) 920: { 921: return null; 922: } 923: 924: /** 925: * Set the default assertion status for classes loaded by this classloader, 926: * used unless overridden by a package or class request. 927: * 928: * @param enabled true to set the default to enabled 929: * @see #setClassAssertionStatus(String, boolean) 930: * @see #setPackageAssertionStatus(String, boolean) 931: * @see #clearAssertionStatus() 932: * @since 1.4 933: */ 934: public void setDefaultAssertionStatus(boolean enabled) 935: { 936: defaultAssertionStatus = enabled; 937: } 938: 939: /** 940: * Set the default assertion status for packages, used unless overridden 941: * by a class request. This default also covers subpackages, unless they 942: * are also specified. The unnamed package should use null for the name. 943: * 944: * @param name the package (and subpackages) to affect 945: * @param enabled true to set the default to enabled 946: * @see #setDefaultAssertionStatus(boolean) 947: * @see #setClassAssertionStatus(String, boolean) 948: * @see #clearAssertionStatus() 949: * @since 1.4 950: */ 951: public synchronized void setPackageAssertionStatus(String name, 952: boolean enabled) 953: { 954: if (packageAssertionStatus == null) 955: packageAssertionStatus 956: = new HashMap(StaticData.systemPackageAssertionStatus); 957: packageAssertionStatus.put(name, Boolean.valueOf(enabled)); 958: } 959: 960: /** 961: * Set the default assertion status for a class. This only affects the 962: * status of top-level classes, any other string is harmless. 963: * 964: * @param name the class to affect 965: * @param enabled true to set the default to enabled 966: * @throws NullPointerException if name is null 967: * @see #setDefaultAssertionStatus(boolean) 968: * @see #setPackageAssertionStatus(String, boolean) 969: * @see #clearAssertionStatus() 970: * @since 1.4 971: */ 972: public synchronized void setClassAssertionStatus(String name, 973: boolean enabled) 974: { 975: if (classAssertionStatus == null) 976: classAssertionStatus = 977: new HashMap(StaticData.systemClassAssertionStatus); 978: // The toString() hack catches null, as required. 979: classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled)); 980: } 981: 982: /** 983: * Resets the default assertion status of this classloader, its packages 984: * and classes, all to false. This allows overriding defaults inherited 985: * from the command line. 986: * 987: * @see #setDefaultAssertionStatus(boolean) 988: * @see #setClassAssertionStatus(String, boolean) 989: * @see #setPackageAssertionStatus(String, boolean) 990: * @since 1.4 991: */ 992: public synchronized void clearAssertionStatus() 993: { 994: defaultAssertionStatus = false; 995: packageAssertionStatus = new HashMap(); 996: classAssertionStatus = new HashMap(); 997: } 998: 999: /** 1000: * Return true if this loader is either the specified class loader 1001: * or an ancestor thereof. 1002: * @param loader the class loader to check 1003: */ 1004: final boolean isAncestorOf(ClassLoader loader) 1005: { 1006: while (loader != null) 1007: { 1008: if (this == loader) 1009: return true; 1010: loader = loader.parent; 1011: } 1012: return false; 1013: } 1014: 1015: private static URL[] getExtClassLoaderUrls() 1016: { 1017: String classpath = SystemProperties.getProperty("java.ext.dirs", ""); 1018: StringTokenizer tok = new StringTokenizer(classpath, File.pathSeparator); 1019: ArrayList list = new ArrayList(); 1020: while (tok.hasMoreTokens()) 1021: { 1022: try 1023: { 1024: File f = new File(tok.nextToken()); 1025: File[] files = f.listFiles(); 1026: if (files != null) 1027: for (int i = 0; i < files.length; i++) 1028: list.add(files[i].toURL()); 1029: } 1030: catch(Exception x) 1031: { 1032: } 1033: } 1034: URL[] urls = new URL[list.size()]; 1035: list.toArray(urls); 1036: return urls; 1037: } 1038: 1039: private static void addFileURL(ArrayList list, String file) 1040: { 1041: try 1042: { 1043: list.add(new File(file).toURL()); 1044: } 1045: catch(java.net.MalformedURLException x) 1046: { 1047: } 1048: } 1049: 1050: private static URL[] getSystemClassLoaderUrls() 1051: { 1052: String classpath = SystemProperties.getProperty("java.class.path", "."); 1053: StringTokenizer tok = new StringTokenizer(classpath, File.pathSeparator, true); 1054: ArrayList list = new ArrayList(); 1055: while (tok.hasMoreTokens()) 1056: { 1057: String s = tok.nextToken(); 1058: if (s.equals(File.pathSeparator)) 1059: addFileURL(list, "."); 1060: else 1061: { 1062: addFileURL(list, s); 1063: if (tok.hasMoreTokens()) 1064: { 1065: // Skip the separator. 1066: tok.nextToken(); 1067: // If the classpath ended with a separator, 1068: // append the current directory. 1069: if (!tok.hasMoreTokens()) 1070: addFileURL(list, "."); 1071: } 1072: } 1073: } 1074: URL[] urls = new URL[list.size()]; 1075: list.toArray(urls); 1076: return urls; 1077: } 1078: 1079: static ClassLoader defaultGetSystemClassLoader() 1080: { 1081: return createAuxiliarySystemClassLoader( 1082: createSystemClassLoader(getSystemClassLoaderUrls(), 1083: createExtClassLoader(getExtClassLoaderUrls(), null))); 1084: } 1085: 1086: static ClassLoader createExtClassLoader(URL[] urls, ClassLoader parent) 1087: { 1088: if (urls.length > 0) 1089: return new URLClassLoader(urls, parent); 1090: else 1091: return parent; 1092: } 1093: 1094: static ClassLoader createSystemClassLoader(URL[] urls, ClassLoader parent) 1095: { 1096: return 1097: new URLClassLoader(urls, parent) 1098: { 1099: protected synchronized Class loadClass(String name, 1100: boolean resolve) 1101: throws ClassNotFoundException 1102: { 1103: SecurityManager sm = SecurityManager.current; 1104: if (sm != null) 1105: { 1106: int lastDot = name.lastIndexOf('.'); 1107: if (lastDot != -1) 1108: sm.checkPackageAccess(name.substring(0, lastDot)); 1109: } 1110: return super.loadClass(name, resolve); 1111: } 1112: }; 1113: } 1114: 1115: static ClassLoader createAuxiliarySystemClassLoader(ClassLoader parent) 1116: { 1117: String loader = SystemProperties.getProperty("java.system.class.loader", null); 1118: if (loader == null) 1119: { 1120: return parent; 1121: } 1122: try 1123: { 1124: Constructor c = Class.forName(loader, false, parent) 1125: .getConstructor(new Class[] { ClassLoader.class }); 1126: return (ClassLoader)c.newInstance(new Object[] { parent }); 1127: } 1128: catch (Exception e) 1129: { 1130: System.err.println("Requested system classloader " + loader + " failed."); 1131: throw (Error) 1132: new Error("Requested system classloader " + loader + " failed.") 1133: .initCause(e); 1134: } 1135: } 1136: 1137: /** 1138: * Before doing anything "dangerous" please call this method to make sure 1139: * this class loader instance was properly constructed (and not obtained 1140: * by exploiting the finalizer attack) 1141: * @see #initialized 1142: */ 1143: private void checkInitialized() 1144: { 1145: if (! initialized) 1146: throw new SecurityException("attempt to use uninitialized class loader"); 1147: } 1148: }
GNU Classpath (0.20) |