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