mirror of
https://github.com/2003scape/deep-c-rsc.git
synced 2024-03-22 05:49:51 -04:00
1265 lines
41 KiB
Java
1265 lines
41 KiB
Java
/*
|
|
* This file is modified by Ivan Maidanski <ivmai@ivmaisoft.com>
|
|
* Project name: JCGO-SUNAWT (http://www.ivmaisoft.com/jcgo/)
|
|
*/
|
|
|
|
/*
|
|
* @(#)AppletViewer.java 1.157 03/01/23
|
|
*
|
|
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
|
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*/
|
|
|
|
package sun.applet;
|
|
|
|
import java.util.*;
|
|
import java.io.*;
|
|
import java.awt.*;
|
|
import java.awt.event.*;
|
|
import java.awt.print.*;
|
|
import javax.print.attribute.*;
|
|
import java.applet.*;
|
|
import java.net.URL;
|
|
import java.net.MalformedURLException;
|
|
import java.net.SocketPermission;
|
|
import sun.misc.Ref;
|
|
import java.security.AccessController;
|
|
import java.security.PrivilegedAction;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
import java.lang.reflect.Method;
|
|
import sun.awt.SunToolkit;
|
|
import sun.awt.AppContext;
|
|
import java.lang.ref.WeakReference;
|
|
|
|
/**
|
|
* A frame to show the applet tag in.
|
|
*/
|
|
class TextFrame extends Frame {
|
|
|
|
/**
|
|
* Create the tag frame.
|
|
*/
|
|
TextFrame(int x, int y, String title, String text) {
|
|
setTitle(title);
|
|
TextArea txt = new TextArea(20, 60);
|
|
txt.setText(text);
|
|
txt.setEditable(false);
|
|
|
|
add("Center", txt);
|
|
|
|
Panel p = new Panel();
|
|
add("South", p);
|
|
Button b = new Button(amh.getMessage("button.dismiss", "Dismiss"));
|
|
p.add(b);
|
|
|
|
class ActionEventListener implements ActionListener {
|
|
public void actionPerformed(ActionEvent evt) {
|
|
dispose();
|
|
}
|
|
}
|
|
b.addActionListener(new ActionEventListener());
|
|
|
|
pack();
|
|
move(x, y);
|
|
setVisible(true);
|
|
|
|
WindowListener windowEventListener = new WindowAdapter() {
|
|
|
|
public void windowClosing(WindowEvent evt) {
|
|
dispose();
|
|
}
|
|
};
|
|
|
|
addWindowListener(windowEventListener);
|
|
}
|
|
private static AppletMessageHandler amh = new AppletMessageHandler("textframe");
|
|
|
|
}
|
|
|
|
/**
|
|
* Lets us construct one using unix-style one shot behaviors
|
|
*/
|
|
|
|
class StdAppletViewerFactory implements AppletViewerFactory
|
|
{
|
|
public AppletViewer createAppletViewer(int x, int y,
|
|
URL doc, Hashtable atts) {
|
|
return new AppletViewer(x, y, doc, atts, System.out, this);
|
|
}
|
|
|
|
public MenuBar getBaseMenuBar() {
|
|
return new MenuBar();
|
|
}
|
|
|
|
public boolean isStandalone() {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The applet viewer makes it possible to run a Java applet without using a browser.
|
|
* For details on the syntax that <B>appletviewer</B> supports, see
|
|
* <a href="../../../docs/tooldocs/appletviewertags.html">AppletViewer Tags</a>.
|
|
* (The document named appletviewertags.html in the JDK's docs/tooldocs directory,
|
|
* once the JDK docs have been installed.)
|
|
*/
|
|
public class AppletViewer extends Frame implements AppletContext,
|
|
Printable {
|
|
|
|
/**
|
|
* Some constants...
|
|
*/
|
|
private static String defaultSaveFile = "Applet.ser";
|
|
|
|
/**
|
|
* The panel in which the applet is being displayed.
|
|
*/
|
|
AppletViewerPanel panel;
|
|
|
|
/**
|
|
* The status line.
|
|
*/
|
|
Label label;
|
|
|
|
/**
|
|
* output status messages to this stream
|
|
*/
|
|
|
|
PrintStream statusMsgStream;
|
|
|
|
/**
|
|
* For cloning
|
|
*/
|
|
AppletViewerFactory factory;
|
|
|
|
|
|
private final class UserActionListener implements ActionListener {
|
|
public void actionPerformed(ActionEvent evt) {
|
|
processUserAction(evt);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create the applet viewer
|
|
*/
|
|
public AppletViewer(int x, int y, URL doc, Hashtable atts,
|
|
PrintStream statusMsgStream, AppletViewerFactory factory) {
|
|
this.factory = factory;
|
|
this.statusMsgStream = statusMsgStream;
|
|
setTitle(amh.getMessage("tool.title", atts.get("code")));
|
|
|
|
MenuBar mb = factory.getBaseMenuBar();
|
|
|
|
Menu m = new Menu(amh.getMessage("menu.applet"));
|
|
|
|
addMenuItem(m, "menuitem.restart");
|
|
addMenuItem(m, "menuitem.reload");
|
|
addMenuItem(m, "menuitem.stop");
|
|
addMenuItem(m, "menuitem.save");
|
|
addMenuItem(m, "menuitem.start");
|
|
addMenuItem(m, "menuitem.clone");
|
|
m.add(new MenuItem("-"));
|
|
addMenuItem(m, "menuitem.tag");
|
|
addMenuItem(m, "menuitem.info");
|
|
addMenuItem(m, "menuitem.edit").disable();
|
|
addMenuItem(m, "menuitem.encoding");
|
|
m.add(new MenuItem("-"));
|
|
addMenuItem(m, "menuitem.print");
|
|
m.add(new MenuItem("-"));
|
|
addMenuItem(m, "menuitem.props");
|
|
m.add(new MenuItem("-"));
|
|
addMenuItem(m, "menuitem.close");
|
|
if (factory.isStandalone()) {
|
|
addMenuItem(m, "menuitem.quit");
|
|
}
|
|
|
|
mb.add(m);
|
|
|
|
setMenuBar(mb);
|
|
|
|
add("Center", panel = new AppletViewerPanel(doc, atts));
|
|
add("South", label = new Label(amh.getMessage("label.hello")));
|
|
panel.init();
|
|
appletPanels.addElement(panel);
|
|
|
|
pack();
|
|
move(x, y);
|
|
setVisible(true);
|
|
|
|
WindowListener windowEventListener = new WindowAdapter() {
|
|
|
|
public void windowClosing(WindowEvent evt) {
|
|
appletClose();
|
|
}
|
|
|
|
public void windowIconified(WindowEvent evt) {
|
|
appletStop();
|
|
}
|
|
|
|
public void windowDeiconified(WindowEvent evt) {
|
|
appletStart();
|
|
}
|
|
};
|
|
|
|
class AppletEventListener implements AppletListener
|
|
{
|
|
final Frame frame;
|
|
|
|
public AppletEventListener(Frame frame)
|
|
{
|
|
this.frame = frame;
|
|
}
|
|
|
|
public void appletStateChanged(AppletEvent evt)
|
|
{
|
|
AppletPanel src = (AppletPanel)evt.getSource();
|
|
|
|
switch (evt.getID()) {
|
|
case AppletPanel.APPLET_RESIZE: {
|
|
if(src != null) {
|
|
resize(preferredSize());
|
|
validate();
|
|
}
|
|
break;
|
|
}
|
|
case AppletPanel.APPLET_LOADING_COMPLETED: {
|
|
Applet a = src.getApplet(); // sun.applet.AppletPanel
|
|
|
|
// Fixed #4754451: Applet can have methods running on main
|
|
// thread event queue.
|
|
//
|
|
// The cause of this bug is that the frame of the applet
|
|
// is created in main thread group. Thus, when certain
|
|
// AWT/Swing events are generated, the events will be
|
|
// dispatched through the wrong event dispatch thread.
|
|
//
|
|
// To fix this, we rearrange the AppContext with the frame,
|
|
// so the proper event queue will be looked up.
|
|
//
|
|
// Swing also maintains a Frame list for the AppContext,
|
|
// so we will have to rearrange it as well.
|
|
//
|
|
if (a != null)
|
|
AppletPanel.changeFrameAppContext(frame, SunToolkit.targetToAppContext(a));
|
|
else
|
|
AppletPanel.changeFrameAppContext(frame, AppContext.getAppContext());
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
addWindowListener(windowEventListener);
|
|
panel.addAppletListener(new AppletEventListener(this));
|
|
|
|
// Start the applet
|
|
showStatus(amh.getMessage("status.start"));
|
|
initEventQueue();
|
|
}
|
|
|
|
// XXX 99/9/10 probably should be "private"
|
|
public MenuItem addMenuItem(Menu m, String s) {
|
|
MenuItem mItem = new MenuItem(amh.getMessage(s));
|
|
mItem.addActionListener(new UserActionListener());
|
|
return m.add(mItem);
|
|
}
|
|
|
|
/**
|
|
* Send the initial set of events to the appletviewer event queue.
|
|
* On start-up the current behaviour is to load the applet and call
|
|
* Applet.init() and Applet.start().
|
|
*/
|
|
private void initEventQueue() {
|
|
// appletviewer.send.event is an undocumented and unsupported system
|
|
// property which is used exclusively for testing purposes.
|
|
String eventList = System.getProperty("appletviewer.send.event");
|
|
|
|
if (eventList == null) {
|
|
// Add the standard events onto the event queue.
|
|
panel.sendEvent(AppletPanel.APPLET_LOAD);
|
|
panel.sendEvent(AppletPanel.APPLET_INIT);
|
|
panel.sendEvent(AppletPanel.APPLET_START);
|
|
} else {
|
|
// We're testing AppletViewer. Force the specified set of events
|
|
// onto the event queue, wait for the events to be processed, and
|
|
// exit.
|
|
|
|
// The list of events that will be executed is provided as a
|
|
// ","-separated list. No error-checking will be done on the list.
|
|
String [] events = splitSeparator(",", eventList);
|
|
|
|
for (int i = 0; i < events.length; i++) {
|
|
System.out.println("Adding event to queue: " + events[i]);
|
|
if (events[i].equals("dispose"))
|
|
panel.sendEvent(AppletPanel.APPLET_DISPOSE);
|
|
else if (events[i].equals("load"))
|
|
panel.sendEvent(AppletPanel.APPLET_LOAD);
|
|
else if (events[i].equals("init"))
|
|
panel.sendEvent(AppletPanel.APPLET_INIT);
|
|
else if (events[i].equals("start"))
|
|
panel.sendEvent(AppletPanel.APPLET_START);
|
|
else if (events[i].equals("stop"))
|
|
panel.sendEvent(AppletPanel.APPLET_STOP);
|
|
else if (events[i].equals("destroy"))
|
|
panel.sendEvent(AppletPanel.APPLET_DESTROY);
|
|
else if (events[i].equals("quit"))
|
|
panel.sendEvent(AppletPanel.APPLET_QUIT);
|
|
else if (events[i].equals("error"))
|
|
panel.sendEvent(AppletPanel.APPLET_ERROR);
|
|
else
|
|
// non-fatal error if we get an unrecognized event
|
|
System.out.println("Unrecognized event name: " + events[i]);
|
|
}
|
|
|
|
while (!panel.emptyEventQueue()) ;
|
|
appletSystemExit();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Split a string based on the presence of a specified separator. Returns
|
|
* an array of arbitrary length. The end of each element in the array is
|
|
* indicated by the separator of the end of the string. If there is a
|
|
* separator immediately before the end of the string, the final element
|
|
* will be empty. None of the strings will contain the separator. Useful
|
|
* when separating strings such as "foo/bar/bas" using separator "/".
|
|
*
|
|
* @param sep The separator.
|
|
* @param s The string to split.
|
|
* @return An array of strings. Each string in the array is determined
|
|
* by the location of the provided sep in the original string,
|
|
* s. Whitespace not stripped.
|
|
*/
|
|
private String [] splitSeparator(String sep, String s) {
|
|
Vector v = new Vector();
|
|
int tokenStart = 0;
|
|
int tokenEnd = 0;
|
|
|
|
while ((tokenEnd = s.indexOf(sep, tokenStart)) != -1) {
|
|
v.addElement(s.substring(tokenStart, tokenEnd));
|
|
tokenStart = tokenEnd+1;
|
|
}
|
|
// Add the final element.
|
|
v.addElement(s.substring(tokenStart));
|
|
|
|
String [] retVal = new String[v.size()];
|
|
v.copyInto(retVal);
|
|
return retVal;
|
|
}
|
|
|
|
/*
|
|
* Methods for java.applet.AppletContext
|
|
*/
|
|
|
|
private static Map audioClips = new HashMap();
|
|
|
|
/**
|
|
* Get an audio clip.
|
|
*/
|
|
public AudioClip getAudioClip(URL url) {
|
|
checkConnect(url);
|
|
synchronized (audioClips) {
|
|
AudioClip clip = (AudioClip)audioClips.get(url);
|
|
if (clip == null) {
|
|
audioClips.put(url, clip = new AppletAudioClip(url));
|
|
}
|
|
return clip;
|
|
}
|
|
}
|
|
|
|
private static Map imageRefs = new HashMap();
|
|
|
|
/**
|
|
* Get an image.
|
|
*/
|
|
public Image getImage(URL url) {
|
|
return getCachedImage(url);
|
|
}
|
|
|
|
static Image getCachedImage(URL url) {
|
|
// System.getSecurityManager().checkConnection(url.getHost(), url.getPort());
|
|
return (Image)getCachedImageRef(url).get();
|
|
}
|
|
|
|
/**
|
|
* Get an image ref.
|
|
*/
|
|
static Ref getCachedImageRef(URL url) {
|
|
synchronized (imageRefs) {
|
|
AppletImageRef ref = (AppletImageRef)imageRefs.get(url);
|
|
if (ref == null) {
|
|
ref = new AppletImageRef(url);
|
|
imageRefs.put(url, ref);
|
|
}
|
|
return ref;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Flush the image cache.
|
|
*/
|
|
static void flushImageCache() {
|
|
imageRefs.clear();
|
|
}
|
|
|
|
static Vector appletPanels = new Vector();
|
|
|
|
/**
|
|
* Get an applet by name.
|
|
*/
|
|
public Applet getApplet(String name) {
|
|
AppletSecurity security = (AppletSecurity)System.getSecurityManager();
|
|
name = name.toLowerCase();
|
|
SocketPermission panelSp =
|
|
new SocketPermission(panel.getCodeBase().getHost(), "connect");
|
|
for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) {
|
|
AppletPanel p = (AppletPanel)e.nextElement();
|
|
String param = p.getParameter("name");
|
|
if (param != null) {
|
|
param = param.toLowerCase();
|
|
}
|
|
if (name.equals(param) &&
|
|
p.getDocumentBase().equals(panel.getDocumentBase())) {
|
|
|
|
SocketPermission sp =
|
|
new SocketPermission(p.getCodeBase().getHost(), "connect");
|
|
|
|
if (panelSp.implies(sp)) {
|
|
return p.applet;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Return an enumeration of all the accessible
|
|
* applets on this page.
|
|
*/
|
|
public Enumeration getApplets() {
|
|
AppletSecurity security = (AppletSecurity)System.getSecurityManager();
|
|
Vector v = new Vector();
|
|
SocketPermission panelSp =
|
|
new SocketPermission(panel.getCodeBase().getHost(), "connect");
|
|
|
|
for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) {
|
|
AppletPanel p = (AppletPanel)e.nextElement();
|
|
if (p.getDocumentBase().equals(panel.getDocumentBase())) {
|
|
|
|
SocketPermission sp =
|
|
new SocketPermission(p.getCodeBase().getHost(), "connect");
|
|
if (panelSp.implies(sp)) {
|
|
v.addElement(p.applet);
|
|
}
|
|
}
|
|
}
|
|
return v.elements();
|
|
}
|
|
|
|
/**
|
|
* Ignore.
|
|
*/
|
|
public void showDocument(URL url) {
|
|
}
|
|
|
|
/**
|
|
* Ignore.
|
|
*/
|
|
public void showDocument(URL url, String target) {
|
|
}
|
|
|
|
/**
|
|
* Show status.
|
|
*/
|
|
public void showStatus(String status) {
|
|
label.setText(status);
|
|
}
|
|
|
|
public void setStream(String key, InputStream stream)throws IOException{
|
|
// We do nothing.
|
|
}
|
|
|
|
public InputStream getStream(String key){
|
|
// We do nothing.
|
|
return null;
|
|
}
|
|
|
|
public Iterator getStreamKeys(){
|
|
// We do nothing.
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* System parameters.
|
|
*/
|
|
static Hashtable systemParam = new Hashtable();
|
|
|
|
static {
|
|
systemParam.put("codebase", "codebase");
|
|
systemParam.put("code", "code");
|
|
systemParam.put("alt", "alt");
|
|
systemParam.put("width", "width");
|
|
systemParam.put("height", "height");
|
|
systemParam.put("align", "align");
|
|
systemParam.put("vspace", "vspace");
|
|
systemParam.put("hspace", "hspace");
|
|
}
|
|
|
|
/**
|
|
* Print the HTML tag.
|
|
*/
|
|
public static void printTag(PrintStream out, Hashtable atts) {
|
|
out.print("<applet");
|
|
|
|
String v = (String)atts.get("codebase");
|
|
if (v != null) {
|
|
out.print(" codebase=\"" + v + "\"");
|
|
}
|
|
|
|
v = (String)atts.get("code");
|
|
if (v == null) {
|
|
v = "applet.class";
|
|
}
|
|
out.print(" code=\"" + v + "\"");
|
|
v = (String)atts.get("width");
|
|
if (v == null) {
|
|
v = "150";
|
|
}
|
|
out.print(" width=" + v);
|
|
|
|
v = (String)atts.get("height");
|
|
if (v == null) {
|
|
v = "100";
|
|
}
|
|
out.print(" height=" + v);
|
|
|
|
v = (String)atts.get("name");
|
|
if (v != null) {
|
|
out.print(" name=\"" + v + "\"");
|
|
}
|
|
out.println(">");
|
|
|
|
// A very slow sorting algorithm
|
|
int len = atts.size();
|
|
String params[] = new String[len];
|
|
len = 0;
|
|
for (Enumeration e = atts.keys() ; e.hasMoreElements() ;) {
|
|
String param = (String)e.nextElement();
|
|
int i = 0;
|
|
for (; i < len ; i++) {
|
|
if (params[i].compareTo(param) >= 0) {
|
|
break;
|
|
}
|
|
}
|
|
System.arraycopy(params, i, params, i + 1, len - i);
|
|
params[i] = param;
|
|
len++;
|
|
}
|
|
|
|
for (int i = 0 ; i < len ; i++) {
|
|
String param = params[i];
|
|
if (systemParam.get(param) == null) {
|
|
out.println("<param name=" + param +
|
|
" value=\"" + atts.get(param) + "\">");
|
|
}
|
|
}
|
|
out.println("</applet>");
|
|
}
|
|
|
|
/**
|
|
* Make sure the atrributes are uptodate.
|
|
*/
|
|
public void updateAtts() {
|
|
Dimension d = panel.size();
|
|
Insets in = panel.insets();
|
|
panel.atts.put("width",
|
|
new Integer(d.width - (in.left + in.right)).toString());
|
|
panel.atts.put("height",
|
|
new Integer(d.height - (in.top + in.bottom)).toString());
|
|
}
|
|
|
|
/**
|
|
* Restart the applet.
|
|
*/
|
|
void appletRestart() {
|
|
panel.sendEvent(AppletPanel.APPLET_STOP);
|
|
panel.sendEvent(AppletPanel.APPLET_DESTROY);
|
|
panel.sendEvent(AppletPanel.APPLET_INIT);
|
|
panel.sendEvent(AppletPanel.APPLET_START);
|
|
}
|
|
|
|
/**
|
|
* Reload the applet.
|
|
*/
|
|
void appletReload() {
|
|
panel.sendEvent(AppletPanel.APPLET_STOP);
|
|
panel.sendEvent(AppletPanel.APPLET_DESTROY);
|
|
/* panel.sendEvent(AppletPanel.APPLET_DISPOSE); */
|
|
|
|
/**
|
|
* Fixed #4501142: Classlaoder sharing policy doesn't
|
|
* take "archive" into account. This will be overridden
|
|
* by Java Plug-in. [stanleyh]
|
|
*/
|
|
/* AppletPanel.flushClassLoader(panel.getClassLoaderCacheKey()); */
|
|
|
|
/*
|
|
* Make sure we don't have two threads running through the event queue
|
|
* at the same time.
|
|
*/
|
|
/* try {
|
|
panel.joinAppletThread();
|
|
panel.release();
|
|
} catch (InterruptedException e) {
|
|
return; // abort the reload
|
|
}
|
|
|
|
panel.createAppletThread(); */
|
|
panel.sendEvent(AppletPanel.APPLET_LOAD);
|
|
panel.sendEvent(AppletPanel.APPLET_INIT);
|
|
panel.sendEvent(AppletPanel.APPLET_START);
|
|
}
|
|
|
|
/**
|
|
* Save the applet to a well known file (for now) as a serialized object
|
|
*/
|
|
void appletSave() {
|
|
AccessController.doPrivileged(new PrivilegedAction() {
|
|
|
|
public Object run() {
|
|
// XXX: this privileged block should be made smaller
|
|
// by initializing a private static variable with "user.dir"
|
|
|
|
// Applet needs to be stopped for serialization to succeed.
|
|
// Since panel.sendEvent only queues the event, there is a
|
|
// chance that the event will not be processed before
|
|
// serialization begins. However, by sending the event before
|
|
// FileDialog is created, enough time is given such that this
|
|
// situation is unlikely to ever occur.
|
|
|
|
panel.sendEvent(AppletPanel.APPLET_STOP);
|
|
FileDialog fd = new FileDialog(AppletViewer.this,
|
|
amh.getMessage("appletsave.filedialogtitle"),
|
|
FileDialog.SAVE);
|
|
// needed for a bug under Solaris...
|
|
fd.setDirectory(System.getProperty("user.dir"));
|
|
fd.setFile(defaultSaveFile);
|
|
fd.show();
|
|
String fname = fd.getFile();
|
|
if (fname == null) {
|
|
// Restart applet if Save is cancelled.
|
|
panel.sendEvent(AppletPanel.APPLET_START);
|
|
return null; // cancelled
|
|
}
|
|
String dname = fd.getDirectory();
|
|
File file = new File(dname, fname);
|
|
|
|
try {
|
|
BufferedOutputStream s = new BufferedOutputStream(new FileOutputStream(file));
|
|
ObjectOutputStream os = new ObjectOutputStream(s);
|
|
showStatus(amh.getMessage("appletsave.err1",
|
|
panel.applet.toString(), file.toString()));
|
|
os.writeObject(panel.applet);
|
|
} catch (IOException ex) {
|
|
System.err.println(amh.getMessage("appletsave.err2", ex));
|
|
} finally {
|
|
panel.sendEvent(AppletPanel.APPLET_START);
|
|
}
|
|
return null;
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Clone the viewer and the applet.
|
|
*/
|
|
void appletClone() {
|
|
Point p = location();
|
|
updateAtts();
|
|
factory.createAppletViewer(p.x + XDELTA, p.y + YDELTA,
|
|
panel.documentURL, (Hashtable)panel.atts.clone());
|
|
}
|
|
|
|
/**
|
|
* Show the applet tag.
|
|
*/
|
|
void appletTag() {
|
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
updateAtts();
|
|
printTag(new PrintStream(out), panel.atts);
|
|
showStatus(amh.getMessage("applettag"));
|
|
|
|
Point p = location();
|
|
new TextFrame(p.x + XDELTA, p.y + YDELTA, amh.getMessage("applettag.textframe"), out.toString());
|
|
}
|
|
|
|
/**
|
|
* Show the applet info.
|
|
*/
|
|
void appletInfo() {
|
|
String str = panel.applet.getAppletInfo();
|
|
if (str == null) {
|
|
str = amh.getMessage("appletinfo.applet");
|
|
}
|
|
str += "\n\n";
|
|
|
|
String atts[][] = panel.applet.getParameterInfo();
|
|
if (atts != null) {
|
|
for (int i = 0 ; i < atts.length ; i++) {
|
|
str += atts[i][0] + " -- " + atts[i][1] + " -- " + atts[i][2] + "\n";
|
|
}
|
|
} else {
|
|
str += amh.getMessage("appletinfo.param");
|
|
}
|
|
|
|
Point p = location();
|
|
new TextFrame(p.x + XDELTA, p.y + YDELTA, amh.getMessage("appletinfo.textframe"), str);
|
|
|
|
}
|
|
|
|
/**
|
|
* Show character encoding type
|
|
*/
|
|
void appletCharacterEncoding() {
|
|
showStatus(amh.getMessage("appletencoding", encoding));
|
|
}
|
|
|
|
/**
|
|
* Edit the applet.
|
|
*/
|
|
void appletEdit() {
|
|
}
|
|
|
|
/**
|
|
* Print the applet.
|
|
*/
|
|
void appletPrint() {
|
|
PrinterJob pj = PrinterJob.getPrinterJob();
|
|
|
|
if (pj != null) {
|
|
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
|
|
if (pj.printDialog(aset)) {
|
|
pj.setPrintable(this);
|
|
try {
|
|
pj.print(aset);
|
|
statusMsgStream.println(amh.getMessage("appletprint.finish"));
|
|
} catch (PrinterException e) {
|
|
statusMsgStream.println(amh.getMessage("appletprint.fail"));
|
|
}
|
|
} else {
|
|
statusMsgStream.println(amh.getMessage("appletprint.cancel"));
|
|
}
|
|
} else {
|
|
statusMsgStream.println(amh.getMessage("appletprint.fail"));
|
|
}
|
|
}
|
|
|
|
public int print(Graphics graphics, PageFormat pf, int pageIndex) {
|
|
if (pageIndex > 0) {
|
|
return Printable.NO_SUCH_PAGE;
|
|
} else {
|
|
Graphics2D g2d = (Graphics2D)graphics;
|
|
g2d.translate(pf.getImageableX(), pf.getImageableY());
|
|
panel.applet.printAll(graphics);
|
|
return Printable.PAGE_EXISTS;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Properties.
|
|
*/
|
|
static AppletProps props;
|
|
public static synchronized void networkProperties() {
|
|
if (props == null) {
|
|
props = new AppletProps();
|
|
}
|
|
props.addNotify();
|
|
props.setVisible(true);
|
|
}
|
|
|
|
/**
|
|
* Start the applet.
|
|
*/
|
|
void appletStart() {
|
|
panel.sendEvent(AppletPanel.APPLET_START);
|
|
}
|
|
|
|
/**
|
|
* Stop the applet.
|
|
*/
|
|
void appletStop() {
|
|
panel.sendEvent(AppletPanel.APPLET_STOP);
|
|
}
|
|
|
|
/**
|
|
* Shutdown a viewer.
|
|
* Stop, Destroy, Dispose and Quit a viewer
|
|
*/
|
|
private void appletShutdown(AppletPanel p) {
|
|
p.sendEvent(AppletPanel.APPLET_STOP);
|
|
p.sendEvent(AppletPanel.APPLET_DESTROY);
|
|
p.sendEvent(AppletPanel.APPLET_DISPOSE);
|
|
p.sendEvent(AppletPanel.APPLET_QUIT);
|
|
}
|
|
|
|
/**
|
|
* Close this viewer.
|
|
* Stop, Destroy, Dispose and Quit an AppletView, then
|
|
* reclaim resources and exit the program if this is
|
|
* the last applet.
|
|
*/
|
|
void appletClose() {
|
|
|
|
// The caller thread is event dispatch thread, so
|
|
// spawn a new thread to avoid blocking the event queue
|
|
// when calling appletShutdown.
|
|
//
|
|
final AppletPanel p = panel;
|
|
|
|
new Thread(new Runnable()
|
|
{
|
|
public void run()
|
|
{
|
|
appletShutdown(p);
|
|
appletPanels.removeElement(p);
|
|
dispose();
|
|
|
|
if (countApplets() == 0) {
|
|
appletSystemExit();
|
|
}
|
|
}
|
|
}).start();
|
|
}
|
|
|
|
/**
|
|
* Exit the program.
|
|
* Exit from the program (if not stand alone) - do no clean-up
|
|
*/
|
|
private void appletSystemExit() {
|
|
if (factory.isStandalone())
|
|
System.exit(0);
|
|
}
|
|
|
|
/**
|
|
* Quit all viewers.
|
|
* Shutdown all viewers properly then
|
|
* exit from the program (if not stand alone)
|
|
*/
|
|
protected void appletQuit()
|
|
{
|
|
// The caller thread is event dispatch thread, so
|
|
// spawn a new thread to avoid blocking the event queue
|
|
// when calling appletShutdown.
|
|
//
|
|
new Thread(new Runnable()
|
|
{
|
|
public void run()
|
|
{
|
|
for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) {
|
|
AppletPanel p = (AppletPanel)e.nextElement();
|
|
appletShutdown(p);
|
|
}
|
|
appletSystemExit();
|
|
}
|
|
}).start();
|
|
}
|
|
|
|
/**
|
|
* Handle events.
|
|
*/
|
|
public void processUserAction(ActionEvent evt) {
|
|
|
|
String label = ((MenuItem)evt.getSource()).getLabel();
|
|
|
|
if (amh.getMessage("menuitem.restart").equals(label)) {
|
|
appletRestart();
|
|
return;
|
|
}
|
|
|
|
if (amh.getMessage("menuitem.reload").equals(label)) {
|
|
appletReload();
|
|
return;
|
|
}
|
|
|
|
if (amh.getMessage("menuitem.clone").equals(label)) {
|
|
appletClone();
|
|
return;
|
|
}
|
|
|
|
if (amh.getMessage("menuitem.stop").equals(label)) {
|
|
appletStop();
|
|
return;
|
|
}
|
|
|
|
if (amh.getMessage("menuitem.save").equals(label)) {
|
|
appletSave();
|
|
return;
|
|
}
|
|
|
|
if (amh.getMessage("menuitem.start").equals(label)) {
|
|
appletStart();
|
|
return;
|
|
}
|
|
|
|
if (amh.getMessage("menuitem.tag").equals(label)) {
|
|
appletTag();
|
|
return;
|
|
}
|
|
|
|
if (amh.getMessage("menuitem.info").equals(label)) {
|
|
appletInfo();
|
|
return;
|
|
}
|
|
|
|
if (amh.getMessage("menuitem.encoding").equals(label)) {
|
|
appletCharacterEncoding();
|
|
return;
|
|
}
|
|
|
|
if (amh.getMessage("menuitem.edit").equals(label)) {
|
|
appletEdit();
|
|
return;
|
|
}
|
|
|
|
if (amh.getMessage("menuitem.print").equals(label)) {
|
|
appletPrint();
|
|
return;
|
|
}
|
|
|
|
if (amh.getMessage("menuitem.props").equals(label)) {
|
|
networkProperties();
|
|
return;
|
|
}
|
|
|
|
if (amh.getMessage("menuitem.close").equals(label)) {
|
|
appletClose();
|
|
return;
|
|
}
|
|
|
|
if (factory.isStandalone() && amh.getMessage("menuitem.quit").equals(label)) {
|
|
appletQuit();
|
|
return;
|
|
}
|
|
//statusMsgStream.println("evt = " + evt);
|
|
}
|
|
|
|
/**
|
|
* How many applets are running?
|
|
*/
|
|
|
|
public static int countApplets() {
|
|
return appletPanels.size();
|
|
}
|
|
|
|
|
|
/**
|
|
* The current character.
|
|
*/
|
|
static int c;
|
|
|
|
/**
|
|
* Scan spaces.
|
|
*/
|
|
public static void skipSpace(Reader in) throws IOException {
|
|
while ((c >= 0) &&
|
|
((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r'))) {
|
|
c = in.read();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Scan identifier
|
|
*/
|
|
public static String scanIdentifier(Reader in) throws IOException {
|
|
StringBuffer buf = new StringBuffer();
|
|
while (true) {
|
|
if (((c >= 'a') && (c <= 'z')) ||
|
|
((c >= 'A') && (c <= 'Z')) ||
|
|
((c >= '0') && (c <= '9')) || (c == '_')) {
|
|
buf.append((char)c);
|
|
c = in.read();
|
|
} else {
|
|
return buf.toString();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Scan tag
|
|
*/
|
|
public static Hashtable scanTag(Reader in) throws IOException {
|
|
Hashtable atts = new Hashtable();
|
|
skipSpace(in);
|
|
while (c >= 0 && c != '>') {
|
|
String att = scanIdentifier(in);
|
|
String val = "";
|
|
skipSpace(in);
|
|
if (c == '=') {
|
|
int quote = -1;
|
|
c = in.read();
|
|
skipSpace(in);
|
|
if ((c == '\'') || (c == '\"')) {
|
|
quote = c;
|
|
c = in.read();
|
|
}
|
|
StringBuffer buf = new StringBuffer();
|
|
while ((c > 0) &&
|
|
(((quote < 0) && (c != ' ') && (c != '\t') &&
|
|
(c != '\n') && (c != '\r') && (c != '>'))
|
|
|| ((quote >= 0) && (c != quote)))) {
|
|
buf.append((char)c);
|
|
c = in.read();
|
|
}
|
|
if (c == quote) {
|
|
c = in.read();
|
|
}
|
|
skipSpace(in);
|
|
val = buf.toString();
|
|
}
|
|
//statusMsgStream.println("PUT " + att + " = '" + val + "'");
|
|
if (! val.equals("")) {
|
|
atts.put(att.toLowerCase(java.util.Locale.ENGLISH), val);
|
|
}
|
|
while (true) {
|
|
if ((c == '>') || (c < 0) ||
|
|
((c >= 'a') && (c <= 'z')) ||
|
|
((c >= 'A') && (c <= 'Z')) ||
|
|
((c >= '0') && (c <= '9')) || (c == '_'))
|
|
break;
|
|
c = in.read();
|
|
}
|
|
//skipSpace(in);
|
|
}
|
|
return atts;
|
|
}
|
|
|
|
/* values used for placement of AppletViewer's frames */
|
|
private static int x = 0;
|
|
private static int y = 0;
|
|
private static final int XDELTA = 30;
|
|
private static final int YDELTA = XDELTA;
|
|
|
|
static String encoding = null;
|
|
|
|
static private Reader makeReader(InputStream is) {
|
|
if (encoding != null) {
|
|
try {
|
|
return new BufferedReader(new InputStreamReader(is, encoding));
|
|
} catch (IOException x) { }
|
|
}
|
|
InputStreamReader r = new InputStreamReader(is);
|
|
encoding = r.getEncoding();
|
|
return new BufferedReader(r);
|
|
}
|
|
|
|
/**
|
|
* Scan an html file for <applet> tags
|
|
*/
|
|
public static void parse(URL url, String enc) throws IOException {
|
|
encoding = enc;
|
|
parse(url, System.out, new StdAppletViewerFactory());
|
|
}
|
|
|
|
public static void parse(URL url) throws IOException {
|
|
parse(url, System.out, new StdAppletViewerFactory());
|
|
}
|
|
|
|
public static void parse(URL url, PrintStream statusMsgStream,
|
|
AppletViewerFactory factory) throws IOException {
|
|
// <OBJECT> <EMBED> tag flags
|
|
boolean isAppletTag = false;
|
|
boolean isObjectTag = false;
|
|
boolean isEmbedTag = false;
|
|
|
|
// warning messages
|
|
String requiresNameWarning = amh.getMessage("parse.warning.requiresname");
|
|
String paramOutsideWarning = amh.getMessage("parse.warning.paramoutside");
|
|
String appletRequiresCodeWarning = amh.getMessage("parse.warning.applet.requirescode");
|
|
String appletRequiresHeightWarning = amh.getMessage("parse.warning.applet.requiresheight");
|
|
String appletRequiresWidthWarning = amh.getMessage("parse.warning.applet.requireswidth");
|
|
String objectRequiresCodeWarning = amh.getMessage("parse.warning.object.requirescode");
|
|
String objectRequiresHeightWarning = amh.getMessage("parse.warning.object.requiresheight");
|
|
String objectRequiresWidthWarning = amh.getMessage("parse.warning.object.requireswidth");
|
|
String embedRequiresCodeWarning = amh.getMessage("parse.warning.embed.requirescode");
|
|
String embedRequiresHeightWarning = amh.getMessage("parse.warning.embed.requiresheight");
|
|
String embedRequiresWidthWarning = amh.getMessage("parse.warning.embed.requireswidth");
|
|
String appNotLongerSupportedWarning = amh.getMessage("parse.warning.appnotLongersupported");
|
|
|
|
java.net.URLConnection conn = url.openConnection();
|
|
Reader in = makeReader(conn.getInputStream());
|
|
/* The original URL may have been redirected - this
|
|
* sets it to whatever URL/codebase we ended up getting
|
|
*/
|
|
url = conn.getURL();
|
|
|
|
int ydisp = 1;
|
|
Hashtable atts = null;
|
|
|
|
while(true) {
|
|
c = in.read();
|
|
if (c == -1)
|
|
break;
|
|
|
|
if (c == '<') {
|
|
c = in.read();
|
|
if (c == '/') {
|
|
c = in.read();
|
|
String nm = scanIdentifier(in);
|
|
if (nm.equalsIgnoreCase("applet") ||
|
|
nm.equalsIgnoreCase("object") ||
|
|
nm.equalsIgnoreCase("embed")) {
|
|
|
|
// We can't test for a code tag until </OBJECT>
|
|
// because it is a parameter, not an attribute.
|
|
if(isObjectTag) {
|
|
if (atts.get("code") == null && atts.get("object") == null) {
|
|
statusMsgStream.println(objectRequiresCodeWarning);
|
|
atts = null;
|
|
}
|
|
}
|
|
|
|
if (atts != null) {
|
|
// XXX 5/18 In general this code just simply
|
|
// shouldn't be part of parsing. It's presence
|
|
// causes things to be a little too much of a
|
|
// hack.
|
|
factory.createAppletViewer(x, y, url, atts);
|
|
x += XDELTA;
|
|
y += YDELTA;
|
|
// make sure we don't go too far!
|
|
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
|
|
if ((x > d.width - 300) || (y > d.height - 300)) {
|
|
x = 0;
|
|
y = 2 * ydisp * YDELTA;
|
|
ydisp++;
|
|
}
|
|
}
|
|
atts = null;
|
|
isAppletTag = false;
|
|
isObjectTag = false;
|
|
isEmbedTag = false;
|
|
}
|
|
}
|
|
else {
|
|
String nm = scanIdentifier(in);
|
|
if (nm.equalsIgnoreCase("param")) {
|
|
Hashtable t = scanTag(in);
|
|
String att = (String)t.get("name");
|
|
if (att == null) {
|
|
statusMsgStream.println(requiresNameWarning);
|
|
} else {
|
|
String val = (String)t.get("value");
|
|
if (val == null) {
|
|
statusMsgStream.println(requiresNameWarning);
|
|
} else if (atts != null) {
|
|
atts.put(att.toLowerCase(), val);
|
|
} else {
|
|
statusMsgStream.println(paramOutsideWarning);
|
|
}
|
|
}
|
|
}
|
|
else if (nm.equalsIgnoreCase("applet")) {
|
|
isAppletTag = true;
|
|
atts = scanTag(in);
|
|
if (atts.get("code") == null && atts.get("object") == null) {
|
|
statusMsgStream.println(appletRequiresCodeWarning);
|
|
atts = null;
|
|
} else if (atts.get("width") == null) {
|
|
statusMsgStream.println(appletRequiresWidthWarning);
|
|
atts = null;
|
|
} else if (atts.get("height") == null) {
|
|
statusMsgStream.println(appletRequiresHeightWarning);
|
|
atts = null;
|
|
}
|
|
}
|
|
else if (nm.equalsIgnoreCase("object")) {
|
|
isObjectTag = true;
|
|
atts = scanTag(in);
|
|
// The <OBJECT> attribute codebase isn't what
|
|
// we want. If its defined, remove it.
|
|
if(atts.get("codebase") != null) {
|
|
atts.remove("codebase");
|
|
}
|
|
|
|
if (atts.get("width") == null) {
|
|
statusMsgStream.println(objectRequiresWidthWarning);
|
|
atts = null;
|
|
} else if (atts.get("height") == null) {
|
|
statusMsgStream.println(objectRequiresHeightWarning);
|
|
atts = null;
|
|
}
|
|
}
|
|
else if (nm.equalsIgnoreCase("embed")) {
|
|
isEmbedTag = true;
|
|
atts = scanTag(in);
|
|
|
|
if (atts.get("code") == null && atts.get("object") == null) {
|
|
statusMsgStream.println(embedRequiresCodeWarning);
|
|
atts = null;
|
|
} else if (atts.get("width") == null) {
|
|
statusMsgStream.println(embedRequiresWidthWarning);
|
|
atts = null;
|
|
} else if (atts.get("height") == null) {
|
|
statusMsgStream.println(embedRequiresHeightWarning);
|
|
atts = null;
|
|
}
|
|
}
|
|
else if (nm.equalsIgnoreCase("app")) {
|
|
statusMsgStream.println(appNotLongerSupportedWarning);
|
|
Hashtable atts2 = scanTag(in);
|
|
nm = (String)atts2.get("class");
|
|
if (nm != null) {
|
|
atts2.remove("class");
|
|
atts2.put("code", nm + ".class");
|
|
}
|
|
nm = (String)atts2.get("src");
|
|
if (nm != null) {
|
|
atts2.remove("src");
|
|
atts2.put("codebase", nm);
|
|
}
|
|
if (atts2.get("width") == null) {
|
|
atts2.put("width", "100");
|
|
}
|
|
if (atts2.get("height") == null) {
|
|
atts2.put("height", "100");
|
|
}
|
|
printTag(statusMsgStream, atts2);
|
|
statusMsgStream.println();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
in.close();
|
|
}
|
|
|
|
/**
|
|
* Old main entry point.
|
|
*
|
|
* @deprecated
|
|
*/
|
|
public static void main(String argv[]) {
|
|
// re-route everything to the new main entry point
|
|
Main.main(argv);
|
|
}
|
|
|
|
private static AppletMessageHandler amh = new AppletMessageHandler("appletviewer");
|
|
|
|
private static void checkConnect(URL url)
|
|
{
|
|
SecurityManager security = System.getSecurityManager();
|
|
if (security != null) {
|
|
try {
|
|
java.security.Permission perm =
|
|
url.openConnection().getPermission();
|
|
if (perm != null)
|
|
security.checkPermission(perm);
|
|
else
|
|
security.checkConnect(url.getHost(), url.getPort());
|
|
} catch (java.io.IOException ioe) {
|
|
security.checkConnect(url.getHost(), url.getPort());
|
|
}
|
|
}
|
|
}
|
|
}
|