Package org.apache.cactus.integration.ant

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

/*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 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 acknowlegement:
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowlegement may appear in the software itself,
*    if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Cactus" 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 names without prior written
*    permission of the Apache Group.
*
* 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.  For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.cactus.integration.ant;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import javax.xml.parsers.ParserConfigurationException;

import org.apache.cactus.integration.ant.util.AntLog;
import org.apache.cactus.integration.ant.util.ResourceUtils;
import org.apache.cactus.integration.ant.deployment.WarArchive;
import org.apache.cactus.integration.ant.deployment.WebXml;
import org.apache.cactus.integration.ant.deployment.WebXmlIo;
import org.apache.cactus.integration.ant.deployment.WebXmlMerger;
import org.apache.cactus.integration.ant.deployment.WebXmlVersion;
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.EnumeratedAttribute;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.XMLCatalog;
import org.apache.tools.ant.types.ZipFileSet;
import org.apache.tools.ant.util.FileUtils;
import org.xml.sax.SAXException;

/**
* An Ant task that injects elements necessary to run Cactus tests into an
* existing WAR file.
*
* @author <a href="mailto:cmlenz@apache.org">Christopher Lenz</a>
*
* @version $Id: CactifyWarTask.java,v 1.24 2003/07/01 20:05:24 cmlenz Exp $
*/
public class CactifyWarTask extends War
{

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

    /**
     * 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 -----------------------------------------------------------

    /**
     * Abstract base class for nested redirector elements.
     */
    public abstract static class Redirector
    {

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

        /**
         * The name of the redirector.
         */
        protected String name;

        /**
         * The URL pattern that the redirector will be mapped to.
         */
        protected String mapping;
       
        /**
         * Comma-separated list of role names that should be granted access to
         * the redirector.
         */
        protected String roles;

        // Abstract Methods ----------------------------------------------------

        /**
         * Merges the definition of the redirector into the provided deployment
         * descriptor.
         *
         * @param theWebXml The deployment descriptor into which the redirector
         *        definition should be merged
         */
        public abstract void mergeInto(WebXml theWebXml);

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

        /**
         * Sets the name of the redirector.
         *
         * @param theName The name to set
         */
        public final void setName(String theName)
        {
            this.name = theName;
        }

        /**
         * Sets the URL pattern that the redirector should be mapped to.
         *
         * @param theMapping The URL pattern to set
         */
        public final void setMapping(String theMapping)
        {
            this.mapping = theMapping;
        }

        /**
         * Sets the comma-separated list of role names that should be granted
         * access to the redirector.
         *
         * @param theRoles The roles to set
         */
        public final void setRoles(String theRoles)
        {
            this.roles = theRoles;
        }

        // Protected Methods ---------------------------------------------------

        /**
         * Adds the comma-separated list of security roles to a deployment
         * descriptor.
         *
         * @param theWebXml The deployment descriptor
         */
        protected final void addSecurity(WebXml theWebXml)
        {
            StringTokenizer tokenizer = new StringTokenizer(this.roles, ",");
            List roles = new ArrayList();
            while (tokenizer.hasMoreTokens())
            {
                String role = tokenizer.nextToken().trim();
                if (!theWebXml.hasSecurityRole(role))
                {
                    theWebXml.addSecurityRole(role);
                }
                roles.add(role);
            }
            if (!roles.isEmpty())
            {
                if (!theWebXml.hasLoginConfig())
                {
                    theWebXml.setLoginConfig("BASIC", "Cactus Test Realm");
                }
                if (!theWebXml.hasSecurityConstraint(this.mapping))
                {
                    theWebXml.addSecurityConstraint("Cactus Test Redirector",
                        this.mapping, roles);
                }
            }
        }

    }

    /**
     * Implementation of <code>Redirector</code> for filter test redirectors.
     */
    public static final class FilterRedirector extends Redirector
    {

        /**
         * Default constructor.
         */
        public FilterRedirector()
        {
            this.name = "FilterRedirector";
            this.mapping = DEFAULT_FILTER_REDIRECTOR_MAPPING;
        }

        /**
         * @see CactifyWarTask.Redirector#mergeInto
         */
        public void mergeInto(WebXml theWebXml)
        {
            if (WebXmlVersion.V2_3.compareTo(theWebXml.getVersion()) <= 0)
            {
                theWebXml.addFilter(this.name, FILTER_REDIRECTOR_CLASS);
                theWebXml.addFilterMapping(this.name, this.mapping);
                if (this.roles != null)
                {
                    addSecurity(theWebXml);
                }
            }
        }
       
    }

    /**
     * Implementation of <code>Redirector</code> for JSP test redirectors.
     */
    public static final class JspRedirector extends Redirector
    {

        /**
         * Default constructor.
         */
        public JspRedirector()
        {
            this.name = "JspRedirector";
            this.mapping = DEFAULT_JSP_REDIRECTOR_MAPPING;
        }

        /**
         * @see CactifyWarTask.Redirector#mergeInto
         */
        public void mergeInto(WebXml theWebXml)
        {
            theWebXml.addJspFile(this.name, "/jspRedirector.jsp");
            theWebXml.addServletMapping(this.name, this.mapping);
            if (this.roles != null)
            {
                addSecurity(theWebXml);
            }
        }
       
    }

    /**
     * Implementation of <code>Redirector</code> for servlet test redirectors.
     */
    public static final class ServletRedirector extends Redirector
    {

        /**
         * Default constructor.
         */
        public ServletRedirector()
        {
            this.name = "ServletRedirector";
            this.mapping = DEFAULT_SERVLET_REDIRECTOR_MAPPING;
        }

        /**
         * @see CactifyWarTask.Redirector#mergeInto
         */
        public void mergeInto(WebXml theWebXml)
        {
            theWebXml.addServlet(this.name, SERVLET_REDIRECTOR_CLASS);
            theWebXml.addServletMapping(this.name, this.mapping);
            if (this.roles != null)
            {
                addSecurity(theWebXml);
            }
        }
       
    }

    /**
     * Enumeration for the <em>version</em> attribute.
     */
    public static final class Version extends EnumeratedAttribute
    {

        /**
         * @see org.apache.tools.ant.types.EnumeratedAttribute#getValues()
         */
        public String[] getValues()
        {
            return new String[] {"2.2", "2.3"};
        }

    }

    // 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;

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

    /**
     * @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");
            addZipfileset(currentFiles);

            // Parse the original deployment descriptor
            webXml = getOriginalWebXml();
        }
        else
        {
            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
            {
                webXmlVersion = WebXmlVersion.V2_3;
            }
            try
            {
                webXml = WebXmlIo.newWebXml(webXmlVersion);
            }
            catch (ParserConfigurationException pce)
            {
                throw new BuildException(
                    "Could not create deployment descriptor", pce);
            }
        }

        File tmpWebXml = cactifyWebXml(webXml);
        setWebxml(tmpWebXml);

        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);
    }

    /**
     * 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();
    }

    // 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 WarArchive(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 = ResourceUtils.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
        {
            ResourceUtils.copyResource(getProject(),
                "/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().mergeInto(theWebXml);
        }
        if (!servletRedirectorDefined)
        {
            new ServletRedirector().mergeInto(theWebXml);
        }
        if (!jspRedirectorDefined)
        {
            new JspRedirector().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
     */
    private File cactifyWebXml(WebXml theWebXml)
    {
        addRedirectorDefinitions(theWebXml);
        addJspRedirector();
       
        // 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.setLog(new AntLog(this));
                merger = new WebXmlMerger(theWebXml);
                merger.setLog(new AntLog(this));
                merger.merge(parsedMergeWebXml);
            }
            catch (IOException e)
            {
                throw new BuildException(
                    "Could not merge deployment descriptors", e);
            }
            catch (SAXException e)
            {
                throw new BuildException("Parsing of merge file failed", e);
            }
            catch (ParserConfigurationException e)
            {
                throw new BuildException("XML parser configuration error", 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 tmpWebXml = fileUtils.createTempFile("cactus", "web.xml",
            getProject().getBaseDir());
        tmpWebXml.deleteOnExit();
        try
        {
            WebXmlIo.writeWebXml(theWebXml, tmpWebXml, null, true);
        }
        catch (IOException ioe)
        {
            throw new BuildException(
                "Could not write temporary deployment descriptor", ioe);
        }
        return tmpWebXml;
    }

    /**
     * Extracts and parses the original web deployment descriptor from the
     * web-app.
     *
     * @return The parsed descriptor
     * @throws BuildException If the descriptor is not found or could not be
     *         parsed
     */
    private WebXml getOriginalWebXml() throws BuildException
    {
        // Open the archive as JAR file and extract the deployment descriptor
        WarArchive war = null;
        try
        {
            war = new WarArchive(this.srcFile);
            WebXml webXml = war.getWebXml();
            if (webXml == null)
            {
                throw new BuildException(
                    "The source file does not contain a deployment descriptor");
            }
            return webXml;
        }
        catch (SAXException e)
        {
            throw new BuildException(
                "Parsing of deployment descriptor failed", e);
        }
        catch (IOException e)
        {
            throw new BuildException("Failed to open WAR", e);
        }
        catch (ParserConfigurationException e)
        {
            throw new BuildException("XML parser configuration error", e);
        }
    }

}
TOP

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

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.