home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 25 / CDROM25.iso / Share / prog / VJ11 / VJTRIAL.EXE / IE30Java.exe / classd.exe / sun / applet / AppletViewer.java < prev    next >
Encoding:
Java Source  |  1997-01-27  |  23.0 KB  |  910 lines

  1. /*
  2.  * @(#)AppletViewer.java    1.78 96/04/22
  3.  *
  4.  * Copyright (c) 1994-1995 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19.  
  20. package sun.applet;
  21.  
  22. import java.util.*;
  23. import java.io.*;
  24. import java.awt.*;
  25. import java.applet.*;
  26. import java.net.URL;
  27. import java.net.MalformedURLException;
  28. import sun.awt.image.URLImageSource;
  29.  
  30. /**
  31.  * A frame to show the applet tag in.
  32.  */
  33. class TextFrame extends Frame {
  34.     /**
  35.      * Create the tag frame.
  36.      */
  37.     TextFrame(int x, int y, String title, String text) {
  38.     setTitle(title);
  39.     TextArea txt = new TextArea(20, 60);
  40.     txt.setText(text);
  41.     txt.setEditable(false);
  42.  
  43.     add("Center", txt);
  44.  
  45.     Panel p = new Panel();
  46.     add("South", p);
  47.     p.add(new Button("Dismiss"));
  48.     pack();
  49.     move(x, y);
  50.     show();
  51.     }
  52.  
  53.     /**
  54.      * Handle events.
  55.      */
  56.     public boolean handleEvent(Event evt) {
  57.     switch (evt.id) {
  58.     case Event.ACTION_EVENT:
  59.         if (!"Dismiss".equals(evt.arg)) {
  60.         break;
  61.         }
  62.     case Event.WINDOW_DESTROY:
  63.         dispose();
  64.         return true;
  65.  
  66.     }
  67.     return false;
  68.     }
  69. }
  70.  
  71. /**
  72.  * Construct a cmd-line driven appletviewer - this is the default
  73.  */
  74.  
  75. class StdAppletViewerFactory implements AppletViewerFactory {
  76.     public AppletViewer createAppletViewer(int x, int y, URL doc, 
  77.                        Hashtable atts) {
  78.         return new AppletViewer(x, y, doc, atts, System.out, this);
  79.     }
  80.  
  81.     public MenuBar getBaseMenuBar() {
  82.         return new MenuBar();
  83.     }
  84.     
  85.     public boolean isStandalone() {
  86.         return true;
  87.     }
  88. };
  89.  
  90. /**
  91.  * The toplevel applet viewer.
  92.  */
  93. public class AppletViewer extends Frame implements AppletContext {
  94.     /**
  95.      * Some constants...
  96.      */
  97.     public static String theVersion = "1.0.2";
  98.  
  99.     /**
  100.      * Look here for the properties file
  101.      */
  102.     public static File theUserPropertiesFile;
  103.     public static File theAppletViewerPropsFile;
  104.     
  105.     /**
  106.      * The panel in which the applet is being displayed.
  107.      */
  108.     AppletViewerPanel panel;
  109.  
  110.     /**
  111.      * The status line.
  112.      */
  113.     Label label;
  114.  
  115.     /**
  116.      * output status messages to this stream
  117.      */
  118.     
  119.     PrintStream statusMsgStream;
  120.     
  121.     /**
  122.      * For cloneing
  123.      */
  124.     AppletViewerFactory factory;
  125.     
  126.     static {
  127.     theUserPropertiesFile = new File(System.getProperty("user.home") + 
  128.         File.separator + ".hotjava" +
  129.         File.separator + "properties");
  130.     // ensure the props folder can be made
  131.     new File(theUserPropertiesFile.getParent()).mkdirs();
  132.     theAppletViewerPropsFile = new File(System.getProperty("java.home") + 
  133.         File.separator + "lib" +
  134.         File.separator + "appletviewer.properties");
  135.     }
  136.     
  137.     /**
  138.      * Create the applet viewer
  139.      */
  140.     public AppletViewer(int x, int y, URL doc, Hashtable atts, 
  141.             PrintStream statusMsgStream, 
  142.             AppletViewerFactory factory) {
  143.         this.factory = factory;
  144.     this.statusMsgStream = statusMsgStream;
  145.     setTitle("Applet Viewer: " + atts.get("code"));
  146.  
  147.     MenuBar mb = factory.getBaseMenuBar();
  148.  
  149.     Menu m = new Menu("Applet");
  150.     m.add(new MenuItem("Restart"));
  151.     m.add(new MenuItem("Reload"));
  152.     m.add(new MenuItem("Clone"));
  153.     m.add(new MenuItem("-"));
  154.     m.add(new MenuItem("Tag"));
  155.     m.add(new MenuItem("Info"));
  156.     m.add(new MenuItem("Edit")).disable();
  157.     m.add(new MenuItem("-"));
  158.     m.add(new MenuItem("Properties"));
  159.     m.add(new MenuItem("-"));
  160.     m.add(new MenuItem("Close"));
  161.     
  162.     if (factory.isStandalone())
  163.         m.add(new MenuItem("Quit"));
  164.  
  165.     mb.add(m);
  166.  
  167.     setMenuBar(mb);
  168.  
  169.     reshape(x, y, 400, 200);
  170.     
  171.     add("Center", panel = new AppletViewerPanel(doc, atts));
  172.     add("South", label = new Label("Hello..."));
  173.     panel.init();
  174.     appletPanels.addElement(panel);
  175.  
  176.     pack();
  177.     show();
  178.  
  179.  
  180.     // Start the applet
  181.     showStatus("starting applet...");
  182.     panel.sendEvent(AppletPanel.APPLET_LOAD);
  183.     panel.sendEvent(AppletPanel.APPLET_INIT);
  184.     panel.sendEvent(AppletPanel.APPLET_START);
  185.     }
  186.  
  187.     static Hashtable audioHash = new Hashtable();
  188.  
  189.     /**
  190.      * Get a clip from the static audio cache.
  191.      */
  192.     static synchronized AudioClip getAudioClipFromCache(URL url) {
  193.     System.getSecurityManager().checkConnect(url.getHost(), url.getPort());
  194.     AudioClip clip = (AudioClip)audioHash.get(url);
  195.     if (clip == null) {
  196.         audioHash.put(url, clip = new AppletAudioClip(url));
  197.     }
  198.     return clip;
  199.     }
  200.  
  201.     /**
  202.      * Get an audio clip.
  203.      */
  204.     public AudioClip getAudioClip(URL url) {
  205.     return getAudioClipFromCache(url);
  206.     }
  207.  
  208.     static Hashtable imgHash = new Hashtable();
  209.  
  210.     /**
  211.      * Get an image from the static image cache.
  212.      */
  213.     static synchronized Image getImageFromHash(URL url) {
  214.     System.getSecurityManager().checkConnect(url.getHost(), url.getPort());
  215.     Image img = (Image)imgHash.get(url);
  216.     if (img == null) {
  217.         try {    
  218.         imgHash.put(url, img = Toolkit.getDefaultToolkit().createImage(new URLImageSource(url)));
  219.         } catch (Exception e) {
  220.         }
  221.     }
  222.     return img;
  223.     }
  224.  
  225.     /**
  226.      * Get an image.
  227.      */
  228.     public Image getImage(URL url) {
  229.     return getImageFromHash(url);
  230.     }
  231.  
  232.     static Vector appletPanels = new Vector();
  233.  
  234.     /**
  235.      * Get an applet by name.
  236.      */
  237.     public Applet getApplet(String name) {
  238.     AppletSecurity security = (AppletSecurity)System.getSecurityManager();
  239.     name = name.toLowerCase();
  240.     for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) {
  241.         AppletPanel p = (AppletPanel)e.nextElement();
  242.         String param = p.getParameter("name");
  243.         if (param != null) {
  244.         param = param.toLowerCase();
  245.         }
  246.         if (name.equals(param) && p.getDocumentBase().equals(panel.getDocumentBase())) {
  247.         try {
  248.             security.checkConnect(panel.getCodeBase().getHost(), p.getCodeBase().getHost());
  249.             return p.applet;
  250.         } catch (SecurityException ee) {
  251.         }
  252.         }
  253.     }
  254.     return null;
  255.     }
  256.  
  257.     /**
  258.      * Return an enumeration of all the accessible
  259.      * applets on this page.
  260.      */
  261.     public Enumeration getApplets() {
  262.     AppletSecurity security = (AppletSecurity)System.getSecurityManager();
  263.     Vector v = new Vector();
  264.     for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) {
  265.         AppletPanel p = (AppletPanel)e.nextElement();
  266.         if (p.getDocumentBase().equals(panel.getDocumentBase())) {
  267.         try {
  268.             security.checkConnect(panel.getCodeBase().getHost(), p.getCodeBase().getHost());
  269.             v.addElement(p.applet);
  270.         } catch (SecurityException ee) {
  271.         }
  272.         }
  273.     }
  274.     return v.elements();
  275.     }
  276.  
  277.     /**
  278.      * Ignore.
  279.      */
  280.     public void showDocument(URL url) {    
  281.     }
  282.  
  283.     /**
  284.      * Ignore.
  285.      */
  286.     public void showDocument(URL url, String target) {
  287.     }
  288.  
  289.     /**
  290.      * Show status.
  291.      */
  292.     public void showStatus(String status) {
  293.     label.setText(status);
  294.     }
  295.  
  296.     /**
  297.      * System parameters.
  298.      */
  299.     static Hashtable systemParam = new Hashtable();
  300.  
  301.     static {
  302.     systemParam.put("zipbase", "zipbase");
  303.     systemParam.put("codebase", "codebase");
  304.     systemParam.put("code", "code");
  305.     systemParam.put("alt", "alt");
  306.     systemParam.put("width", "width");
  307.     systemParam.put("height", "height");
  308.     systemParam.put("align", "align");
  309.     systemParam.put("vspace", "vspace");
  310.     systemParam.put("hspace", "hspace");
  311.     }
  312.  
  313.     /**
  314.      * Print the HTML tag.
  315.      */
  316.     static void printTag(PrintStream out, Hashtable atts) {
  317.     out.print("<applet");
  318.  
  319.     String v = (String)atts.get("zipbase");
  320.     if (v != null) {
  321.         out.print(" zipbase=\"" + v + "\"");
  322.     }
  323.  
  324.     v = (String)atts.get("codebase");
  325.     if (v != null) {
  326.         out.print(" codebase=\"" + v + "\"");
  327.     }
  328.  
  329.     v = (String)atts.get("code");
  330.     if (v == null) {
  331.         v = "applet.class";
  332.     }
  333.     out.print(" code=\"" + v + "\"");
  334.  
  335.     v = (String)atts.get("width");
  336.     if (v == null) {
  337.         v = "150";
  338.     }
  339.     out.print(" width=" + v);
  340.  
  341.     v = (String)atts.get("height");
  342.     if (v == null) {
  343.         v = "100";
  344.     }
  345.     out.print(" height=" + v);
  346.  
  347.     v = (String)atts.get("name");
  348.     if (v != null) {
  349.         out.print(" name=\"" + v + "\"");
  350.     }
  351.     out.println(">");
  352.  
  353.     // A very slow sorting algorithm
  354.     int len = atts.size();
  355.     String params[] = new String[len];
  356.     len = 0;
  357.     for (Enumeration e = atts.keys() ; e.hasMoreElements() ;) {
  358.         String param = (String)e.nextElement();
  359.         int i = 0;
  360.         for (; i < len ; i++) {
  361.         if (params[i].compareTo(param) >= 0) {
  362.             break;
  363.         }
  364.         }
  365.         System.arraycopy(params, i, params, i + 1, len - i);
  366.         params[i] = param;
  367.         len++;
  368.     }
  369.  
  370.     for (int i = 0 ; i < len ; i++) {
  371.         String param = params[i];
  372.         if (systemParam.get(param) == null) {
  373.         out.println("<param name=" + param + " value=\"" + atts.get(param) + "\">");
  374.         }
  375.     }
  376.     out.println("</applet>");
  377.     }
  378.  
  379.     /**
  380.      * Make sure the atrributes are uptodate.
  381.      */
  382.     public void updateAtts() {
  383.     Dimension d = panel.size();
  384.     Insets in = panel.insets();
  385.     panel.atts.put("width", new Integer(d.width - (in.left + in.right)).toString());
  386.     panel.atts.put("height", new Integer(d.height - (in.top + in.bottom)).toString());
  387.     }
  388.  
  389.     /**
  390.      * Restart the applet.
  391.      */
  392.     void appletRestart() {
  393.     panel.sendEvent(AppletPanel.APPLET_STOP);
  394.     panel.sendEvent(AppletPanel.APPLET_DESTROY);
  395.     panel.sendEvent(AppletPanel.APPLET_INIT);
  396.     panel.sendEvent(AppletPanel.APPLET_START);
  397.     }
  398.  
  399.     /**
  400.      * Reload the applet.
  401.      */
  402.     void appletReload() {
  403.     panel.sendEvent(AppletPanel.APPLET_STOP);
  404.     panel.sendEvent(AppletPanel.APPLET_DESTROY);
  405.     panel.sendEvent(AppletPanel.APPLET_DISPOSE);
  406.     AppletPanel.flushClassLoader(panel.baseURL);
  407.     panel.sendEvent(AppletPanel.APPLET_LOAD);
  408.     panel.sendEvent(AppletPanel.APPLET_INIT);
  409.     panel.sendEvent(AppletPanel.APPLET_START);
  410.     }
  411.  
  412.     /**
  413.      * Clone the viewer and the applet.
  414.      */
  415.     void appletClone() {
  416.     Point p = location();
  417.     updateAtts();
  418.     factory.createAppletViewer(p.x + 30, p.y + 10, panel.documentURL, (Hashtable)panel.atts.clone());
  419.     }
  420.  
  421.     /**
  422.      * Show the applet tag.
  423.      */
  424.     void appletTag() {
  425.     ByteArrayOutputStream out = new ByteArrayOutputStream();
  426.     updateAtts();
  427.     printTag(new PrintStream(out), panel.atts);
  428.     showStatus("Tag shown");
  429.  
  430.     Point p = location();
  431.     new TextFrame(p.x + 50, p.y + 20, "Applet HTML Tag", out.toString());
  432.     }
  433.  
  434.     /**
  435.      * Show the applet tag.
  436.      */
  437.     void appletInfo() {
  438.     String str = panel.applet.getAppletInfo();
  439.     if (str == null) {
  440.         str = "-- no applet info --";
  441.     }
  442.     str += "\n\n";
  443.  
  444.     String atts[][] = panel.applet.getParameterInfo();
  445.     if (atts != null) {
  446.         for (int i = 0 ; i < atts.length ; i++) {
  447.         str += atts[i][0] + " -- " + atts[i][1] + " -- " + atts[i][2] + "\n";
  448.         }
  449.     } else {
  450.         str += "-- no parameter info --";
  451.     }
  452.     
  453.     Point p = location();
  454.     new TextFrame(p.x + 50, p.y + 20, "Applet Info", str);
  455.     }
  456.  
  457.     /**
  458.      * Edit the applet.
  459.      */
  460.     void appletEdit() {
  461.     }
  462.  
  463.     /**
  464.      * Properties.
  465.      */
  466.     static AppletProps props;
  467.     public static synchronized void networkProperties() {
  468.     if (props == null) {
  469.         props = new AppletProps();
  470.     }
  471.     props.show();
  472.     }
  473.  
  474.     /**
  475.      * Start the applet.
  476.      */
  477.     void appletStart() {
  478.     panel.sendEvent(AppletPanel.APPLET_START);
  479.     }
  480.  
  481.     /**
  482.      * Stop the applet.
  483.      */
  484.     void appletStop() {
  485.     panel.sendEvent(AppletPanel.APPLET_STOP);
  486.     }
  487.  
  488.     /**
  489.      * Close this viewer.
  490.      */
  491.     void appletClose() {
  492.     panel.sendEvent(AppletPanel.APPLET_STOP);
  493.     panel.sendEvent(AppletPanel.APPLET_DESTROY);
  494.     panel.sendEvent(AppletPanel.APPLET_DISPOSE);
  495.     panel.sendEvent(AppletPanel.APPLET_QUIT);
  496.     appletPanels.removeElement(panel);
  497.     dispose();
  498.  
  499.     if (countApplets() == 0) {
  500.         appletQuit();
  501.     }
  502.     }
  503.  
  504.     /**
  505.      * Quit this all viewers.
  506.      */
  507.     protected void appletQuit() {
  508.     if (factory.isStandalone())
  509.         System.exit(0);
  510.     }
  511.  
  512.     /**
  513.      * Handle events.
  514.      */
  515.     public boolean handleEvent(Event evt) {
  516.     switch (evt.id) {
  517.       case AppletPanel.APPLET_RESIZE:
  518.         resize(preferredSize());
  519.         validate();
  520.         return true;
  521.  
  522.       case Event.WINDOW_ICONIFY:
  523.         appletStop();
  524.         return true;
  525.  
  526.       case Event.WINDOW_DEICONIFY:
  527.         appletStart();
  528.         return true;
  529.  
  530.       case Event.WINDOW_DESTROY:
  531.         appletClose();
  532.         return true;
  533.  
  534.       case Event.ACTION_EVENT:
  535.         if ("Restart".equals(evt.arg)) {
  536.         appletRestart();
  537.         return true;
  538.         }
  539.         if ("Reload".equals(evt.arg)) {
  540.         appletReload();
  541.         return true;
  542.         }
  543.         if ("Clone".equals(evt.arg)) {
  544.         appletClone();
  545.         return true;
  546.         } 
  547.         if ("Tag".equals(evt.arg)) {
  548.         appletTag();
  549.         return true;
  550.         }
  551.         if ("Info".equals(evt.arg)) {
  552.         appletInfo();
  553.         return true;
  554.         }
  555.         if ("Edit".equals(evt.arg)) {
  556.         appletEdit();
  557.         return true;
  558.         }
  559.         if ("Properties".equals(evt.arg)) {
  560.         networkProperties();
  561.         return true;
  562.         }
  563.         if ("Close".equals(evt.arg)) {
  564.         appletClose();
  565.         return true;
  566.         }
  567.         if (factory.isStandalone() && "Quit".equals(evt.arg)) {
  568.         appletQuit();
  569.         return true;
  570.         }
  571.         break;
  572.  
  573.       case Event.MOUSE_ENTER:
  574.       case Event.MOUSE_EXIT:
  575.       case Event.MOUSE_MOVE:
  576.       case Event.MOUSE_DRAG:
  577.         return super.handleEvent(evt);
  578.     }
  579.     //statusMsgStream.println("evt = " + evt);
  580.     return super.handleEvent(evt);
  581.     }
  582.  
  583.     /**
  584.      * How many applets are running?
  585.      */
  586.     
  587.     public static int countApplets() {
  588.     return appletPanels.size();
  589.     }
  590.     
  591.     /**
  592.      * Prepare the enviroment for executing applets.
  593.      */
  594.     public static void init() {
  595.     Properties props = new Properties(System.getProperties());
  596.  
  597.     // Define a number of standard properties
  598.     props.put("acl.read", "+");
  599.     props.put("acl.read.default", "");
  600.     props.put("acl.write", "+");
  601.     props.put("acl.write.default", "");
  602.  
  603.     // Standard browser properties
  604.     props.put("browser", "sun.applet.AppletViewer");
  605.     props.put("browser.version", "1.06");
  606.     props.put("browser.vendor", "Sun Microsystems Inc.");
  607.     props.put("http.agent", "JDK/" + theVersion);
  608.  
  609.     // Define which packages can be accessed by applets
  610.     props.put("package.restrict.access.sun", "true");
  611.     props.put("package.restrict.access.netscape", "true");
  612.  
  613.     // Define which packages can be extended by applets
  614.     props.put("package.restrict.definition.java", "true");
  615.     props.put("package.restrict.definition.sun", "true");
  616.     props.put("package.restrict.definition.netscape", "true");
  617.     props.put("package.restrict.definition.com.ms", "true");
  618.  
  619.     // Define which properties can be read by applets.
  620.     // A property named by "key" can be read only when its twin
  621.     // property "key.applet" is true.  The following ten properties
  622.     // are open by default.  Any other property can be explicitly
  623.     // opened up by the browser user setting key.applet=true in
  624.     // ~/.hotjava/properties.   Or vice versa, any of the following can
  625.     // be overridden by the user's properties. 
  626.     props.put("java.version.applet", "true");
  627.     props.put("java.vendor.applet", "true");
  628.     props.put("java.vendor.url.applet", "true");
  629.     props.put("java.class.version.applet", "true");
  630.     props.put("os.name.applet", "true");
  631.     props.put("os.version.applet", "true");
  632.     props.put("os.arch.applet", "true");
  633.     props.put("file.separator.applet", "true");
  634.     props.put("path.separator.applet", "true");
  635.     props.put("line.separator.applet", "true");
  636.     
  637.     // User properties list
  638.     props = new Properties(props);
  639.  
  640.     // Try loading the appletviewer properties file to get messages, etc.
  641.     try {
  642.         FileInputStream in =
  643.         new FileInputStream(theAppletViewerPropsFile);
  644.         props.load(new BufferedInputStream(in));
  645.         in.close();
  646.     } catch (Exception e) {
  647. //            System.out.println("[no appletviewer.properties file found!]");
  648.     }
  649.  
  650.     // Try loading the saved user properties file to override some
  651.     // of the above defaults.
  652.     try {
  653.         FileInputStream in = new FileInputStream(theUserPropertiesFile);
  654.         props.load(new BufferedInputStream(in));
  655.         in.close();
  656.     } catch (Exception e) {
  657.         // is it really necessary to say this?  This is always the case the first
  658.         // time we run..
  659. //        System.out.println("[no properties loaded, using defaults]");
  660.     }
  661.  
  662.     // Install a property list.
  663.     System.setProperties(props);
  664.  
  665.     // Create and install the security manager
  666.     System.setSecurityManager(new AppletSecurity());
  667.  
  668.     // REMIND: Create and install a socket factory!
  669.     }
  670.  
  671.     /**
  672.      * The current character.
  673.      */
  674.     static int c;
  675.  
  676.     /**
  677.      * Scan spaces.
  678.      */
  679.     static void skipSpace(InputStream in) throws IOException {
  680.     while((c >= 0) &&
  681.           ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r'))) {
  682.         c = in.read();
  683.     }
  684.     }
  685.  
  686.     /**
  687.      * Scan identifier
  688.      */
  689.     static String scanIdentifier(InputStream in) throws IOException {
  690.     StringBuffer buf = new StringBuffer();
  691.     while (true) {
  692.         if (((c >= 'a') && (c <= 'z')) ||
  693.         ((c >= 'A') && (c <= 'Z')) ||
  694.         ((c >= '0') && (c <= '9')) || (c == '_')) {
  695.         buf.append((char)c);
  696.         c = in.read();
  697.         } else {
  698.         return buf.toString();
  699.         }
  700.     }
  701.     }
  702.  
  703.     /**
  704.      * Scan tag
  705.      */
  706.     static Hashtable scanTag(InputStream in) throws IOException {
  707.     Hashtable atts = new Hashtable();
  708.     skipSpace(in);
  709.     while (c >= 0 && c != '>') {
  710.         String att = scanIdentifier(in);
  711.         String val = "";
  712.         skipSpace(in);
  713.         if (c == '=') {
  714.         int quote = -1;
  715.         c = in.read();
  716.         skipSpace(in);
  717.         if ((c == '\'') || (c == '\"')) {
  718.             quote = c;
  719.             c = in.read();
  720.         }
  721.         StringBuffer buf = new StringBuffer();
  722.         while ((c > 0) &&
  723.                (((quote < 0) && (c != ' ') && (c != '\t') && 
  724.              (c != '\n') && (c != '\r') && (c != '>'))
  725.             || ((quote >= 0) && (c != quote)))) {
  726.             buf.append((char)c);
  727.             c = in.read();
  728.         }
  729.         if (c == quote) {
  730.             c = in.read();
  731.         }
  732.         skipSpace(in);
  733.         val = buf.toString();
  734.         }
  735.         //statusMsgStream.println("PUT " + att + " = '" + val + "'");
  736.         atts.put(att.toLowerCase(), val);
  737.         skipSpace(in);
  738.     }
  739.     return atts;
  740.     }
  741.  
  742.     static int x = 100;
  743.     static int y = 50;
  744.  
  745.     /**
  746.      * Scan an html file for <applet> tags
  747.      */
  748.     static void parse(URL url) throws IOException {
  749.         parse(url, System.out, new StdAppletViewerFactory());
  750.     }
  751.     
  752.     public static void parse(URL url, PrintStream statusMsgStream, AppletViewerFactory factory) throws IOException {
  753.     InputStream in = url.openStream();
  754.     Hashtable atts = null;
  755.     c = in.read();
  756.     while (c >= 0) {
  757.         if (c == '<') {
  758.         c = in.read();
  759.         if (c == '/') {
  760.             c = in.read();
  761.             String nm = scanIdentifier(in);
  762.             if (nm.equalsIgnoreCase("applet")) {
  763.             if (atts != null) {
  764.                 factory.createAppletViewer(x, y, url, atts);
  765.  
  766.                 x += 50;
  767.                 y += 20;
  768.                 
  769.                 // make sure we don't go too far!
  770.                 Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
  771.                 if (x > d.width - 30)
  772.                     x = 100;
  773.                 if (y > d.height - 30)
  774.                     x = 50;
  775.             }
  776.             atts = null;
  777.             }
  778.         } else {
  779.             String nm = scanIdentifier(in);
  780.             if (nm.equalsIgnoreCase("param")) {
  781.             Hashtable t = scanTag(in);
  782.             String att = (String)t.get("name");
  783.             if (att == null) {
  784.                 statusMsgStream.println("Warning: <param name=... value=...> tag requires name attribute.");
  785.             } else {
  786.                 String val = (String)t.get("value");
  787.                 if (val == null) {
  788.                 statusMsgStream.println("Warning: <param name=... value=...> tag requires value attribute.");
  789.                 } else if (atts != null) {
  790.                 atts.put(att.toLowerCase(), val);
  791.                 } else {
  792.                 statusMsgStream.println("Warning: <param> tag outside <applet> ... </applet>.");
  793.                 }
  794.             }
  795.             } else if (nm.equalsIgnoreCase("applet")) {
  796.             atts = scanTag(in);
  797.             if (atts.get("code") == null) {
  798.                 statusMsgStream.println("Warning: <applet> tag requires code attribute.");
  799.                 atts = null;
  800.             } else if (atts.get("width") == null) {
  801.                 statusMsgStream.println("Warning: <applet> tag requires width attribute.");
  802.                 atts = null;
  803.             } else if (atts.get("height") == null) {
  804.                 statusMsgStream.println("Warning: <applet> tag requires height attribute.");
  805.                 atts = null;
  806.             }
  807.             } else if (nm.equalsIgnoreCase("app")) {
  808.             statusMsgStream.println("Warning: <app> tag no longer supported, use <applet> instead:");
  809.             Hashtable atts2 = scanTag(in);
  810.             nm = (String)atts2.get("class");
  811.             if (nm != null) {
  812.                 atts2.remove("class");
  813.                 atts2.put("code", nm + ".class");
  814.             }
  815.             nm = (String)atts2.get("src");
  816.             if (nm != null) {
  817.                 atts2.remove("src");
  818.                 atts2.put("codebase", nm);
  819.             }
  820.             if (atts2.get("width") == null) {
  821.                 atts2.put("width", "100");
  822.             }
  823.             if (atts2.get("height") == null) {
  824.                 atts2.put("height", "100");
  825.             }
  826.             printTag(statusMsgStream, atts2);
  827.             statusMsgStream.println();
  828.             }
  829.         } 
  830.         } else {
  831.         c = in.read();
  832.         }
  833.     }
  834.     in.close();
  835.     }
  836.  
  837.     /**
  838.      * Print usage
  839.      */
  840.     static void usage() {
  841.         System.out.println("use: appletviewer url|file ...");
  842.     }
  843.  
  844.     /** 
  845.      * mainInit can be called by direct clients
  846.      */
  847.     
  848.     static boolean didInitialize = false;
  849.     
  850.     public static void mainInit() {
  851.     if (! didInitialize) {
  852.         didInitialize = true;
  853.  
  854.         init();
  855.             
  856.         // Show copyright notice unless it was shown before
  857.         if (!theVersion.equals(System.getProperty("appletviewer.version"))) {
  858.         new AppletCopyright().waitForUser();
  859.         }
  860.     }
  861.     }
  862.     
  863.     /**
  864.      * Main
  865.      */
  866.     public static void main(String argv[]) {
  867.     mainInit();
  868.  
  869.     // Parse arguments
  870.     if (argv.length == 0) {
  871.         System.out.println("No input files specified.");
  872.         usage();
  873.         return;
  874.     }
  875.  
  876.     // Parse the documents
  877.     for (int i = 0 ; i < argv.length ; i++) {
  878.         try {
  879.         URL url;
  880.  
  881.         if (argv[i].indexOf(':') <= 1) {
  882.             url = new URL("file:" + System.getProperty("user.dir").replace(File.separatorChar, '/') + "/");
  883.             url = new URL(url, argv[i]);
  884.         } else {
  885.             url = new URL(argv[i]);
  886.         }
  887.  
  888.         parse(url);
  889.         } catch (MalformedURLException e) {
  890.         System.out.println("Bad URL: " + argv[i]
  891.                    + " (" + e.getMessage() + ")");
  892.         System.exit(1);
  893.         } catch (IOException e) {
  894.         System.out.println("I/O exception while reading: " + e.getMessage());
  895.         if (argv[i].indexOf(':') < 0) {
  896.             System.out.println("Make sure that " + argv[i] + " is a file and is readable.");
  897.         } else {
  898.             System.out.println("Is " + argv[i] + " the correct URL?");
  899.         }
  900.         System.exit(1);
  901.         }
  902.     }
  903.     if (countApplets() == 0) {
  904.         System.out.println("Warning: No Applets were started, make sure the input contains an <applet> tag.");
  905.         usage();
  906.         System.exit(1);
  907.     }
  908.     }
  909. }
  910.