Package org.apache.cactus.integration.ant

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

/*
* ========================================================================
*
* Copyright 2003 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.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.ResourceUtils;
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.codehaus.cargo.module.webapp.DefaultWarArchive;
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.WebXmlMerger;
import org.codehaus.cargo.module.webapp.WebXmlVersion;
import org.codehaus.cargo.util.monitor.AntMonitor;
import org.xml.sax.SAXException;

/**
* An Ant task that injects elements necessary to run Cactus tests into an
* existing WAR file.
*
* @version $Id: CactifyWarTask.java 239172 2005-05-17 09:14:26Z grimsell $
*/
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", "myrealm");
                }
                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"};
        }

    }

    /**
     * Implements the nested element ejbref
     */
    public static final class EjbRef
    {
        /**
         * The name
         */
        private String name;
        /**
         * The local interface
         */
        private String localInterface;
        /**
         * The local home interface
         */
        private String localHomeInterface;
        /**
         * The jndi name
         */
        private String jndiName;
        /**
         * The type
         */
        private String type;
       
        /**
         * Returns the jndi name
         *
         * @return Returns the jndiName.
         */
        public String getJndiName()
        {
            return jndiName;
        }
        /**
         * Sets the jndiName
         *
         * @param theJndiName The jndiName to set.
         */
        public void setJndiName(String theJndiName)
        {
            this.jndiName = theJndiName;
        }
       
        /**
         * Returns the local home interface
         *
         * @return Returns the localHomeInterface.
         */
        public String getLocalHomeInterface()
        {
            return localHomeInterface;
        }
       
        /**
         * Sets the local home interface
         *
         * @param theLocalHomeInterface The localHomeInterface to set.
         */
        public void setLocalHomeInterface(String theLocalHomeInterface)
        {
            this.localHomeInterface = theLocalHomeInterface;
        }
       
        /**
         * Return the local interface
         *
         * @return Returns the localInterface.
         */
        public String getLocalInterface()
        {
            return localInterface;
        }
       
        /**
         * Sets the local interface
         *
         * @param theLocalInterface The localInterface to set.
         */
        public void setLocalInterface(String theLocalInterface)
        {
            this.localInterface = theLocalInterface;
        }
       
        /**
         * Returns the name
         *
         * @return Returns the name.
         */
        public String getName()
        {
            return name;
        }
       
        /**
         * Sets the name
         *
         * @param theName The name to set.
         */
        public void setName(String theName)
        {
            this.name = theName;
        }
       
        /**
         * Returns the type
         *
         * @return Returns the type.
         */
        public String getType()
        {
            return type;
        }
       
        /**
         * Sets the type
         *
         * @param theType The type to set.
         */
        public void setType(String theType)
        {
            this.type = theType;
        }
    }
    // 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();

    // 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");
            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
            webXml = getOriginalWebXml();
        }
        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
            {
                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);
    }

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

    // 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(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();
        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.setMonitor(new AntMonitor(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 tmpDir = fileUtils.createTempFile("cactus", "tmp.dir",
            getProject().getBaseDir());
        tmpDir.mkdirs();
        tmpDir.deleteOnExit();
        File webXmlFile = null;
        try
        {
            ZipFileSet fileSet = new ZipFileSet();
            fileSet.setDir(tmpDir);
            File[] files = WebXmlIo.writeAll(theWebXml, tmpDir);
            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
     */
    private WebXml getOriginalWebXml() throws BuildException
    {
        // Open the archive as JAR file and extract the deployment descriptor
        WarArchive war = null;
        try
        {
            war = new DefaultWarArchive(this.srcFile);
            WebXml webXml = war.getWebXml();
            return webXml;
        }
        catch (SAXException e)
        {
            throw new BuildException(
                "Parsing of web.xml 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);
        }
    }

    /**
     * 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();
            if ("Session".equals(ref.getType()))
            {
                theWebXml.addLocalSessionEjbRef(ref.getName(),
                                                ref.getLocalInterface(),
                                                ref.getLocalHomeInterface(),
                                                ref.getJndiName());
            }
            else if ("Entity".equals(ref.getType()))
            {
                theWebXml.addLocalEntityEjbRef(ref.getName(),
                                               ref.getLocalInterface(),
                                               ref.getLocalHomeInterface(),
                                               ref.getJndiName());
            }
        }
    }
}
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.