GNU Classpath (0.18) | ||
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 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 definedPackages = new HashMap(); 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 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 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.defineClass(this, name, data, offset, len, domain); 472: } 473: 474: /** 475: * Links the class, if that has not already been done. Linking basically 476: * resolves all references to other classes made by this class. 477: * 478: * @param c the class to resolve 479: * @throws NullPointerException if c is null 480: * @throws LinkageError if linking fails 481: */ 482: protected final void resolveClass(Class c) 483: { 484: checkInitialized(); 485: VMClassLoader.resolveClass(c); 486: } 487: 488: /** 489: * Helper to find a Class using the system classloader, possibly loading it. 490: * A subclass usually does not need to call this, if it correctly 491: * overrides <code>findClass(String)</code>. 492: * 493: * @param name the name of the class to find 494: * @return the found class 495: * @throws ClassNotFoundException if the class cannot be found 496: */ 497: protected final Class findSystemClass(String name) 498: throws ClassNotFoundException 499: { 500: checkInitialized(); 501: return Class.forName(name, false, StaticData.systemClassLoader); 502: } 503: 504: /** 505: * Returns the parent of this classloader. If the parent of this 506: * classloader is the bootstrap classloader then this method returns 507: * <code>null</code>. A security check may be performed on 508: * <code>RuntimePermission("getClassLoader")</code>. 509: * 510: * @return the parent <code>ClassLoader</code> 511: * @throws SecurityException if the security check fails 512: * @since 1.2 513: */ 514: public final ClassLoader getParent() 515: { 516: // Check if we may return the parent classloader. 517: SecurityManager sm = SecurityManager.current; 518: if (sm != null) 519: { 520: ClassLoader cl = VMStackWalker.getCallingClassLoader(); 521: if (cl != null && ! cl.isAncestorOf(this)) 522: sm.checkPermission(new RuntimePermission("getClassLoader")); 523: } 524: return parent; 525: } 526: 527: /** 528: * Helper to set the signers of a class. This should be called after 529: * defining the class. 530: * 531: * @param c the Class to set signers of 532: * @param signers the signers to set 533: * @since 1.1 534: */ 535: protected final void setSigners(Class c, Object[] signers) 536: { 537: checkInitialized(); 538: c.setSigners(signers); 539: } 540: 541: /** 542: * Helper to find an already-loaded class in this ClassLoader. 543: * 544: * @param name the name of the class to find 545: * @return the found Class, or null if it is not found 546: * @since 1.1 547: */ 548: protected final synchronized Class findLoadedClass(String name) 549: { 550: checkInitialized(); 551: return VMClassLoader.findLoadedClass(this, name); 552: } 553: 554: /** 555: * Get the URL to a resource using this classloader or one of its parents. 556: * First tries to get the resource by calling <code>getResource()</code> 557: * on the parent classloader. If the parent classloader returns null then 558: * it tries finding the resource by calling <code>findResource()</code> on 559: * this classloader. The resource name should be separated by '/' for path 560: * elements. 561: * 562: * <p>Subclasses should not override this method but should override 563: * <code>findResource()</code> which is called by this method. 564: * 565: * @param name the name of the resource relative to this classloader 566: * @return the URL to the resource or null when not found 567: */ 568: public URL getResource(String name) 569: { 570: URL result; 571: 572: if (parent == null) 573: result = VMClassLoader.getResource(name); 574: else 575: result = parent.getResource(name); 576: 577: if (result == null) 578: result = findResource(name); 579: return result; 580: } 581: 582: /** 583: * Returns an Enumeration of all resources with a given name that can 584: * be found by this classloader and its parents. Certain classloaders 585: * (such as the URLClassLoader when given multiple jar files) can have 586: * multiple resources with the same name that come from multiple locations. 587: * It can also occur that a parent classloader offers a resource with a 588: * certain name and the child classloader also offers a resource with that 589: * same name. <code>getResource()</code> only offers the first resource (of the 590: * parent) with a given name. This method lists all resources with the 591: * same name. The name should use '/' as path separators. 592: * 593: * <p>The Enumeration is created by first calling <code>getResources()</code> 594: * on the parent classloader and then calling <code>findResources()</code> 595: * on this classloader.</p> 596: * 597: * @param name the resource name 598: * @return an enumaration of all resources found 599: * @throws IOException if I/O errors occur in the process 600: * @since 1.2 601: */ 602: public final Enumeration getResources(String name) throws IOException 603: { 604: Enumeration parentResources; 605: if (parent == null) 606: parentResources = VMClassLoader.getResources(name); 607: else 608: parentResources = parent.getResources(name); 609: return new DoubleEnumeration(parentResources, findResources(name)); 610: } 611: 612: /** 613: * Called whenever all locations of a named resource are needed. 614: * It is called by <code>getResources()</code> after it has called 615: * <code>parent.getResources()</code>. The results are combined by 616: * the <code>getResources()</code> method. 617: * 618: * <p>The default implementation always returns an empty Enumeration. 619: * Subclasses should override it when they can provide an Enumeration of 620: * URLs (possibly just one element) to the named resource. 621: * The first URL of the Enumeration should be the same as the one 622: * returned by <code>findResource</code>. 623: * 624: * @param name the name of the resource to be found 625: * @return a possibly empty Enumeration of URLs to the named resource 626: * @throws IOException if I/O errors occur in the process 627: * @since 1.2 628: */ 629: protected Enumeration findResources(String name) throws IOException 630: { 631: return EmptyEnumeration.getInstance(); 632: } 633: 634: /** 635: * Called whenever a resource is needed that could not be provided by 636: * one of the parents of this classloader. It is called by 637: * <code>getResource()</code> after <code>parent.getResource()</code> 638: * couldn't provide the requested resource. 639: * 640: * <p>The default implementation always returns null. Subclasses should 641: * override this method when they can provide a way to return a URL 642: * to a named resource. 643: * 644: * @param name the name of the resource to be found 645: * @return a URL to the named resource or null when not found 646: * @since 1.2 647: */ 648: protected URL findResource(String name) 649: { 650: return null; 651: } 652: 653: /** 654: * Get the URL to a resource using the system classloader. 655: * 656: * @param name the name of the resource relative to the system classloader 657: * @return the URL to the resource 658: * @since 1.1 659: */ 660: public static final URL getSystemResource(String name) 661: { 662: return StaticData.systemClassLoader.getResource(name); 663: } 664: 665: /** 666: * Get an Enumeration of URLs to resources with a given name using the 667: * the system classloader. The enumeration firsts lists the resources with 668: * the given name that can be found by the bootstrap classloader followed 669: * by the resources with the given name that can be found on the classpath. 670: * 671: * @param name the name of the resource relative to the system classloader 672: * @return an Enumeration of URLs to the resources 673: * @throws IOException if I/O errors occur in the process 674: * @since 1.2 675: */ 676: public static Enumeration getSystemResources(String name) throws IOException 677: { 678: return StaticData.systemClassLoader.getResources(name); 679: } 680: 681: /** 682: * Get a resource as stream using this classloader or one of its parents. 683: * First calls <code>getResource()</code> and if that returns a URL to 684: * the resource then it calls and returns the InputStream given by 685: * <code>URL.openStream()</code>. 686: * 687: * <p>Subclasses should not override this method but should override 688: * <code>findResource()</code> which is called by this method. 689: * 690: * @param name the name of the resource relative to this classloader 691: * @return an InputStream to the resource, or null 692: * @since 1.1 693: */ 694: public InputStream getResourceAsStream(String name) 695: { 696: try 697: { 698: URL url = getResource(name); 699: if (url == null) 700: return null; 701: return url.openStream(); 702: } 703: catch (IOException e) 704: { 705: return null; 706: } 707: } 708: 709: /** 710: * Get a resource using the system classloader. 711: * 712: * @param name the name of the resource relative to the system classloader 713: * @return an input stream for the resource, or null 714: * @since 1.1 715: */ 716: public static final InputStream getSystemResourceAsStream(String name) 717: { 718: try 719: { 720: URL url = getSystemResource(name); 721: if (url == null) 722: return null; 723: return url.openStream(); 724: } 725: catch (IOException e) 726: { 727: return null; 728: } 729: } 730: 731: /** 732: * Returns the system classloader. The system classloader (also called 733: * the application classloader) is the classloader that is used to 734: * load the application classes on the classpath (given by the system 735: * property <code>java.class.path</code>. This is set as the context 736: * class loader for a thread. The system property 737: * <code>java.system.class.loader</code>, if defined, is taken to be the 738: * name of the class to use as the system class loader, which must have 739: * a public constructor which takes a ClassLoader as a parent. The parent 740: * class loader passed in the constructor is the default system class 741: * loader. 742: * 743: * <p>Note that this is different from the bootstrap classloader that 744: * actually loads all the real "system" classes. 745: * 746: * <p>A security check will be performed for 747: * <code>RuntimePermission("getClassLoader")</code> if the calling class 748: * is not a parent of the system class loader. 749: * 750: * @return the system class loader 751: * @throws SecurityException if the security check fails 752: * @throws IllegalStateException if this is called recursively 753: * @throws Error if <code>java.system.class.loader</code> fails to load 754: * @since 1.2 755: */ 756: public static ClassLoader getSystemClassLoader() 757: { 758: // Check if we may return the system classloader 759: SecurityManager sm = SecurityManager.current; 760: if (sm != null) 761: { 762: ClassLoader cl = VMStackWalker.getCallingClassLoader(); 763: if (cl != null && cl != StaticData.systemClassLoader) 764: sm.checkPermission(new RuntimePermission("getClassLoader")); 765: } 766: 767: return StaticData.systemClassLoader; 768: } 769: 770: /** 771: * Defines a new package and creates a Package object. The package should 772: * be defined before any class in the package is defined with 773: * <code>defineClass()</code>. The package should not yet be defined 774: * before in this classloader or in one of its parents (which means that 775: * <code>getPackage()</code> should return <code>null</code>). All 776: * parameters except the <code>name</code> of the package may be 777: * <code>null</code>. 778: * 779: * <p>Subclasses should call this method from their <code>findClass()</code> 780: * implementation before calling <code>defineClass()</code> on a Class 781: * in a not yet defined Package (which can be checked by calling 782: * <code>getPackage()</code>). 783: * 784: * @param name the name of the Package 785: * @param specTitle the name of the specification 786: * @param specVendor the name of the specification designer 787: * @param specVersion the version of this specification 788: * @param implTitle the name of the implementation 789: * @param implVendor the vendor that wrote this implementation 790: * @param implVersion the version of this implementation 791: * @param sealed if sealed the origin of the package classes 792: * @return the Package object for the specified package 793: * @throws IllegalArgumentException if the package name is null or it 794: * was already defined by this classloader or one of its parents 795: * @see Package 796: * @since 1.2 797: */ 798: protected Package definePackage(String name, String specTitle, 799: String specVendor, String specVersion, 800: String implTitle, String implVendor, 801: String implVersion, URL sealed) 802: { 803: if (getPackage(name) != null) 804: throw new IllegalArgumentException("Package " + name 805: + " already defined"); 806: Package p = new Package(name, specTitle, specVendor, specVersion, 807: implTitle, implVendor, implVersion, sealed); 808: synchronized (definedPackages) 809: { 810: definedPackages.put(name, p); 811: } 812: return p; 813: } 814: 815: /** 816: * Returns the Package object for the requested package name. It returns 817: * null when the package is not defined by this classloader or one of its 818: * parents. 819: * 820: * @param name the package name to find 821: * @return the package, if defined 822: * @since 1.2 823: */ 824: protected Package getPackage(String name) 825: { 826: Package p; 827: if (parent == null) 828: p = VMClassLoader.getPackage(name); 829: else 830: p = parent.getPackage(name); 831: 832: if (p == null) 833: { 834: synchronized (definedPackages) 835: { 836: p = (Package) definedPackages.get(name); 837: } 838: } 839: return p; 840: } 841: 842: /** 843: * Returns all Package objects defined by this classloader and its parents. 844: * 845: * @return an array of all defined packages 846: * @since 1.2 847: */ 848: protected Package[] getPackages() 849: { 850: // Get all our packages. 851: Package[] packages; 852: synchronized(definedPackages) 853: { 854: packages = new Package[definedPackages.size()]; 855: definedPackages.values().toArray(packages); 856: } 857: 858: // If we have a parent get all packages defined by our parents. 859: Package[] parentPackages; 860: if (parent == null) 861: parentPackages = VMClassLoader.getPackages(); 862: else 863: parentPackages = parent.getPackages(); 864: 865: Package[] allPackages = new Package[parentPackages.length 866: + packages.length]; 867: System.arraycopy(parentPackages, 0, allPackages, 0, 868: parentPackages.length); 869: System.arraycopy(packages, 0, allPackages, parentPackages.length, 870: packages.length); 871: return allPackages; 872: } 873: 874: /** 875: * Called by <code>Runtime.loadLibrary()</code> to get an absolute path 876: * to a (system specific) library that was requested by a class loaded 877: * by this classloader. The default implementation returns 878: * <code>null</code>. It should be implemented by subclasses when they 879: * have a way to find the absolute path to a library. If this method 880: * returns null the library is searched for in the default locations 881: * (the directories listed in the <code>java.library.path</code> system 882: * property). 883: * 884: * @param name the (system specific) name of the requested library 885: * @return the full pathname to the requested library, or null 886: * @see Runtime#loadLibrary() 887: * @since 1.2 888: */ 889: protected String findLibrary(String name) 890: { 891: return null; 892: } 893: 894: /** 895: * Set the default assertion status for classes loaded by this classloader, 896: * used unless overridden by a package or class request. 897: * 898: * @param enabled true to set the default to enabled 899: * @see #setClassAssertionStatus(String, boolean) 900: * @see #setPackageAssertionStatus(String, boolean) 901: * @see #clearAssertionStatus() 902: * @since 1.4 903: */ 904: public void setDefaultAssertionStatus(boolean enabled) 905: { 906: defaultAssertionStatus = enabled; 907: } 908: 909: /** 910: * Set the default assertion status for packages, used unless overridden 911: * by a class request. This default also covers subpackages, unless they 912: * are also specified. The unnamed package should use null for the name. 913: * 914: * @param name the package (and subpackages) to affect 915: * @param enabled true to set the default to enabled 916: * @see #setDefaultAssertionStatus(String, boolean) 917: * @see #setClassAssertionStatus(String, boolean) 918: * @see #clearAssertionStatus() 919: * @since 1.4 920: */ 921: public synchronized void setPackageAssertionStatus(String name, 922: boolean enabled) 923: { 924: if (packageAssertionStatus == null) 925: packageAssertionStatus 926: = new HashMap(StaticData.systemPackageAssertionStatus); 927: packageAssertionStatus.put(name, Boolean.valueOf(enabled)); 928: } 929: 930: /** 931: * Set the default assertion status for a class. This only affects the 932: * status of top-level classes, any other string is harmless. 933: * 934: * @param name the class to affect 935: * @param enabled true to set the default to enabled 936: * @throws NullPointerException if name is null 937: * @see #setDefaultAssertionStatus(String, boolean) 938: * @see #setPackageAssertionStatus(String, boolean) 939: * @see #clearAssertionStatus() 940: * @since 1.4 941: */ 942: public synchronized void setClassAssertionStatus(String name, 943: boolean enabled) 944: { 945: if (classAssertionStatus == null) 946: classAssertionStatus = 947: new HashMap(StaticData.systemClassAssertionStatus); 948: // The toString() hack catches null, as required. 949: classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled)); 950: } 951: 952: /** 953: * Resets the default assertion status of this classloader, its packages 954: * and classes, all to false. This allows overriding defaults inherited 955: * from the command line. 956: * 957: * @see #setDefaultAssertionStatus(boolean) 958: * @see #setClassAssertionStatus(String, boolean) 959: * @see #setPackageAssertionStatus(String, boolean) 960: * @since 1.4 961: */ 962: public synchronized void clearAssertionStatus() 963: { 964: defaultAssertionStatus = false; 965: packageAssertionStatus = new HashMap(); 966: classAssertionStatus = new HashMap(); 967: } 968: 969: /** 970: * Return true if this loader is either the specified class loader 971: * or an ancestor thereof. 972: * @param loader the class loader to check 973: */ 974: final boolean isAncestorOf(ClassLoader loader) 975: { 976: while (loader != null) 977: { 978: if (this == loader) 979: return true; 980: loader = loader.parent; 981: } 982: return false; 983: } 984: 985: private static URL[] getExtClassLoaderUrls() 986: { 987: String classpath = SystemProperties.getProperty("java.ext.dirs", ""); 988: StringTokenizer tok = new StringTokenizer(classpath, File.pathSeparator); 989: ArrayList list = new ArrayList(); 990: while (tok.hasMoreTokens()) 991: { 992: try 993: { 994: File f = new File(tok.nextToken()); 995: File[] files = f.listFiles(); 996: if (files != null) 997: for (int i = 0; i < files.length; i++) 998: list.add(files[i].toURL()); 999: } 1000: catch(Exception x) 1001: { 1002: } 1003: } 1004: URL[] urls = new URL[list.size()]; 1005: list.toArray(urls); 1006: return urls; 1007: } 1008: 1009: private static void addFileURL(ArrayList list, String file) 1010: { 1011: try 1012: { 1013: list.add(new File(file).toURL()); 1014: } 1015: catch(java.net.MalformedURLException x) 1016: { 1017: } 1018: } 1019: 1020: private static URL[] getSystemClassLoaderUrls() 1021: { 1022: String classpath = SystemProperties.getProperty("java.class.path", "."); 1023: StringTokenizer tok = new StringTokenizer(classpath, File.pathSeparator, true); 1024: ArrayList list = new ArrayList(); 1025: while (tok.hasMoreTokens()) 1026: { 1027: String s = tok.nextToken(); 1028: if (s.equals(File.pathSeparator)) 1029: addFileURL(list, "."); 1030: else 1031: { 1032: addFileURL(list, s); 1033: if (tok.hasMoreTokens()) 1034: { 1035: // Skip the separator. 1036: tok.nextToken(); 1037: // If the classpath ended with a separator, 1038: // append the current directory. 1039: if (!tok.hasMoreTokens()) 1040: addFileURL(list, "."); 1041: } 1042: } 1043: } 1044: URL[] urls = new URL[list.size()]; 1045: list.toArray(urls); 1046: return urls; 1047: } 1048: 1049: static ClassLoader defaultGetSystemClassLoader() 1050: { 1051: return createAuxiliarySystemClassLoader( 1052: createSystemClassLoader(getSystemClassLoaderUrls(), 1053: createExtClassLoader(getExtClassLoaderUrls(), null))); 1054: } 1055: 1056: static ClassLoader createExtClassLoader(URL[] urls, ClassLoader parent) 1057: { 1058: if (urls.length > 0) 1059: return new URLClassLoader(urls, parent); 1060: else 1061: return parent; 1062: } 1063: 1064: static ClassLoader createSystemClassLoader(URL[] urls, ClassLoader parent) 1065: { 1066: return 1067: new URLClassLoader(urls, parent) 1068: { 1069: protected synchronized Class loadClass(String name, 1070: boolean resolve) 1071: throws ClassNotFoundException 1072: { 1073: SecurityManager sm = SecurityManager.current; 1074: if (sm != null) 1075: { 1076: int lastDot = name.lastIndexOf('.'); 1077: if (lastDot != -1) 1078: sm.checkPackageAccess(name.substring(0, lastDot)); 1079: } 1080: return super.loadClass(name, resolve); 1081: } 1082: }; 1083: } 1084: 1085: static ClassLoader createAuxiliarySystemClassLoader(ClassLoader parent) 1086: { 1087: String loader = SystemProperties.getProperty("java.system.class.loader", null); 1088: if (loader == null) 1089: { 1090: return parent; 1091: } 1092: try 1093: { 1094: Constructor c = Class.forName(loader, false, parent) 1095: .getConstructor(new Class[] { ClassLoader.class }); 1096: return (ClassLoader)c.newInstance(new Object[] { parent }); 1097: } 1098: catch (Exception e) 1099: { 1100: System.err.println("Requested system classloader " + loader + " failed."); 1101: throw (Error) 1102: new Error("Requested system classloader " + loader + " failed.") 1103: .initCause(e); 1104: } 1105: } 1106: 1107: /** 1108: * Before doing anything "dangerous" please call this method to make sure 1109: * this class loader instance was properly constructed (and not obtained 1110: * by exploiting the finalizer attack) 1111: * @see #initialized 1112: */ 1113: private void checkInitialized() 1114: { 1115: if (! initialized) 1116: throw new SecurityException("attempt to use uninitialized class loader"); 1117: } 1118: }
GNU Classpath (0.18) |