package org.apache.maven.abbot;

/* ====================================================================
 *   Copyright 2004 The Apache Software Foundation.
 *
 *   Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 * ====================================================================
 */

import java.io.File;

import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.optional.junit.FormatterElement;
import org.apache.tools.ant.taskdefs.optional.junit.JUnitTask;
import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest;

/**
 * Proxy for testing webstart application with Abbot. It replaces the main
 * class of the application to test and uses the JUnit Ant task test runner
 * to execute the Abbot tests. In order to use this class, it must be 
 * referenced as the main class in the JNLP file. 
 * 
 * @version $Id$
 */
public class AbbotWebstartTestRunner
{
    /**
     * Name of the generic TestCase to execute. That test will execute all the
     * XML Abbot scripts.
     */
    private static final String GENERIC_TEST = AbbotTestAll.class.getName();

    /**
     * Directory where junit reports are to be generated.
     */
    private static final String REPORT_DIR = 
        System.getProperty("maven.abbot.reports.dir", "");

    /**
     * Name given by the user to the suite of tests being executed. The Abbot
     * test report will be name after the content of this property. This is
     * useful when you're calling the Abbot plugin several times in a row as
     * otherwise the reports will overwrite each other.
     */
    private static final String TESTSUITE_NAME = 
        System.getProperty("maven.abbot.suite.name");
    
    /**
     * Entry point for starting the Ant JUnit test runner which will start
     * all our Abbot script tests. 
     * 
     * @param args the parameters that we need to use to start the Ant test
     *        runner
     * @throws Exception in case of unanticipated error
     */
    public static void main(String[] args) throws Exception
    {
        AbbotWebstartTestRunner main = new AbbotWebstartTestRunner();
        main.execute(GENERIC_TEST, REPORT_DIR);
    }
    
    /**
     * Execute the JUnit test runner using the Ant JUnitTask task. 
     * 
     * Note: We absolutely need to call System.exit() as all webstart 
     * applications are required to do so. This is required for the
     * application to close at the end of the tests
     * (see http://www.vamphq.com/jwsfaq.html#linger).
     * 
     * @param testName the name of the generic test that will in turn run all
     *        the Abbot XML scripts
     * @param reportdir directory where junit reports are to be generated
     * @throws Exception in case of unanticipated error
     */
    public void execute(String testName, String reportDir)
    {
        try
        {
            executeAntJunitTestRunner(testName, reportDir);
            System.exit(0);
        }
        catch (Throwable t)
        {
            System.exit(1);
        }
    }
    
    /**
     * Execute the JUnit test runner using the Ant JUnitTask task.
     * 
     * @param testName the name of the generic test that will in turn run all
     *        the Abbot XML scripts
     * @param reportdir directory where junit reports are to be generated
     * @throws Exception in case of unanticipated error
     */
    private void executeAntJunitTestRunner(String testName, String reportDir)
    	throws Exception
    {
        Project project = new Project();
	    project.init();
	    
	    JUnitTask junit = new JUnitTask();
	    junit.setProject(project);

	    // Do not fork so that we use the same classpath that was used to
	    // start this class.
	    junit.setFork(false);
	    
	    // Set properties of the JUnit Ant task

	    // Set formatter
	    junit.addFormatter(createFormatterElement("xml"));
	    junit.addFormatter(createFormatterElement("plain"));
	    
	    // Add tests to run
	    JUnitTest test = new JUnitTest(testName);
	    test.setTodir(new File(reportDir));

        // Sets the name of the report file is the user has specified a name.
        // Otherwise the name of the AbbotTestAll class will be used.
        if (TESTSUITE_NAME != null)
        {
	        test.setOutfile(TESTSUITE_NAME);
        }
        junit.addTest(test);

	    // Other settings
	    junit.setHaltonerror(true);
	    junit.setHaltonfailure(true);
	    
	    // Execute the task...
	    junit.execute();        
    }
    
    /**
     * @param type the formatter type ("xml", "plain" or "brief")
     * @return a properly set {@link FormatterElement} object 
     */
    private FormatterElement createFormatterElement(String type)
    {
	    FormatterElement formatterElement = new FormatterElement();
	    FormatterElement.TypeAttribute typeAttribute =
	        new FormatterElement.TypeAttribute();
	    typeAttribute.setValue(type);
	    formatterElement.setType(typeAttribute);
	    return formatterElement;
    }
}
