Mercurial > hg > release > icedtea7-2.0
changeset 2160:3f733a43a8b2
Re-designed frame embedding code so that the applet is dynamically
packed into given handle. This increases stability and breaks
reliance on the assumption that the browser will always provide a
handle in a certain sequence.
2010-02-02 Deepak Bhole <dbhole@redhat.com>
* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java: Re-designed frame
embedding code so that the applet is dynamically packed into given handle.
author | Andrew John Hughes <ahughes@redhat.com> |
---|---|
date | Thu, 20 May 2010 14:10:23 +0100 |
parents | 216f095954ab |
children | d145cab2903c |
files | ChangeLog plugin/icedteanp/java/sun/applet/PluginAppletViewer.java |
diffstat | 2 files changed, 411 insertions(+), 372 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Mon Feb 01 12:28:24 2010 +0100 +++ b/ChangeLog Thu May 20 14:10:23 2010 +0100 @@ -1,3 +1,8 @@ +2010-02-02 Deepak Bhole <dbhole@redhat.com> + + * plugin/icedteanp/java/sun/applet/PluginAppletViewer.java: Re-designed frame + embedding code so that the applet is dynamically packed into given handle. + 2010-02-01 Xerxes RĂ„nby <xerxes@zafena.se> * ports/hotspot/src/share/vm/shark/sharkCompiler.cpp
--- a/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java Mon Feb 01 12:28:24 2010 +0100 +++ b/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java Thu May 20 14:10:23 2010 +0100 @@ -91,6 +91,7 @@ import java.net.URI; import java.net.URL; import java.security.AccessController; +import java.security.AllPermission; import java.security.PrivilegedAction; import java.util.Enumeration; import java.util.HashMap; @@ -114,19 +115,200 @@ * Lets us construct one using unix-style one shot behaviors */ - class PluginAppletViewerFactory + class PluginAppletPanelFactory { - public PluginAppletViewer createAppletViewer(int identifier, - long handle, int x, int y, - URL doc, Hashtable atts) { - PluginAppletViewer pluginappletviewer = new PluginAppletViewer(identifier, handle, x, y, doc, atts, System.out, this); - return pluginappletviewer; + + public AppletPanel createPanel(PluginStreamHandler streamhandler, + int identifier, + long handle, int x, int y, + final URL doc, final Hashtable atts) { + + AppletViewerPanel panel = (AppletViewerPanel) AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + try { + AppletPanel panel = new NetxPanel(doc, atts, false); + AppletViewerPanel.debug("Using NetX panel"); + PluginDebug.debug(atts.toString()); + return panel; + } catch (Exception ex) { + AppletViewerPanel.debug("Unable to start NetX applet - defaulting to Sun applet", ex); + return new AppletViewerPanel(doc, atts); + } + } + }); + + double heightFactor = 1.0; + double widthFactor = 1.0; + + if (atts.get("heightPercentage") != null) { + heightFactor = (Integer) atts.get("heightPercentage")/100.0; + } + + if (atts.get("widthPercentage") != null) { + widthFactor = (Integer) atts.get("widthPercentage")/100.0; + } + + + // put inside initial 0 handle frame + PluginAppletViewer.reFrame(null, identifier, System.out, + heightFactor, widthFactor, 0, panel); + + panel.init(); + + // Start the applet + initEventQueue(panel); + + // Applet initialized. Find out it's classloader and add it to the list + String portComponent = doc.getPort() != -1 ? ":" + doc.getPort() : ""; + String codeBase = doc.getProtocol() + "://" + doc.getHost() + portComponent; + + if (atts.get("codebase") != null) { + try { + URL appletSrcURL = new URL(codeBase + (String) atts.get("codebase")); + codeBase = appletSrcURL.getProtocol() + "://" + appletSrcURL.getHost(); + } catch (MalformedURLException mfue) { + // do nothing + } + } + + + // Wait for the panel to initialize + // (happens in a separate thread) + Applet a; + + // Wait for panel to come alive + int maxWait = 5000; // wait 5 seconds max for panel to come alive + int wait = 0; + while ((panel == null) || (!((NetxPanel) panel).isAlive() && wait < maxWait)) { + try { + Thread.sleep(50); + wait += 50; + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + + // Wait for the panel to initialize + // (happens in a separate thread) + while (panel.getApplet() == null && + ((NetxPanel) panel).isAlive()) { + try { + Thread.sleep(50); + PluginDebug.debug("Waiting for applet to initialize..."); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + + a = panel.getApplet(); + + // Still null? + if (panel.getApplet() == null) { + streamhandler.write("instance " + identifier + " reference " + -1 + " fatalError " + "Initialization failed"); + return null; + } + + PluginDebug.debug("Applet " + a.getClass() + " initialized"); + streamhandler.write("instance " + identifier + " initialized"); + + AppletSecurityContextManager.getSecurityContext(0).associateSrc(((NetxPanel) panel).getAppletClassLoader(), doc); + AppletSecurityContextManager.getSecurityContext(0).associateInstance(identifier, ((NetxPanel) panel).getAppletClassLoader()); + + return panel; } public boolean isStandalone() { return false; } + + /** + * 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(AppletPanel panel) { + // appletviewer.send.event is an undocumented and unsupported system + // property which is used exclusively for testing purposes. + PrivilegedAction pa = new PrivilegedAction() { + public Object run() { + return System.getProperty("appletviewer.send.event"); + } + }; + String eventList = (String) AccessController.doPrivileged(pa); + + 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++) { + PluginDebug.debug("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 + PluginDebug.debug("Unrecognized event name: " + events[i]); + } + + while (!panel.emptyEventQueue()) ; + } + } + + + /** + * 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; + } } class PluginParseRequest @@ -146,7 +328,7 @@ */ private static String defaultSaveFile = "Applet.ser"; - private static enum PAV_INIT_STATUS {PRE_INIT, ACTIVE, INACTIVE}; + private static enum PAV_INIT_STATUS {PRE_INIT, IN_INIT, INIT_COMPLETE, INACTIVE}; /** * The panel in which the applet is being displayed. @@ -164,11 +346,6 @@ PrintStream statusMsgStream; - /** - * For cloning - */ - PluginAppletViewerFactory factory; - int identifier; private static HashMap<Integer, PluginParseRequest> requests = @@ -188,203 +365,152 @@ private double proposedHeightFactor; private double proposedWidthFactor; + private long handle = 0; + private WindowListener windowEventListener = null; + private AppletEventListener appletEventListener = null; + /** * Null constructor to allow instantiation via newInstance() */ public PluginAppletViewer() { } - /** - * Create the applet viewer - */ - public PluginAppletViewer(final int identifier, 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; - this.identifier = identifier; - // FIXME: when/where do we remove this? - PluginDebug.debug ("PARSING: PUTTING " + identifier + " " + this); - applets.put(identifier, this); + public static void reFrame(PluginAppletViewer oldFrame, + int identifier, PrintStream statusMsgStream, + double heightFactor, double widthFactor, long handle, + AppletViewerPanel panel) { + + PluginDebug.debug("Reframing " + panel); + + // SecurityManager MUST be set, and only privileged code may call reFrame() + System.getSecurityManager().checkPermission(new AllPermission()); + // Same handle => nothing to do + if (oldFrame != null && handle == oldFrame.handle) + return; - // we intercept height and width specifications here because - proposedHeightFactor = 1.0; - proposedWidthFactor = 1.0; + PluginAppletViewer newFrame = new PluginAppletViewer(handle, identifier, statusMsgStream, heightFactor, widthFactor); + newFrame.panel = panel; - if (atts.get("heightPercentage") != null) { - proposedHeightFactor = (Integer) atts.get("heightPercentage")/100.0; - } - - if (atts.get("widthPercentage") != null) { - proposedWidthFactor = (Integer) atts.get("widthPercentage")/100.0; + if (oldFrame != null) { + applets.remove(oldFrame.identifier); + oldFrame.removeWindowListener(oldFrame.windowEventListener); + panel.removeAppletListener(oldFrame.appletEventListener); + oldFrame.remove(panel); + oldFrame.dispose(); } - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - try { - panel = new NetxPanel(doc, atts, false); - AppletViewerPanel.debug("Using NetX panel"); - PluginDebug.debug(atts.toString()); - } catch (Exception ex) { - AppletViewerPanel.debug("Unable to start NetX applet - defaulting to Sun applet", ex); - panel = new AppletViewerPanel(doc, atts); - } - return null; - } - }); + newFrame.add("Center", panel); + newFrame.pack(); - add("Center", panel); - panel.init(); - appletPanels.addElement(panel); - - pack(); + newFrame.appletEventListener = new AppletEventListener(newFrame, newFrame); + panel.addAppletListener(newFrame.appletEventListener); - // 0 handle implies 0x0 plugin, don't show it else it creates an entry in the window list - if (handle != 0) - setVisible(true); - - WindowListener windowEventListener = new WindowAdapter() { - - public void windowClosing(WindowEvent evt) { - appletClose(); - } + applets.put(identifier, newFrame); - public void windowIconified(WindowEvent evt) { - appletStop(); - } - - public void windowDeiconified(WindowEvent evt) { - appletStart(); - } - }; - - class AppletEventListener implements AppletListener - { - final Frame frame; + // dispose oldframe if necessary + if (oldFrame != null) { + oldFrame.dispose(); + } - public AppletEventListener(Frame frame) - { - this.frame = frame; - } - - public void appletStateChanged(AppletEvent evt) - { - AppletPanel src = (AppletPanel)evt.getSource(); + PluginDebug.debug(panel + " reframed"); + } - 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 + /** + * Create new plugin appletviewer frame + */ + private PluginAppletViewer(long handle, final int identifier, + PrintStream statusMsgStream, double heightFactor, + double widthFactor) { - // 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()); + super(handle, true); + this.statusMsgStream = statusMsgStream; + this.identifier = identifier; + this.proposedHeightFactor = heightFactor; + this.proposedWidthFactor = widthFactor; - break; - } - } - } - }; + if (!appletPanels.contains(panel)) + appletPanels.addElement(panel); - addWindowListener(windowEventListener); - panel.addAppletListener(new AppletEventListener(this)); - - // Start the applet - showStatus(amh.getMessage("status.start")); - initEventQueue(); - - // Wait for the panel to initialize - // (happens in a separate thread) - Applet a; + windowEventListener = new WindowAdapter() { - // Wait for panel to come alive - int maxWait = 5000; // wait 5 seconds max for panel to come alive - int wait = 0; - while ((panel == null) || (!((NetxPanel) panel).isAlive() && wait < maxWait)) { - try { - Thread.sleep(50); - wait += 50; - } catch (InterruptedException ie) { - ie.printStackTrace(); - } - } - - // Wait for the panel to initialize - // (happens in a separate thread) - while (panel.getApplet() == null && - ((NetxPanel) panel).isAlive()) { - try { - Thread.sleep(50); - PluginDebug.debug("Waiting for applet to initialize..."); - } catch (InterruptedException ie) { - ie.printStackTrace(); - } - } - - a = panel.getApplet(); + public void windowClosing(WindowEvent evt) { + appletClose(); + } - // Still null? - if (panel.getApplet() == null) { - this.streamhandler.write("instance " + identifier + " reference " + -1 + " fatalError " + "Initialization failed"); - return; - } - - PluginDebug.debug("Applet " + a.getClass() + " initialized"); - - // Applet initialized. Find out it's classloader and add it to the list - String portComponent = doc.getPort() != -1 ? ":" + doc.getPort() : ""; - String codeBase = doc.getProtocol() + "://" + doc.getHost() + portComponent; + public void windowIconified(WindowEvent evt) { + appletStop(); + } - if (atts.get("codebase") != null) { - try { - URL appletSrcURL = new URL(codeBase + (String) atts.get("codebase")); - codeBase = appletSrcURL.getProtocol() + "://" + appletSrcURL.getHost(); - } catch (MalformedURLException mfue) { - // do nothing - } - } + public void windowDeiconified(WindowEvent evt) { + appletStart(); + } + }; - AppletSecurityContextManager.getSecurityContext(0).associateSrc(((NetxPanel) panel).getAppletClassLoader(), doc); - AppletSecurityContextManager.getSecurityContext(0).associateInstance(identifier, ((NetxPanel) panel).getAppletClassLoader()); - - try { - write("initialized"); - } catch (IOException ioe) { - ioe.printStackTrace(); - } + addWindowListener(windowEventListener); } - public static void setStreamhandler(PluginStreamHandler sh) { - streamhandler = sh; - } + private static class AppletEventListener implements AppletListener + { + final Frame frame; + final PluginAppletViewer appletViewer; + + public AppletEventListener(Frame frame, PluginAppletViewer appletViewer) + { + this.frame = frame; + this.appletViewer = appletViewer; + } + + public void appletStateChanged(AppletEvent evt) + { + AppletPanel src = (AppletPanel)evt.getSource(); + + switch (evt.getID()) { + case AppletPanel.APPLET_RESIZE: { + if(src != null) { + appletViewer.resize(appletViewer.preferredSize()); + appletViewer.validate(); + } + break; + } + case AppletPanel.APPLET_LOADING_COMPLETED: { + Applet a = src.getApplet(); // sun.applet.AppletPanel - public static void setPluginCallRequestFactory(PluginCallRequestFactory rf) { - requestFactory = rf; - } + // 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()); + + status.put(appletViewer.identifier, PAV_INIT_STATUS.INIT_COMPLETE); + + break; + } + } + } + } + + public static void setStreamhandler(PluginStreamHandler sh) { + streamhandler = sh; + } + + public static void setPluginCallRequestFactory(PluginCallRequestFactory rf) { + requestFactory = rf; + } /** * Handle an incoming message from the plugin. @@ -415,84 +541,34 @@ } - status.put(identifier, PAV_INIT_STATUS.PRE_INIT); - - PluginParseRequest request = requests.get(identifier); - if (request == null) { - request = new PluginParseRequest(); - requests.put(identifier, request); - } - int index = message.indexOf(' ', "tag".length() + 1); - request.documentbase = - UrlUtil.decode(message.substring("tag".length() + 1, index)); - request.tag = message.substring(index + 1); - PluginDebug.debug ("REQUEST TAG: " + request.tag + " " + - Thread.currentThread()); - - if (request.handle != 0) { - PluginDebug.debug ("REQUEST TAG, PARSING " + - Thread.currentThread()); - PluginAppletViewer.parse - (identifier, request.handle, - new StringReader(request.tag), - new URL(request.documentbase)); - requests.remove(identifier); - - // Panel initialization cannot be aborted mid-way. - // Once it is initialized, double check to see if this - // panel needs to stay around.. - if (status.get(identifier).equals(PAV_INIT_STATUS.INACTIVE)) { - PluginDebug.debug("Inactive flag set. Destroying applet instance " + identifier); - applets.get(identifier).handleMessage(-1, "destroy"); - } else { - status.put(identifier, PAV_INIT_STATUS.ACTIVE); - } - - } else { - PluginDebug.debug ("REQUEST HANDLE NOT SET: " + request.handle + ". BYPASSING"); - } - } - - } else if (message.startsWith("handle")) { - synchronized(requests) { - - // Check if we should proceed with init - // (=> no if destroy was called after handle, but before - // tag) - if (status.containsKey(identifier) && - status.get(identifier).equals(PAV_INIT_STATUS.INACTIVE)) { - - PluginDebug.debug("Inactive flag set. Refusing to initialize instance " + identifier); - requests.remove(identifier); - return; - - } - status.put(identifier, PAV_INIT_STATUS.PRE_INIT); - PluginParseRequest request = requests.get(identifier); - if (request == null) { - request = new PluginParseRequest(); - requests.put(identifier, request); - } - request.handle = Long.parseLong - (message.substring("handle".length() + 1)); - PluginDebug.debug ("REQUEST HANDLE: " + request.handle); - if (request.tag != null) { - PluginDebug.debug ("REQUEST HANDLE, PARSING " + - Thread.currentThread()); - PluginAppletViewer.parse - (identifier, request.handle, - new StringReader(request.tag), - new URL(request.documentbase)); - requests.remove(identifier); - PluginDebug.debug ("REQUEST HANDLE, DONE PARSING " + - Thread.currentThread()); + PluginParseRequest request = requests.get(identifier); + if (request == null) { + request = new PluginParseRequest(); + requests.put(identifier, request); + } + int index = message.indexOf(' ', "tag".length() + 1); + request.documentbase = + UrlUtil.decode(message.substring("tag".length() + 1, index)); + request.tag = message.substring(index + 1); + PluginDebug.debug ("REQUEST TAG, PARSING " + + Thread.currentThread()); + PluginAppletViewer.parse + (identifier, request.handle, + new StringReader(request.tag), + new URL(request.documentbase)); + requests.remove(identifier); - } else { - PluginDebug.debug ("REQUEST TAG NOT SET: " + request.tag + ". BYPASSING"); + // Panel initialization cannot be aborted mid-way. + // Once it is initialized, double check to see if this + // panel needs to stay around.. + if (status.get(identifier).equals(PAV_INIT_STATUS.INACTIVE)) { + PluginDebug.debug("Inactive flag set. Destroying applet instance " + identifier); + applets.get(identifier).handleMessage(-1, "destroy"); } } + } else { PluginDebug.debug ("Handling message: " + message + " instance " + identifier + " " + Thread.currentThread()); @@ -534,7 +610,37 @@ if (status.get(identifier).equals(PAV_INIT_STATUS.INACTIVE)) return; - applets.get(identifier).handleMessage(reference, message); + if (message.startsWith("handle")) { + + PluginDebug.debug("handle command waiting for applet to complete loading."); + int maxWait = 10000; // wait 10 seconds max for applet to fully load + int wait = 0; + while (!status.get(identifier).equals(PAV_INIT_STATUS.INIT_COMPLETE) && + (wait < maxWait)) { + + try { + Thread.sleep(50); + wait += 50; + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + + if (!status.get(identifier).equals(PAV_INIT_STATUS.INIT_COMPLETE)) + throw new Exception("Applet initialization timeout"); + + PluginDebug.debug("Applet loading complete. Proceeding to reframe."); + long handle = Long.parseLong + (message.substring("handle".length() + 1)); + + PluginAppletViewer oldFrame = applets.get(identifier); + reFrame(oldFrame, oldFrame.identifier, oldFrame.statusMsgStream, + oldFrame.proposedHeightFactor, oldFrame.proposedWidthFactor, + handle, oldFrame.panel); + + } else { + applets.get(identifier).handleMessage(reference, message); + } } } catch (Exception e) { @@ -553,33 +659,45 @@ { if (message.startsWith("width")) { - // 0 => width, 1=> width_value, 2 => height, 3=> height_value - String[] dimMsg = message.split(" "); - - final int height = (int) (proposedHeightFactor*Integer.parseInt(dimMsg[3])); - final int width = (int) (proposedWidthFactor*Integer.parseInt(dimMsg[1])); + // Wait for panel to come alive + int maxWait = 5000; // wait 5 seconds max for panel to come alive + int wait = 0; + while (!status.get(identifier).equals(PAV_INIT_STATUS.INIT_COMPLETE) && wait < maxWait) { + try { + Thread.sleep(50); + wait += 50; + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } - if (panel instanceof NetxPanel) - ((NetxPanel) panel).updateSizeInAtts(height, width); + // 0 => width, 1=> width_value, 2 => height, 3=> height_value + String[] dimMsg = message.split(" "); - try { - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { + final int height = (int) (proposedHeightFactor*Integer.parseInt(dimMsg[3])); + final int width = (int) (proposedWidthFactor*Integer.parseInt(dimMsg[1])); - setSize(width, height); + if (panel instanceof NetxPanel) + ((NetxPanel) panel).updateSizeInAtts(height, width); + + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + + setSize(width, height); - // There is a rather odd drawing bug whereby resizing - // the panel makes no difference on initial call - // because the panel thinks that it is already the - // right size. Validation has no effect there either. - // So we work around by setting size to 1, validating, - // and then setting to the right size and validating - // again. This is not very efficient, and there is - // probably a better way -- but resizing happens - // quite infrequently, so for now this is how we do it + // There is a rather odd drawing bug whereby resizing + // the panel makes no difference on initial call + // because the panel thinks that it is already the + // right size. Validation has no effect there either. + // So we work around by setting size to 1, validating, + // and then setting to the right size and validating + // again. This is not very efficient, and there is + // probably a better way -- but resizing happens + // quite infrequently, so for now this is how we do it - panel.setSize(1,1); - panel.validate(); + panel.setSize(1,1); + panel.validate(); panel.setSize(width, height); panel.validate(); @@ -592,6 +710,7 @@ // do nothing e.printStackTrace(); } + } else if (message.startsWith("destroy")) { dispose(); status.put(identifier, PAV_INIT_STATUS.INACTIVE); @@ -649,94 +768,6 @@ doLayout(); } - /** - * 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. - PrivilegedAction pa = new PrivilegedAction() { - public Object run() { - return System.getProperty("appletviewer.send.event"); - } - }; - String eventList = (String) AccessController.doPrivileged(pa); - - 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++) { - PluginDebug.debug("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 - PluginDebug.debug("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 */ @@ -1544,8 +1575,8 @@ * Exit from the program (if not stand alone) - do no clean-up */ private void appletSystemExit() { - if (factory.isStandalone()) - System.exit(0); + // Do nothing. Exit is handled by another + // block of code, called when _all_ applets are gone } /** @@ -1734,7 +1765,7 @@ public static void parse(int identifier, long handle, Reader in, URL url, String enc) throws IOException { encoding = enc; - parse(identifier, handle, in, url, System.out, new PluginAppletViewerFactory()); + parse(identifier, handle, in, url, System.out, new PluginAppletPanelFactory()); } public static void parse(int identifier, long handle, Reader in, URL url) @@ -1747,7 +1778,8 @@ PrivilegedAction pa = new PrivilegedAction() { public Object run() { try { - parse(fIdentifier, fHandle, fIn, fUrl, System.out, new PluginAppletViewerFactory()); + parse(fIdentifier, fHandle, fIn, fUrl, + System.out, new PluginAppletPanelFactory()); } catch (IOException ioe) { return ioe; } @@ -1764,7 +1796,7 @@ public static void parse(int identifier, long handle, Reader in, URL url, PrintStream statusMsgStream, - PluginAppletViewerFactory factory) + PluginAppletPanelFactory factory) throws IOException { // <OBJECT> <EMBED> tag flags @@ -1824,7 +1856,9 @@ // shouldn't be part of parsing. It's presence // causes things to be a little too much of a // hack. - factory.createAppletViewer(identifier, handle, x, y, url, atts); + // Let user know we are starting up + streamhandler.write("instance " + identifier + " status " + amh.getMessage("status.start")); + factory.createPanel(streamhandler, identifier, handle, x, y, url, atts); x += XDELTA; y += YDELTA; // make sure we don't go too far!