/* AppletTag.java - representation of an HTML APPLET tag
Copyright (C) 2003 Thomas Fitzsimmons
This file is part of gcjappletviewer.
gcjappletviewer is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
gcjappletviewer 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 for more details.
You should have received a copy of the GNU General Public License
along with gcjappletviewer; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package gnu.gcjwebplugin;
import java.awt.Dimension;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class AppletTag
{
String name;
String code;
String codebase;
// Comma-delimited list of archives.
String archives;
HashMap parameters;
Dimension dimensions = new Dimension (0, 0);
// documentbase is not specified in an applet tag but we keep it
// here anyway, for convenience.
URL documentbase;
public AppletTag (String name, String code, String codebase,
String archives, HashMap parameters,
Dimension dimensions)
{
this.name = name;
this.code = code;
this.codebase = codebase;
this.archives = archives;
this.parameters = parameters;
this.dimensions = dimensions;
}
private AppletTag (StreamTokenizer tagTokenizer)
throws IOException
{
while (tagTokenizer.nextToken() != '>')
{
if (tagTokenizer.sval != null)
{
if (tagTokenizer.ttype == StreamTokenizer.TT_WORD)
{
if (tagTokenizer.sval.equals("name"))
name = parseElementString (tagTokenizer);
else if (tagTokenizer.sval.equals("code"))
code = parseElementString (tagTokenizer);
else if (tagTokenizer.sval.equals("codebase"))
codebase = parseElementString (tagTokenizer);
else if (tagTokenizer.sval.equals("archive"))
archives = parseElementString (tagTokenizer);
else if (tagTokenizer.sval.equals("height"))
{
tagTokenizer.nextToken();
tagTokenizer.nextToken();
if (tagTokenizer.ttype == StreamTokenizer.TT_NUMBER)
dimensions.height = (int) tagTokenizer.nval;
else
dimensions.height = Integer.parseInt(tagTokenizer.sval);
}
else if (tagTokenizer.sval.equals("width"))
{
tagTokenizer.nextToken();
tagTokenizer.nextToken();
if (tagTokenizer.ttype == StreamTokenizer.TT_NUMBER)
dimensions.width = (int) tagTokenizer.nval;
else
dimensions.width = Integer.parseInt(tagTokenizer.sval);
}
}
}
}
}
// Parse a case-sensitive element.
private static String parseElementString (StreamTokenizer tagTokenizer)
throws IOException
{
String value;
tagTokenizer.lowerCaseMode (false);
tagTokenizer.nextToken ();
tagTokenizer.nextToken ();
value = new String (tagTokenizer.sval);
tagTokenizer.lowerCaseMode (true);
return value;
}
// Parse an applet parameter.
private void parseParam(StreamTokenizer tagTokenizer)
throws IOException
{
String key = null;
String val = null;
// Set non-alphabetic chars that may appear in file names to word
// chars so that we can parse each unquoted file name as a single
// token.
tagTokenizer.wordChars('!', '!');
tagTokenizer.wordChars('#', '&');
tagTokenizer.wordChars('(', '/');
tagTokenizer.wordChars('{', '~');
tagTokenizer.wordChars('[', '_');
while (tagTokenizer.nextToken() != '>')
{
if (tagTokenizer.sval != null)
{
if (tagTokenizer.sval.equals("name"))
{
tagTokenizer.nextToken();
tagTokenizer.nextToken();
key = new String(tagTokenizer.sval);
}
else if (tagTokenizer.sval.equals("value"))
{
tagTokenizer.nextToken();
tagTokenizer.lowerCaseMode(false);
tagTokenizer.nextToken();
if (tagTokenizer.ttype == tagTokenizer.TT_NUMBER)
{
// Chop off scale of nval.
int unscaled_nval = (int) tagTokenizer.nval;
// See if nval represents an integer value.
if (Double.compare (tagTokenizer.nval,
(double) unscaled_nval) == 0)
val = Integer.toString(unscaled_nval);
else
val = Double.toString(tagTokenizer.nval);
}
else
{
val = new String(tagTokenizer.sval);
}
tagTokenizer.lowerCaseMode(true);
}
}
if (key != null && val != null)
{
key = key.toLowerCase();
parameters.put(key, val);
}
}
// Reset non-alphabetic word chars to ordinary chars.
tagTokenizer.ordinaryChar('!');
tagTokenizer.ordinaryChars('#', '&');
tagTokenizer.ordinaryChars('(', '/');
tagTokenizer.ordinaryChars('{', '~');
tagTokenizer.ordinaryChars('[', '_');
}
public static List parseAppletTags (String location)
throws IOException
{
List tags = new ArrayList ();
URL documentbase;
try
{
// Try parsing location as a URL.
documentbase = new URL (location);
System.out.println ("recognized URL: " + location);
List urlTags = parseAppletTags (documentbase);
tags.addAll (urlTags);
}
catch (MalformedURLException e)
{
if (location.endsWith (".class"))
{
System.out.println ("unrecognized file: " + location);
}
else
{
// location is not a URL. See if it is an HTML file.
String path;
if (location.startsWith(File.separator))
{
path = new File (location).getCanonicalPath();
}
else
{
path = new File (System.getProperty("user.dir")
+ File.separator
+ location).getCanonicalPath();
}
documentbase = new URL("file", "", path);
System.out.println ("recognized file: " + location);
List urlTags = parseAppletTags (documentbase);
tags.addAll (urlTags);
}
}
return tags;
}
// Parse all applet tags that appear in the documentbase URL.
private static List parseAppletTags(URL documentbase)
throws IOException
{
URLConnection uc = documentbase.openConnection();
InputStream input = uc.getInputStream();
StreamTokenizer tagTokenizer =
new StreamTokenizer(new InputStreamReader(input));
AppletTag currentTag = null;
ArrayList tags = new ArrayList ();
int token;
tagTokenizer.lowerCaseMode(true);
tagTokenizer.ordinaryChar('/');
token = tagTokenizer.nextToken();
while (token != tagTokenizer.TT_EOF)
{
// Start of an HTML tag.
if (token == '<')
{
token = tagTokenizer.nextToken();
if (token == tagTokenizer.TT_WORD)
{
// An APPLET tag.
if (tagTokenizer.sval.equals("applet"))
{
currentTag = new AppletTag(tagTokenizer);
currentTag.documentbase = uc.getURL ();
}
else if (tagTokenizer.sval.equals("param"))
{
// Parse APPLET parameters only.
if (currentTag != null)
currentTag.parseParam(tagTokenizer);
}
}
else
{
if (token == '/')
{
token = tagTokenizer.nextToken();
if (token == tagTokenizer.TT_WORD
&& tagTokenizer.sval.equals("applet"))
{
tags.add (currentTag);
currentTag = null;
}
}
}
}
token = tagTokenizer.nextToken();
}
input.close();
return tags;
}
// FIXME: move to AppletViewer constructor.
private URL computeCodebaseURL (URL documentbaseURL)
throws MalformedURLException
{
URL codebaseURL;
// If no codebase was specified default to documentbase.
if (codebase == null || codebase.equals(""))
{
if (documentbaseURL.getFile().endsWith("/"))
codebaseURL = documentbaseURL;
else
{
String dirname = documentbaseURL.getFile();
// Determine dirname for file by stripping everything
// past the last slash.
int slashpos = dirname.lastIndexOf('/');
if (slashpos != -1)
dirname = dirname.substring(0, slashpos + 1);
codebaseURL = new URL(documentbaseURL.getProtocol(),
documentbaseURL.getHost(),
documentbaseURL.getPort(),
dirname);
}
}
else
{
// codebase was specified
if (codebase.endsWith("/"))
codebaseURL = new URL(documentbaseURL, codebase);
else
codebaseURL = new URL(documentbaseURL, codebase + "/");
}
return codebaseURL;
}
public String toString()
{
return
" name = " + name + "\n"
+ " code = " + code + "\n"
+ " codebase = " + codebase + "\n"
+ " archive = " + archives + "\n"
+ " parameters = " + parameters + "\n"
+ " dimensions = " + dimensions + "\n"
+ " documentbase = " + documentbase + "\n";
}
}