| /* |
| * The Apache Software License, Version 1.1 |
| * |
| * |
| * Copyright (c) 2001-2003 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Xalan" and "Apache Software Foundation" must |
| * not be used to endorse or promote products derived from this |
| * software without prior written permission. For written |
| * permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * nor may "Apache" appear in their name, without prior written |
| * permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation and was |
| * originally based on software copyright (c) 2000, Lotus |
| * Development Corporation., http://www.lotus.com. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| */ |
| |
| /* |
| * |
| * TestletImpl.java |
| * |
| */ |
| package org.apache.qetest; |
| |
| |
| |
| /** |
| * Simple implementation of a testlet, a sort of mini-test. |
| * <p>A TestletImpl defines some common implementations that |
| * may be useful, including sample implementations that |
| * can be copied if you don't want to exend this class.</p> |
| * |
| * <p>The most useful implementation is of main(String[]), which |
| * allows a Testlet to be executed independently from the command |
| * line. See the code comments for a way to get this behavior in |
| * your testlet without having to re-implement the whole main |
| * method - by just including a static{} initializer with the |
| * fully qualified classname of your class.</p> |
| * |
| * <b>Note:</b> Testlets based on this class are probably |
| * not threadsafe, and must be executed singly! |
| * See comments for thisClassName. |
| * |
| * @author Shane_Curcuru@lotus.com |
| * @version $Id$ |
| */ |
| public class TestletImpl implements Testlet |
| { |
| |
| //----------------------------------------------------- |
| //---- Implement Testlet interface methods |
| //----------------------------------------------------- |
| |
| /** |
| * Accesor method for a brief description of this test. |
| * |
| * @return String "TestletImpl: default implementation, does nothing" |
| */ |
| public String getDescription() |
| { |
| return "TestletImpl: default implementation, does nothing"; |
| } |
| |
| |
| /** |
| * Accesor methods for our Logger. |
| * |
| * @param l the Logger to have this test use for logging |
| * results; or null to use a default logger |
| */ |
| public void setLogger(Logger l) |
| { |
| // if null, set a default one |
| if (null == l) |
| logger = getDefaultLogger(); |
| else |
| logger = l; |
| } |
| |
| |
| /** |
| * Accesor methods for our Logger. |
| * |
| * @return Logger we tell all our secrets to. |
| */ |
| public Logger getLogger() |
| { |
| return logger; |
| } |
| |
| |
| /** |
| * Get a default Logger for use with this Testlet. |
| * Gets a default ConsoleLogger (only if a Logger isn't |
| * currently set!). |
| * |
| * @return current logger; if null, then creates a |
| * Logger.DEFAULT_LOGGER and returns that; if it cannot |
| * create one, throws a RuntimeException |
| */ |
| public Logger getDefaultLogger() |
| { |
| if (logger != null) |
| return logger; |
| |
| try |
| { |
| Class rClass = Class.forName(Logger.DEFAULT_LOGGER); |
| return (Logger)rClass.newInstance(); |
| } |
| catch (Exception e) |
| { |
| // Must re-throw the exception, since returning |
| // null or the like could lead to recursion |
| e.printStackTrace(); |
| throw new RuntimeException(e.toString()); |
| } |
| } |
| |
| |
| /** |
| * Return this TestletImpl's default Datalet. |
| * |
| * @return Datalet <code>defaultDatalet</code>. |
| */ |
| public Datalet getDefaultDatalet() |
| { |
| return defaultDatalet; |
| } |
| |
| |
| /** |
| * Run this TestletImpl: execute it's test and return. |
| * This must (obviously) be overriden by subclasses. Here, |
| * we simply log a message for debugging purposes. |
| * |
| * @param Datalet to use as data points for the test. |
| */ |
| public void execute(Datalet datalet) |
| { |
| logger.logMsg(Logger.STATUSMSG, "TestletImpl.execute(" + datalet + ")"); |
| } |
| |
| |
| //----------------------------------------------------- |
| //---- Implement useful worker methods and main() |
| //----------------------------------------------------- |
| |
| /** |
| * Process default command line args. |
| * Provides simple usage functionality: given a first arg of |
| * -h, -H, -?, prints a usage statement based on getDescription() |
| * and on getDefaultDatalet().getDescription() |
| * |
| * @param args command line args from the JVM |
| * @return true if we got and handled any default command line |
| * args (i.e. you can quit now); false otherwise (i.e. you |
| * should go ahead and execute) |
| */ |
| protected boolean handledDefaultArgs(String[] args) |
| { |
| // We don't handle null or blank args |
| if ((null == args) || (0 == args.length)) |
| return false; |
| |
| // Provide basic processing for help, usage cases |
| if ("-h".equals(args[0]) |
| || "-H".equals(args[0]) |
| || "-?".equals(args[0]) |
| ) |
| { |
| logger.logMsg(Logger.STATUSMSG, thisClassName + " usage:"); |
| logger.logMsg(Logger.STATUSMSG, " Testlet: " + getDescription()); |
| logger.logMsg(Logger.STATUSMSG, " Datalet: " + getDefaultDatalet().getDescription()); |
| return true; |
| } |
| |
| // Otherwise, don't handle any other args |
| return false; |
| } |
| |
| |
| /** |
| * Default implementation for command line use. |
| * Note subclasses can easily get the functionality we provide |
| * here without having to copy this method merely by copying the |
| * static initalization block shown above, replacing the |
| * "thisClassName" with their own FQCN. |
| * |
| * This default implementation installs a default Logger, then |
| * checks for and handles a few default command line args, and |
| * then executes the Testlet. |
| * |
| * //@todo How do we easily specify alternate Datalets or |
| * data to load a Datalet from? What about the Datalet that |
| * actually wants the first arg to be -h? |
| * |
| * @param args command line args from the JVM |
| */ |
| public static void main(String[] args) |
| { |
| if (true) |
| System.out.println("TestletImpl.main"); |
| TestletImpl t = null; |
| try |
| { |
| // Create an instance of the specific class at runtime |
| // This relies on subclasses to reset 'thisClassName' |
| // in their own static[] initialization block! |
| t = (TestletImpl)Class.forName(thisClassName).newInstance(); |
| |
| // Set a default logger automatically |
| t.setLogger(t.getDefaultLogger()); |
| |
| // Process default -h, etc. args |
| if (!t.handledDefaultArgs(args)) |
| { |
| if (args.length > 0) |
| { |
| // If we do have any args, then attempt to |
| // load the correct-typed Datalet from the args |
| Class dataletClass = t.getDefaultDatalet().getClass(); |
| t.logger.logMsg(Logger.TRACEMSG, "Loading Datalet " |
| + dataletClass.getName() + " from args"); |
| Datalet d = (Datalet)dataletClass.newInstance(); |
| d.load(args); |
| t.execute(d); |
| } |
| else |
| { |
| // Otherwise, use the defaultDatalet for that Testlet |
| t.logger.logMsg(Logger.TRACEMSG, "Using defaultDatalet"); |
| t.execute(t.getDefaultDatalet()); |
| } |
| } |
| } |
| catch (Exception e) |
| { |
| if ((null != t) && (null != t.logger)) |
| { |
| // Use the logger which is (hopefully) OK |
| t.logger.checkErr("TestletImpl threw: " + e.toString()); |
| java.io.StringWriter sw = new java.io.StringWriter(); |
| java.io.PrintWriter pw = new java.io.PrintWriter(sw); |
| e.printStackTrace(pw); |
| t.logger.logArbitrary(Logger.ERRORMSG, sw.toString()); |
| } |
| else |
| { |
| // Otherwise, just dump to System.err |
| System.err.println("TestletImpl threw: " + e.toString()); |
| e.printStackTrace(); |
| } |
| } |
| } |
| |
| |
| /** |
| * The FQCN of the current class. |
| * See comments in main() and in the static initializer. |
| * <b>Note:</b> Testlets based on this class are probably |
| * not threadsafe, and must be executed singly! |
| */ |
| protected static String thisClassName = null; |
| |
| |
| /** |
| * A static initializer setting the value of thisClassName. |
| * Subclasses must copy this static block, and replace the |
| * name of "...TestletImpl" with their own name. Then, when |
| * a user executes the subclassed Testlet on the command line |
| * or calls it's main() method, the correct thing will happen. |
| */ |
| static { thisClassName = "org.apache.qetest.TestletImpl"; } |
| |
| |
| /** |
| * Our Logger, who we tell all our secrets to. |
| */ |
| protected Logger logger = null; |
| |
| |
| /** |
| * Our deafult Datalet: in this case, not very interesting. |
| * Provide a default 'null' datalet so unsuspecting callers |
| * don't get NullPointerExceptions. |
| */ |
| protected Datalet defaultDatalet = new NullDatalet(); |
| |
| } // end of class TestletImpl |