/* * Copyright (c) 1995, 2008, Oracle and/or its affiliates. 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.applet; import java.applet.*;import java.awt.*;import java.awt.event.*;import java.awt.image.ColorModel;import java.awt.image.MemoryImageSource;import java.io.*;import java.lang.ref.WeakReference;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.net.InetAddress;import java.net.JarURLConnection;import java.net.MalformedURLException;import java.net.SocketPermission;import java.net.URL;import java.net.UnknownHostException;import java.security.*;import java.util.*;import java.util.Collections;import java.util.Locale;import java.util.WeakHashMap;import sun.awt.AppContext;import sun.awt.EmbeddedFrame;import sun.awt.SunToolkit;import sun.misc.MessageUtils;import sun.misc.PerformanceLogger;import sun.misc.Queue;import sun.security.util.SecurityConstants; /** * Applet panel class. The panel manages and manipulates the * applet as it is being loaded. It forks a separate thread in a new * thread group to call the applet's init(), start(), stop(), and * destroy() methods. * * @author Arthur van Hoff */publicabstract class AppletPanel extends Panel implements AppletStub, Runnable { /** * The applet (if loaded). */ Applet applet; /** * Applet will allow initialization. Should be * set to false if loading a serialized applet * that was pickled in the init=true state. */ protected boolean doInit = true; /** * The classloader for the applet. */ protected AppletClassLoader loader; /* applet event ids */ public final static int APPLET_DISPOSE = 0; public final static int APPLET_LOAD = 1; public final static int APPLET_INIT = 2; public final static int APPLET_START = 3; public final static int APPLET_STOP = 4; public final static int APPLET_DESTROY = 5; public final static int APPLET_QUIT = 6; public final static int APPLET_ERROR = 7; /* send to the parent to force relayout */ public final static int APPLET_RESIZE = 51234; /* sent to a (distant) parent to indicate that the applet is being * loaded or as completed loading */ public final static int APPLET_LOADING = 51235; public final static int APPLET_LOADING_COMPLETED = 51236; /** * The current status. One of: * APPLET_DISPOSE, * APPLET_LOAD, * APPLET_INIT, * APPLET_START, * APPLET_STOP, * APPLET_DESTROY, * APPLET_ERROR. */ protected int status; /** * The thread for the applet. */ protected Thread handler; /** * The initial applet size. */ Dimension defaultAppletSize = new Dimension(10, 10); /** * The current applet size. */ Dimension currentAppletSize = new Dimension(10, 10); MessageUtils mu = new MessageUtils(); /** * The thread to use during applet loading */ Thread loaderThread = null; /** * Flag to indicate that a loading has been cancelled */ boolean loadAbortRequest = false; /* abstract classes */ abstract protected String getCode(); abstract protected String getJarFiles(); abstract protected String getSerializedObject(); abstract public int getWidth(); abstract public int getHeight(); abstract public boolean hasInitialFocus(); private static int threadGroupNumber = 0; protected void setupAppletAppContext() { // do nothing } /* * Creates a thread to run the applet. This method is called * each time an applet is loaded and reloaded. */ synchronized void createAppletThread() { // Create a thread group for the applet, and start a new // thread to load the applet. String nm = "applet-" + getCode(); loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey()); loader.grab(); // Keep this puppy around! // 4668479: Option to turn off codebase lookup in AppletClassLoader // during resource requests. [stanley.ho] String param = getParameter("codebase_lookup"); if (param != null && param.equals("false")) loader.setCodebaseLookup(false); else loader.setCodebaseLookup(true); ThreadGroup appletGroup = loader.getThreadGroup(); handler = new Thread(appletGroup, this, "thread " + nm); // set the context class loader for this thread AccessController.doPrivileged(new PrivilegedAction() { public Object run() { handler.setContextClassLoader(loader); return null; } }); handler.start(); } void joinAppletThread() throws InterruptedException { if (handler != null) { handler.join(); handler = null; } } void release() { if (loader != null) { loader.release(); loader = null; } } /** * Construct an applet viewer and start the applet. */ public void init() { try { // Get the width (if any) defaultAppletSize.width = getWidth(); currentAppletSize.width = defaultAppletSize.width; // Get the height (if any) defaultAppletSize.height = getHeight(); currentAppletSize.height = defaultAppletSize.height; } catch (NumberFormatException e) { // Turn on the error flag and let TagAppletPanel // do the right thing. status = APPLET_ERROR; showAppletStatus("badattribute.exception"); showAppletLog("badattribute.exception"); showAppletException(e); } setLayout(new BorderLayout()); createAppletThread(); } /** * Minimum size */ public Dimension minimumSize() { return new Dimension(defaultAppletSize.width, defaultAppletSize.height); } /** * Preferred size */ public Dimension preferredSize() { return new Dimension(currentAppletSize.width, currentAppletSize.height); } private AppletListener listeners; /** * AppletEvent Queue */ private Queue queue = null; synchronized public void addAppletListener(AppletListener l) { listeners = AppletEventMulticaster.add(listeners, l); } synchronized public void removeAppletListener(AppletListener l) { listeners = AppletEventMulticaster.remove(listeners, l); } /** * Dispatch event to the listeners.. */ public void dispatchAppletEvent(int id, Object argument) { //System.out.println("SEND= " + id); if (listeners != null) { AppletEvent evt = new AppletEvent(this, id, argument); listeners.appletStateChanged(evt); } } /** * Send an event. Queue it for execution by the handler thread. */ public void sendEvent(int id) { synchronized(this) { if (queue == null) { //System.out.println("SEND0= " + id); queue = new Queue(); } Integer eventId = Integer.valueOf(id); queue.enqueue(eventId); notifyAll(); } if (id == APPLET_QUIT) { try { joinAppletThread(); // Let the applet event handler exit } catch (InterruptedException e) { } // AppletClassLoader.release() must be called by a Thread // not within the applet's ThreadGroup if (loader == null) loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey()); release(); } } /** * Get an event from the queue. */ synchronized AppletEvent getNextEvent() throws InterruptedException { while (queue == null || queue.isEmpty()) { wait(); } Integer eventId = (Integer)queue.dequeue(); return new AppletEvent(this, eventId.intValue(), null); } boolean emptyEventQueue() { if ((queue == null) || (queue.isEmpty())) return true; else return false; } /** * This kludge is specific to get over AccessControlException thrown during * Applet.stop() or destroy() when static thread is suspended. Set a flag * in AppletClassLoader to indicate that an * AccessControlException for RuntimePermission "modifyThread" or * "modifyThreadGroup" had occurred. */ private void setExceptionStatus(AccessControlException e) { Permission p = e.getPermission(); if (p instanceof RuntimePermission) { if (p.getName().startsWith("modifyThread")) { if (loader == null) loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey()); loader.setExceptionStatus(); } } } /** * Execute applet events. * Here is the state transition diagram * * Note: (XXX) is the action * APPLET_XXX is the state * (applet code loaded) --> APPLET_LOAD -- (applet init called)--> APPLET_INIT -- ( * applet start called) --> APPLET_START -- (applet stop called) -->APPLET_STOP --(applet * destroyed called) --> APPLET_DESTROY -->(applet gets disposed) --> * APPLET_DISPOSE -->.... * * In the legacy lifecycle model. The applet gets loaded, inited and started. So it stays * in the APPLET_START state unless the applet goes away(refresh page or leave the page). * So the applet stop method called and the applet enters APPLET_STOP state. Then if the applet * is revisited, it will call applet start method and enter the APPLET_START state and stay there. * * In the modern lifecycle model. When the applet first time visited, it is same as legacy lifecycle * model. However, when the applet page goes away. It calls applet stop method and enters APPLET_STOP * state and then applet destroyed method gets called and enters APPLET_DESTROY state. * * This code is also called by AppletViewer. In AppletViewer "Restart" menu, the applet is jump from * APPLET_STOP to APPLET_DESTROY and to APPLET_INIT . * * Also, the applet can jump from APPLET_INIT state to APPLET_DESTROY (in Netscape/Mozilla case). * Same as APPLET_LOAD to * APPLET_DISPOSE since all of this are triggered by browser. * * */ public void run() { Thread curThread = Thread.currentThread(); if (curThread == loaderThread) { // if we are in the loader thread, cause // loading to occur. We may exit this with // status being APPLET_DISPOSE, APPLET_ERROR, // or APPLET_LOAD runLoader(); return; } boolean disposed = false; while (!disposed && !curThread.isInterrupted()) { AppletEvent evt; try { evt = getNextEvent(); } catch (InterruptedException e) { showAppletStatus("bail"); return; } //showAppletStatus("EVENT = " + evt.getID()); try { switch (evt.getID()) { case APPLET_LOAD: if (!okToLoad()) { break; } // This complexity allows loading of applets to be // interruptable. The actual thread loading runs // in a separate thread, so it can be interrupted // without harming the applet thread. // So that we don't have to worry about // concurrency issues, the main applet thread waits // until the loader thread terminates. // (one way or another). if (loaderThread == null) { // REMIND: do we want a name? //System.out.println("------------------- loading applet"); setLoaderThread(new Thread(this)); loaderThread.start(); // we get to go to sleep while this runs loaderThread.join(); setLoaderThread(null); } else { // REMIND: issue an error -- this case should never // occur. } break; case APPLET_INIT: // AppletViewer "Restart" will jump from destroy method to // init, that is why we need to check status w/ APPLET_DESTROY if (status != APPLET_LOAD && status != APPLET_DESTROY) { showAppletStatus("notloaded"); break; } applet.resize(defaultAppletSize); if (doInit) { if (PerformanceLogger.loggingEnabled()) { PerformanceLogger.setTime("Applet Init"); PerformanceLogger.outputLog(); } applet.init(); } //Need the default(fallback) font to be created in this AppContext Font f = getFont(); if (f == null || "dialog".equals(f.getFamily().toLowerCase(Locale.ENGLISH)) && f.getSize() == 12 && f.getStyle() == Font.PLAIN) { setFont(new Font(Font.DIALOG, Font.PLAIN, 12)); } doInit = true; // allow restarts // Validate the applet in event dispatch thread // to avoid deadlock. try { final AppletPanel p = this; EventQueue.invokeAndWait(new Runnable() { public void run() { p.validate(); } }); } catch(InterruptedException ie) { } catch(InvocationTargetException ite) { } status = APPLET_INIT; showAppletStatus("inited"); break; case APPLET_START: { if (status != APPLET_INIT && status != APPLET_STOP) { showAppletStatus("notinited"); break; } applet.resize(currentAppletSize); applet.start(); // Validate and show the applet in event dispatch thread // to avoid deadlock. try { final AppletPanel p = this; final Applet a = applet; EventQueue.invokeAndWait(new Runnable() { public void run() { p.validate(); a.setVisible(true); // Fix for BugTraq ID 4041703. // Set the default focus for an applet. if (hasInitialFocus()) setDefaultFocus(); } }); } catch(InterruptedException ie) { } catch(InvocationTargetException ite) { } status = APPLET_START; showAppletStatus("started");Lines 1–500 of 1318. Load more
/* * Copyright (c) 1995, 2008, Oracle and/or its affiliates. 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.applet; import java.applet.*; import java.awt.*; import java.awt.event.*; import java.awt.image.ColorModel; import java.awt.image.MemoryImageSource; import java.io.*; import java.lang.ref.WeakReference; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.InetAddress; import java.net.JarURLConnection; import java.net.MalformedURLException; import java.net.SocketPermission; import java.net.URL; import java.net.UnknownHostException; import java.security.*; import java.util.*; import java.util.Collections; import java.util.Locale; import java.util.WeakHashMap; import sun.awt.AppContext; import sun.awt.EmbeddedFrame; import sun.awt.SunToolkit; import sun.misc.MessageUtils; import sun.misc.PerformanceLogger; import sun.misc.Queue; import sun.security.util.SecurityConstants; /** * Applet panel class. The panel manages and manipulates the * applet as it is being loaded. It forks a separate thread in a new * thread group to call the applet's init(), start(), stop(), and * destroy() methods. * * @author Arthur van Hoff */ public abstract class AppletPanel extends Panel implements AppletStub, Runnable { /** * The applet (if loaded). */ Applet applet; /** * Applet will allow initialization. Should be * set to false if loading a serialized applet * that was pickled in the init=true state. */ protected boolean doInit = true; /** * The classloader for the applet. */ protected AppletClassLoader loader; /* applet event ids */ public final static int APPLET_DISPOSE = 0; public final static int APPLET_LOAD = 1; public final static int APPLET_INIT = 2; public final static int APPLET_START = 3; public final static int APPLET_STOP = 4; public final static int APPLET_DESTROY = 5; public final static int APPLET_QUIT = 6; public final static int APPLET_ERROR = 7; /* send to the parent to force relayout */ public final static int APPLET_RESIZE = 51234; /* sent to a (distant) parent to indicate that the applet is being * loaded or as completed loading */ public final static int APPLET_LOADING = 51235; public final static int APPLET_LOADING_COMPLETED = 51236; /** * The current status. One of: * APPLET_DISPOSE, * APPLET_LOAD, * APPLET_INIT, * APPLET_START, * APPLET_STOP, * APPLET_DESTROY, * APPLET_ERROR. */ protected int status; /** * The thread for the applet. */ protected Thread handler; /** * The initial applet size. */ Dimension defaultAppletSize = new Dimension(10, 10); /** * The current applet size. */ Dimension currentAppletSize = new Dimension(10, 10); MessageUtils mu = new MessageUtils(); /** * The thread to use during applet loading */ Thread loaderThread = null; /** * Flag to indicate that a loading has been cancelled */ boolean loadAbortRequest = false; /* abstract classes */ abstract protected String getCode(); abstract protected String getJarFiles(); abstract protected String getSerializedObject(); abstract public int getWidth(); abstract public int getHeight(); abstract public boolean hasInitialFocus(); private static int threadGroupNumber = 0; protected void setupAppletAppContext() { // do nothing } /* * Creates a thread to run the applet. This method is called * each time an applet is loaded and reloaded. */ synchronized void createAppletThread() { // Create a thread group for the applet, and start a new // thread to load the applet. String nm = "applet-" + getCode(); loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey()); loader.grab(); // Keep this puppy around! // 4668479: Option to turn off codebase lookup in AppletClassLoader // during resource requests. [stanley.ho] String param = getParameter("codebase_lookup"); if (param != null && param.equals("false")) loader.setCodebaseLookup(false); else loader.setCodebaseLookup(true); ThreadGroup appletGroup = loader.getThreadGroup(); handler = new Thread(appletGroup, this, "thread " + nm); // set the context class loader for this thread AccessController.doPrivileged(new PrivilegedAction() { public Object run() { handler.setContextClassLoader(loader); return null; } }); handler.start(); } void joinAppletThread() throws InterruptedException { if (handler != null) { handler.join(); handler = null; } } void release() { if (loader != null) { loader.release(); loader = null; } } /** * Construct an applet viewer and start the applet. */ public void init() { try { // Get the width (if any) defaultAppletSize.width = getWidth(); currentAppletSize.width = defaultAppletSize.width; // Get the height (if any) defaultAppletSize.height = getHeight(); currentAppletSize.height = defaultAppletSize.height; } catch (NumberFormatException e) { // Turn on the error flag and let TagAppletPanel // do the right thing. status = APPLET_ERROR; showAppletStatus("badattribute.exception"); showAppletLog("badattribute.exception"); showAppletException(e); } setLayout(new BorderLayout()); createAppletThread(); } /** * Minimum size */ public Dimension minimumSize() { return new Dimension(defaultAppletSize.width, defaultAppletSize.height); } /** * Preferred size */ public Dimension preferredSize() { return new Dimension(currentAppletSize.width, currentAppletSize.height); } private AppletListener listeners; /** * AppletEvent Queue */ private Queue queue = null; synchronized public void addAppletListener(AppletListener l) { listeners = AppletEventMulticaster.add(listeners, l); } synchronized public void removeAppletListener(AppletListener l) { listeners = AppletEventMulticaster.remove(listeners, l); } /** * Dispatch event to the listeners.. */ public void dispatchAppletEvent(int id, Object argument) { //System.out.println("SEND= " + id); if (listeners != null) { AppletEvent evt = new AppletEvent(this, id, argument); listeners.appletStateChanged(evt); } } /** * Send an event. Queue it for execution by the handler thread. */ public void sendEvent(int id) { synchronized(this) { if (queue == null) { //System.out.println("SEND0= " + id); queue = new Queue(); } Integer eventId = Integer.valueOf(id); queue.enqueue(eventId); notifyAll(); } if (id == APPLET_QUIT) { try { joinAppletThread(); // Let the applet event handler exit } catch (InterruptedException e) { } // AppletClassLoader.release() must be called by a Thread // not within the applet's ThreadGroup if (loader == null) loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey()); release(); } } /** * Get an event from the queue. */ synchronized AppletEvent getNextEvent() throws InterruptedException { while (queue == null || queue.isEmpty()) { wait(); } Integer eventId = (Integer)queue.dequeue(); return new AppletEvent(this, eventId.intValue(), null); } boolean emptyEventQueue() { if ((queue == null) || (queue.isEmpty())) return true; else return false; } /** * This kludge is specific to get over AccessControlException thrown during * Applet.stop() or destroy() when static thread is suspended. Set a flag * in AppletClassLoader to indicate that an * AccessControlException for RuntimePermission "modifyThread" or * "modifyThreadGroup" had occurred. */ private void setExceptionStatus(AccessControlException e) { Permission p = e.getPermission(); if (p instanceof RuntimePermission) { if (p.getName().startsWith("modifyThread")) { if (loader == null) loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey()); loader.setExceptionStatus(); } } } /** * Execute applet events. * Here is the state transition diagram * * Note: (XXX) is the action * APPLET_XXX is the state * (applet code loaded) --> APPLET_LOAD -- (applet init called)--> APPLET_INIT -- ( * applet start called) --> APPLET_START -- (applet stop called) -->APPLET_STOP --(applet * destroyed called) --> APPLET_DESTROY -->(applet gets disposed) --> * APPLET_DISPOSE -->.... * * In the legacy lifecycle model. The applet gets loaded, inited and started. So it stays * in the APPLET_START state unless the applet goes away(refresh page or leave the page). * So the applet stop method called and the applet enters APPLET_STOP state. Then if the applet * is revisited, it will call applet start method and enter the APPLET_START state and stay there. * * In the modern lifecycle model. When the applet first time visited, it is same as legacy lifecycle * model. However, when the applet page goes away. It calls applet stop method and enters APPLET_STOP * state and then applet destroyed method gets called and enters APPLET_DESTROY state. * * This code is also called by AppletViewer. In AppletViewer "Restart" menu, the applet is jump from * APPLET_STOP to APPLET_DESTROY and to APPLET_INIT . * * Also, the applet can jump from APPLET_INIT state to APPLET_DESTROY (in Netscape/Mozilla case). * Same as APPLET_LOAD to * APPLET_DISPOSE since all of this are triggered by browser. * * */ public void run() { Thread curThread = Thread.currentThread(); if (curThread == loaderThread) { // if we are in the loader thread, cause // loading to occur. We may exit this with // status being APPLET_DISPOSE, APPLET_ERROR, // or APPLET_LOAD runLoader(); return; } boolean disposed = false; while (!disposed && !curThread.isInterrupted()) { AppletEvent evt; try { evt = getNextEvent(); } catch (InterruptedException e) { showAppletStatus("bail"); return; } //showAppletStatus("EVENT = " + evt.getID()); try { switch (evt.getID()) { case APPLET_LOAD: if (!okToLoad()) { break; } // This complexity allows loading of applets to be // interruptable. The actual thread loading runs // in a separate thread, so it can be interrupted // without harming the applet thread. // So that we don't have to worry about // concurrency issues, the main applet thread waits // until the loader thread terminates. // (one way or another). if (loaderThread == null) { // REMIND: do we want a name? //System.out.println("------------------- loading applet"); setLoaderThread(new Thread(this)); loaderThread.start(); // we get to go to sleep while this runs loaderThread.join(); setLoaderThread(null); } else { // REMIND: issue an error -- this case should never // occur. } break; case APPLET_INIT: // AppletViewer "Restart" will jump from destroy method to // init, that is why we need to check status w/ APPLET_DESTROY if (status != APPLET_LOAD && status != APPLET_DESTROY) { showAppletStatus("notloaded"); break; } applet.resize(defaultAppletSize); if (doInit) { if (PerformanceLogger.loggingEnabled()) { PerformanceLogger.setTime("Applet Init"); PerformanceLogger.outputLog(); } applet.init(); } //Need the default(fallback) font to be created in this AppContext Font f = getFont(); if (f == null || "dialog".equals(f.getFamily().toLowerCase(Locale.ENGLISH)) && f.getSize() == 12 && f.getStyle() == Font.PLAIN) { setFont(new Font(Font.DIALOG, Font.PLAIN, 12)); } doInit = true; // allow restarts // Validate the applet in event dispatch thread // to avoid deadlock. try { final AppletPanel p = this; EventQueue.invokeAndWait(new Runnable() { public void run() { p.validate(); } }); } catch(InterruptedException ie) { } catch(InvocationTargetException ite) { } status = APPLET_INIT; showAppletStatus("inited"); break; case APPLET_START: { if (status != APPLET_INIT && status != APPLET_STOP) { showAppletStatus("notinited"); break; } applet.resize(currentAppletSize); applet.start(); // Validate and show the applet in event dispatch thread // to avoid deadlock. try { final AppletPanel p = this; final Applet a = applet; EventQueue.invokeAndWait(new Runnable() { public void run() { p.validate(); a.setVisible(true); // Fix for BugTraq ID 4041703. // Set the default focus for an applet. if (hasInitialFocus()) setDefaultFocus(); } }); } catch(InterruptedException ie) { } catch(InvocationTargetException ite) { } status = APPLET_START; showAppletStatus("started");