Package org.apache.cactus.integration.ant

Source Code of org.apache.cactus.integration.ant.CactusTask

/*
* ========================================================================
*
* Copyright 2003-2005 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.
*
* ========================================================================
*/
package org.apache.cactus.integration.ant;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.ResourceBundle;

import org.apache.cactus.integration.ant.container.Container;
import org.apache.cactus.integration.ant.container.ContainerRunner;
import org.apache.cactus.integration.ant.deployment.DeployableFile;
import org.apache.cactus.integration.ant.deployment.EarParser;
import org.apache.cactus.integration.ant.deployment.WarParser;
import org.apache.cactus.integration.ant.util.AntLog;
import org.apache.cactus.integration.ant.util.AntTaskFactory;
import org.apache.cactus.integration.ant.util.DefaultAntTaskFactory;
import org.apache.cactus.integration.ant.util.PropertySet;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.optional.junit.JUnitTask;
import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest;
import org.apache.tools.ant.types.Environment;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Environment.Variable;

/**
* An Ant task that extends the optional JUnit task to provide support for
* in-container testing.
*
* @version $Id: CactusTask.java 239130 2005-01-29 15:49:18Z vmassol $
*/
public class CactusTask extends JUnitTask
{
    // Instance Variables ------------------------------------------------------

    /**
     * The nested containerset element.
     */
    private ContainerSet containerSet;

    /**
     * The archive that contains the enterprise application that should be
     * tested.
     */
    private File earFile;

    /**
     * The archive that contains the web-app that is ready to be tested.
     */
    private File warFile;

    /**
     * System properties that will be set in the container JVM.
     */
    private List systemProperties = new ArrayList();

    /**
     * Additional classpath entries for the classpath that will be used to
     * start the containers.
     */
    private Path containerClasspath;
   
    // Constructors ------------------------------------------------------------
   
    /**
     * Constructor.
     *
     * @throws Exception If the constructor of JUnitTask throws an exception
     */
    public CactusTask() throws Exception
    {
        // TODO: Fix comment for this constructor as it doesn't seem quite
        // right. Explain why we don't call the super constructor?
    }

    // Public Methods ----------------------------------------------------------

    /**
     * @see org.apache.tools.ant.Task#init()
     */
    public void init()
    {
        super.init();
       
        addClasspathEntry("/org/aspectj/lang/JoinPoint.class");
        addClasspathEntry("/org/apache/cactus/ServletTestCase.class");
        addClasspathEntry(
            "/org/apache/cactus/integration/ant/CactusTask.class");
        addClasspathEntry("/org/apache/commons/logging/Log.class");
        addClasspathEntry("/org/apache/commons/httpclient/HttpClient.class");
    }

    /**
     * @see org.apache.tools.ant.Task#execute()
     */
    public void execute() throws BuildException
    {
        if ((this.warFile == null) && (this.earFile == null))
        {
            throw new BuildException("You must specify either the [warfile] or "
                + "the [earfile] attribute");
        }

        if ((this.warFile != null) && (this.earFile != null))
        {
            throw new BuildException("You must specify either the [warfile] or "
                + "the [earfile] attribute but not both");
        }

        // Parse deployment descriptors for WAR or EAR files
        DeployableFile deployableFile;
        if (this.warFile != null)
        {
            deployableFile = WarParser.parse(this.warFile);
        }
        else
        {
            deployableFile = EarParser.parse(this.earFile);
        }

        addRedirectorNameProperties(deployableFile);
       
        if (this.containerSet == null)
        {
            log("No containers specified, tests will run locally",
                Project.MSG_VERBOSE);
            super.execute();
        }
        else
        {
            Container[] containers = this.containerSet.getContainers();
            Variable contextUrl = new Variable();
            contextUrl.setKey("cactus.contextURL");
            addSysproperty(contextUrl);

            AntTaskFactory antTaskFactory = new DefaultAntTaskFactory(
                getProject(), getTaskName(), getLocation(), getOwningTarget());
           
            for (int i = 0; i < containers.length; i++)
            {
                containers[i].setAntTaskFactory(antTaskFactory);
                containers[i].setLog(new AntLog(this));

                // Clone the DeployableFile instance as each container can
                // override default deployment properties (e.g. port, context
                // root, etc).
                DeployableFile thisDeployable = null;
                try
                {
                    thisDeployable = (DeployableFile) deployableFile.clone();
                }
                catch (CloneNotSupportedException e)
                {
                    throw new BuildException(e);
                }
                containers[i].setDeployableFile(thisDeployable);

                // Allow the container to override the default test context.
                // This is to support container extensions to the web.xml file.
                // Most containers allow defining the root context in these
                // extensions.
                if (containers[i].getTestContext() != null)
                {
                    thisDeployable.setTestContext(
                        containers[i].getTestContext());
                }              
               
                containers[i].setSystemProperties(
                    (Variable[]) this.systemProperties.toArray(
                        new Variable[0]));

                // Add extra classpath entries
                containers[i].setContainerClasspath(this.containerClasspath);
               
                if (containers[i].isEnabled())
                {
                    containers[i].init();
                    log("--------------------------------------------------"
                        + "---------------", Project.MSG_INFO);
                    log("Running tests against " + containers[i].getName()
                        + " @ " + containers[i].getBaseURL(),
                        Project.MSG_INFO);
                    log("--------------------------------------------------"
                        + "---------------", Project.MSG_INFO);
                    contextUrl.setValue(containers[i].getBaseURL() + "/"
                        + thisDeployable.getTestContext());
                    executeInContainer(containers[i], thisDeployable);
                }
            }
        }
    }

    /**
     * Adds the nested containers element (only one is permitted).
     *
     * @param theContainerSet The nested element to add
     */
    public final void addContainerSet(ContainerSet theContainerSet)
    {
        if (this.containerSet != null)
        {
            throw new BuildException(
                "Only one nested containerset element supported");
        }
        this.containerSet = theContainerSet;
    }

    /**
     * Sets the enterprise application archive that will be tested. It must
     * already contain the test-cases and the required libraries as a web
     * module.
     *
     * @param theEarFile The EAR file to set 
     */
    public final void setEarFile(File theEarFile)
    {
        if (this.warFile != null)
        {
            throw new BuildException(
                "You may only specify one of [earfile] and [warfile]");
        }
        this.earFile = theEarFile;
    }

    /**
     * Sets the web application archive that will be tested. It must already
     * contain the test-cases and the required libraries.
     *
     * @param theWarFile The WAR file to set 
     */
    public final void setWarFile(File theWarFile)
    {
        if (this.earFile != null)
        {
            throw new BuildException(
                "You may only specify one of [earfile] and [warfile]");
        }
        this.warFile = theWarFile;
    }

    /**
     * Adds a system property to both client side and server side JVMs.
     * @see JUnitTask#addSysproperty(Environment.Variable)
     */
    public void addSysproperty(Environment.Variable theProperty)
    {
        addCactusServerProperty(theProperty);
        super.addSysproperty(theProperty);
    }

    /**
     * Called by Ant when the Variable object has been properly initialized.
     *
     * @param theProperty the system property to set
     */
    public void addConfiguredSysproperty(Environment.Variable theProperty)
    {
        addSysproperty(theProperty);
    }

    /**
     * Adds a set of properties that will be used as system properties
     * either on the client side or on the server side.
     *
     * @param thePropertySet the set of properties to be added
     */
    public void addConfiguredCactusproperty(PropertySet thePropertySet)
    {
        // Add all properties from the properties file
        ResourceBundle bundle = thePropertySet.readProperties();
        Enumeration keys = bundle.getKeys();
        while (keys.hasMoreElements())
        {
            String key = (String) keys.nextElement();
            Variable var = new Variable();
            var.setKey(key);
            var.setValue(bundle.getString(key));
            if (thePropertySet.isServer())
            {
                addCactusServerProperty(var);
            }
            else
            {
                super.addSysproperty(var);
            }
        }
    }

    /**
     * Adds container classpath to the classpath that will be used for starting
     * the container.
     *
     * @return reference to the classpath
     * @since Cactus 1.6
     */
    public Path createContainerClasspath()
    {
        if (this.containerClasspath == null)
        {
            this.containerClasspath = new Path(this.project);           
        }
       
        return this.containerClasspath.createPath();
    }   
   
    // Private Methods ---------------------------------------------------------

    /**
     * Adds a Cactus system property for the client side JVM.
     *
     * @param theKey The property name
     * @param theValue The property value
     */
    private void addCactusClientProperty(String theKey, String theValue)
    {
        log("Adding Cactus client system property [" + theKey
            + "] with value [" + theValue + "]", Project.MSG_VERBOSE);
        Variable sysProperty = new Variable();
        sysProperty.setKey(theKey);
        sysProperty.setValue(theValue);
        super.addSysproperty(sysProperty);
    }

    /**
     * Adds a Cactus system property for the server side JVM.
     *
     * @param theProperty The system property to set in the container JVM
     */
    private void addCactusServerProperty(Variable theProperty)
    {
        log("Adding Cactus server system property ["
            + theProperty.getKey() + "] with value ["
            + theProperty.getValue() + "]", Project.MSG_VERBOSE);
        this.systemProperties.add(theProperty);
    }

    /**
     * Adds a Cactus system property for the server side JVM.
     *
     * @param theKey The property name
     * @param theValue The property value
     */
    private void addCactusServerProperty(String theKey, String theValue)
    {
        Variable property = new Variable();
        property.setKey(theKey);
        property.setValue(theValue);
        addCactusServerProperty(property);
    }
   
    /**
     * Extracts the redirector mappings from the deployment descriptor and sets
     * the corresponding system properties.
     *
     * @param theFile The file to deploy in the container
     */
    private void addRedirectorNameProperties(DeployableFile theFile)
    {
        String filterRedirectorMapping =
            theFile.getFilterRedirectorMapping();
        if (filterRedirectorMapping != null)
        {
            addCactusClientProperty("cactus.filterRedirectorName",
                filterRedirectorMapping.substring(1));
        }
        else
        {
            log("No mapping of the filter redirector found",
                Project.MSG_VERBOSE);
        }

        String jspRedirectorMapping =
            theFile.getJspRedirectorMapping();
        if (jspRedirectorMapping != null)
        {
            addCactusClientProperty("cactus.jspRedirectorName",
                jspRedirectorMapping.substring(1));
        }
        else
        {
            log("No mapping of the JSP redirector found",
                Project.MSG_VERBOSE);
        }

        String servletRedirectorMapping =
            theFile.getServletRedirectorMapping();
        if (servletRedirectorMapping != null)
        {
            addCactusClientProperty("cactus.servletRedirectorName",
                servletRedirectorMapping.substring(1));
        }
        else
        {
            throw new BuildException("The WAR has not been cactified");
        }
    }

    /**
     * Executes the unit tests in the given container.
     *
     * @param theContainer The container to run the tests against
     * @param theFile the file to deploy in the container
     */
    private void executeInContainer(Container theContainer,
        DeployableFile theFile)
    {
        log("Starting up container", Project.MSG_VERBOSE);
        ContainerRunner runner = new ContainerRunner(theContainer);
        runner.setLog(new AntLog(this));
        try
        {
            URL url = new URL(theContainer.getBaseURL() + "/"
                + theFile.getTestContext()
                + theFile.getServletRedirectorMapping()
                + "?Cactus_Service=RUN_TEST");
            runner.setURL(url);
            if (this.containerSet.getTimeout() > 0)
            {
                runner.setTimeout(this.containerSet.getTimeout());
            }
            runner.startUpContainer();
            log("Server name retrieved from 'Server' HTTP header: ["
                + runner.getServerName() + "]", Project.MSG_VERBOSE);
            try
            {
                Enumeration tests = getIndividualTests();
                while (tests.hasMoreElements())
                {
                    JUnitTest test = (JUnitTest) tests.nextElement();
                    if (test.shouldRun(getProject())
                     && !theContainer.isExcluded(test.getName()))
                    {
                        if (theContainer.getToDir() != null)
                        {
                            test.setTodir(theContainer.getToDir());
                        }
                        execute(test);
                    }
                }
            }
            finally
            {
                log("Shutting down container", Project.MSG_VERBOSE);
                runner.shutDownContainer();
                log("Container shut down", Project.MSG_VERBOSE);
            }
        }
        catch (MalformedURLException mue)
        {
            throw new BuildException("Malformed test URL", mue);
        }
    }
}
TOP

Related Classes of org.apache.cactus.integration.ant.CactusTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.