// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
package net.sourceforge.jnlp.runtime;
import net.sourceforge.jnlp.util.logging.OutputController;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import java.lang.reflect.InvocationTargetException;
import java.net.*;
import java.io.*;
import javax.swing.*;
import net.sourceforge.jnlp.*;
import net.sourceforge.jnlp.splashscreen.SplashController;
import net.sourceforge.jnlp.util.*;
/**
* The applet environment including stub, context, and frame. The
* default environment puts the applet in a non-resiable frame;
* this can be changed by obtaining the frame and setting it
* resizable.
*
* @author Jon A. Maxwell (JAM) - initial author
* @version $Revision: 1.12 $
*/
public class AppletEnvironment implements AppletContext, AppletStub {
/** the JNLP file */
private JNLPFile file;
/** the applet */
private Applet applet;
/** the parameters */
private Map parameters;
/** the applet container */
private Container cont;
/** weak references to the audio clips */
private WeakList weakClips = new WeakList();
/** whether the applet has been started / displayed */
private boolean appletStarted = false;
/** whether the applet has been destroyed */
private boolean destroyed = false;
/**
* Create a new applet environment for the applet specified by
* the JNLP file.
*/
public AppletEnvironment(JNLPFile file, final AppletInstance appletInstance, Container cont) {
this.file = file;
this.applet = appletInstance.getApplet();
parameters = file.getApplet().getParameters();
this.cont = cont;
}
/**
* Create a new applet environment for the applet specified by
* the JNLP file, in a new frame.
*/
public AppletEnvironment(JNLPFile file, final AppletInstance appletInstance) {
this(file, appletInstance, null);
Frame frame = new Frame(file.getApplet().getName() + " - Applet");
frame.setResizable(false);
appletInstance.addWindow(frame);
// may not need this once security manager can close windows
// that do not have app code on the stack
WindowListener closer = new WindowAdapter() {
public void windowClosing(WindowEvent event) {
appletInstance.destroy();
JNLPRuntime.exit(0);
}
};
frame.addWindowListener(closer);
this.cont = frame;
}
/**
* Checks whether the applet has been destroyed, and throws an
* IllegalStateException if the applet has been destroyed of.
*
* @throws IllegalStateException
*/
private void checkDestroyed() {
if (destroyed)
throw new IllegalStateException("Illegal applet stub/context access: applet destroyed.");
}
/**
* Disposes the applet's resources and disables the applet
* environment from further use; after calling this method the
* applet stub and context methods throw IllegalStateExceptions.
*/
public void destroy() {
destroyed = true;
List clips = weakClips.hardList();
for (AppletAudioClip clip : clips) {
clip.dispose();
}
}
/**
* Returns the frame that contains the applet. Disposing this
* frame will destroy the applet.
*/
public Container getAppletFrame() {
// TODO: rename this method to getAppletContainer ?
return cont;
}
/**
* container must be SplashContoler
*
*/
public SplashController getSplashControler() {
return (SplashController)cont;
}
/**
* Initialize, start, and show the applet.
*/
public void startApplet() {
checkDestroyed();
if (appletStarted)
return;
appletStarted = true;
try {
AppletDesc appletDesc = file.getApplet();
if (cont instanceof AppletStub)
applet.setStub((AppletStub) cont);
else
applet.setStub(this);
cont.setLayout(new BorderLayout());
cont.add("Center", applet);
cont.validate();
// This is only needed if the applet is in its own frame.
if (cont instanceof Frame) {
Frame frame = (Frame) cont;
frame.pack(); // cause insets to be calculated
Insets insets = frame.getInsets();
frame.setSize(appletDesc.getWidth() + insets.left + insets.right,
appletDesc.getHeight() + insets.top + insets.bottom);
}
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
// do first because some applets need to be displayed before
// starting (they use Component.getImage or something)
cont.setVisible(true);
applet.init();
applet.start();
cont.invalidate(); // this should force the applet to
cont.validate(); // the correct size and to repaint
cont.repaint();
}
});
} catch (InterruptedException ie) {
} catch (InvocationTargetException ite) {
}
} catch (Exception ex) {
OutputController.getLogger().log(ex);
// should also kill the applet?
}
}
// applet context methods
/**
* Returns the applet if the applet's name is specified,
* otherwise return null.
*/
public Applet getApplet(String name) {
checkDestroyed();
if (name != null && name.equals(file.getApplet().getName()))
return applet;
else
return null;
}
/**
* Set the applet of this environment; can only be called once.
*/
public void setApplet(Applet applet) {
if (this.applet != null) {
OutputController.getLogger().log(new IllegalStateException("Applet can only be set once."));
return;
}
this.applet = applet;
}
/**
* Returns an enumeration that contains only the applet
* from the JNLP file.
*/
public Enumeration