Package org.apache.cactus.integration.ant

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

/*
* ========================================================================
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.io.FileInputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import org.apache.cactus.integration.api.cactify.FilterRedirector;
import org.apache.cactus.integration.api.cactify.JspRedirector;
import org.apache.cactus.integration.api.cactify.Redirector;
import org.apache.cactus.integration.api.cactify.ServletRedirector;
import org.apache.cactus.integration.api.version.Version;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.War;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.XMLCatalog;
import org.apache.tools.ant.types.ZipFileSet;
import org.codehaus.cargo.container.internal.util.ResourceUtils;
import org.codehaus.cargo.module.webapp.DefaultWarArchive;
import org.codehaus.cargo.module.webapp.EjbRef;
import org.codehaus.cargo.module.webapp.WarArchive;
import org.codehaus.cargo.module.webapp.WebXml;
import org.codehaus.cargo.module.webapp.WebXmlIo;
import org.codehaus.cargo.module.webapp.WebXmlUtils;
import org.codehaus.cargo.module.webapp.WebXmlVersion;
import org.codehaus.cargo.module.webapp.merge.WebXmlMerger;
import org.codehaus.cargo.util.log.AntLogger;
import org.jdom.JDOMException;

/**
* An Ant task that injects elements necessary to run Cactus tests into an
* existing WAR file.
*
* @version $Id: CactifyWarTask.java 394252 2006-04-15 04:20:17Z felipeal $
*/
public class CactifyWarTask extends War
{

    // Constants ---------------------------------------------------------------

    /**
     * Context of the cactus web application.
     */
    private String context;

    /**
     * Name of the generated web app file.
     */
    private String FILE_NAME = "cactus.war";

    /**
     * Get some non-crypto-grade randomness from various places.
     */
    private static Random rand = new Random(System.currentTimeMillis()
            + Runtime.getRuntime().freeMemory());

    /**
     * The name of the Cactus filter redirector class.
     */
    private static final String FILTER_REDIRECTOR_CLASS =
        "org.apache.cactus.server.FilterTestRedirector";

    /**
     * The default mapping of the Cactus filter redirector.
     */
    private static final String DEFAULT_FILTER_REDIRECTOR_MAPPING =
        "/FilterRedirector";

    /**
     * The default mapping of the Cactus JSP redirector.
     */
    private static final String DEFAULT_JSP_REDIRECTOR_MAPPING =
        "/JspRedirector";

    /**
     * The name of the Cactus servlet redirector class.
     */
    private static final String SERVLET_REDIRECTOR_CLASS =
        "org.apache.cactus.server.ServletTestRedirector";

    /**
     * The default mapping of the Cactus servlet redirector.
     */
    private static final String DEFAULT_SERVLET_REDIRECTOR_MAPPING =
        "/ServletRedirector";

    // Inner Classes -----------------------------------------------------------

    // Instance Variables ------------------------------------------------------

    /**
     * The archive that contains the web-app that should be cactified.
     */
    private File srcFile;

    /**
     * Location of the descriptor of which the content should be merged into
     * the descriptor of the cactified archive.
     */
    private File mergeWebXml;

    /**
     * The Cactus test redirectors.
     */
    private List redirectors = new ArrayList();

    /**
     * For resolving entities such as DTDs.
     */
    private XMLCatalog xmlCatalog = null;

    /**
     * The web-app version to use when creating a WAR from scratch.
     */
    private String version = null;

    /**
     * List of ejb-refs to add to the deployment descriptor
     * of the cactified war.
     */
    private List ejbRefs = new ArrayList();
    /**
     * The cargo ResourceUtils.
     */
    private ResourceUtils utils = new ResourceUtils();

    /**
     * Determines if cactus jars should be included.
     */
    private boolean includeCactusJars = true;

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


    /**
     * {@inheritDoc}
     * @see org.apache.tools.ant.Task#execute()
     */
    public void execute() throws BuildException
    {
        WebXml webXml = null;
        if (this.srcFile != null)
        {
            log("Analyzing war: " + this.srcFile.getAbsolutePath(),
                Project.MSG_INFO);

            // Add everything that's in the source WAR to the destination WAR
            ZipFileSet currentFiles = new ZipFileSet();
            currentFiles.setSrc(this.srcFile);
            currentFiles.createExclude().setName("WEB-INF/web.xml");
            currentFiles.createExclude().setName("WEB-INF/weblogic.xml");
            currentFiles.createExclude().setName("WEB-INF/orion-web.xml");
            currentFiles.createExclude().setName("WEB-INF/ibm-web-bnd.xmi");
            addZipfileset(currentFiles);

            // Parse the original deployment descriptor
            try
            {
                webXml = getOriginalWebXml();

            }
            catch (JDOMException e)
            {
                throw new BuildException("Unable to get the original exception", e);
            }
        }
        if (this.srcFile == null || webXml == null)
        {
            if (this.version == null)
            {
                throw new BuildException("You need to specify either the "
                    + "[srcfile] or the [version] attribute");
            }
            WebXmlVersion webXmlVersion = null;
            if (this.version.equals("2.2"))
            {
                webXmlVersion = WebXmlVersion.V2_2;
            }
            else if (this.version.equals("2.3"))
            {
                webXmlVersion = WebXmlVersion.V2_3;
            }
            else
            {
                webXmlVersion = WebXmlVersion.V2_4;
            }

            webXml = WebXmlIo.newWebXml(webXmlVersion);
        }

        File tmpWebXml = null;
        try
        {
            tmpWebXml = cactifyWebXml(webXml);
        }
        catch (JDOMException e)
        {
            throw new BuildException("Unable to cactify your application.", e);
        }
        setWebxml(tmpWebXml);

        if(includeCactusJars)
        {
            addCactusJars();
        }

        try
        {
            super.execute();
        }
        finally
        {
            // Even though the temporary descriptor will get deleted
            // automatically when the VM exits, delete it explicitly here just
            // to be a better citizen
            tmpWebXml.delete();
        }
    }

    /**
     * Adds a Cactus filter test redirector.
     *
     * @param theFilterRedirector The redirector to add
     */
    public final void addFilterRedirector(FilterRedirector theFilterRedirector)
    {
        this.redirectors.add(theFilterRedirector);
    }

    /**
     * Adds a Cactus JSP test redirector.
     *
     * @param theJspRedirector The redirector to add
     */
    public final void addJspRedirector(JspRedirector theJspRedirector)
    {
        this.redirectors.add(theJspRedirector);
    }

    /**
     * Adds a Cactus servlet test redirector.
     *
     * @param theServletRedirector The redirector to add
     */
    public final void addServletRedirector(
        ServletRedirector theServletRedirector)
    {
        this.redirectors.add(theServletRedirector);
    }

    /**
     * Adds an XML catalog to the internal catalog.
     *
     * @param theXmlCatalog the XMLCatalog instance to use to look up DTDs
     */
    public final void addConfiguredXMLCatalog(XMLCatalog theXmlCatalog)
    {
        if (this.xmlCatalog == null)
        {
            this.xmlCatalog = new XMLCatalog();
            this.xmlCatalog.setProject(getProject());
        }
        this.xmlCatalog.addConfiguredXMLCatalog(theXmlCatalog);
    }

    /**
     * Adds a configured EjbRef instance. Called by Ant.
     *
     * @param theEjbRef the EjbRef to add
     */
    public final void addConfiguredEjbref(EjbRef theEjbRef)
    {
        ejbRefs.add(theEjbRef);
    }

    /**
     * The descriptor to merge into the original file.
     *
     * @param theMergeFile the <code>web.xml</code> to merge
     */
    public final void setMergeWebXml(File theMergeFile)
    {
        this.mergeWebXml = theMergeFile;
    }

    /**
     * Sets the web application archive that should be cactified.
     *
     * @param theSrcFile The WAR file to set
     */
    public final void setSrcFile(File theSrcFile)
    {
        this.srcFile = theSrcFile;
    }

    /**
     * Sets the web-app version to use when creating a WAR file from scratch.
     *
     * @param theVersion The version
     */
    public final void setVersion(Version theVersion)
    {
        this.version = theVersion.getValue();
    }

    /**
     * Sets whether the cactus jars should be included or not.
     * If not set, the jars are included by default.
     *
     * @param includeCactusJars <code>true</code> if cactus jars should be included,
     * <code>false</code> otherwise.
     */
    public final void setIncludeCactusJars(boolean includeCactusJars)
    {
        this.includeCactusJars = includeCactusJars;
    }


    // Private Methods ---------------------------------------------------------

    /**
     * Adds the libraries required by Cactus on the server side.
     */
    private void addCactusJars()
    {
        addJarWithClass("org.aspectj.lang.JoinPoint", "AspectJ Runtime");
        addJarWithClass("org.apache.cactus.ServletTestCase",
            "Cactus Framework");
        addJarWithClass("org.apache.commons.logging.Log",
            "Commons-Logging");
        addJarWithClass("org.apache.commons.httpclient.HttpClient",
            "Commons-HttpClient");
        addJarWithClass("junit.framework.TestCase", "JUnit");
    }

    /**
     * Adds the JAR file containing the specified resource to the WEB-INF/lib
     * folder of a web-application archive.
     *
     * @param theClassName The name of the class that the JAR contains
     * @param theDescription A description of the JAR that should be displayed
     *        to the user in log messages
     */
    private void addJarWithClass(String theClassName, String theDescription)
    {
        String resourceName = "/" + theClassName.replace('.', '/') + ".class";
        if (this.srcFile != null)
        {
            try
            {
                WarArchive srcWar = new DefaultWarArchive(
                    new FileInputStream(srcFile));
                if (srcWar.containsClass(theClassName))
                {
                    log("The " + theDescription + " JAR is already present in "
                        + "the WAR", Project.MSG_VERBOSE);
                    return;
                }
            }
            catch (IOException ioe)
            {
                log("Problem reading source WAR to when trying to detect "
                    + "already present JAR files (" + ioe + ")",
                    Project.MSG_WARN);
            }
        }
        ZipFileSet jar = new ZipFileSet();

        File file = utils.getResourceLocation(resourceName);
        if (file != null)
        {
            jar.setFile(file);
            addLib(jar);
        }
        else
        {
            log("Could not find the " + theDescription + " JAR",
                Project.MSG_WARN);
            log("You need to add the JAR to the classpath of the task",
                Project.MSG_INFO);
            log("(Searched for class " + theClassName + ")", Project.MSG_DEBUG);
        }
    }

    /**
     * Adds the Cactus JSP redirector file to the web application.
     */
    private void addJspRedirector()
    {
        // Now copy the actual JSP redirector file into the web application
        File jspRedirectorFile = new File(
            new File(System.getProperty("java.io.tmpdir")),
            "jspRedirector.jsp");
        jspRedirectorFile.deleteOnExit();
        try
        {
            utils.copyResource("/org/apache/cactus/server/jspRedirector.jsp",
                jspRedirectorFile);
        }
        catch (IOException e)
        {
            log("Could not copy the JSP redirector (" + e.getMessage() + ")",
                Project.MSG_WARN);
        }
        FileSet fileSet = new FileSet();
        fileSet.setFile(jspRedirectorFile);
        addFileset(fileSet);
    }

    /**
     * Adds the definitions corresponding to the nested redirector elements to
     * the provided deployment descriptor.
     *
     * @param theWebXml The deployment descriptor
     */
    private void addRedirectorDefinitions(WebXml theWebXml)
    {
        boolean filterRedirectorDefined = false;
        boolean jspRedirectorDefined = false;
        boolean servletRedirectorDefined = false;

        // add the user defined redirectors
        for (Iterator i = this.redirectors.iterator(); i.hasNext();)
        {

            Redirector redirector = (Redirector) i.next();
            if (redirector instanceof FilterRedirector)
            {
                filterRedirectorDefined = true;
            }
            else if (redirector instanceof JspRedirector)
            {
                jspRedirectorDefined = true;
            }
            else if (redirector instanceof ServletRedirector)
            {
                servletRedirectorDefined = true;
            }
            redirector.mergeInto(theWebXml);
        }

        // now add the default redirectors if they haven't been provided by
        // the user
        if (!filterRedirectorDefined)
        {
            new FilterRedirector(new AntLogger(getProject()))
                .mergeInto(theWebXml);
        }
        if (!servletRedirectorDefined)
        {
            new ServletRedirector(new AntLogger(getProject()))
                .mergeInto(theWebXml);
        }
        if (!jspRedirectorDefined)
        {
            new JspRedirector(new AntLogger(getProject())).mergeInto(theWebXml);
        }
    }

    /**
     * Enhances the provided web deployment descriptor with the definitions
     * required for testing with Cactus.
     *
     * @param theWebXml The original deployment descriptor
     * @return A temporary file containing the cactified descriptor
     * @throws JDOMException in case a JDOM exception is thrown.
     */
    private File cactifyWebXml(WebXml theWebXml) throws JDOMException
    {
        addRedirectorDefinitions(theWebXml);
        addJspRedirector();
        addEjbRefs(theWebXml);

        // If the user has specified a deployment descriptor to merge into the
        // cactified descriptor, perform the merge
        if (this.mergeWebXml != null)
        {
            try
            {
                WebXml parsedMergeWebXml = WebXmlIo.parseWebXmlFromFile(
                    this.mergeWebXml, this.xmlCatalog);
                WebXmlMerger merger = new WebXmlMerger(theWebXml);
                merger.setLogger(new AntLogger(this));

                merger.merge(parsedMergeWebXml);
            }
            catch (IOException e)
            {
                throw new BuildException(
                    "Could not merge deployment descriptors", e);
            }
        }

        // Serialize the cactified deployment descriptor into a temporary file,
        // so that it can get picked up by the War task
        //FileUtils fileUtils = FileUtils.newFileUtils();
        File tmpDir = createTempFile("cactus", "tmp.dir",
            getProject().getBaseDir(), true);
        tmpDir.mkdirs();
        tmpDir.deleteOnExit();
        File webXmlFile = null;
        try
        {
            ZipFileSet fileSet = new ZipFileSet();
            fileSet.setDir(tmpDir);
            tmpDir.mkdir();
            File[] files = WebXmlIo.writeAll(theWebXml,
                tmpDir.getAbsolutePath());


            for (int i = 0; i < files.length; i++)
            {
                File f = files[i];
                f.deleteOnExit();
                if (f.getName().equals("web.xml"))
                {
                    webXmlFile = f;
                }
                else
                {
                    fileSet.createInclude().setName(f.getName());
                }
            }
            addWebinf(fileSet);
        }
        catch (IOException ioe)
        {
            throw new BuildException(
                "Could not write temporary deployment descriptor", ioe);
        }
        return webXmlFile;
    }

    /**
     * Extracts and parses the original web deployment descriptor from the
     * web-app.
     *
     * @return The parsed descriptor or null if not found
     * @throws BuildException If the descriptor could not be
     *         parsed
     * @throws JDOMException in case is JDOM exception is thrown.
     */
    private WebXml getOriginalWebXml() throws BuildException, JDOMException
    {
        // Open the archive as JAR file and extract the deployment descriptor
        WarArchive war = null;
        try
        {
            war = new DefaultWarArchive(new FileInputStream(this.srcFile));
            WebXml webXml = war.getWebXml();
            return webXml;
        }
        catch (IOException e)
        {
            throw new BuildException("Failed to open WAR", e);
        }
    }

    /**
     * Add ejb references to a web.xml.
     *
     * @param theWebXml the web.xml to modify
     */
    private void addEjbRefs(WebXml theWebXml)
    {
        Iterator i = ejbRefs.iterator();
        while (i.hasNext())
        {
            EjbRef ref = (EjbRef) i.next();
            WebXmlUtils.addEjbRef(theWebXml, ref);
        }
    }

    /**
     * A method to create the temporary files.
     * @param thePrefix the prefix of the filename.
     * @param theSuffix the suffix of the filename
     * @param theParentDir the parent directory
     * @param isDeleteOnExit should we delete the directories on exit?
     * @return the temporary file
     */
    public File createTempFile(String thePrefix, String theSuffix,
                                   File theParentDir, boolean isDeleteOnExit)
    {
    File result = null;
    String parent = (theParentDir == null)
            ? System.getProperty("java.io.tmpdir")
            : theParentDir.getPath();

        DecimalFormat fmt = new DecimalFormat("#####");
        synchronized (rand)
        {
            do
            {
                result = new File(parent,
                   thePrefix + fmt.format(Math.abs(rand.nextInt()))
                   + theSuffix);
            }
            while (result.exists());
        }
        if (isDeleteOnExit)
        {
            result.deleteOnExit();
        }
        return result;
    }

    /**
     * Gets the file name.
     *
     * @return the name of the web app file
     */
    public String getFileName()
    {
        return FILE_NAME;
    }

    /**
     * Returns the context.
     *
     * @return <code>java.lang.String</code>
     */
    public String getContext() {
        return context;
    }

    /**
     * Sets the context.
     *
     * @param context
     */
    public void setContext(String context) {
        this.context = context;
    }


}
TOP

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

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.