/*  GetAppletCL.java by Mark D. LaDue */

/*  April 3, 1998 */

/*  Copyright (c) 1998 Mark D. LaDue
    You may study, use, modify, and distribute this example for any purpose.
    This example is provided WITHOUT WARRANTY either expressed or implied.  */

/*  This applet exhibits the unexpected ability to create and use its
    own AppletClassLoader to get classes from an arbitrary URL.  To
    demonstrate that ability, after creating a class loader it downloads
    a simple class file from the URL
    http://www.mindspring.com/~mladue/Test/Dummy.class.  It then prints
    the class's "dumb" field and executes its print() method to prove
    that it actually works.  The applet was designed for and works
    with Netscape's Communicator 4.04 running on both Solaris and
    Windows NT platforms.  In order to compile the applet, you will need
    to make sure that the Communicator's classes are in your CLASSPATH.  */

import java.awt.*;
import java.lang.reflect.*;
import java.net.*;
import netscape.applet.*;
import sun.rmi.server.*;

public class GetAppletCL extends java.applet.Applet implements Runnable {

    Thread controller = null;
    URL url;
    String url_str = new String("http://www.mindspring.com/~mladue/Test/");
    String class_str = new String("Dummy");
    Class new_class = null;
    TextArea console = null;
    Object dum = null;
    Field fie = null;
    String fie_str = null;
    Method met = null;

    public void init() {
        console = new TextArea("GetAppletCL is a harmless demo.\n\n", 20, 80);
        console.setEditable(false);
        add("Center", console);
        console.appendText("This applet will create and use its own ClassLoader\n");
        console.appendText("when run by Netscape Communicator 4.04.\n");
        console.appendText("Here's an account of the action as it happens:\n\n");
        try {
            url = new URL(url_str);
            console.appendText("Formed a new URL: " + url.toString() + ".\n");
        }
        catch (MalformedURLException murle) {console.appendText("Bad URL!\n");}
        console.appendText("Applet from: " + getCodeBase().toString()+ ".\n");
    }

    public void start() {
        if (controller == null) {
            controller = new Thread(this);
            controller.start();
        }
    }

    public void stop() {
        if (controller != null) {
            controller.stop();
            controller = null;
        }
    }

    public void run() {
        RMIClassLoader rmi_cl = RMIClassLoader.getClassLoader(url);
        console.appendText("Created an RMIClassLoader with codebase URL "
                           + rmi_cl.getCodeBase().toString() + ".\n");
        ClassLoader cl = (ClassLoader)rmi_cl;
        AppletClassLoader acl = (AppletClassLoader)cl;
        console.appendText("Cast it to an AppletClassLoader.\n");

/* You can also do it this way if you like */

//      AppletClassLoader acl = new AppletClassLoader(url, null);
//      console.appendText("Created an AppletClassLoader with codebase URL "
//                         + acl.getCodeBase().toString() + ".\n");

        try {
            new_class = acl.loadClass(class_str);
            console.appendText("Got the class " + class_str + " from "
                               + url.toString() + ".\n");
        }
        catch (ClassNotFoundException cnfe) {
            console.appendText("Couldn't find the class " + class_str
                               + " at " + url.toString() + ".\n");
        }
        try {
            dum = new_class.newInstance();
            console.appendText("Created a new instance of " + class_str + ".\n");
        }
        catch (Exception except) {
            console.appendText("Couldn't create a new instance of the class " 
                               + class_str + ".\n");
        }
        try {
            fie = new_class.getField("dumb");
            console.appendText("Got a \"dumb\" Field object for " + class_str
                                + ".\n");
        }
        catch (Exception except) {
            console.appendText("Couldn't get a \"dumb\" "
                               + "Field object for the class " 
                               + class_str + ".\n");
        }
        try {
            fie_str = (String) fie.get(dum);
            console.appendText("Got the \"dumb\" field of " + class_str + ".\n");
        }
        catch (Exception except) {
            console.appendText("Couldn't get the \"dumb\" field of the class " 
                               + class_str + ".\n");
        }
        console.appendText("The \"dumb\" field of " + class_str + " is " +
                           "\"" + fie_str + "\"\n");
        try {
            met = new_class.getMethod("print", null);
            console.appendText("Got a \"print()\" Method object for "
                               + class_str + ".\n");
        }
        catch (Exception except) {
            console.appendText("Couldn't get a \"print()\" "
                               + "Method object for the class " 
                               + class_str + ".\n");
        }
        try {
            met.invoke(dum, null);
            console.appendText("Invoked the \"print()\" "
                                + "method of " + class_str + ".\n");
            console.appendText("(Look in the Java Console for the result.)\n");
        }
        catch (Exception except) {
            console.appendText("Couldn't invoke the \"print()\" "
                               + "method of the class " 
                               + class_str + ".\n");
        }
        console.appendText("That's the end of the demo.");
    }
}
