/**************************************************************************
* Copyright (c) 2001 by Acunia N.V. All rights reserved. *
* *
* This software is copyrighted by and is the sole property of Acunia N.V. *
* and its licensors, if any. All rights, title, ownership, or other *
* interests in the software remain the property of Acunia N.V. and its *
* licensors, if any. *
* *
* This software may only be used in accordance with the corresponding *
* license agreement. Any unauthorized use, duplication, transmission, *
* distribution or disclosure of this software is expressly forbidden. *
* *
* This Copyright notice may not be removed or modified without prior *
* written consent of Acunia N.V. *
* *
* Acunia N.V. reserves the right to modify this software without notice. *
* *
* Acunia N.V. *
* Vanden Tymplestraat 35 info@acunia.com *
* 3000 Leuven http://www.acunia.com *
* Belgium - EUROPE *
**************************************************************************/
package com.acunia.wonka.appletviewer;
import java.applet.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.*;
import java.net.*;
import java.util.*;
public class AppletViewer extends Frame implements ActionListener, AppletStub, AppletContext, AudioClip {
private static Toolkit toolkit = Toolkit.getDefaultToolkit();
private static Hashtable applets = new Hashtable(17);
private static String encoding = "8859_1";
private static int counter = 1;
private URL codebase;
private URL documentbase;
private Class appletClass;
private Properties parameters;
private boolean active;
private String align = null;
Applet applet;
int hspace;
int vspace;
int appletH = 234;
int appletW = 400;
//GUI elements ...
private Label status;
private Button start;
private Button stop;
private Button destroy;
private Panel buttons;
//end GUI elements ...
private AppletViewer(String location) throws Exception {
super("AppletViewer");
setupAppletData(location);
start = new Button("start");
start.addActionListener(this);
stop = new Button("stop");
stop.addActionListener(this);
destroy = new Button("destroy");
destroy.addActionListener(this);
buttons = new Panel(new GridLayout(3,1));
buttons.add(start);
buttons.add(stop);
buttons.add(destroy);
this.add(buttons, BorderLayout.EAST);
status = new Label(applet.getName());
this.add(status,BorderLayout.SOUTH);
this.setTitle("AppletViewer: '"+applet.getName()+"'");
this.add(new WrapperPanel(this),BorderLayout.CENTER);
this.setFrameSize();
}
// ActionListener API ...
public void actionPerformed(ActionEvent event){
Object button = event.getSource();
if(button == start){
active = true;
applet.start();
}
else if(button == stop){
active = false;
applet.stop();
}
else if(button == destroy){
active = false;
applet.stop();
applet.destroy();
this.dispose();
}
}
// end ActionListener.
//AppletContext API ...
public Applet getApplet(String name){
return (Applet)applets.get(name);
}
public Enumeration getApplets(){
return applets.elements();
}
public AudioClip getAudioClip(URL url){
return this;
}
public Image getImage(URL url){
return toolkit.createImage(url);
}
public void showDocument(URL url) {
System.err.println("showDocument is called "+url);
//TODO ...
throw new UnsupportedOperationException("'showDocument(URL url)' is not supported");
}
public void showDocument(URL url, String frame){
try {
showDocument(new URL(url,frame));
}
catch(MalformedURLException murle){}
}
public void showStatus(String msg){
System.out.println("showStatus: "+msg);
status.setText(msg);
}
// end AppletContext.
//AppletStub API ...
public void appletResize(int width, int height){
//System.out.println("appletResize is called for "+applet+" w = "+width+", h = "+height);
if(width > 0 && height > 0){
appletW = width;
appletH = height;
setFrameSize();
}
}
public AppletContext getAppletContext(){
return this;
}
public URL getCodeBase(){
return codebase;
}
public URL getDocumentBase(){
return documentbase;
}
public String getParameter(String name){
return parameters.getProperty(name);
}
public boolean isActive(){
return active;
}
// end AppletStub.
//AudioClip API ...
public void play(){}
public void stop(){}
public void loop(){}
// end AudioClip
private void readParams(String page){
String lowerCasePage = page.toLowerCase();
parameters = new Properties();
try {
int i = lowerCasePage.indexOf("param name=");
while (i != -1){
i += 11;
int j = lowerCasePage.indexOf("value=",i);
String name = unquoteString(page.substring(i,j).trim());
j += 6;
i = lowerCasePage.indexOf('>',j);
parameters.setProperty(name, unquoteString(page.substring(j,i).trim()));
i = lowerCasePage.indexOf("param name=", i);
}
}
catch(RuntimeException e){
e.printStackTrace();
}
}
private void setFrameSize(){
int width = appletW + buttons.getPreferredSize().width + 2 * hspace;
int height = appletH + status.getPreferredSize().height + 2 * vspace;
this.setSize(width,height);
}
private void setupAppletData(String location) throws Exception {
try {
documentbase = new URL(location);
}
catch(MalformedURLException mue){
documentbase = new URL(new File("").toURL(), location);
}
InputStream in = documentbase.openStream();
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] bytes = new byte[4096];
int len = in.read(bytes);
while(len != -1){
out.write(bytes, 0, len);
len = in.read(bytes);
}
String content = new String(out.toByteArray(),encoding);
String base = documentbase.getFile();
int index = base.lastIndexOf('/');
if(index != -1){
base = base.substring(0,index+1);
}
documentbase = new URL(documentbase.getProtocol(), documentbase.getHost(), base);
//lets parse the content off the html page ...
index = content.indexOf("<applet");
int end = -1;
int close = -1;
if(index != -1){
end = content.indexOf("</applet>", index);
close = content.indexOf(">", index);
}
else {
index = content.indexOf("<APPLET");
if(index != -1){
end = content.indexOf("</APPLET>", index);
close = content.indexOf(">", index);
}
else {
throw new IllegalArgumentException("no applet specified in html code");
}
}
if(end < close || close == -1 || end == -1){
throw new IllegalArgumentException("bad html syntax encountered");
}
String code = null;
String archive = null;
String cb = null;
String name = null;
StringTokenizer st = new StringTokenizer(content.substring(index+7,close));
while(st.hasMoreTokens()){
String token = st.nextToken();
index = token.indexOf('=');
if(index == -1){
System.err.println("AppletViewer: bad token encountered '"+token+"'");
continue;
}
String option = token.substring(0,index);
if(option.equalsIgnoreCase("code")){
code = unquoteString(token.substring(index+1));
if(code.endsWith(".class")){
code = code.substring(0,code.length()-6);
}
}
else if(option.equalsIgnoreCase("archive")){
archive = unquoteString(token.substring(index+1));
while(archive.endsWith(",") && st.hasMoreTokens()){
archive = archive + st.nextToken();
}
}
else if(option.equalsIgnoreCase("name")){
name = unquoteString(token.substring(index+1));
}
else if(option.equalsIgnoreCase("codebase")){
cb = unquoteString(token.substring(index+1));
}
else if(option.equalsIgnoreCase("width")){
try {
int value = Integer.parseInt(unquoteString(token.substring(index+1)));
if(value > 0){
appletW = value;
}
}
catch(RuntimeException rt){}
}
else if(option.equalsIgnoreCase("height")){
try {
int value = Integer.parseInt(unquoteString(token.substring(index+1)));
if(value > 0){
appletH= value;
}
}
catch(RuntimeException rt){}
}
else if(option.equalsIgnoreCase("vspace")){
try {
int value = Integer.parseInt(unquoteString(token.substring(index+1)));
if(value > 0){
vspace = value;
}
}
catch(RuntimeException rt){}
}
else if(option.equalsIgnoreCase("hspace")){
try {
int value = Integer.parseInt(unquoteString(token.substring(index+1)));
if(value > 0){
hspace = value;
}
}
catch(RuntimeException rt){}
}
else if(option.equalsIgnoreCase("align")){
align = unquoteString(token.substring(index+1));
//TODO ... do alignment !
}
}
readParams(content.substring(close,end));
codebase = (cb != null) ? new URL(documentbase, cb) : documentbase;
AppletClassLoader loader = AppletClassLoader.createAppletClassLoader(codebase, documentbase, archive);
appletClass = Class.forName(code, true, loader);
applet = (Applet) appletClass.newInstance();
/**
** we make the applet invisible. This will prevent the paint method to be called before init is called.
*/
applet.setVisible(false);
applet.setStub(this);
if (name == null){
name = "applet nr "+counter+" of type "+appletClass;
counter++;
}
applet.setName(name);
applets.put(applet.getName(),applet);
}
private String unquoteString(String quoted){
if(quoted.startsWith("\"")){
quoted = quoted.substring(1);
}
if(quoted.endsWith("\"")){
quoted = quoted.substring(0,quoted.length()-1);
}
return quoted;
}
protected static class WrapperPanel extends Panel {
private AppletViewer view;
WrapperPanel(AppletViewer view){
super(null);
this.setBackground(Color.white);
this.view = view;
this.add(view.applet);
}
public void setBounds(int x, int y, int width, int height){
super.setBounds(x,y,width,height);
view.applet.setBounds(view.hspace, view.vspace, view.appletW, view.appletH);
}
}
// The main method ...
public static void main(String[] args){
for(int i=0 ; i < args.length ; i++){
try {
AppletViewer view = new AppletViewer(args[i]);
view.applet.init();
view.applet.setVisible(true);
view.active = true;
view.applet.start();
view.setVisible(true);
view.validate();
}
catch(Exception e){
System.err.println("failed to load '"+args[i]+"' due to "+e);
e.printStackTrace();
}
}
}
}