home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / modules / edtplug / classes / netscape / test / plugin / composer / DocInfo.java < prev    next >
Encoding:
Java Source  |  1998-04-08  |  11.2 KB  |  317 lines

  1. /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. package netscape.test.plugin.composer;
  20.  
  21. import java.io.*;
  22. import java.util.*;
  23. import java.awt.*;
  24. import java.net.*;
  25. import netscape.plugin.composer.*;
  26. import netscape.plugin.composer.io.*;
  27.  
  28. /** Calculate some simple statistics about the document.
  29.  * Shows how to call awt (and by extension any user interface
  30.  * toolkit) from a plugin.
  31.  */
  32.  
  33. public class DocInfo extends Plugin {
  34.     /** Test the plugin. Not required for normal operation of the plugin.
  35.      * You can use this to run the plugin from the command line:
  36.      * java -classpath <your-class-path> <your-plugin-name> args...
  37.      * where args... are passed on to the Test class.
  38.      * You can remove this code before shipping your plugin.
  39.      */
  40.     static public void main(String[] args) {
  41.         Test.perform(args, new DocInfo());
  42.     }
  43.     /** Execute the command.
  44.      * @param document the current document state.
  45.      */
  46.     public boolean perform(Document document) throws IOException{
  47.         DocInfoDialog dialog = new DocInfoDialog(getResource("title"));
  48.         dialog.setText(getStats(document));
  49.         dialog.reshape(50,50,500,300);
  50.         dialog.show(); // make the window visible.
  51.         dialog.requestFocus(); // Make sure the window is on top and gets focus.
  52.         dialog.waitForExit(); //Wait for the user to exit the dialog.
  53.         dialog.dispose(); // Cleans up the native OS window associated with the dialog.
  54.         return true;
  55.     }
  56.     /** Get the human readable name of the plugin. Defaults to the name of the plugin class.
  57.      * @return the human readable name of the plugin.
  58.      */
  59.     public String getName()
  60.     {
  61.         return getResource("name");
  62.     }
  63.  
  64.     /** Get the human readable category of the plugin. Defaults to the name of the plugin class.
  65.      * @return the human readable category of the plugin.
  66.      */
  67.     public String getCategory()
  68.     {
  69.         return getResource("category");
  70.     }
  71.  
  72.     /** Get the human readable hint for the plugin. This is a one-sentence description of
  73.      * what the plugin does. Defaults to the name of the plugin class.
  74.      * @return the human readable hint for the plugin.
  75.      */
  76.     public String getHint()
  77.     {
  78.         return getResource("hint");
  79.     }
  80.  
  81.      /** Get the document stats.
  82.      */
  83.     String getStats(Document document) throws IOException{
  84.         StringBuffer b = new StringBuffer();
  85.         try {
  86.             DocStats stats = new DocStats(document);
  87.             b.append(formatProp("chars", stats.textBytes));
  88.             b.append(formatProp("words", stats.wordCount));
  89.             b.append("\n");
  90.             b.append(formatProp("images", stats.imageCount));
  91.             b.append(formatProp("totalImageBytes", stats.imageBytes));
  92.             int totalBytes = stats.textBytes + stats.imageBytes;
  93.             b.append(formatProp("totalBytes", totalBytes));
  94.             b.append(formatProp("min14400", (totalBytes / 1440 + 1)));
  95.             b.append("\n\n\n");
  96.             b.append(formatProp("base", document.getBase().toString()));
  97.             b.append(formatProp("workDir", document.getWorkDirectory().toString()));
  98.             b.append(formatProp("workDirURL", document.getWorkDirectoryURL().toString()));
  99.         } catch (Throwable t) {
  100.         }
  101.         // If this is an "edit" event, we'll fail when we try to actually get
  102.         // the document statistics. But the following should work anyway.
  103.         try {
  104.             String eventName = document.getEventName();
  105.             b.append(formatProp("eventName", eventName != null ? eventName : "null"));
  106.             URL docURL = document.getDocumentURL();
  107.             b.append(formatProp("documentURL", docURL != null ? docURL.toString() : "null"));
  108.         } catch (Throwable t) {
  109.         }
  110.         return b.toString();
  111.     }
  112.     /** Internationalizable format function.
  113.      */
  114.     String formatProp(String key, int num){
  115.         return formatProp(key, Integer.toString(num));
  116.     }
  117.     String formatProp(String key, String string){
  118.         return format(getResource(key), string);
  119.     }
  120.  
  121.     static String getResource(String key){
  122.         if ( resources == null ) {
  123.             resources = ResourceBundle.getBundle(
  124.                 "netscape.test.plugin.composer.DocInfoResources");
  125.         }
  126.         String result = resources.getString(key);
  127.         if ( result == null ) {
  128.             result = key;
  129.         }
  130.  
  131.         return result;
  132.     }
  133.     String format(String formatString, String arg){
  134.         String args[] = new String[1];
  135.         args[0] = arg;
  136.         return format(formatString, args);
  137.     }
  138.  
  139.     /** Poor man's internationalizable formatting.
  140.      * @param formatString The format string. Occurences of ^0 are replaced by
  141.      * args[0], ^1 by args[1], and so on. Use ^^ to signify a singe ^.
  142.      * @param args The argument array.
  143.      * @return the formatted string.
  144.      */
  145.     String format(String formatString, String[] args){
  146.         int len = formatString.length();
  147.         StringBuffer b = new StringBuffer(len);
  148.         for(int index = 0; index < len; index++ ){
  149.             char c = formatString.charAt(index);
  150.             if ( c == '^') {
  151.                 if ( index + 1 < len ) {
  152.                     c = formatString.charAt(++index);
  153.                     if ( c >= '0' && c <= '9') {
  154.                         int argIndex = c - '0';
  155.                         if ( argIndex < args.length) {
  156.                             b.append(args[argIndex]);
  157.                             continue;
  158.                         }
  159.                         else {
  160.                             b.append('^');
  161.                             // And fall thru to append the character.
  162.                         }
  163.                     }
  164.                 }
  165.             }
  166.             b.append(c);
  167.         }
  168.         return b.toString();
  169.     }
  170.  
  171.     private static ResourceBundle resources;
  172. }
  173.  
  174. /** Calculate some simple statistics for a document
  175.  */
  176.  
  177. class DocStats{
  178.     public DocStats(Document document) throws IOException{
  179.         LexicalStream s = new LexicalStream(document.getInput());
  180.         boolean inBody = false;
  181.         String BODY = "BODY";
  182.         String IMG = "IMG";
  183.         String SRC = "SRC";
  184.         for(;;){
  185.             // Get the next token of the document.
  186.             Token token = s.next();
  187.             if ( token == null ) break; //  Null means we've finished the document.
  188.             // Add to the total byte count.
  189.             // This is not an accurate measurement
  190.             // because many unicode characters
  191.             // will ultimately be encoded as more than
  192.             // one byte.
  193.             textBytes += token.toString().length();
  194.             if (token instanceof Tag ) {
  195.                 Tag tag = (Tag) token;
  196.                 boolean isOpen = tag.isOpen();
  197.                 String tagName = tag.getName();
  198.                 if ( tagName.equals(BODY) ) {
  199.                     inBody = isOpen;
  200.                 }
  201.                 else if ( isOpen ) {
  202.                     // Check for images
  203.                     if ( tagName.equals(IMG) ){
  204.                         imageCount++;
  205.                         String src = tag.lookupAttribute(SRC);
  206.                         if ( src != null ) {
  207.                             try {
  208.                                 URL base = document.getBase();
  209.                                 URL srcURL = new URL(base, src);
  210.                                 imageBytes += getSize(srcURL);
  211.                             } catch(Throwable t){
  212.                                 System.err.println("Couldn't open " + src);
  213.                                 t.printStackTrace();
  214.                             }
  215.                         }
  216.                     }
  217.                 }
  218.             }
  219.             else if ( inBody ) {
  220.                 if ( token instanceof Text ) {
  221.                     Text text = (Text) token;
  222.                     if ( ! text.isNewline() ){
  223.                         countWords(text.getText());
  224.                     }
  225.                 }
  226.             }
  227.         }
  228.     }
  229.  
  230.     protected int getSize(URL srcURL){
  231.         System.err.println("URL: " + srcURL);
  232.         int size = 0;
  233.         try {
  234.             URLConnection connection = srcURL.openConnection();
  235.             size = connection.getContentLength();
  236.             if ( size < 0 ) {
  237.                 size = 0;
  238.                 byte[] dummy = new byte[1000];
  239.                 InputStream in = connection.getInputStream();
  240.                 int skipped;
  241.                 while((skipped = (int) in.read(dummy)) > 0) {
  242.                     size += skipped;
  243.                 }
  244.                 in.close();
  245.             }
  246.         } catch(Throwable t){
  247.             System.err.println("Couldn't open URL " + srcURL);
  248.             t.printStackTrace();
  249.         }
  250.         return size;
  251.     }
  252.     protected void countWords(String text){
  253.         // This is an approximate measure because
  254.         // some tags don't cause word breaks.
  255.         char c;
  256.         int len = text.length();
  257.         boolean nonSpaceFound = false;
  258.         for(int i = 0; i < len; i++ ){
  259.             c = text.charAt(i);
  260.             if ( Character.isWhitespace(c)){
  261.                 wordCount++;
  262.             }
  263.             else {
  264.                 if ( ! nonSpaceFound ) {
  265.                     nonSpaceFound = true;
  266.                     wordCount++;
  267.                 }
  268.             }
  269.         }
  270.     }
  271.  
  272.     public int textBytes;
  273.     public int wordCount;
  274.     public int imageCount;
  275.     public int imageBytes;
  276. }
  277.  
  278. /** An awt dialog for interacting with the user. This is like
  279.  * the java.awt.Dialog class, except that it doesn't require a
  280.  * parent Frame.
  281.  */
  282. class DocInfoDialog extends Frame {
  283.     public DocInfoDialog(String title) {
  284.         super(title);
  285.         add("Center", text = new TextArea());
  286.      }
  287.     /** Handle window close event.
  288.     */
  289.     public boolean handleEvent(Event event) {
  290.         if (event.id == Event.WINDOW_DESTROY) {
  291.             hide();
  292.             signalExit();
  293.             return true;
  294.         } else {
  295.             return super.handleEvent(event);
  296.         }
  297.     }
  298.     public void setText(String text){
  299.         this.text.setText(text);
  300.     }
  301.     synchronized public void waitForExit() {
  302.         while ( ! bExited ) {
  303.             try {
  304.                 wait();
  305.             } catch ( InterruptedException e){
  306.             }
  307.         }
  308.     }
  309.     synchronized public void signalExit() {
  310.         bExited = true;
  311.         notifyAll();
  312.     }
  313.     private Button quit;
  314.     private TextArea text;
  315.     private boolean bExited = false;
  316. }
  317.