Java/Development Class/Applet Loader
Applet Loader Demo
<source lang="java">
import java.applet.Applet; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.Hashtable; import javax.swing.JFrame; public class MainClass {
public static void main(String args[]) { String name = "http://urlWithClassName"; try { if (!name.endsWith(".class")) { System.err.println("That doesn"t look like a byte code file!"); return; } URL u = new URL(name); URLClassLoader ucl = new URLClassLoader(u); // parse out the name of the class from the URL String s = u.getFile(); String classname = s.substring(s.lastIndexOf("/"), s.lastIndexOf(".class")); Class AppletClass = ucl.loadClass(classname, true); Applet apl = (Applet) AppletClass.newInstance(); JFrame f = new JFrame(); f.setSize(200, 200); f.add("Center", apl); apl.init(); apl.start(); f.setVisible(true); } catch (Exception e) { System.err.println(e); } }
} class URLClassLoader extends ClassLoader {
Hashtable cache = new Hashtable(); URL url; public URLClassLoader(URL u) { this.url = u; } public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { Class cls = (Class) cache.get(name); if (cls == null) { try { cls = findSystemClass(name); } catch (ClassNotFoundException e) { } } if (cls == null) { byte classData[] = loadClassData(name); cls = defineClass(classData, 0, classData.length); cache.put(name, cls); } if (resolve) { resolveClass(cls); } return cls; } private byte[] loadClassData(String name) throws ClassNotFoundException { byte[] buffer; InputStream theClassInputStream = null; int bufferLength = 128; try { URL classURL = new URL(url, name + ".class"); URLConnection uc = classURL.openConnection(); uc.setAllowUserInteraction(false); try { theClassInputStream = uc.getInputStream(); } catch (NullPointerException e) { System.err.println(e); throw new ClassNotFoundException(name + " input stream problem"); } int contentLength = uc.getContentLength(); // A lot of web servers don"t send content-lengths // for .class files if (contentLength == -1) { buffer = new byte[bufferLength * 16]; } else { buffer = new byte[contentLength]; } int bytesRead = 0; int offset = 0; while (bytesRead >= 0) { bytesRead = theClassInputStream.read(buffer, offset, bufferLength); if (bytesRead == -1) break; offset += bytesRead; if (contentLength == -1 && offset == buffer.length) { // grow the array byte temp[] = new byte[offset * 2]; System.arraycopy(buffer, 0, temp, 0, offset); buffer = temp; } else if (offset > buffer.length) { throw new ClassNotFoundException(name + " error reading data into the array"); } } if (offset < buffer.length) { // shrink the array byte temp[] = new byte[offset]; System.arraycopy(buffer, 0, temp, 0, offset); buffer = temp; } // Make sure all the bytes were received if (contentLength != -1 && offset != contentLength) { throw new ClassNotFoundException("Only " + offset + " bytes received for " + name + "\n Expected " + contentLength + " bytes"); } } catch (Exception e) { throw new ClassNotFoundException(name + " " + e); } finally { try { if (theClassInputStream != null) theClassInputStream.close(); } catch (IOException e) { } } return buffer; }
}
</source>
Dummy Applet Context
<source lang="java">
/**
* Copyright(c) 1996 DTAI, Incorporated (http://www.dtai.ru) * * All rights reserved * * Permission to use, copy, modify and distribute this material for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of DTAI, Incorporated not be used in * advertising or publicity pertaining to this material without the * specific, prior written permission of an authorized representative of * DTAI, Incorporated. * * DTAI, INCORPORATED MAKES NO REPRESENTATIONS AND EXTENDS NO WARRANTIES, * EXPRESS OR IMPLIED, WITH RESPECT TO THE SOFTWARE, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR ANY PARTICULAR PURPOSE, AND THE WARRANTY AGAINST * INFRINGEMENT OF PATENTS OR OTHER INTELLECTUAL PROPERTY RIGHTS. THE * SOFTWARE IS PROVIDED "AS IS", AND IN NO EVENT SHALL DTAI, INCORPORATED OR * ANY OF ITS AFFILIATES BE LIABLE FOR ANY DAMAGES, INCLUDING ANY * LOST PROFITS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES RELATING * TO THE SOFTWARE. */
import java.awt.*; import java.applet.*; import java.net.*; import java.util.*; import java.io.*; /**
* DummyAppletContext - implements AppletContext and AppletStub to allow any * applet to easily run as an application. The only thing it can"t do is * access URL"s. Applet parameters are entered on the command line with * name as one word and value as the next. * * @version 1.1 * @author DTAI, Incorporated * * $Id: DummyAppletContext.java,v 1.5 1996/10/08 21:15:09 kadel Exp $ * * $Source: /cvs/java/classes/COM/dtai/gui/DummyAppletContext.java,v $ */
public class DummyAppletContext
extends Frame implements AppletStub, AppletContext, URLStreamHandlerFactory { private TextField status; private Hashtable params = new Hashtable(); private Vector applets = new Vector(); private int initial_width; private int initial_height; /** * Entry point into the standalone program. * * @param args the command line arguments */ public static void main ( String args[] ) { new DummyAppletContext( args ); } /** * Constructor for the main class, given an existing applet object. * * @param applet the applet embedded in this AppletContext * @param args the command line arguments. Contains possibly * height and width, and any applet parameters */ public DummyAppletContext( Applet applet, String args[] ) { this( applet, 640, 480, args ); } /** * Constructor for the main class, given an existing applet object and a default * frame (window) width and height. * * @param applet the applet embedded in this AppletContext * @param default_width the default width of the window * @param default_height the default width of the window * @param args the command line arguments. Contains possibly * height and width, and any applet parameters */ public DummyAppletContext( Applet applet, int default_width, int default_height, String args[] ) { super ( applet.getClass().getName() ); init( applet, default_width, default_height, args, 0 ); } /** * Constructor for the main class, from the command line arguments. * * @param args the command line arguments. Contains the name of the applet * class, possibly height and width, and any applet parameters. */ public DummyAppletContext( String args[] ) { super ( args[0] ); try { Applet applet = (Applet)Class.forName( args[0] ).newInstance(); init( applet, 640, 480, args, 1 ); } catch ( Exception e ) { e.printStackTrace(); System.exit( 1 ); } } /* * PRIVATE initialization function. * * @param applet the applet embedded in this AppletContext * @param default_width the default width of the window * @param default_height the default width of the window * @param args the command line arguments. Contains possibly * height and width, and any applet parameters * @param startidx index in the args array at which to start parsing */ private void init( Applet applet, int default_width, int default_height, String args[], int startidx ) { URL.setURLStreamHandlerFactory( this ); applets.addElement( applet ); applet.setStub(this); initial_width = default_width; initial_height = default_height; parseArgs( args, startidx ); status = new TextField(); status.setEditable( false ); add( "Center", applet ); add( "South", status ); appletResize( initial_width, initial_height ); show(); applet.init(); applet.start(); } /** * Parse the command line arguments. Get the initial width and height of * the window if specified (-width [value] -height [value]), and the * applet parameters (name value pairs). * * @param args the command line arguments. Contains possibly * height and width, and any applet parameters * @param startidx index in the args array at which to start parsing */ public void parseArgs( String args[], int startidx ) { for ( int idx = startidx; idx < ( args.length - startidx ); idx+=2 ) { try { if ( args[idx].equals( "-width" ) ) { initial_width = Integer.parseInt( args[idx+1] ); } else if ( args[idx].equals( "-height" ) ) { initial_height = Integer.parseInt( args[idx+1] ); } else { params.put( args[idx], args[idx+1] ); } } catch ( NumberFormatException nfe ) { System.err.println("Warning: command line argument "+args[idx]+ " is not a valid number." ); } } } /** * Event handler to catch the Frame (window) close action, * and exit the program. * * @param evt The event that occurred * @return false if the event was not handled by this object. */ public boolean handleEvent( Event evt ) { if ( evt.id == Event.WINDOW_DESTROY ) { System.exit(0); } return super.handleEvent(evt); }
/************ AppletStub methods *************/
/** * Returns true if the applet is active. * * @return always true */ public boolean isActive() { return true; } /** * Gets the document URL. * * @return a "file:" URL for the current directory */ public URL getDocumentBase() { URL url = null; try { File dummy = new File( "dummy.html" ); String path = dummy.getAbsolutePath(); if ( ! File.separator.equals( "/" ) ) { StringBuffer buffer = new StringBuffer(); if ( path.charAt(0) != File.separator.charAt(0) ) { buffer.append( "/" ); } StringTokenizer st = new StringTokenizer( path, File.separator ); while ( st.hasMoreTokens() ) { buffer.append( st.nextToken() + "/" ); } if ( File.separator.equals( "\\" ) && ( buffer.charAt(2) == ":" ) ) { buffer.setCharAt( 2, "|" ); } else { } path = buffer.toString(); path = path.substring( 0, path.length()-1 ); } url = new URL( "file", "", -1, path ); } catch ( MalformedURLException mue ) { mue.printStackTrace(); } return url; } /** * Gets the codebase URL. * * @return in this case, the same value as getDocumentBase() */ public final URL getCodeBase() { return getDocumentBase(); } /** * Gets a parameter of the applet. * * @param name the name of the parameter * @return the value, or null if not defined */ public final String getParameter( String name ) { return (String)params.get( name ); } /** * Gets a handler to the applet"s context. * * @return this object */ public final AppletContext getAppletContext() { return this; } /** * Called when the applet wants to be resized. This causes the * Frame (window) to be resized to accomodate the new Applet size. * * @param width the new width of the applet * @param height the new height of the applet */ public void appletResize( int width, int height ) { Insets insets = insets(); resize( ( width + insets.left + insets.right ), ( height + status.preferredSize().height + insets.top + insets.bottom ) ); }
/************ AppletContext methods *************/
/** * Gets an audio clip. (There doesn"t seem to be a "Toolkit" for * audio clips in my JDK, so this always returns null. You could * implement this differently, returning a dummy AudioClip object * for which the class could be defined at the bottom of this file.) * * @param url URL of the AudioClip to load * @return the AudioClip object if it exists (in our case, * this is always null */ public final AudioClip getAudioClip( URL url ) { return null; } /** * Gets an image. This usually involves downloading it * over the net. However, the environment may decide to * cache images. This method takes an array of URLs, * each of which will be tried until the image is found. * * @param url URL of the Image to load * @return the Image object */ public final Image getImage( URL url ) { return Toolkit.getDefaultToolkit().getImage( filenameFromURL( url ) ); } /* * PRIVATE utility function. Ignores the protocol, and returns a * filename for a file on the local filesystem (which may or may * not exist, of course). * * @param url URL to be converted to a filename on the local * filesystem. * @return the filename */ private String filenameFromURL( URL url ) { String filename = url.getFile(); if ( filename.charAt(1) == "|" ) { StringBuffer buf = new StringBuffer( filename ); buf.setCharAt( 1, ":" ); filename = buf.toString(); } else if ( filename.charAt(2) == "|" ) { StringBuffer buf = new StringBuffer( filename ); buf.setCharAt( 2, ":" ); filename = buf.toString(); } return filename; } /** * Gets an applet by name. * * @param name the name of the applet * @return null if the applet does not exist, and it never * does since we never name the applet. */ public final Applet getApplet( String name ) { return null; } /** * Enumerates the applets in this context. Only applets * that are accessible will be returned. This list always * includes the applet itself. * * @return the Enumeration -- contains ONLY the applet created with * this DummyAppletContext */ public final Enumeration getApplets() { return applets.elements(); } /** * Shows a new document. This may be ignored by * the applet context (and in our case, it is, but we"ll show the * user, in the status area, that the document was requested and * WOULD be loaded if in a browser). * * @param url URL to load */ public void showDocument( URL url ) { status.setText( "AppletContext request to show URL " + url.toString() ); } /** * Show a new document in a target window or frame. This may be ignored by * the applet context. (Again, it is ignored, but we"ll show the * request information to the user in the status area.) * * This method accepts the target strings: * _self show in current frame * _parent show in parent frame * _top show in top-most frame * _blank show in new unnamed top-level window * <other> show in new top-level window named <other> * * @param url URL to load * @param target the target string */ public void showDocument( URL url, String target ) { status.setText( "AppletContext request to show URL " + url.toString() + " in target: " + target ); } /** * Show a status string in the status area (the Text object at the bottom * of the window. * * @param text the text to display */ public void showStatus( String text ) { status.setText( text ); }
/************ URLStreamHandlerFactory methods *************/
/** * Creates a new URLStreamHandler instance with the specified protocol. * * @param protocol the protocol to use (ftp, http, nntp, etc.). * THIS PROTOCOL IS IGNORED BY THIS APPLET CONTEXT */ public URLStreamHandler createURLStreamHandler( String protocol ) { return new DummyURLStreamHandler(); }
} /*
* A URL stream handler for all protocols, used to return our * dummy implementation of URLConnection to open up a local * file when called upon. */
class DummyURLStreamHandler extends URLStreamHandler {
protected final URLConnection openConnection( URL u ) throws IOException { return new DummyURLConnection( u ); }
} /*
* Our dummy implementation of URLConnection used to open up a local * file when called upon with a given URL of ANY protocol type. This * allows the applet to easily use the "getInputStream()" function. */
class DummyURLConnection extends URLConnection {
boolean connected = false; InputStream instream; /* * Constructor for the DummyURLConnection */ protected DummyURLConnection( URL url ) { super( url ); } /* * open the local file */ public void connect() throws IOException { if ( ! connected ) { String filename = url.getFile(); if ( filename.charAt(1) == "|" ) { StringBuffer buf = new StringBuffer( filename ); buf.setCharAt( 1, ":" ); filename = buf.toString(); } else if ( filename.charAt(2) == "|" ) { StringBuffer buf = new StringBuffer( filename ); buf.setCharAt( 2, ":" ); filename = buf.toString(); } instream = new FileInputStream( filename ); } } /* * return the open stream to the local file (open if necessary). */ public InputStream getInputStream() throws IOException { if ( ! connected ) { connect(); } if ( instream == null ) { throw new IOException(); } return instream; }
}
</source>