| /* VMClassLoader.java -- Reference implementation of native interface | |
| required by ClassLoader | |
| Copyright (C) 1998, 2001, 2002, 2003, 2004, 2005 Free Software Foundation | |
| This file is part of GNU Classpath. | |
| GNU Classpath is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 2, or (at your option) | |
| any later version. | |
| GNU Classpath is distributed in the hope that it will be useful, but | |
| WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| General Public License for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with GNU Classpath; see the file COPYING. If not, write to the | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| 02110-1301 USA. | |
| Linking this library statically or dynamically with other modules is | |
| making a combined work based on this library. Thus, the terms and | |
| conditions of the GNU General Public License cover the whole | |
| combination. | |
| As a special exception, the copyright holders of this library give you | |
| permission to link this library with independent modules to produce an | |
| executable, regardless of the license terms of these independent | |
| modules, and to copy and distribute the resulting executable under | |
| terms of your choice, provided that you also meet, for each linked | |
| independent module, the terms and conditions of the license of that | |
| module. An independent module is a module which is not derived from | |
| or based on this library. If you modify this library, you may extend | |
| this exception to your version of the library, but you are not | |
| obligated to do so. If you do not wish to do so, delete this | |
| exception statement from your version. */ | |
| package java.lang; | |
| import gnu.java.util.EmptyEnumeration; | |
| import java.lang.reflect.Constructor; | |
| import java.io.File; | |
| import java.io.IOException; | |
| import java.net.URL; | |
| import java.net.URLClassLoader; | |
| import java.security.AllPermission; | |
| import java.security.Permission; | |
| import java.security.Permissions; | |
| import java.security.ProtectionDomain; | |
| import java.util.ArrayList; | |
| import java.util.Enumeration; | |
| import java.util.HashMap; | |
| import java.util.HashSet; | |
| import java.util.Map; | |
| import java.util.StringTokenizer; | |
| import gnu.gcj.runtime.BootClassLoader; | |
| /** | |
| * java.lang.VMClassLoader is a package-private helper for VMs to implement | |
| * on behalf of java.lang.ClassLoader. | |
| * | |
| * @author John Keiser | |
| * @author Mark Wielaard <mark@klomp.org> | |
| * @author Eric Blake <ebb9@email.byu.edu> | |
| */ | |
| final class VMClassLoader | |
| { | |
| // Protection Domain definitions | |
| // FIXME: should there be a special protection domain used for native code? | |
| // The permission required to check what a classes protection domain is. | |
| static final Permission protectionDomainPermission | |
| = new RuntimePermission("getProtectionDomain"); | |
| // The protection domain returned if we cannot determine it. | |
| static ProtectionDomain unknownProtectionDomain; | |
| static | |
| { | |
| Permissions permissions = new Permissions(); | |
| permissions.add(new AllPermission()); | |
| unknownProtectionDomain = new ProtectionDomain(null, permissions); | |
| } | |
| static final HashMap definedPackages = new HashMap(); | |
| // This is a helper for handling java.endorsed.dirs. It is null | |
| // until we've initialized the system, at which point it is created. | |
| static BootClassLoader bootLoader; | |
| // This keeps track of shared libraries we've already tried to load. | |
| private static HashSet tried_libraries; | |
| // Holds one of the LIB_* constants; used to determine how shared | |
| // library loads are done. | |
| private static int lib_control; | |
| private static final int LIB_FULL = 0; | |
| private static final int LIB_CACHE = 1; | |
| private static final int LIB_NEVER = 2; | |
| /** | |
| * Helper to define a class using a string of bytes. This assumes that | |
| * the security checks have already been performed, if necessary. | |
| * | |
| * <strong>For backward compatibility, this just ignores the protection | |
| * domain; that is the wrong behavior, and you should directly implement | |
| * this method natively if you can.</strong> | |
| * | |
| * @param name the name to give the class, or null if unknown | |
| * @param data the data representing the classfile, in classfile format | |
| * @param offset the offset into the data where the classfile starts | |
| * @param len the length of the classfile data in the array | |
| * @param pd the protection domain | |
| * @return the class that was defined | |
| * @throws ClassFormatError if data is not in proper classfile format | |
| */ | |
| static final native Class defineClass(ClassLoader cl, String name, | |
| byte[] data, int offset, int len, | |
| ProtectionDomain pd) | |
| throws ClassFormatError; | |
| /** | |
| * Helper to resolve all references to other classes from this class. | |
| * | |
| * @param c the class to resolve | |
| */ | |
| static final void resolveClass(Class clazz) | |
| { | |
| // There doesn't seem to be a need for this to do anything. | |
| // Testing reveals that the JDK doesn't seem to do anything here, | |
| // either. | |
| } | |
| /** | |
| * Helper to load a class from the bootstrap class loader. | |
| * | |
| * @param name the class name to load | |
| * @param resolve whether to resolve it | |
| * @return the class, loaded by the bootstrap classloader or null | |
| * if the class wasn't found. Returning null is equivalent to throwing | |
| * a ClassNotFoundException (but a possible performance optimization). | |
| */ | |
| static final native Class loadClass(String name, boolean resolve) | |
| throws ClassNotFoundException; | |
| /** | |
| * Helper to load a resource from the bootstrap class loader. | |
| * | |
| * In libgcj, this does nothing, as the default system loader knows | |
| * how to find resources that have been linked in. | |
| * | |
| * @param name the resource to find | |
| * @return the URL to the resource | |
| */ | |
| static URL getResource(String name) | |
| { | |
| if (bootLoader != null) | |
| return bootLoader.bootGetResource(name); | |
| return null; | |
| } | |
| /** | |
| * Helper to get a list of resources from the bootstrap class loader. | |
| * | |
| * In libgcj, this does nothing, as the default system loader knows | |
| * how to find resources that have been linked in. | |
| * | |
| * @param name the resource to find | |
| * @return an enumeration of resources | |
| * @throws IOException if one occurs | |
| */ | |
| static Enumeration getResources(String name) throws IOException | |
| { | |
| if (bootLoader != null) | |
| return bootLoader.bootGetResources(name); | |
| return EmptyEnumeration.getInstance(); | |
| } | |
| /** | |
| * Helper to get a package from the bootstrap class loader. The default | |
| * implementation of returning null may be adequate, or you may decide | |
| * that this needs some native help. | |
| * | |
| * @param name the name to find | |
| * @return the named package, if it exists | |
| */ | |
| static synchronized Package getPackage(String name) | |
| { | |
| return (Package) definedPackages.get(name); | |
| } | |
| /** | |
| * Helper to get all packages from the bootstrap class loader. The default | |
| * implementation of returning an empty array may be adequate, or you may | |
| * decide that this needs some native help. | |
| * | |
| * @return all named packages, if any exist | |
| */ | |
| static synchronized Package[] getPackages() | |
| { | |
| Package[] packages = new Package[definedPackages.size()]; | |
| return (Package[]) definedPackages.values().toArray(packages); | |
| } | |
| // Define a package for something loaded natively. | |
| static synchronized void definePackageForNative(String className) | |
| { | |
| int lastDot = className.lastIndexOf('.'); | |
| if (lastDot != -1) | |
| { | |
| String packageName = className.substring(0, lastDot); | |
| if (getPackage(packageName) == null) | |
| { | |
| // FIXME: this assumes we're defining the core, which | |
| // isn't necessarily so. We could detect this and set up | |
| // appropriately. We could also look at a manifest file | |
| // compiled into the .so. | |
| Package p = new Package(packageName, | |
| "Java Platform API Specification", | |
| "GNU", "1.4", "gcj", "GNU", | |
| null, // FIXME: gcj version. | |
| null); | |
| definedPackages.put(packageName, p); | |
| } | |
| } | |
| } | |
| /** | |
| * Helper for java.lang.Integer, Byte, etc to get the TYPE class | |
| * at initialization time. The type code is one of the chars that | |
| * represents the primitive type as in JNI. | |
| * | |
| * <ul> | |
| * <li>'Z' - boolean</li> | |
| * <li>'B' - byte</li> | |
| * <li>'C' - char</li> | |
| * <li>'D' - double</li> | |
| * <li>'F' - float</li> | |
| * <li>'I' - int</li> | |
| * <li>'J' - long</li> | |
| * <li>'S' - short</li> | |
| * <li>'V' - void</li> | |
| * </ul> | |
| * | |
| * @param type the primitive type | |
| * @return a "bogus" class representing the primitive type | |
| */ | |
| static final native Class getPrimitiveClass(char type); | |
| /** | |
| * The system default for assertion status. This is used for all system | |
| * classes (those with a null ClassLoader), as well as the initial value for | |
| * every ClassLoader's default assertion status. | |
| * | |
| * XXX - Not implemented yet; this requires native help. | |
| * | |
| * @return the system-wide default assertion status | |
| */ | |
| static final boolean defaultAssertionStatus() | |
| { | |
| return true; | |
| } | |
| /** | |
| * The system default for package assertion status. This is used for all | |
| * ClassLoader's packageAssertionStatus defaults. It must be a map of | |
| * package names to Boolean.TRUE or Boolean.FALSE, with the unnamed package | |
| * represented as a null key. | |
| * | |
| * XXX - Not implemented yet; this requires native help. | |
| * | |
| * @return a (read-only) map for the default packageAssertionStatus | |
| */ | |
| static final Map packageAssertionStatus() | |
| { | |
| return new HashMap(); | |
| } | |
| /** | |
| * The system default for class assertion status. This is used for all | |
| * ClassLoader's classAssertionStatus defaults. It must be a map of | |
| * class names to Boolean.TRUE or Boolean.FALSE | |
| * | |
| * XXX - Not implemented yet; this requires native help. | |
| * | |
| * @return a (read-only) map for the default classAssertionStatus | |
| */ | |
| static final Map classAssertionStatus() | |
| { | |
| return new HashMap(); | |
| } | |
| static native ClassLoader getSystemClassLoaderInternal(); | |
| static native void initBootLoader(String libdir); | |
| static void initialize(String libdir) | |
| { | |
| initBootLoader(libdir); | |
| String p | |
| = System.getProperty ("gnu.gcj.runtime.VMClassLoader.library_control", | |
| ""); | |
| if ("never".equals(p)) | |
| lib_control = LIB_NEVER; | |
| else if ("cache".equals(p)) | |
| lib_control = LIB_CACHE; | |
| else if ("full".equals(p)) | |
| lib_control = LIB_FULL; | |
| else | |
| lib_control = LIB_NEVER; | |
| tried_libraries = new HashSet(); | |
| } | |
| /** | |
| * Possibly load a .so and search it for classes. | |
| */ | |
| static native Class nativeFindClass(String name); | |
| static ClassLoader getSystemClassLoader() | |
| { | |
| // This method is called as the initialization of systemClassLoader, | |
| // so if there is a null value, this is the first call and we must check | |
| // for java.system.class.loader. | |
| String loader = System.getProperty("java.system.class.loader"); | |
| ClassLoader default_sys = getSystemClassLoaderInternal(); | |
| if (loader != null) | |
| { | |
| try | |
| { | |
| Class load_class = Class.forName(loader, true, default_sys); | |
| Constructor c | |
| = load_class.getConstructor(new Class[] { ClassLoader.class }); | |
| default_sys | |
| = (ClassLoader) c.newInstance(new Object[] { default_sys }); | |
| } | |
| catch (Exception ex) | |
| { | |
| throw new Error("Failed to load requested system classloader " | |
| + loader, ex); | |
| } | |
| } | |
| return default_sys; | |
| } | |
| } |