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