/*
 * 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");
                      break;
                  }

                case APPLET_STOP:
                    if (status != APPLET_START) {
                        showAppletStatus("notstarted");
                        break;
                    }
                    status = APPLET_STOP;

                    // Hide the applet in event dispatch thread
                    // to avoid deadlock.
                    try {
                        final Applet a = applet;

                        EventQueue.invokeAndWait(new Runnable() {
                                public void run()
                                {
                                    a.setVisible(false);
                                }
                            });
                    }
                    catch(InterruptedException ie) {
                    }
                    catch(InvocationTargetException ite) {
                    }


                    // During Applet.stop(), any AccessControlException on an involved Class remains in
                    // the "memory" of the AppletClassLoader.  If the same instance of the ClassLoader is
                    // reused, the same exception will occur during class loading.  Set the AppletClassLoader's
                    // exceptionStatusSet flag to allow recognition of what had happened
                    // when reusing AppletClassLoader object.
                    try {
                        applet.stop();
                    } catch (java.security.AccessControlException e) {
                        setExceptionStatus(e);
                        // rethrow exception to be handled as it normally would be.
                        throw e;
                    }
                    showAppletStatus("stopped");
                    break;

                case APPLET_DESTROY:
                    if (status != APPLET_STOP && status != APPLET_INIT) {
                        showAppletStatus("notstopped");
                        break;
                    }
                    status = APPLET_DESTROY;

                    // During Applet.destroy(), any AccessControlException on an involved Class remains in
                    // the "memory" of the AppletClassLoader.  If the same instance of the ClassLoader is
                    // reused, the same exception will occur during class loading.  Set the AppletClassLoader's
                    // exceptionStatusSet flag to allow recognition of what had happened
                    // when reusing AppletClassLoader object.
                    try {
                        applet.destroy();
                    } catch (java.security.AccessControlException e) {
                        setExceptionStatus(e);
                        // rethrow exception to be handled as it normally would be.
                        throw e;
                    }
                    showAppletStatus("destroyed");
                    break;

                case APPLET_DISPOSE:
                    if (status != APPLET_DESTROY && status != APPLET_LOAD) {
                        showAppletStatus("notdestroyed");
                        break;
                    }
                    status = APPLET_DISPOSE;

                    try
                    {
                        final Applet a = applet;

                        EventQueue.invokeAndWait(new Runnable()
                        {
                            public void run()
                            {
                                remove(a);
                            }
                        });
                    }
                    catch(InterruptedException ie)
                    {
                    }
                    catch(InvocationTargetException ite)
                    {
                    }
                    applet = null;
                    showAppletStatus("disposed");
                    disposed = true;
                    break;

                case APPLET_QUIT:
                    return;
                }
            } catch (Exception e) {
                status = APPLET_ERROR;
                if (e.getMessage() != null) {
                    showAppletStatus("exception2", e.getClass().getName(),
                                     e.getMessage());
                } else {
                    showAppletStatus("exception", e.getClass().getName());
                }
                showAppletException(e);
            } catch (ThreadDeath e) {
                showAppletStatus("death");
                return;
            } catch (Error e) {
                status = APPLET_ERROR;
                if (e.getMessage() != null) {
                    showAppletStatus("error2", e.getClass().getName(),
                                     e.getMessage());
                } else {
                    showAppletStatus("error", e.getClass().getName());
                }
                showAppletException(e);
            }
            clearLoadAbortRequest();
        }
    }

    /**
     * Gets most recent focus owner component associated with the given window.
     * It does that without calling Window.getMostRecentFocusOwner since it
     * provides its own logic contradicting with setDefautlFocus. Instead, it
     * calls KeyboardFocusManager directly.
     */
    private Component getMostRecentFocusOwnerForWindow(Window w) {
        Method meth = (Method)AccessController.doPrivileged(new PrivilegedAction() {
                public Object run() {
                    Method meth = null;
                    try {
                        meth = KeyboardFocusManager.class.getDeclaredMethod("getMostRecentFocusOwner", new Class[] {Window.class});
                        meth.setAccessible(true);
                    } catch (Exception e) {
                        // Must never happen
                        e.printStackTrace();
                    }
                    return meth;
                }
            });
        if (meth != null) {
            // Meth refers static method
            try {
                return (Component)meth.invoke(null, new Object[] {w});
            } catch (Exception e) {
                // Must never happen
                e.printStackTrace();
            }
        }
        // Will get here if exception was thrown or meth is null
        return w.getMostRecentFocusOwner();
    }

    /*
     * Fix for BugTraq ID 4041703.
     * Set the focus to a reasonable default for an Applet.
     */
    private void setDefaultFocus() {
        Component toFocus = null;
        Container parent = getParent();

        if(parent != null) {
            if (parent instanceof Window) {
                toFocus = getMostRecentFocusOwnerForWindow((Window)parent);
                if (toFocus == parent || toFocus == null) {
                    toFocus = parent.getFocusTraversalPolicy().
                        getInitialComponent((Window)parent);
                }
            } else if (parent.isFocusCycleRoot()) {
                toFocus = parent.getFocusTraversalPolicy().
                    getDefaultComponent(parent);
            }
        }

        if (toFocus != null) {
            if (parent instanceof EmbeddedFrame) {
                ((EmbeddedFrame)parent).synthesizeWindowActivation(true);
            }
            // EmbeddedFrame might have focus before the applet was added.
            // Thus after its activation the most recent focus owner will be
            // restored. We need the applet's initial focusabled component to
            // be focused here.
            toFocus.requestFocusInWindow();
        }
    }

    /**
     * Load the applet into memory.
     * Runs in a seperate (and interruptible) thread from the rest of the
     * applet event processing so that it can be gracefully interrupted from
     * things like HotJava.
     */
    private void runLoader() {
        if (status != APPLET_DISPOSE) {
            showAppletStatus("notdisposed");
            return;
        }

        dispatchAppletEvent(APPLET_LOADING, null);

        // REMIND -- might be cool to visually indicate loading here --
        // maybe do animation?
        status = APPLET_LOAD;

        // Create a class loader
        loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey());

        // Load the archives if present.
        // REMIND - this probably should be done in a separate thread,
        // or at least the additional archives (epll).

        String code = getCode();

        // setup applet AppContext
        // this must be called before loadJarFiles
        setupAppletAppContext();

        try {
            loadJarFiles(loader);
            applet = createApplet(loader);
        } catch (ClassNotFoundException e) {
            status = APPLET_ERROR;
            showAppletStatus("notfound", code);
            showAppletLog("notfound", code);
            showAppletException(e);
            return;
        } catch (InstantiationException e) {
            status = APPLET_ERROR;
            showAppletStatus("nocreate", code);
            showAppletLog("nocreate", code);
            showAppletException(e);
            return;
        } catch (IllegalAccessException e) {
            status = APPLET_ERROR;
            showAppletStatus("noconstruct", code);
            showAppletLog("noconstruct", code);
            showAppletException(e);
            // sbb -- I added a return here
            return;
        } catch (Exception e) {
            status = APPLET_ERROR;
            showAppletStatus("exception", e.getMessage());
            showAppletException(e);
            return;
        } catch (ThreadDeath e) {
            status = APPLET_ERROR;
            showAppletStatus("death");
            return;
        } catch (Error e) {
            status = APPLET_ERROR;
            showAppletStatus("error", e.getMessage());
            showAppletException(e);
            return;
        } finally {
            // notify that loading is no longer going on
            dispatchAppletEvent(APPLET_LOADING_COMPLETED, null);
        }

        // Fixed #4508194: NullPointerException thrown during
        // quick page switch
        //
        if (applet != null)
        {
            // Stick it in the frame
            applet.setStub(this);
            applet.hide();
            add("Center", applet);
            showAppletStatus("loaded");
            validate();
        }
    }

    protected Applet createApplet(final AppletClassLoader loader) throws ClassNotFoundException,
                                                                         IllegalAccessException, IOException, InstantiationException, InterruptedException {
        final String serName = getSerializedObject();
        String code = getCode();

        if (code != null && serName != null) {
            System.err.println(amh.getMessage("runloader.err"));
//          return null;
            throw new InstantiationException("Either \"code\" or \"object\" should be specified, but not both.");
        }
        if (code == null && serName == null) {
            String msg = "nocode";
            status = APPLET_ERROR;
            showAppletStatus(msg);
            showAppletLog(msg);
            repaint();
        }
        if (code != null) {
            applet = (Applet)loader.loadCode(code).newInstance();
            doInit = true;
        } else {
            // serName is not null;
            InputStream is = (InputStream)
                java.security.AccessController.doPrivileged(
                                                            new java.security.PrivilegedAction() {
                                                                public Object run() {
                                                                    return loader.getResourceAsStream(serName);
                                                                }
                                                            });
            ObjectInputStream ois =
                new AppletObjectInputStream(is, loader);
            Object serObject = ois.readObject();
            applet = (Applet) serObject;
            doInit = false; // skip over the first init
        }

        // Determine the JDK level that the applet targets.
        // This is critical for enabling certain backward
        // compatibility switch if an applet is a JDK 1.1
        // applet. [stanley.ho]
        findAppletJDKLevel(applet);

        if (Thread.interrupted()) {
            try {
                status = APPLET_DISPOSE; // APPLET_ERROR?
                applet = null;
                // REMIND: This may not be exactly the right thing: the
                // status is set by the stop button and not necessarily
                // here.
                showAppletStatus("death");
            } finally {
                Thread.currentThread().interrupt(); // resignal interrupt
            }
            return null;
        }
        return applet;
    }

    protected void loadJarFiles(AppletClassLoader loader) throws IOException,
                                                                 InterruptedException {
        // Load the archives if present.
        // REMIND - this probably should be done in a separate thread,
        // or at least the additional archives (epll).
        String jarFiles = getJarFiles();

        if (jarFiles != null) {
            StringTokenizer st = new StringTokenizer(jarFiles, ",", false);
            while(st.hasMoreTokens()) {
                String tok = st.nextToken().trim();
                try {
                    loader.addJar(tok);
                } catch (IllegalArgumentException e) {
                    // bad archive name
                    continue;
                }
            }
        }
    }

    /**
     * Request that the loading of the applet be stopped.
     */
    protected synchronized void stopLoading() {
        // REMIND: fill in the body
        if (loaderThread != null) {
            //System.out.println("Interrupting applet loader thread: " + loaderThread);
            loaderThread.interrupt();
        } else {
            setLoadAbortRequest();
        }
    }


    protected synchronized boolean okToLoad() {
        return !loadAbortRequest;
    }

    protected synchronized void clearLoadAbortRequest() {
        loadAbortRequest = false;
    }

    protected synchronized void setLoadAbortRequest() {
        loadAbortRequest = true;
    }


    private synchronized void setLoaderThread(Thread loaderThread) {
        this.loaderThread = loaderThread;
    }

    /**
     * Return true when the applet has been started.
     */
    public boolean isActive() {
        return status == APPLET_START;
    }


    private EventQueue appEvtQ = null;
    /**
     * Is called when the applet wants to be resized.
     */
    public void appletResize(int width, int height) {
        currentAppletSize.width = width;
        currentAppletSize.height = height;
        final Dimension currentSize = new Dimension(currentAppletSize.width,
                                                    currentAppletSize.height);

        if(loader != null) {
            AppContext appCtxt = loader.getAppContext();
            if(appCtxt != null)
                appEvtQ = (java.awt.EventQueue)appCtxt.get(AppContext.EVENT_QUEUE_KEY);
        }

        final AppletPanel ap = this;
        if (appEvtQ != null){
            appEvtQ.postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(),
                                                  new Runnable(){
                                                      public void run(){
                                                          if(ap != null)
                                                          {
                                                              ap.dispatchAppletEvent(APPLET_RESIZE, currentSize);
                                                          }
                                                      }
                                                  }));
        }
    }

    public void setBounds(int x, int y, int width, int height) {
        super.setBounds(x, y, width, height);
        currentAppletSize.width = width;
        currentAppletSize.height = height;
    }

    public Applet getApplet() {
        return applet;
    }

    /**
     * Status line. Called by the AppletPanel to provide
     * feedback on the Applet's state.
     */
    protected void showAppletStatus(String status) {
        getAppletContext().showStatus(amh.getMessage(status));
    }

    protected void showAppletStatus(String status, Object arg) {
        getAppletContext().showStatus(amh.getMessage(status, arg));
    }
    protected void showAppletStatus(String status, Object arg1, Object arg2) {
        getAppletContext().showStatus(amh.getMessage(status, arg1, arg2));
    }

    /**
     * Called by the AppletPanel to print to the log.
     */
    protected void showAppletLog(String msg) {
        System.out.println(amh.getMessage(msg));
    }

    protected void showAppletLog(String msg, Object arg) {
        System.out.println(amh.getMessage(msg, arg));
    }

    /**
     * Called by the AppletPanel to provide
     * feedback when an exception has happened.
     */
    protected void showAppletException(Throwable t) {
        t.printStackTrace();
        repaint();
    }

    /**
     * Get caching key for classloader cache
     */
    public String getClassLoaderCacheKey()
    {
        /**
         * Fixed #4501142: Classlaoder sharing policy doesn't
         * take "archive" into account. This will be overridden
         * by Java Plug-in.                     [stanleyh]
         */
        return getCodeBase().toString();
    }

    /**
     * The class loaders
     */
    private static HashMap classloaders = new HashMap();

    /**
     * Flush a class loader.
     */
    public static synchronized void flushClassLoader(String key) {
        classloaders.remove(key);
    }

    /**
     * Flush all class loaders.
     */
    public static synchronized void flushClassLoaders() {
        classloaders = new HashMap();
    }

    /**
     * This method actually creates an AppletClassLoader.
     *
     * It can be override by subclasses (such as the Plug-in)
     * to provide different classloaders.
     */
    protected AppletClassLoader createClassLoader(final URL codebase) {
        return new AppletClassLoader(codebase);
    }

    /**
     * Get a class loader. Create in a restricted context
     */
    synchronized AppletClassLoader getClassLoader(final URL codebase, final String key) {
        AppletClassLoader c = (AppletClassLoader)classloaders.get(key);
        if (c == null) {
            AccessControlContext acc =
                getAccessControlContext(codebase);
            c = (AppletClassLoader)
                AccessController.doPrivileged(new PrivilegedAction() {
                        public Object run() {
                            AppletClassLoader ac = createClassLoader(codebase);
                            /* Should the creation of the classloader be
                             * within the class synchronized block?  Since
                             * this class is used by the plugin, take care
                             * to avoid deadlocks, or specialize
                             * AppletPanel within the plugin.  It may take
                             * an arbitrary amount of time to create a
                             * class loader (involving getting Jar files
                             * etc.) and may block unrelated applets from
                             * finishing createAppletThread (due to the
                             * class synchronization). If
                             * createAppletThread does not finish quickly,
                             * the applet cannot process other messages,
                             * particularly messages such as destroy
                             * (which timeout when called from the browser).
                             */
                            synchronized (getClass()) {
                                AppletClassLoader res =
                                    (AppletClassLoader)classloaders.get(key);
                                if (res == null) {
                                    classloaders.put(key, ac);
                                    return ac;
                                } else {
                                    return res;
                                }
                            }
                        }
                    },acc);
        }
        return c;
    }

    /**
     * get the context for the AppletClassLoader we are creating.
     * the context is granted permission to create the class loader,
     * connnect to the codebase, and whatever else the policy grants
     * to all codebases.
     */
    private AccessControlContext getAccessControlContext(final URL codebase) {

        PermissionCollection perms = (PermissionCollection)
            AccessController.doPrivileged(new PrivilegedAction() {
                    public Object run() {
                        Policy p = java.security.Policy.getPolicy();
                        if (p != null) {
                            return p.getPermissions(new CodeSource(null,
                                                                   (java.security.cert.Certificate[]) null));
                        } else {
                            return null;
                        }
                    }
                });

        if (perms == null)
            perms = new Permissions();

        //XXX: this is needed to be able to create the classloader itself!

        perms.add(SecurityConstants.CREATE_CLASSLOADER_PERMISSION);

        Permission p;
        java.net.URLConnection urlConnection = null;
        try {
            urlConnection = codebase.openConnection();
            p = urlConnection.getPermission();
        } catch (java.io.IOException ioe) {
            p = null;
        }

        if (p != null)
            perms.add(p);

        if (p instanceof FilePermission) {

            String path = p.getName();

            int endIndex = path.lastIndexOf(File.separatorChar);

            if (endIndex != -1) {
                path = path.substring(0, endIndex+1);

                if (path.endsWith(File.separator)) {
                    path += "-";
                }
                perms.add(new FilePermission(path,
                                             SecurityConstants.FILE_READ_ACTION));
            }
        } else {
            URL locUrl = codebase;
            if (urlConnection instanceof JarURLConnection) {
                locUrl = ((JarURLConnection)urlConnection).getJarFileURL();
            }
            String host = locUrl.getHost();
            if (host != null && (host.length() > 0))
                perms.add(new SocketPermission(host,
                                               SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION));
        }

        ProtectionDomain domain =
            new ProtectionDomain(new CodeSource(codebase,
                                                (java.security.cert.Certificate[]) null), perms);
        AccessControlContext acc =
            new AccessControlContext(new ProtectionDomain[] { domain });

        return acc;
    }

    public Thread getAppletHandlerThread() {
        return handler;
    }

    public int getAppletWidth() {
        return currentAppletSize.width;
    }

    public int getAppletHeight() {
        return currentAppletSize.height;
    }

    public static void changeFrameAppContext(Frame frame, AppContext newAppContext)
    {
        // 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.

        // Check if frame's AppContext has already been set properly
        AppContext oldAppContext = SunToolkit.targetToAppContext(frame);

        if (oldAppContext == newAppContext)
            return;

        // Synchronization on Window.class is needed for locking the
        // critical section of the window list in AppContext.
        synchronized (Window.class)
        {
            WeakReference weakRef = null;
            // Remove frame from the Window list in wrong AppContext
            {
                // Lookup current frame's AppContext
                Vector<WeakReference<Window>> windowList = (Vector<WeakReference<Window>>)oldAppContext.get(Window.class);
                if (windowList != null) {
                    for (WeakReference ref : windowList) {
                        if (ref.get() == frame) {
                            weakRef = ref;
                            break;
                        }
                    }
                    // Remove frame from wrong AppContext
                    if (weakRef != null)
                        windowList.remove(weakRef);
                }
            }

            // Put the frame into the applet's AppContext map
            SunToolkit.insertTargetMapping(frame, newAppContext);

            // Insert frame into the Window list in the applet's AppContext map
            {
                Vector<WeakReference<Window>> windowList = (Vector)newAppContext.get(Window.class);
                if (windowList == null) {
                    windowList = new Vector<WeakReference<Window>>();
                    newAppContext.put(Window.class, windowList);
                }
                // use the same weakRef here as it is used elsewhere
                windowList.add(weakRef);
            }
        }
    }

    // Flag to indicate if applet is targeted for JDK 1.1.
    private boolean jdk11Applet = false;

    // Flag to indicate if applet is targeted for JDK 1.2.
    private boolean jdk12Applet = false;

    /**
     * Determine JDK level of an applet.
     */
    private void findAppletJDKLevel(Applet applet)
    {
        // To determine the JDK level of an applet, the
        // most reliable way is to check the major version
        // of the applet class file.

        // synchronized on applet class object, so calling from
        // different instances of the same applet will be
        // serialized.
        Class appletClass = applet.getClass();

        synchronized(appletClass)  {
            // Determine if the JDK level of an applet has been
            // checked before.
            Boolean jdk11Target = (Boolean) loader.isJDK11Target(appletClass);
            Boolean jdk12Target = (Boolean) loader.isJDK12Target(appletClass);

            // if applet JDK level has been checked before, retrieve
            // value and return.
            if (jdk11Target != null || jdk12Target != null) {
                jdk11Applet = (jdk11Target == null) ? false : jdk11Target.booleanValue();
                jdk12Applet = (jdk12Target == null) ? false : jdk12Target.booleanValue();
                return;
            }

            String name = appletClass.getName();

            // first convert any '.' to '/'
            name = name.replace('.', '/');

            // append .class
            final String resourceName = name + ".class";

            InputStream is = null;
            byte[] classHeader = new byte[8];

            try {
                is = (InputStream) java.security.AccessController.doPrivileged(
                    new java.security.PrivilegedAction() {
                        public Object run() {
                            return loader.getResourceAsStream(resourceName);
                        }
                    });

                // Read the first 8 bytes of the class file
                int byteRead = is.read(classHeader, 0, 8);
                is.close();

                // return if the header is not read in entirely
                // for some reasons.
                if (byteRead != 8)
                    return;
            }
            catch (IOException e)   {
                return;
            }

            // Check major version in class file header
            int major_version = readShort(classHeader, 6);

            // Major version in class file is as follows:
            //   45 - JDK 1.1
            //   46 - JDK 1.2
            //   47 - JDK 1.3
            //   48 - JDK 1.4
            //   49 - JDK 1.5
            if (major_version < 46)
                jdk11Applet = true;
            else if (major_version == 46)
                jdk12Applet = true;

            // Store applet JDK level in AppContext for later lookup,
            // e.g. page switch.
            loader.setJDK11Target(appletClass, jdk11Applet);
            loader.setJDK12Target(appletClass, jdk12Applet);
        }
    }

    /**
     * Return true if applet is targeted to JDK 1.1.
     */
    protected boolean isJDK11Applet()   {
        return jdk11Applet;
    }

    /**
     * Return true if applet is targeted to JDK1.2.
     */
    protected boolean isJDK12Applet()   {
        return jdk12Applet;
    }

    /**
     * Read short from byte array.
     */
    private int readShort(byte[] b, int off)    {
        int hi = readByte(b[off]);
        int lo = readByte(b[off + 1]);
        return (hi << 8) | lo;
    }

    private int readByte(byte b) {
        return ((int)b) & 0xFF;
    }


    private static AppletMessageHandler amh = new AppletMessageHandler("appletpanel");
}
