package java.lang; import com.google.gwt.core.client.JavaScriptObject; import java.io.InputStream; import java.net.URL; import java.util.Objects; /** * This stripped down ClassLoader class is simply here to give us cross-platform support for code * that might need a valid classloader. * * <p> * xapi-gwt-reflect does call into the one and only system classloader, to define mappings of * java-names to runtime classes, in order to enable Class.forName() and ClassLoader.loadClass(); * </p> * * @author "James X. Nelson (james@wetheinter.net)" * */ public class ClassLoader { // The parent class loader for delegation private final ClassLoader parent; // A JSO with all known classes; // We access this value via reflection in ConstPool#extractClasses private final JavaScriptObject classes = JavaScriptObject.createObject(); // NOPMD /** * Creates a new class loader using the specified parent class loader for delegation. * * @param parent The parent class loader */ protected ClassLoader(final ClassLoader parent) { this.parent = parent; } /** * Creates a new class loader using the <tt>ClassLoader</tt> returned by the method * {@link #getSystemClassLoader() <tt>getSystemClassLoader()</tt>} as the parent class loader. */ protected ClassLoader() { this(getSystemClassLoader()); } // -- Class -- /** * Loads the class with the specified <a href="#name">binary name</a>. This method searches for * classes in the same manner as the {@link #loadClass(String, boolean)} method. It is invoked by * the Java virtual machine to resolve class references. Invoking this method is equivalent to * invoking {@link #loadClass(String, boolean) <tt>loadClass(name, * false)</tt>}. * </p> * * @param name The <a href="#name">binary name</a> of the class * * @return The resulting <tt>Class</tt> object * * @throws ClassNotFoundException If the class was not found */ public Class<?> loadClass(final String name) throws ClassNotFoundException { return this.loadClass(name, false); } /** * Loads the class with the specified <a href="#name">binary name</a>. The default implementation * of this method searches for classes in the following order: * * <ol> * <li> * <p> * Invoke {@link #findLoadedClass(String)} to check if the class has already been loaded. * </p> * </li> * * <li> * <p> * Invoke the {@link #loadClass(String) <tt>loadClass</tt>} method on the parent class loader. If * the parent is <tt>null</tt> the class loader built-in to the virtual machine is used, instead. * </p> * </li> * * <li> * <p> * Invoke the {@link #findClass(String)} method to find the class. * </p> * </li> * * </ol> * * <p> * If the class was found using the above steps, and the <tt>resolve</tt> flag is true, this * method will then invoke the {@link #resolveClass(Class)} method on the resulting <tt>Class</tt> * object. * </p> * * <p> * Subclasses of <tt>ClassLoader</tt> are encouraged to override {@link #findClass(String)}, * rather than this method. * </p> * * @param name The <a href="#name">binary name</a> of the class * * @param resolve If <tt>true</tt> then resolve the class * * @return The resulting <tt>Class</tt> object * * @throws ClassNotFoundException If the class could not be found */ protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException { // First, check if the class has already been loaded Class clazz = null; // TODO: reimplement this goodness findLoadedClass(name); if (clazz == null) { try { if (this.parent == null) { // clazz = findBootstrapClassOrNull(name); } else { clazz = this.parent.loadClass(name, false); } } catch (final ClassNotFoundException e) { // NOPMD // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (clazz == null) { // If still not found, then invoke findClass in order // to find the class. clazz = this.findClass(name); } } // if (resolve) { // resolveClass(c); // } return clazz; } // This method is invoked by the virtual machine to load a class. private Class loadClassInternal(final String name) throws ClassNotFoundException { return this.loadClass(name); } /** * Finds the class with the specified <a href="#name">binary name</a>. This method should be * overridden by class loader implementations that follow the delegation model for loading * classes, and will be invoked by the {@link #loadClass <tt>loadClass</tt>} method after checking * the parent class loader for the requested class. The default implementation throws a * <tt>ClassNotFoundException</tt>. * </p> * * @param name The <a href="#name">binary name</a> of the class * * @return The resulting <tt>Class</tt> object * * @throws ClassNotFoundException If the class could not be found * * @since 1.2 */ protected Class<?> findClass(final String name) throws ClassNotFoundException { throw new ClassNotFoundException(name); } /** * Our ClassLoader doesn't actually load anything; it just holds a jso mapping from class name to * class object. */ public final native Class<?> defineClass(String name, Class<?> cls) /*-{ this.@java.lang.ClassLoader::classes[name] = cls; return cls; }-*/; /** * Finds a class with the specified <a href="#name">binary name</a>, loading it if necessary. * * <p> * This method loads the class through the system class loader (see * {@link #getSystemClassLoader()}). The <tt>Class</tt> object returned might have more than one * <tt>ClassLoader</tt> associated with it. Subclasses of <tt>ClassLoader</tt> need not usually * invoke this method, because most class loaders need to override just * {@link #findClass(String)}. * </p> * * @param name The <a href="#name">binary name</a> of the class * * @return The <tt>Class</tt> object for the specified <tt>name</tt> * * @throws ClassNotFoundException If the class could not be found * * @see #ClassLoader(ClassLoader) * @see #getParent() */ protected final Class<?> findSystemClass(final String name) throws ClassNotFoundException { return getSystemClassLoader().loadClass(name); } /** * No-op for compatibility. */ protected final void setSigners(final Class<?> pclass, final Object[] signers) { // do nothing } // -- Resource -- public URL getResource(final String name) { // TODO return a magic url backed by an IO request return null; } /** * Unsupported. */ public InputStream getResourceAsStream(final String name) { throw new UnsupportedOperationException(); // URL url = getResource(name); // try { // return url != null ? url.openStream() : null; // } catch (IOException e) { // return null; // } } /** * Unsupported. */ public static InputStream getSystemResourceAsStream(final String name) { throw new UnsupportedOperationException(); // URL url = getSystemResource(name); // try { // return url != null ? url.openStream() : null; // } catch (IOException e) { // return null; // } } /** * Returns the parent class loader for delegation. Some implementations may use <tt>null</tt> to * represent the bootstrap class loader. This method will return <tt>null</tt> in such * implementations if this class loader's parent is the bootstrap class loader. * */ public final ClassLoader getParent() { return this.parent; } private static ClassLoader cl; /** * get system class loader. * * @return ClassLoader */ public static ClassLoader getSystemClassLoader() { if (cl == null) { // NOPMD cl = new ClassLoader(null); } return cl; } // Returns true if the specified class loader can be found in this class // loader's delegation chain. @SuppressWarnings("checkstyle:rightCurly") boolean isAncestor(final ClassLoader cl) { ClassLoader acl = this; do { acl = acl.parent; if (Objects.equals(cl, acl)) { return true; } } while (acl != null); return false; } // Returns the invoker's class loader, or null if none. // NOTE: This must always be invoked when there is exactly one intervening // frame from the core libraries on the stack between this method's // invocation and the desired invoker. static ClassLoader getCallerClassLoader() { return getSystemClassLoader(); } // Invoked in the java.lang.Runtime class to implement load and loadLibrary. static void loadLibrary(final Class fromClass, final String name, final boolean isAbsolute) {} }