Milán Major

netscape-revival

1 branch
Code

sun-java/classsrc/sun/applet/AppletClassLoader.java

/*
 * @(#)AppletClassLoader.java	1.21 95/10/09  
 *
 * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL purposes and without
 * fee is hereby granted provided that this copyright notice
 * appears in all copies. Please refer to the file "copyright.html"
 * for further important copyright and licensing information.
 *
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 */

package sun.applet;

import java.util.Hashtable;
import java.io.InputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;

/**
 * This class defines an applet class loader.
 *
 * @version 	1.21, 09 Oct 1995
 * @author 	Arthur van Hoff
 */
class AppletClassLoader extends ClassLoader {
    Hashtable classes = new Hashtable();
    URL base;

    /**
     * Load applets from a base URL.
     */
    AppletClassLoader(URL base) {
	// Strip the tail end of the URL so that it ends in a /
	String file = base.getFile();
	int i = file.lastIndexOf('/');
	if ((i > 0) && (i < file.length()-1)) {
	    try {
		base = new URL(base, file.substring(0, i+1));
	    } catch (MalformedURLException e) {
	    }
	}
	this.base = base;
    }

    /**
     * Load a class from a URL.
     */
    private Class loadClass(URL url) throws IOException {
	InputStream in = null;
	try {
	    try {
		URLConnection c = url.openConnection();
		c.setAllowUserInteraction(false);
		in = c.getInputStream();

		int len = c.getContentLength();
		byte data[] = new byte[(len == -1) ? 4096 : len];
		int total = 0, n;
		
		while ((n = in.read(data, total, data.length - total)) >= 0) {
		    if ((total += n) == data.length) {
			if (len < 0) {
			    byte newdata[] = new byte[total * 2];
			    System.arraycopy(data, 0, newdata, 0, total);
			    data = newdata;
			} else {
			    break;
			}
		    }
		}
		return defineClass(data, 0, total);
	    } finally {
		if (in != null) {
		    in.close();
		}
	    }
	} catch (IOException e) {
	    e.printStackTrace();
	    throw e;
	} catch (Throwable e) {
	    e.printStackTrace();
	    throw new IOException("class not loaded: " + url);
	}
    }

    /**
     * Load a class from this class loader.
     */
    public Class loadClass(String name) throws ClassNotFoundException {
	return loadClass(name, true);
    }

    /**
     * Load and resolve a class.
     */
    protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
	Class cl = (Class)classes.get(name);
	if (cl == null) {
	    SecurityManager security = System.getSecurityManager();
	    if (security != null) {
		int i = name.lastIndexOf('.');
		if (i >= 0) {
		    security.checkPackageAccess(name.substring(0, i));
		}
	    }
	    try {
		return findSystemClass(name);
	    } catch (Throwable e) {
	    }

	    cl = findClass(name);
	}
	if (cl == null) {
	    throw new ClassNotFoundException(name);
	}
	if (resolve) {
	    resolveClass(cl);
	}
	return cl;
    }

    /**
     * This method finds a class. The returned class
     * may be unresolved. This method has to be synchronized
     * to avoid two threads loading the same class at the same time.
     * Must be called with the actual class name.
     */
    private synchronized Class findClass(String name) {
	Class cl = (Class)classes.get(name);
	if (cl != null) {
	    return cl;
	}

	System.out.println(Thread.currentThread().getName() + " find class " + name);

	SecurityManager security = System.getSecurityManager();
	if (security != null) {
	    int i = name.lastIndexOf('.');
	    if (i >= 0) {
		security.checkPackageDefinition(name.substring(0, i));
	    }
	}

	String cname = name.replace('.', '/') + ".class";

	try {
	    URL url = new URL(base, cname);
	    System.out.println("Opening stream to: " + url + " to get " + name);
	    cl = loadClass(url);
	    if (!name.equals(cl.getName())) {
		Class oldcl = cl;
		cl = null;
		throw new ClassFormatError(name + " != " + oldcl.getName());
	    }
	    classes.put(name, cl);
	} catch (FileNotFoundException e) {
	    System.err.println("File not found when looking for: " + name);
	} catch (ClassFormatError e) {
	    System.err.println("File format exception when loading: " + name);
	} catch (IOException e) {
	    System.err.println("I/O exception when loading: " + name);
	} catch (Exception e) {
	    System.err.println(e + " exception when loading: " + name);
	} catch (ThreadDeath e) {
	    System.err.println(e + " killed when loading: " + name);
	    throw e;
	} catch (Error e) {
	    System.err.println(e + " error when loading: " + name);
	}
	return cl;
    }
}