view patches/icedtea-plugin.patch @ 1049:abdb5c94757d

More refactoring. Moved classes to a shorter path, removed classes provided by the JDK tarball (they were there by mistake).
author Deepak Bhole <dbhole@redhat.com>
date Tue, 23 Sep 2008 16:52:24 -0400
parents 3e5d21f2b7a4
children
line wrap: on
line source

diff -urN openjdk.orig/jdk/make/launchers/Makefile openjdk/jdk/make/launchers/Makefile
--- openjdk.orig/jdk/make/launchers/Makefile	2008-06-29 09:40:07.000000000 -0400
+++ openjdk/jdk/make/launchers/Makefile	2008-06-29 09:40:16.000000000 -0400
@@ -92,6 +92,7 @@
   -J-Dcom.sun.CORBA.activation.Port=1049 \
   -J-Dcom.sun.CORBA.POA.ORBServerId=1, )
 $(call make-launcher, pack200, com.sun.java.util.jar.pack.Driver, , --pack)
+$(call make-launcher, pluginappletviewer, sun.applet.PluginMain, , )
 $(call make-launcher, policytool, sun.security.tools.PolicyTool, , )
 $(call make-launcher, rmic, sun.rmi.rmic.Main, , )
 $(call make-launcher, rmid, sun.rmi.server.Activation, , )
diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginMain.java openjdk/jdk/src/share/classes/sun/applet/PluginMain.java
--- openjdk.orig/jdk/src/share/classes/sun/applet/PluginMain.java	1969-12-31 19:00:00.000000000 -0500
+++ openjdk/jdk/src/share/classes/sun/applet/PluginMain.java	2008-01-14 14:18:53.000000000 -0500
@@ -0,0 +1,274 @@
+/*
+ * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.applet;
+
+import java.io.*;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import java.net.*;
+import java.nio.charset.Charset;
+import java.util.*;
+import sun.net.www.ParseUtil;
+
+class PluginParseRequest
+{
+  long handle;
+  String tag;
+  String documentbase;
+  boolean alreadySent;
+}
+
+/**
+ * The main entry point into PluginAppletViewer.
+ */
+public class PluginMain
+{
+    // A mapping of instance IDs to PluginAppletViewers.
+    private static HashMap appletWindows = new HashMap();
+    private static HashMap parseRequests = new HashMap();
+    private static String currentKey;
+    private static PluginAppletViewer currentWindow;
+    private static PluginParseRequest currentRequest;
+    private static BufferedReader pluginInputStream;
+    private static BufferedWriter pluginOutputStream;
+    // This is used in init().	Getting rid of this is desirable but depends
+    // on whether the property that uses it is necessary/standard.
+    public static final String theVersion = System.getProperty("java.version");
+
+    /**
+     * The main entry point into AppletViewer.
+     */
+    public static void main(String args[])
+	throws IOException
+    {
+	if(args.length != 2) {
+	    // Indicate to plugin that appletviewer is installed correctly.
+	    System.exit(0);
+	}
+	// INSTALL THE SECURITY MANAGER
+	init();
+	start(new FileInputStream(args[0]), new FileOutputStream(args[1]));
+	System.exit(0);
+    }
+
+    private static void init() {
+	Properties avProps = new Properties();
+
+	// ADD OTHER RANDOM PROPERTIES
+	// XXX 5/18 need to revisit why these are here, is there some
+	// standard for what is available?
+
+	// Standard browser properties
+	avProps.put("browser", "sun.applet.AppletViewer");
+	avProps.put("browser.version", "1.06");
+	avProps.put("browser.vendor", "Sun Microsystems Inc.");
+	avProps.put("http.agent", "Java(tm) 2 SDK, Standard Edition v" + theVersion);
+
+	// Define which packages can be extended by applets
+	// XXX 5/19 probably not needed, not checked in AppletSecurity
+	avProps.put("package.restrict.definition.java", "true");
+	avProps.put("package.restrict.definition.sun", "true");
+
+	// Define which properties can be read by applets.
+	// A property named by "key" can be read only when its twin
+	// property "key.applet" is true.  The following ten properties
+	// are open by default.	 Any other property can be explicitly
+	// opened up by the browser user by calling appletviewer with
+	// -J-Dkey.applet=true
+	avProps.put("java.version.applet", "true");
+	avProps.put("java.vendor.applet", "true");
+	avProps.put("java.vendor.url.applet", "true");
+	avProps.put("java.class.version.applet", "true");
+	avProps.put("os.name.applet", "true");
+	avProps.put("os.version.applet", "true");
+	avProps.put("os.arch.applet", "true");
+	avProps.put("file.separator.applet", "true");
+	avProps.put("path.separator.applet", "true");
+	avProps.put("line.separator.applet", "true");
+
+	// Read in the System properties.  If something is going to be
+	// over-written, warn about it.
+	Properties sysProps = System.getProperties();
+	for (Enumeration e = sysProps.propertyNames(); e.hasMoreElements(); ) {
+	    String key = (String) e.nextElement();
+	    String val = (String) sysProps.getProperty(key);
+	    avProps.setProperty(key, val);
+	}
+
+	// INSTALL THE PROPERTY LIST
+	System.setProperties(avProps);
+
+	// Create and install the security manager
+	System.setSecurityManager(new AppletSecurity());
+
+	// REMIND: Create and install a socket factory!
+    }
+
+    static void registerWindow(PluginAppletViewer pluginappletviewer)
+    {
+	appletWindows.put(currentKey, pluginappletviewer);
+	currentWindow = (PluginAppletViewer)appletWindows.get(currentKey);
+    }
+
+    private static void deregisterWindow(PluginAppletViewer pluginappletviewer)
+    {
+	appletWindows.remove(currentWindow);
+	currentWindow.dispose();
+	currentWindow = null;
+    }
+
+    static void start(InputStream inputstream, OutputStream outputstream)
+	throws MalformedURLException, IOException
+    {
+	// Set up input and output pipes.  Use UTF-8 encoding.
+	pluginInputStream =
+	    new BufferedReader(new InputStreamReader(inputstream,
+						     Charset.forName("UTF-8")));
+	pluginOutputStream =
+	    new BufferedWriter(new OutputStreamWriter
+			       (outputstream, Charset.forName("UTF-8")));
+
+	write("running");
+
+	// Read first message.
+	String message = read();
+
+	while(true) {
+	    if (message.startsWith("instance")) {
+		// Read applet instance identifier.
+		currentKey = message.substring("instance".length() + 1);
+		currentWindow =
+		    (PluginAppletViewer)appletWindows.get(currentKey);
+		currentRequest = null;
+		if (currentWindow == null) {
+		    if (!parseRequests.containsKey(currentKey))
+			parseRequests.put(currentKey, new PluginParseRequest());
+		    currentRequest =
+			(PluginParseRequest)parseRequests.get(currentKey);
+		}
+	    } else if (message.startsWith("tag")) {
+		if (currentRequest != null) {
+		    int index = message.indexOf(' ', "tag".length() + 1);
+		    currentRequest.documentbase =
+			message.substring("tag".length() + 1, index);
+		    currentRequest.tag = message.substring(index + 1);
+		    if (currentRequest.handle != 0
+			&& !currentRequest.alreadySent) {
+			PluginAppletViewer.parse
+			    (currentRequest.handle, 1, 1,
+			     new StringReader(currentRequest.tag),
+			     new URL(currentRequest.documentbase));
+			parseRequests.remove(currentKey);
+		    }
+		}
+	    } else if (message.startsWith("handle")) {
+		if (currentRequest != null) {
+		    currentRequest.handle = Long.parseLong
+			(message.substring("handle".length() + 1, 
+						message.indexOf("width") - 1));
+		    int width = Integer.parseInt(message.substring
+					(message.indexOf("width") + 
+					"width".length() + 1, 
+					message.indexOf("height") - 1));
+		    int height = Integer.parseInt(message.substring(
+					message.indexOf("height") + 
+					"height".length() + 1));
+		    if (currentRequest.tag != null
+		       && !currentRequest.alreadySent) {
+			PluginAppletViewer.parse
+			    (currentRequest.handle, width, height,
+			     new StringReader(currentRequest.tag),
+			     new URL(currentRequest.documentbase));
+			parseRequests.remove(currentKey);
+		    }
+		}
+	    } else if (message.startsWith("width")) {
+		int width =
+		    Integer.parseInt(message.substring("width".length() + 1));
+		int height = currentWindow.getHeight();
+		currentWindow.updateAtts(width, height);
+	 	currentWindow.setSize(width, height);
+	    } else if (message.startsWith("height")) {
+		int height =
+		    Integer.parseInt(message.substring("height".length() + 1));
+		int width = currentWindow.getWidth();
+		currentWindow.updateAtts(width, height);
+	        currentWindow.setSize(width, height);
+	    } else if (message.startsWith("destroy")
+		       && currentWindow != null) {
+		deregisterWindow(currentWindow);
+	    }
+
+	    // Read next message.
+	    message = read();
+	}
+    }
+
+    /**
+     * Write string to plugin.
+     * 
+     * @param message the message to write
+     *
+     * @exception IOException if an error occurs
+     */
+    static void write(String message)
+	throws IOException
+    {
+	pluginOutputStream.write(message, 0, message.length());
+	pluginOutputStream.newLine();
+	pluginOutputStream.flush();
+
+	System.err.println("  PIPE: appletviewer wrote: " + message);
+    }
+
+    /**
+     * Read string from plugin.
+     *
+     * @return the read string
+     *
+     * @exception IOException if an error occurs
+     */
+    static String read()
+	throws IOException
+    {
+	String message = pluginInputStream.readLine();
+	System.err.println("  PIPE: appletviewer read: " + message);
+	if (message == null || message.equals("shutdown")) {
+	    try {
+		// Close input/output channels to plugin.
+		pluginInputStream.close();
+		pluginOutputStream.close();
+	    } catch (IOException exception) {
+		// Deliberately ignore IOException caused by broken
+		// pipe since plugin may have already detached.
+	    }
+
+	    System.err.println("APPLETVIEWER: exiting appletviewer");
+	    System.exit(0);
+	}
+	return message;
+    }
+}
diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginAppletViewer.java openjdk/jdk/src/share/classes/sun/applet/PluginAppletViewer.java
--- openjdk.orig/jdk/src/share/classes/sun/applet/PluginAppletViewer.java	2008-06-24 22:55:57.286013713 -0400
+++ openjdk/jdk/src/share/classes/sun/applet/PluginAppletViewer.java	2008-06-29 10:34:07.000000000 -0400
@@ -0,0 +1,1008 @@
+/*
+ * Copyright 1995-2004 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.applet;
+
+import java.util.*;
+import java.io.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.print.*;
+import javax.print.attribute.*;
+import java.applet.*;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.net.SocketPermission;
+import sun.misc.Ref;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import sun.awt.SunToolkit;
+import sun.awt.AppContext;
+import sun.awt.X11.*;
+import java.lang.ref.WeakReference;
+import net.sourceforge.jnlp.NetxPanel;
+
+/**
+ * Lets us construct one using unix-style one shot behaviors
+ */
+
+class PluginAppletViewerFactory
+{
+    public PluginAppletViewer createAppletViewer(long handle, int x, int y,
+						 URL doc, Hashtable atts) {
+        PluginAppletViewer pluginappletviewer = new PluginAppletViewer(handle, x, y, doc, atts, System.out, this);
+        PluginMain.registerWindow(pluginappletviewer);
+        return pluginappletviewer;
+    }
+
+    public boolean isStandalone()
+    {
+        return false;
+    }
+}
+
+/*
+ */
+public class PluginAppletViewer extends XEmbeddedFrame
+    implements AppletContext, Printable {
+    /**
+     * Some constants...
+     */
+    private static String defaultSaveFile = "Applet.ser";
+
+    /**
+     * The panel in which the applet is being displayed.
+     */
+    AppletViewerPanel panel;
+
+    /**
+     * The status line.
+     */
+    Label label;
+
+    /**
+     * output status messages to this stream
+     */
+
+    PrintStream statusMsgStream;
+
+    /**
+     * For cloning
+     */
+    PluginAppletViewerFactory factory;
+
+    /**
+     * Create the applet viewer
+     */
+    public PluginAppletViewer(long handle, int x, int y, final URL doc,
+                              final Hashtable atts, PrintStream statusMsgStream,
+                              PluginAppletViewerFactory factory) {
+        super(handle, true);
+    	this.factory = factory;
+	this.statusMsgStream = statusMsgStream;
+
+	try {
+		panel = new NetxPanel(doc, atts);
+		AppletViewerPanel.debug("Using NetX panel");
+	} catch (Exception ex) {
+		AppletViewerPanel.debug("Unable to start NetX applet - defaulting to Sun applet", ex);
+		panel = new AppletViewerPanel(doc, atts);
+	}
+	add("Center", panel);
+	panel.init();
+	appletPanels.addElement(panel);
+
+	pack();
+	setVisible(true);
+
+	WindowListener windowEventListener = new WindowAdapter() {
+
+	    public void windowClosing(WindowEvent evt) {
+		appletClose();
+	    }
+
+	    public void windowIconified(WindowEvent evt) {
+		appletStop();
+	    }
+
+	    public void windowDeiconified(WindowEvent evt) {
+		appletStart();
+	    }
+	};
+
+	class AppletEventListener implements AppletListener  
+	{
+	    final Frame frame;
+
+	    public AppletEventListener(Frame frame)
+	    {
+		this.frame = frame;
+	    }
+
+	    public void appletStateChanged(AppletEvent evt) 
+	    {
+		AppletPanel src = (AppletPanel)evt.getSource();
+
+		switch (evt.getID()) {
+                    case AppletPanel.APPLET_RESIZE: {
+			if(src != null) {
+			    resize(preferredSize());
+			    validate();
+                        }
+			break;
+		    }
+		    case AppletPanel.APPLET_LOADING_COMPLETED: {
+			Applet a = src.getApplet(); // sun.applet.AppletPanel
+			
+			// Fixed #4754451: Applet can have methods running on main
+			// thread event queue. 
+			// 
+			// The cause of this bug is that the frame of the applet 
+			// is created in main thread group. Thus, when certain 
+			// AWT/Swing events are generated, the events will be
+			// dispatched through the wrong event dispatch thread.
+			//
+			// To fix this, we rearrange the AppContext with the frame,
+			// so the proper event queue will be looked up.
+			//
+			// Swing also maintains a Frame list for the AppContext,
+			// so we will have to rearrange it as well.
+			//
+			if (a != null)
+			    AppletPanel.changeFrameAppContext(frame, SunToolkit.targetToAppContext(a));
+			else
+			    AppletPanel.changeFrameAppContext(frame, AppContext.getAppContext());
+
+			break;
+		    }
+		}
+	    }
+	};
+
+	ComponentListener componentListener = new ComponentAdapter() {
+		public void componentResized(ComponentEvent event)
+  		{
+		    if (panel != null)
+		      {
+		        ComponentListener[] l = panel.getComponentListeners();
+		        for (int i = 0; i < l.length; i++)
+		          l[i].componentResized(event);
+			panel.validate();
+		      }
+		  }
+
+		public void componentMoved(ComponentEvent event)
+		  {
+		    if (panel != null)
+		      {
+		        ComponentListener[] l = panel.getComponentListeners();
+		        for (int i = 0; i < l.length; i++)
+		          l[i].componentMoved(event);
+			panel.validate();
+		      }
+		  }
+        };
+
+	HierarchyBoundsListener hierarchyBoundsListener = new HierarchyBoundsAdapter() {
+		public void ancestorMoved(HierarchyEvent e)
+		  {
+		     if (panel != null)
+                      {
+		        HierarchyBoundsListener[] l = panel.getHierarchyBoundsListeners();
+		        for (int i = 0; i < l.length; i++)
+		          l[i].ancestorMoved(e);
+			panel.validate();
+		      }
+		  }
+
+		public void ancestorResized(HierarchyEvent e)
+		  {
+		    if (panel != null)
+		      {
+		        HierarchyBoundsListener[] l = panel.getHierarchyBoundsListeners();
+		        for (int i = 0; i < l.length; i++)
+		          l[i].ancestorResized(e);
+			panel.validate();
+		      }
+		  }
+	};
+
+	addWindowListener(windowEventListener);
+        addComponentListener(componentListener);
+        addHierarchyBoundsListener(hierarchyBoundsListener);
+	panel.addAppletListener(new AppletEventListener(this));
+
+	// Start the applet
+        showStatus(amh.getMessage("status.start"));
+	initEventQueue();
+    }
+
+    /**
+     * Send the initial set of events to the appletviewer event queue.
+     * On start-up the current behaviour is to load the applet and call
+     * Applet.init() and Applet.start().
+     */
+    private void initEventQueue() {
+	// appletviewer.send.event is an undocumented and unsupported system
+	// property which is used exclusively for testing purposes.
+	String eventList = System.getProperty("appletviewer.send.event");
+
+	if (eventList == null) {
+	    // Add the standard events onto the event queue.
+	    panel.sendEvent(AppletPanel.APPLET_LOAD);
+	    panel.sendEvent(AppletPanel.APPLET_INIT);
+	    panel.sendEvent(AppletPanel.APPLET_START);
+	} else {
+	    // We're testing AppletViewer.  Force the specified set of events
+	    // onto the event queue, wait for the events to be processed, and
+	    // exit.
+
+	    // The list of events that will be executed is provided as a
+	    // ","-separated list.  No error-checking will be done on the list.
+  	    String [] events = splitSeparator(",", eventList);
+
+ 	    for (int i = 0; i < events.length; i++) {
+ 		System.out.println("Adding event to queue: " + events[i]);
+ 		if (events[i].equals("dispose"))
+ 		    panel.sendEvent(AppletPanel.APPLET_DISPOSE);
+ 		else if (events[i].equals("load"))
+ 		    panel.sendEvent(AppletPanel.APPLET_LOAD);
+ 		else if (events[i].equals("init"))
+ 		    panel.sendEvent(AppletPanel.APPLET_INIT);
+ 		else if (events[i].equals("start"))
+ 		    panel.sendEvent(AppletPanel.APPLET_START);
+ 		else if (events[i].equals("stop"))
+ 		    panel.sendEvent(AppletPanel.APPLET_STOP);
+ 		else if (events[i].equals("destroy"))
+ 		    panel.sendEvent(AppletPanel.APPLET_DESTROY);
+ 		else if (events[i].equals("quit"))
+ 		    panel.sendEvent(AppletPanel.APPLET_QUIT);
+ 		else if (events[i].equals("error"))
+ 		    panel.sendEvent(AppletPanel.APPLET_ERROR);
+ 		else
+		    // non-fatal error if we get an unrecognized event
+ 		    System.out.println("Unrecognized event name: " + events[i]);
+ 	    }
+
+  	    while (!panel.emptyEventQueue()) ;
+ 	    appletSystemExit();
+	}
+    }
+
+    /**
+     * Split a string based on the presence of a specified separator.  Returns
+     * an array of arbitrary length.  The end of each element in the array is
+     * indicated by the separator of the end of the string.  If there is a
+     * separator immediately before the end of the string, the final element
+     * will be empty.  None of the strings will contain the separator.  Useful
+     * when separating strings such as "foo/bar/bas" using separator "/".
+     *
+     * @param sep  The separator.
+     * @param s    The string to split.
+     * @return     An array of strings.  Each string in the array is determined
+     *             by the location of the provided sep in the original string,
+     *             s.  Whitespace not stripped.
+     */
+    private String [] splitSeparator(String sep, String s) {
+ 	Vector v = new Vector();
+	int tokenStart = 0;
+	int tokenEnd   = 0;
+
+	while ((tokenEnd = s.indexOf(sep, tokenStart)) != -1) {
+	    v.addElement(s.substring(tokenStart, tokenEnd));
+	    tokenStart = tokenEnd+1;
+	}
+	// Add the final element.
+	v.addElement(s.substring(tokenStart));
+
+	String [] retVal = new String[v.size()];
+	v.copyInto(retVal);
+ 	return retVal;
+    }
+
+    /*
+     * Methods for java.applet.AppletContext
+     */
+
+    private static Map audioClips = new HashMap();
+
+    /**
+     * Get an audio clip.
+     */
+    public AudioClip getAudioClip(URL url) {
+	checkConnect(url);
+	synchronized (audioClips) {
+	    AudioClip clip = (AudioClip)audioClips.get(url);
+	    if (clip == null) {
+		audioClips.put(url, clip = new AppletAudioClip(url));
+	    }
+	    return clip;
+	}
+    }
+
+    private static Map imageRefs = new HashMap();
+
+    /**
+     * Get an image.
+     */
+    public Image getImage(URL url) {
+	return getCachedImage(url);
+    }
+
+    static Image getCachedImage(URL url) {
+	// System.getSecurityManager().checkConnection(url.getHost(), url.getPort());
+	return (Image)getCachedImageRef(url).get();
+    }
+
+    /**
+     * Get an image ref.
+     */
+    static Ref getCachedImageRef(URL url) {
+	synchronized (imageRefs) {
+	    AppletImageRef ref = (AppletImageRef)imageRefs.get(url);
+	    if (ref == null) {
+		ref = new AppletImageRef(url);
+		imageRefs.put(url, ref);
+	    }
+	    return ref;
+	}
+    }
+
+    /**
+     * Flush the image cache.
+     */
+    static void flushImageCache() {
+	imageRefs.clear();
+    }
+
+    static Vector appletPanels = new Vector();
+
+    /**
+     * Get an applet by name.
+     */
+    public Applet getApplet(String name) {
+	AppletSecurity security = (AppletSecurity)System.getSecurityManager();
+	name = name.toLowerCase();
+	SocketPermission panelSp =
+	    new SocketPermission(panel.getCodeBase().getHost(), "connect");
+	for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) {
+	    AppletPanel p = (AppletPanel)e.nextElement();
+	    String param = p.getParameter("name");
+	    if (param != null) {
+		param = param.toLowerCase();
+	    }
+	    if (name.equals(param) &&
+		p.getDocumentBase().equals(panel.getDocumentBase())) {
+
+		SocketPermission sp =
+		    new SocketPermission(p.getCodeBase().getHost(), "connect");
+
+		if (panelSp.implies(sp)) {
+		    return p.applet;
+		}
+	    }
+	}
+	return null;
+    }
+
+    /**
+     * Return an enumeration of all the accessible
+     * applets on this page.
+     */
+    public Enumeration getApplets() {
+	AppletSecurity security = (AppletSecurity)System.getSecurityManager();
+	Vector v = new Vector();
+	SocketPermission panelSp =
+	    new SocketPermission(panel.getCodeBase().getHost(), "connect");
+
+	for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) {
+	    AppletPanel p = (AppletPanel)e.nextElement();
+	    if (p.getDocumentBase().equals(panel.getDocumentBase())) {
+
+		SocketPermission sp =
+		    new SocketPermission(p.getCodeBase().getHost(), "connect");
+		if (panelSp.implies(sp)) {
+		    v.addElement(p.applet);
+		}
+	    }
+	}
+	return v.elements();
+    }
+
+    /**
+     * Ignore.
+     */
+    public void showDocument(URL url) {
+	showDocument(url, "_self");
+    }
+
+    /**
+     * Ignore.
+     */
+    public void showDocument(URL url, String target) {
+	try {
+	    PluginMain.write("url " + url + " " + target);
+	} catch (IOException exception) {
+	    // Deliberately ignore IOException.  showDocument may be
+	    // called from threads other than the main thread after
+	    // PluginMain.pluginOutputStream has been closed.
+	}
+    }
+
+    /**
+     * Show status.
+     */
+    public void showStatus(String status) {
+	try {
+	    PluginMain.write("status " + status);
+	} catch (IOException exception) {
+	    // Deliberately ignore IOException.  showStatus may be
+	    // called from threads other than the main thread after
+	    // PluginMain.pluginOutputStream has been closed.
+	}
+    }
+
+    public void setStream(String key, InputStream stream)throws IOException{
+	// We do nothing.
+    }
+
+    public InputStream getStream(String key){
+	// We do nothing.
+	return null;
+    }
+
+    public Iterator getStreamKeys(){
+	// We do nothing.
+	return null;
+    }
+
+    /**
+     * System parameters.
+     */
+    static Hashtable systemParam = new Hashtable();
+
+    static {
+	systemParam.put("codebase", "codebase");
+	systemParam.put("code", "code");
+	systemParam.put("alt", "alt");
+	systemParam.put("width", "width");
+	systemParam.put("height", "height");
+	systemParam.put("align", "align");
+	systemParam.put("vspace", "vspace");
+	systemParam.put("hspace", "hspace");
+    }
+
+    /**
+     * Print the HTML tag.
+     */
+    public static void printTag(PrintStream out, Hashtable atts) {
+	out.print("<applet");
+
+	String v = (String)atts.get("codebase");
+	if (v != null) {
+	    out.print(" codebase=\"" + v + "\"");
+	}
+
+	v = (String)atts.get("code");
+	if (v == null) {
+	    v = "applet.class";
+	}
+	out.print(" code=\"" + v + "\"");
+	v = (String)atts.get("width");
+	if (v == null) {
+	    v = "150";
+	}
+	out.print(" width=" + v);
+
+	v = (String)atts.get("height");
+	if (v == null) {
+	    v = "100";
+	}
+	out.print(" height=" + v);
+
+	v = (String)atts.get("name");
+	if (v != null) {
+	    out.print(" name=\"" + v + "\"");
+	}
+	out.println(">");
+
+	// A very slow sorting algorithm
+	int len = atts.size();
+	String params[] = new String[len];
+	len = 0;
+	for (Enumeration e = atts.keys() ; e.hasMoreElements() ;) {
+	    String param = (String)e.nextElement();
+	    int i = 0;
+	    for (; i < len ; i++) {
+		if (params[i].compareTo(param) >= 0) {
+		    break;
+		}
+	    }
+	    System.arraycopy(params, i, params, i + 1, len - i);
+	    params[i] = param;
+	    len++;
+	}
+
+	for (int i = 0 ; i < len ; i++) {
+	    String param = params[i];
+	    if (systemParam.get(param) == null) {
+		out.println("<param name=" + param +
+			    " value=\"" + atts.get(param) + "\">");
+	    }
+	}
+	out.println("</applet>");
+    }
+
+    /**
+     * Make sure the attributes are up-to-date.
+     */
+    public void updateAtts(int width, int height) {
+	panel.atts.remove("width");
+	panel.atts.remove("height");
+	panel.atts.put("width", new Integer(width).toString());
+	panel.atts.put("height", new Integer(height).toString());
+    }
+
+    /**
+     * Restart the applet.
+     */
+    void appletRestart() {
+	panel.sendEvent(AppletPanel.APPLET_STOP);
+	panel.sendEvent(AppletPanel.APPLET_DESTROY);
+	panel.sendEvent(AppletPanel.APPLET_INIT);
+	panel.sendEvent(AppletPanel.APPLET_START);
+    }
+
+    /**
+     * Reload the applet.
+     */
+    void appletReload() {
+	panel.sendEvent(AppletPanel.APPLET_STOP);
+	panel.sendEvent(AppletPanel.APPLET_DESTROY);
+	panel.sendEvent(AppletPanel.APPLET_DISPOSE);
+
+	/**
+	 * Fixed #4501142: Classlaoder sharing policy doesn't 
+	 * take "archive" into account. This will be overridden
+	 * by Java Plug-in.			[stanleyh]
+	 */
+	AppletPanel.flushClassLoader(panel.getClassLoaderCacheKey());
+
+        /*
+         * Make sure we don't have two threads running through the event queue
+         * at the same time.
+         */
+        try {
+            panel.joinAppletThread();
+	    panel.release();
+        } catch (InterruptedException e) {
+            return;   // abort the reload
+        }
+
+        panel.createAppletThread();
+	panel.sendEvent(AppletPanel.APPLET_LOAD);
+	panel.sendEvent(AppletPanel.APPLET_INIT);
+	panel.sendEvent(AppletPanel.APPLET_START);
+    }
+
+    public int print(Graphics graphics, PageFormat pf, int pageIndex) {
+        return Printable.NO_SUCH_PAGE;
+    }
+
+    /**
+     * Start the applet.
+     */
+    void appletStart() {
+	panel.sendEvent(AppletPanel.APPLET_START);
+    }
+
+    /**
+     * Stop the applet.
+     */
+    void appletStop() {
+	panel.sendEvent(AppletPanel.APPLET_STOP);
+    }
+
+    /**
+     * Shutdown a viewer.
+     * Stop, Destroy, Dispose and Quit a viewer
+     */
+    private void appletShutdown(AppletPanel p) {
+	p.sendEvent(AppletPanel.APPLET_STOP);
+	p.sendEvent(AppletPanel.APPLET_DESTROY);
+	p.sendEvent(AppletPanel.APPLET_DISPOSE);
+	p.sendEvent(AppletPanel.APPLET_QUIT);
+    }
+
+    /**
+     * Close this viewer.
+     * Stop, Destroy, Dispose and Quit an AppletView, then
+     * reclaim resources and exit the program if this is
+     * the last applet.
+     */
+    void appletClose() {
+
+	// The caller thread is event dispatch thread, so
+	// spawn a new thread to avoid blocking the event queue
+	// when calling appletShutdown.
+	//
+	final AppletPanel p = panel;
+
+	new Thread(new Runnable()
+	{
+	    public void run()
+	    {
+    		appletShutdown(p);
+		appletPanels.removeElement(p);
+		dispose();
+
+		if (countApplets() == 0) {
+		    appletSystemExit();
+		}
+	    }
+	}).start();
+    }
+
+    /**
+     * Exit the program.
+     * Exit from the program (if not stand alone) - do no clean-up
+     */
+    private void appletSystemExit() {
+	if (factory.isStandalone())
+	    System.exit(0);
+    }
+
+    /**
+     * How many applets are running?
+     */
+
+    public static int countApplets() {
+	return appletPanels.size();
+    }
+
+
+    /**
+     * The current character.
+     */
+    static int c;
+
+    /**
+     * Scan spaces.
+     */
+    public static void skipSpace(Reader in) throws IOException {
+        while ((c >= 0) &&
+	       ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r'))) {
+	    c = in.read();
+	}
+    }
+
+    /**
+     * Scan identifier
+     */
+    public static String scanIdentifier(Reader in) throws IOException {
+	StringBuffer buf = new StringBuffer();
+	while (true) {
+	    if (((c >= 'a') && (c <= 'z')) ||
+		((c >= 'A') && (c <= 'Z')) ||
+		((c >= '0') && (c <= '9')) || (c == '_')) {
+		buf.append((char)c);
+		c = in.read();
+	    } else {
+		return buf.toString();
+	    }
+	}
+    }
+
+    /**
+     * Scan tag
+     */
+    public static Hashtable scanTag(Reader in) throws IOException {
+	Hashtable atts = new Hashtable();
+	skipSpace(in);
+        while (c >= 0 && c != '>') {
+	    String att = scanIdentifier(in);
+	    String val = "";
+	    skipSpace(in);
+	    if (c == '=') {
+		int quote = -1;
+		c = in.read();
+		skipSpace(in);
+		if ((c == '\'') || (c == '\"')) {
+		    quote = c;
+		    c = in.read();
+		}
+		StringBuffer buf = new StringBuffer();
+                while ((c > 0) &&
+		       (((quote < 0) && (c != ' ') && (c != '\t') &&
+                         (c != '\n') && (c != '\r') && (c != '>'))
+			|| ((quote >= 0) && (c != quote)))) {
+		    buf.append((char)c);
+		    c = in.read();
+		}
+		if (c == quote) {
+		    c = in.read();
+		}
+		skipSpace(in);
+		val = buf.toString();
+	    }
+	    //statusMsgStream.println("PUT " + att + " = '" + val + "'");
+	    if (! val.equals("")) {
+		atts.put(att.toLowerCase(java.util.Locale.ENGLISH), val);
+	    }
+            while (true) {
+                if ((c == '>') || (c < 0) ||
+                    ((c >= 'a') && (c <= 'z')) ||
+                    ((c >= 'A') && (c <= 'Z')) ||
+                    ((c >= '0') && (c <= '9')) || (c == '_'))
+                    break;
+                c = in.read();
+            }
+            //skipSpace(in);
+	}
+	return atts;
+    }
+
+    /* values used for placement of AppletViewer's frames */
+    private static int x = 0;
+    private static int y = 0;
+    private static final int XDELTA = 30;
+    private static final int YDELTA = XDELTA;
+
+    static String encoding = null;
+
+    static private Reader makeReader(InputStream is) {
+	if (encoding != null) {
+	    try {
+		return new BufferedReader(new InputStreamReader(is, encoding));
+	    } catch (IOException x) { }
+	}
+	InputStreamReader r = new InputStreamReader(is);
+	encoding = r.getEncoding();
+	return new BufferedReader(r);
+    }
+
+    /**
+     * Scan an html file for <applet> tags
+     */
+    public static void parse(long handle, Reader in, URL url, String enc)
+        throws IOException {
+        encoding = enc;
+        parse(handle, 1, 1, in, url, System.out, new PluginAppletViewerFactory());
+    }
+
+    public static void parse(long handle, int width, int height, Reader in, URL url)
+        throws IOException {
+        parse(handle, width, height,
+		in, url, System.out, new PluginAppletViewerFactory());
+    }
+
+    public static void parse(long handle, int width, int height, Reader in, 
+				URL url,
+	                        PrintStream statusMsgStream,
+        	                PluginAppletViewerFactory factory)
+        throws IOException
+    {
+        // <OBJECT> <EMBED> tag flags
+        boolean isAppletTag = false;
+        boolean isObjectTag = false;
+        boolean isEmbedTag = false;
+
+	// warning messages
+        String requiresNameWarning = amh.getMessage("parse.warning.requiresname");
+        String paramOutsideWarning = amh.getMessage("parse.warning.paramoutside");
+        String appletRequiresCodeWarning = amh.getMessage("parse.warning.applet.requirescode");
+        String appletRequiresHeightWarning = amh.getMessage("parse.warning.applet.requiresheight");
+        String appletRequiresWidthWarning = amh.getMessage("parse.warning.applet.requireswidth");
+        String objectRequiresCodeWarning = amh.getMessage("parse.warning.object.requirescode");
+        String objectRequiresHeightWarning = amh.getMessage("parse.warning.object.requiresheight");
+        String objectRequiresWidthWarning = amh.getMessage("parse.warning.object.requireswidth");
+        String embedRequiresCodeWarning = amh.getMessage("parse.warning.embed.requirescode");
+        String embedRequiresHeightWarning = amh.getMessage("parse.warning.embed.requiresheight");
+        String embedRequiresWidthWarning = amh.getMessage("parse.warning.embed.requireswidth");
+        String appNotLongerSupportedWarning = amh.getMessage("parse.warning.appnotLongersupported");
+
+	java.net.URLConnection conn = url.openConnection();
+	/* The original URL may have been redirected - this
+	 * sets it to whatever URL/codebase we ended up getting
+	 */
+	url = conn.getURL();
+
+	int ydisp = 1;
+	Hashtable atts = null;
+
+        while(true) {
+	    c = in.read();
+	    if (c == -1)
+		break;
+
+	    if (c == '<') {
+		c = in.read();
+		if (c == '/') {
+		    c = in.read();
+		    String nm = scanIdentifier(in);
+		    if (nm.equalsIgnoreCase("applet") ||
+                        nm.equalsIgnoreCase("object") ||
+                        nm.equalsIgnoreCase("embed")) {
+
+                        // We can't test for a code tag until </OBJECT>
+                        // because it is a parameter, not an attribute.
+                        if(isObjectTag) {
+                            if (atts.get("code") == null && atts.get("object") == null) {
+                                statusMsgStream.println(objectRequiresCodeWarning);
+                                atts = null;
+                            }
+                        }
+
+			if (atts != null) {
+			    atts.remove("width");
+			    atts.remove("height");
+			    atts.put("width", new Integer(width).toString());
+			    atts.put("height", new Integer(height).toString());
+
+			    // XXX 5/18 In general this code just simply
+			    // shouldn't be part of parsing.  It's presence
+			    // causes things to be a little too much of a
+			    // hack.
+                            factory.createAppletViewer(handle, x, y, url, atts);
+			    x += XDELTA;
+			    y += YDELTA;
+			    // make sure we don't go too far!
+			    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
+			    if ((x > d.width - 300) || (y > d.height - 300)) {
+				x = 0;
+				y = 2 * ydisp * YDELTA;
+				ydisp++;
+			    }
+			}
+			atts = null;
+                        isAppletTag = false;
+                        isObjectTag = false;
+                        isEmbedTag = false;
+		    }
+		}
+		else {
+		    String nm = scanIdentifier(in);
+		    if (nm.equalsIgnoreCase("param")) {
+			Hashtable t = scanTag(in);
+			String att = (String)t.get("name");
+			if (att == null) {
+			    statusMsgStream.println(requiresNameWarning);
+			} else {
+			    String val = (String)t.get("value");
+			    if (val == null) {
+				statusMsgStream.println(requiresNameWarning);
+			    } else if (atts != null) {
+				String name = att.toLowerCase();
+				atts.put(name, val);
+			    } else {
+				statusMsgStream.println(paramOutsideWarning);
+			    }
+			}
+		    }
+		    else if (nm.equalsIgnoreCase("applet")) {
+                        isAppletTag = true;
+			atts = scanTag(in);
+			if (atts.get("code") == null && atts.get("object") == null) {
+			    statusMsgStream.println(appletRequiresCodeWarning);
+			    atts = null;
+			} else if (atts.get("width") == null) {
+			    statusMsgStream.println(appletRequiresWidthWarning);
+			    atts = null;
+			} else if (atts.get("height") == null) {
+			    statusMsgStream.println(appletRequiresHeightWarning);
+			    atts = null;
+			}
+		    }
+		    else if (nm.equalsIgnoreCase("object")) {
+                        isObjectTag = true;
+			atts = scanTag(in);
+                        // The <OBJECT> attribute codebase isn't what
+                        // we want. If its defined, remove it.
+                        if(atts.get("codebase") != null) {
+                            atts.remove("codebase");
+                        }
+
+                        if (atts.get("width") == null) {
+			    statusMsgStream.println(objectRequiresWidthWarning);
+			    atts = null;
+			} else if (atts.get("height") == null) {
+			    statusMsgStream.println(objectRequiresHeightWarning);
+			    atts = null;
+			}
+		    }
+		    else if (nm.equalsIgnoreCase("embed")) {
+                        isEmbedTag = true;
+			atts = scanTag(in);
+
+			if (atts.get("code") == null && atts.get("object") == null) {
+			    statusMsgStream.println(embedRequiresCodeWarning);
+			    atts = null;
+			} else if (atts.get("width") == null) {
+			    statusMsgStream.println(embedRequiresWidthWarning);
+			    atts = null;
+			} else if (atts.get("height") == null) {
+			    statusMsgStream.println(embedRequiresHeightWarning);
+			    atts = null;
+			}
+		    }
+		    else if (nm.equalsIgnoreCase("app")) {
+			statusMsgStream.println(appNotLongerSupportedWarning);
+			Hashtable atts2 = scanTag(in);
+			nm = (String)atts2.get("class");
+			if (nm != null) {
+			    atts2.remove("class");
+			    atts2.put("code", nm + ".class");
+			}
+			nm = (String)atts2.get("src");
+			if (nm != null) {
+			    atts2.remove("src");
+			    atts2.put("codebase", nm);
+			}
+			if (atts2.get("width") == null) {
+			    atts2.put("width", "100");
+			}
+			if (atts2.get("height") == null) {
+			    atts2.put("height", "100");
+			}
+			printTag(statusMsgStream, atts2);
+			statusMsgStream.println();
+		    }
+		}
+	    }
+	}
+	in.close();
+    }
+
+    /**
+     * Old main entry point.
+     *
+     * @deprecated
+     */
+    @Deprecated
+    public static void main(String args[]) throws IOException {
+        PluginMain.main(args);
+    }
+
+    private static AppletMessageHandler amh = new AppletMessageHandler("appletviewer");
+
+    private static void checkConnect(URL url)
+    {
+	SecurityManager security = System.getSecurityManager();
+	if (security != null) {
+	    try {
+		java.security.Permission perm =
+		    url.openConnection().getPermission();
+		if (perm != null)
+		    security.checkPermission(perm);
+		else
+		    security.checkConnect(url.getHost(), url.getPort());
+	    } catch (java.io.IOException ioe) {
+		    security.checkConnect(url.getHost(), url.getPort());
+	    }
+	}
+    }
+}