001// XmlApplet.java: base class for Æfred applet demos. 002// NO WARRANTY! See README, and copyright below. 003// $Id$ 004// Modified 11/8/98 to add package statement. 005package com.microstar.xml.demo; 006 007import java.applet.Applet; 008import java.awt.BorderLayout; 009import java.awt.Button; 010import java.awt.Event; 011import java.awt.FlowLayout; 012import java.awt.Panel; 013import java.awt.TextArea; 014import java.net.MalformedURLException; 015import java.net.URL; 016 017import com.microstar.xml.XmlHandler; 018import com.microstar.xml.XmlParser; 019 020/** 021 * Base class for Ælfred demonstration applications. 022 * <p>This class fills in the basic interface, and provides 023 * an I/O infrastructure for simple applications and applets. 024 * @author Copyright (c) 1997, 1998 by Microstar Software Ltd.; 025 * @author written by David Megginson <dmeggins@microstar.com> 026 * @version 1.1 027 * @since Ptolemy II 0.2 028 * @see com.microstar.xml.XmlParser 029 * @see com.microstar.xml.XmlHandler 030 * @see EventDemo 031 * @see TimerDemo 032 * @see DtdDemo 033 * @see StreamDemo 034 */ 035@SuppressWarnings("serial") 036public class XmlApplet extends Applet implements XmlHandler { 037 /** 038 * Flag to show whether we're running as an applet or application. 039 */ 040 public boolean isApplet = false; 041 042 public XmlParser parser; 043 044 ////////////////////////////////////////////////////////////////////// 045 // Implementation of XmlParser interface. 046 // 047 // The following methods provide a full skeleton implementation of the 048 // XmlHandler interface, so that subclasses can override only 049 // the methods they need. 050 ////////////////////////////////////////////////////////////////////// 051 052 /** 053 * Resolve an external entity. 054 * <p>This method could generate a new URL by looking up the 055 * public identifier in a hash table, or it could replace the 056 * URL supplied with a different, local one; for now, however, 057 * just return the URL supplied. 058 * @see com.microstar.xml.XmlHandler#resolveEntity 059 */ 060 @Override 061 public Object resolveEntity(String publicId, String systemId) { 062 return null; 063 } 064 065 @Override 066 public void startExternalEntity(String systemId) { 067 } 068 069 @Override 070 public void endExternalEntity(String systemId) { 071 } 072 073 /** 074 * Handle the start of the document. 075 * <p>Do nothing for now. Subclasses can override this method 076 * if they want to take a specific action. 077 * <p>This method will always be called first. 078 * @see com.microstar.xml.XmlHandler#startDocument 079 */ 080 @Override 081 public void startDocument() { 082 } 083 084 /** 085 * Handle the end the document. 086 * <p>Do nothing for now. Subclasses can override this method 087 * if they want to take a specific action. 088 * <p>This method will always be called last. 089 * @see com.microstar.xml.XmlHandler#endDocument 090 */ 091 @Override 092 public void endDocument() { 093 } 094 095 /** 096 * Handle a DOCTYPE declaration. 097 * <p>Do nothing for now. Subclasses can override this method 098 * if they want to take a specific action. 099 * <p>Well-formed XML documents might not have one of these. 100 * <p>The query methods in XmlParser will return useful 101 * values only after this callback. 102 * @see com.microstar.xml.XmlHandler#doctypeDecl 103 */ 104 @Override 105 public void doctypeDecl(String name, String pubid, String sysid) { 106 } 107 108 /** 109 * Handle an attribute value specification. 110 * <p>Do nothing for now. Subclasses can override this method 111 * if they want to take a specific action. 112 * @see com.microstar.xml.XmlHandler#attribute 113 */ 114 @Override 115 public void attribute(String name, String value, boolean isSpecified) { 116 } 117 118 /** 119 * Handle the start of an element. 120 * <p>Do nothing for now. Subclasses can override this method 121 * if they want to take a specific action. 122 * @see com.microstar.xml.XmlHandler#startElement 123 */ 124 @Override 125 public void startElement(String name) { 126 } 127 128 /** 129 * Handle the end of an element. 130 * <p>Do nothing for now. Subclasses can override this method 131 * if they want to take a specific action. 132 * @see com.microstar.xml.XmlHandler#endElement 133 */ 134 @Override 135 public void endElement(String name) { 136 } 137 138 /** 139 * Handle character data. 140 * <p>Do nothing for now. Subclasses can override this method 141 * if they want to take a specific action. 142 * @see com.microstar.xml.XmlHandler#charData 143 */ 144 @Override 145 public void charData(char[] ch, int start, int length) { 146 } 147 148 /** 149 * Handle ignorable whitespace. 150 * <p>Do nothing for now. Subclasses can override this method 151 * if they want to take a specific action. 152 * @see com.microstar.xml.XmlHandler#ignorableWhitespace 153 */ 154 @Override 155 public void ignorableWhitespace(char[] ch, int start, int length) { 156 } 157 158 /** 159 * Handle a processing instruction. 160 * <p>Do nothing for now. Subclasses can override this method 161 * if they want to take a specific action. 162 * @see com.microstar.xml.XmlHandler#processingInstruction 163 */ 164 @Override 165 public void processingInstruction(String target, String data) { 166 } 167 168 /** 169 * Handle a parsing error. 170 * <p>By default, print a message and throw an Error. 171 * <p>Subclasses can override this method if they want to do something 172 * different. 173 * @see com.microstar.xml.XmlHandler#error 174 */ 175 @Override 176 public void error(String message, String url, int line, int column) { 177 displayText("FATAL ERROR: " + message); 178 displayText(" at " + url + ": line " + line + " column " + column); 179 throw new Error(message); 180 } 181 182 ////////////////////////////////////////////////////////////////////// 183 // General utility methods. 184 ////////////////////////////////////////////////////////////////////// 185 186 /** 187 * Start a parse in application mode. 188 * <p>Output will go to STDOUT. 189 * @see #displayText(String) 190 * @see com.microstar.xml.XmlParser#parse(String, String, String) 191 */ 192 void doParse(String url) throws java.lang.Exception { 193 /* String docURL =*/makeAbsoluteURL(url); 194 195 // create the parser 196 parser = new XmlParser(); 197 parser.setHandler(this); 198 parser.parse(makeAbsoluteURL(url), null, (String) null); 199 } 200 201 static String makeAbsoluteURL(String url) throws MalformedURLException { 202 URL baseURL; 203 204 String currentDirectory = System.getProperty("user.dir"); 205 206 String fileSep = System.getProperty("file.separator"); 207 String file = currentDirectory.replace(fileSep.charAt(0), '/') + '/'; 208 209 if (file.charAt(0) != '/') { 210 file = "/" + file; 211 } 212 213 baseURL = new URL("file", null, file); 214 return new URL(baseURL, url).toString(); 215 } 216 217 /** 218 * Display text on STDOUT or in an applet TextArea. 219 */ 220 void displayText(String text) { 221 if (isApplet) { 222 textArea.append(text + '\n'); 223 } else { 224 System.out.println(text); 225 } 226 } 227 228 /** 229 * Escape a string for printing. 230 */ 231 String escape(char[] ch, int length) { 232 StringBuffer out = new StringBuffer(); 233 234 for (int i = 0; i < length; i++) { 235 switch (ch[i]) { 236 case '\\': 237 out.append("\\\\"); 238 break; 239 240 case '\n': 241 out.append("\\n"); 242 break; 243 244 case '\t': 245 out.append("\\t"); 246 break; 247 248 case '\r': 249 out.append("\\r"); 250 break; 251 252 case '\f': 253 out.append("\\f"); 254 break; 255 256 default: 257 out.append(ch[i]); 258 break; 259 } 260 } 261 262 return out.toString(); 263 } 264 265 ////////////////////////////////////////////////////////////////////// 266 // Applet support. 267 // 268 // These methods and variables are used only if we are running as an 269 // applet. 270 ////////////////////////////////////////////////////////////////////// 271 TextArea textArea; 272 273 Panel buttonPanel; 274 275 Button startButton; 276 277 /** 278 * Initialise the applet the first time it runs. 279 */ 280 @Override 281 public void init() { 282 startButton = new Button("Parse " + getParameter("url")); 283 isApplet = true; 284 textArea = new TextArea(); 285 buttonPanel = new Panel(); 286 buttonPanel.setLayout(new FlowLayout()); 287 setLayout(new BorderLayout()); 288 buttonPanel.add("Center", startButton); 289 add("Center", textArea); 290 add("South", buttonPanel); 291 } 292 293 /** 294 * React to a button press. 295 * <p>This uses the old event model, so that it will work with 296 * existing browsers. It will cause a 'deprecated' warning 297 * when you compile. 298 */ 299 @Override 300 public boolean action(Event ev, Object target) { 301 if (target == startButton.getLabel()) { 302 try { 303 startParse(); 304 } catch (Exception e) { 305 System.err.println(e.getMessage()); 306 } 307 308 return true; 309 } else { 310 return false; 311 } 312 } 313 314 /** 315 * Start a parse (in response to a button press). 316 * <p>Erase the text area, then start the parser running, using 317 * the value of the "url" parameter. 318 * @exception Exception If thrown by the parser. 319 */ 320 public void startParse() throws java.lang.Exception { 321 textArea.setText(""); 322 323 try { 324 XmlParser parser = new XmlParser(); 325 parser.setHandler(this); 326 ; 327 parser.parse( 328 new URL(getDocumentBase(), getParameter("url")).toString(), 329 null, (String) null); 330 } catch (Exception e) { 331 displayText("Caught exception (" + e.getClass().toString() + "): " 332 + e.getMessage()); 333 } 334 } 335} 336 337// end of XmlApplet.java