/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package netscape.test.plugin.composer; import netscape.plugin.composer.*; import java.io.*; import java.util.Properties; import java.net.*; import java.util.*; /** The composer plugin testbed. Allows you to test your plugin * seperately from the Netscape Composer. * *
 *
 * You run Test from the command line by doing this:
 *
 * java -classpath classPath netscape.test.plugin.composer.Test ..args..
 *
 * Where ..args.. are one or more of:
 *
 *  -plugin plugin    Use the named plugin. Defaults to
 *                    netscape.plugin.composer.Plugin
 *  -in file          Use the named file as the input text document.
 *  -out file         Use the named file as the output text document.
 *  -string string    Use the given string as the test document.
 *                    Defaults to a small built-in test document.
 *  -workDir dir      Use the given dir as the work directory.
 *                    Defaults to java's user.dir property.
 *  -eventName event  Simulate an event of the given name.
 * 
* * Normally you don't derive from or instantiate Test. You just run it from the command * line. However, for special test purposes, it might make sense to derive from Test and * override methods like createDocument and createPlugin. */ public class Test { /** Hook for plugins to test themselves. If you have a plugin MyPlugin, add this * code to it to enable it to be tested in a stand-alone situation. *
     * /** Test the plugin. Not required for normal operation of the plugin.
     *  * You can use this to run the plugin from the command line:
     *  * java -classpath   args...
     *  * where args... are passed on to the Test class.
     *  * You can remove this code before shipping your plugin.
     *  * /
     * static public void main(String[] args) {
     *   Test.perform(args, new MyPlugin());
     * }
     * 
* Note: This method calls System.exit() at the end of the test. * It does so because otherwise any AWT threads that may have been * started will not be closed down, and as a result, the application will * never finish running. *

* The system exit code will be 0 if the test succeded. * 1 if the test failed. * -1 if an uncaught exception was thrown. */ public static void perform(String[] args, Plugin plugin){ int status = 0; try { Test test = new Test(args); test.setPlugin(plugin); status = test.test(); } catch (Throwable t) { System.err.println("Exception caught while running test."); t.printStackTrace(); status = -1; } System.exit(status); } /** Public main function. Called from outside. Creates and runs the test. * If you derive a new class from Test, you can make your own version of * main that looks like this: *

     * public static void main(String[] args){
     *     int status = 0;
     *     try {
     *         MyTest test = new MyTest(args);
     *         status = test.test();
     *     } catch (Throwable t) {
     *         t.printStackTrace();
     *         status = -1;
     *     }
     *     System.exit(status);
     * }
     * 
*/ public static void main(String[] args){ int status = 0; try { Test test = new Test(args); status = test.test(); } catch (Throwable t) { t.printStackTrace(); status = -1; } System.exit(status); } /** Parses the command-line arguments. * @param args The command-line arguments. */ protected Test(String[] args){ int length = args.length; for(int i = 0; i < length; i++ ){ String s = args[i]; if ( s.equalsIgnoreCase("-plugin") ){ argCheck(args, i, 1); duplicateCheck(args, i, pluginArg); pluginArg = args[++i]; } else if ( s.equalsIgnoreCase("-in") ){ argCheck(args, i, 1); duplicateCheck(args, i, inArg); inArg = args[++i]; } else if ( s.equalsIgnoreCase("-out") ){ argCheck(args, i, 1); duplicateCheck(args, i, outArg); outArg = args[++i]; } else if ( s.equalsIgnoreCase("-string") ){ argCheck(args, i, 1); duplicateCheck(args, i, stringArg); stringArg = args[++i]; } else if ( s.equalsIgnoreCase("-workDir") ){ argCheck(args, i, 1); duplicateCheck(args, i, workDirArg); workDirArg = args[++i]; } else if ( s.equalsIgnoreCase("-eventName") ){ argCheck(args, i, 1); duplicateCheck(args, i, eventNameArg); eventNameArg = args[++i]; } else { usage("Don't understand argument " + s); } } if ( inArg != null && stringArg != null ) { usage("Can't specify both -in and -string. Choose one."); } } private void duplicateCheck(String[] args, int index, String arg){ if ( arg != null ) { usage("duplicate flag not allowed. Only specify one " + args[index]); } } private void argCheck(String[] args, int index, int needed){ if ( args.length <= index + needed ) { usage("flag " + args[index] + " needs " + needed + " arguments."); } } /** Prints usage information, and then exits. * @param error A string to print to System.err just before printing the usage info. */ protected void usage(String error){ System.err.println(error); System.err.println("usage: [-plugin plugin][-in file | -string string][-out file][-workDir dir]\n" + " -plugin plugin Use the named plugin. Defaults to\n" + " netscape.plugin.composer.Plugin\n" + " -in file Use the named file as the input document.\n" + " -out file Use the named file as the output document.\n" + " -string string Use the given string as the test document.\n" + " Defaults to a small built-in test document.\n" + " -workDir dir Use the given dir as the work directory.\n" + " Defaults to java's user.dir property.\n" + " -eventName event Simulate an event of the given name.\n" ); System.exit(-1); } /** Perform the test. Override to implement an alternative test * technique. * @return 0 if the plug-in returned false, or 1 if the plug-in returned true. */ protected int test() throws IOException { int status = 0; TestDocument document = createDocument(); Plugin plugin = createPlugin(); // plugin.setProperties(createProperties()); System.out.println("Plugin class: " + plugin.getClass().toString()); System.out.println(" category: " + plugin.getCategory()); System.out.println(" name: " + plugin.getName()); System.out.println(" hint: " + plugin.getHint()); System.out.println("-------------------------------"); System.out.println("Original Document:\n"); System.out.println(" base: " + document.getBase()); System.out.println(" workDirectory: " + document.getWorkDirectory()); System.out.println(" workDirectoryURL: " + document.getWorkDirectoryURL()); System.out.println(" documentURL: " + document.getDocumentURL()); System.out.println(" eventName: " + document.getEventName()); System.out.println("Text:\n" + document.getText()); System.out.println("-------------------------------"); System.out.println("Calling plugin...\n"); String startText = document.getText(); boolean result = plugin.perform(document); System.out.println("-------------------------------"); System.out.println("Plugin.perform returned: " + result); System.out.println("-------------------------------"); if ( result && outArg != null ) { writeDoc(document.getText(), new File(outArg)); } if ( result ) { status = 0; } else { status = 1; } return status; } /** Writes the document text to the supplied file. */ protected void writeDoc(String doc, File out){ try { FileWriter s = new FileWriter(out); s.write(doc); s.close(); } catch(IOException e){ e.printStackTrace(); } } /** Called when the plug-in that's being tested has set some new text into the test document. * The default implementation just prints the text to System.out. * Override this if you want to do something more sophisiticated, * like comparing the old text with the new text. * @param text the new text of the test document. */ protected void newText(String text){ System.out.println("-------------------------------"); System.out.println("New Document text:\n"); System.out.println(text); } /** Called when the plug-in that's being tested has called redirectDocumentOpen. * The default implementation just prints the new URL to System.out. * Override this if you want to do something more sophisticated. * @param eventName the current event. (Should always be "edit", or else the plug-in * behaving incorrectly.) * @param newURL the new URL that the open should be redirected to. */ public void reportRedirectDocumentOpen(String eventName, String newURL){ System.out.println("-------------------------------"); System.out.println("redirectDocumentOpen: " + newURL); if ( eventName == null || !eventName.equals("edit") ) { System.out.println("Warning!!! This call has no effect, because the eventName is " + (eventName == null ? "null" : eventName)); } } /** Override this to create your own type of document. */ protected TestDocument createDocument() throws IOException { String workDir = ""; URL base = null; String text = ""; if ( workDirArg != null ) { workDir = workDirArg; } workDir = new File(workDir).getAbsolutePath(); if ( stringArg != null ) { text = stringArg; } else if ( inArg != null ) { StringBuffer fileContents = new StringBuffer(); File file = new File(inArg); file = new File(file.getAbsolutePath()); // System.err.println("file: " + file + " size: " + file.length()); /* // JDK 1.1 code FileReader in = new FileReader(file); int c; try { while ( (c = in.read()) >= 0 ) { fileContents.append( (char) c); } } catch (Throwable t){ t.printStackTrace(); } // System.err.println("file contents: " + fileContents.length() + " '" + fileContents + "'"); in.close(); text = fileContents.toString(); */ FileInputStream in = new FileInputStream(file); int c; try { while ( (c = in.read()) >= 0 ) { fileContents.append( (char) c); } } catch (Throwable t){ t.printStackTrace(); } // System.err.println("file contents: " + fileContents.length() + " '" + fileContents + "'"); in.close(); text = fileContents.toString(); base = toURL(file, true); } else { text = "A test document\n" + "\n" + "

Netscape

\n" + "

The quick brown fox " + "" + "jumped " + "" + "over the lazy dog.

\n" + "\n" + "\n"; base = toURL(new File(""), false); } URL docURL = null; if ( inArg != null ) { docURL = toURL(new File(inArg), false); } TestDocument document = new TestDocument(this, text, base, workDir, toURL(new File(workDir), false), docURL, eventNameArg ); return document; } /** Convert a File to a URL. * @param file a file. * @param base if true, don't include the file's name in the url, just the path. This * is handy for creating a base URL for a file. * @return the corresponding URL. */ static URL toURL(File file, boolean getBase) throws MalformedURLException { String path = file.getAbsolutePath(); file = new File(path); /* Absolutize. */ StringTokenizer tokenizer = new StringTokenizer(path, File.separator); StringBuffer urlBuf = new StringBuffer("file:"); boolean bEncodeIllegalCharacters = false; String allowedInURLs = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "$-_@.&+-"; boolean trimLast = getBase && ! file.isDirectory(); while(tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); if ( trimLast && ! tokenizer.hasMoreTokens() ) { break; } urlBuf.append("/"); if ( bEncodeIllegalCharacters ) { /* Escape letters not allowed in URLs */ for(int i = 0; i < token.length(); i++){ char c = token.charAt(i); if ( allowedInURLs.indexOf(c) < 0 ){ /* Not allowed */ urlBuf.append("%" + Integer.toHexString(c)); } else { urlBuf.append((char) c); } } } else { urlBuf.append(token); } } if ( (getBase && ! file.isDirectory()) || ( file.isDirectory() && ! urlBuf.toString().endsWith("/"))) { urlBuf.append("/"); } URL url = new URL(urlBuf.toString()); return url; } /** Used to set the plugin programmaticly. Used by the Test.perform method. */ public void setPlugin(Plugin plugin){ this.plugin = plugin; } /** Override this to create your own plugin. (Normally you would * use the -plugin command line option. Or supply the argument to * the Test.perform method.) */ protected Plugin createPlugin(){ if ( plugin != null ) return plugin; String pluginClassName = new String("netscape.plugin.composer.Plugin"); if ( pluginArg != null ) { pluginClassName = pluginArg; } plugin = null; try { plugin = (Plugin) Class.forName(pluginClassName).newInstance(); } catch (Throwable t){ t.printStackTrace(); } return plugin; } /** Override this to create your own properties. The default is to read the * propertiesArg */ protected Properties createProperties(){ String propertiesFile = new String("netscape_plugin_composer.ini"); if ( propertiesArg != null ) { propertiesFile = propertiesArg; } Properties properties = new Properties(); try { FileInputStream in = new FileInputStream(propertiesFile); properties.load(in); in.close(); } catch (Throwable t){ t.printStackTrace(); } return properties; } /** The argument the user supplied for -properties. Null if they didn't supply one. */ protected String propertiesArg; /** The argument the user supplied for -plugin. Null if they didn't supply one. */ protected String pluginArg; /** The argument the user supplied for -in. Null if they didn't supply one. */ protected String inArg; /** The argument the user supplied for -out. Null if they didn't supply one. */ protected String outArg; /** The argument the user supplied for -string. Null if they didn't supply one. */ protected String stringArg; /** The argument the user supplied for -workDir. Null if they didn't supply one. */ protected String workDirArg; /** The plugin the user supplied programmaticly. Null if they didn't supply one. */ protected Plugin plugin; protected String eventNameArg; }