Package org.apache.cactus.integration.ant.container.jboss

Source Code of org.apache.cactus.integration.ant.container.jboss.JBoss3xContainer

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

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.cactus.integration.ant.container.AbstractJavaContainer;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.Copy;
import org.apache.tools.ant.taskdefs.Java;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.util.FileUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
* Special container support for the JBoss application server.
*
* @version $Id: JBoss3xContainer.java 239130 2005-01-29 15:49:18Z vmassol $
*/
public class JBoss3xContainer extends AbstractJavaContainer
{
    // Instance Variables ------------------------------------------------------

    /**
     * The JBoss 3.x installation directory.
     */
    private File dir;

    /**
     * The name of the server configuration to use for running the tests.
     */
    private String config = "default";

    /**
     * The location of a directory where to find the JBoss server
     * configurations.
     */
    private File configDir;
   
    /**
     * The port to which the container should be bound.
     */
    private int port = 8080;

    /**
     * The server JNDI Port (used during shutdown)
     */
    private int jndiPort = 1099;
   
    /**
     * The JBoss version detected by reading the Manifest file in the
     * installation directory.
     */
    private String version;

    /**
     * The context root of the tested application.
     */
    private String testContextRoot;

    /**
     * The temporary directory from which the container will be started.
     */
    private File tmpDir;
   
    // Public Methods ----------------------------------------------------------

    /**
     * Sets the JBoss installation directory.
     *
     * @param theDir The directory to set
     * @throws BuildException If the specified directory doesn't contain a valid
     *         JBoss 3.x installation
     */
    public final void setDir(File theDir) throws BuildException
    {
        this.dir = theDir;
    }

    /**
     * Sets the name of the server configuration to use for running the tests.
     *
     * @param theConfig The configuration name
     */
    public final void setConfig(String theConfig)
    {
        this.config = theConfig;
    }

    /**
     * Sets the location of the server configuration directory.
     *
     * @param theConfigDir The configuration directory
     */
    public final void setConfigDir(File theConfigDir)
    {
        this.configDir = theConfigDir;
    }
   
    /**
     * Sets the port that will be used to poll the server to verify if
     * it is started. This is needed for the use case where the user
     * has defined his own JBoss configuration by using the
     * {@link #setConfig(String)} call and has defined a port other
     * than the default one.
     *
     * Note: This value is not yet used to set the port
     * to which the container will listen to. The reason is that this is
     * hard to implement with JBoss and nobody had the courage to implement
     * it yet...
     *
     * @param thePort The port to set
     */
    public final void setPort(int thePort)
    {
        this.port = thePort;
    }

    /**
     * Specify the JNDI port to use.
     *
     * @param theJndiPort The JNDI port
     */
    public final void setJndiPort(int theJndiPort)
    {
        this.jndiPort = theJndiPort;
    }

    /**
     * Sets the temporary directory from which the container is run.
     *
     * @param theTmpDir The temporary directory to set
     */
    public final void setTmpDir(File theTmpDir)
    {
        this.tmpDir = theTmpDir;
    }
   
    // Container Implementation ------------------------------------------------

    /**
     * @see AbstractJavaContainer#getTestContext()
     */
    public String getTestContext()
    {
        return this.testContextRoot;
    }
   
    /**
     * @see AbstractJavaContainer#getName()
     */
    public final String getName()
    {
        return "JBoss " + this.version;
    }

    /**
     * @see AbstractJavaContainer#getPort()
     */
    public final int getPort()
    {
        return this.port;
    }

    /**
     * Returns the server JNDI port.
     *
     * @return The JNDI port
     */
    public final int getJndiPort()
    {
        return this.jndiPort;
    }

    /**
     * @return The temporary directory from which the container will be
     *         started.
     */
    protected final File getTmpDir()
    {
        return this.tmpDir;
    }

    /**
     * @see AbstractJavaContainer#init()
     */
    public final void init()
    {
        // Verify the installation directory
        this.version = getVersion(this.dir);
        if (this.version == null)
        {
            throw new BuildException(this.dir
                + " not recognized as a JBoss 3.x installation");
        }
        if (!this.version.startsWith("3"))
        {
            throw new BuildException(
                "This element doesn't support version " + this.version
                + " of JBoss");
        }

        // Try to infer the test root context from the JBoss specific
        // <code>jboss-web.xml</code> file.
        this.testContextRoot = getTestContextFromJBossWebXml();
       
        // TODO: as long as we don't have a way to set the port on the JBoss
        // instance, we'll at least need to extract the port from a config file
        // in the installation directory
    }

    /**
     * @see AbstractJavaContainer#startUp()
     */
    public final void startUp()
    {
        try
        {
            // TODO: It seems JBoss 3.2.x does not support server
            // configurations located in directories with spaces in their name.
            // Thus we define the default tmp dir to default to where default
            // JBoss server configurations are located. This should be removed
            // once we find out how to make JBoss work when using the default
            // tmp dir of System.getProperty("java.io.tmpdir")
            if (getTmpDir() == null)
            {
                setTmpDir(new File(this.dir, "server/cactus"));
            }           
           
            File customServerDir = setupTempDirectory(getTmpDir(),
                "cactus/jboss3x");
            cleanTempDirectory(customServerDir);
           
            prepare("cactus/jboss3x", customServerDir);
           
            File binDir = new File(this.dir, "bin");
           
            Java java = createJavaForStartUp();
            java.setDir(binDir);
           
            java.addSysproperty(
                createSysProperty("program.name",
                    new File(binDir, "run.bat")));
            java.addSysproperty(
                createSysProperty("jboss.server.home.dir", customServerDir));
            java.addSysproperty(
                createSysProperty("jboss.server.home.url",
                    customServerDir.toURL().toString()));

            Path classpath = java.createClasspath();
            classpath.createPathElement().setLocation(
                new File(binDir, "run.jar"));
            addToolsJarToClasspath(classpath);
            java.setClassname("org.jboss.Main");
            java.createArg().setValue("-c");
            java.createArg().setValue(this.config);
            java.execute();
        }
        catch (IOException ioe)
        {
            getLog().error("Failed to startup the container", ioe);
            throw new BuildException(ioe);
        }
    }

    /**
     * @see AbstractJavaContainer#shutDown()
     */
    public final void shutDown()
    {
        File binDir = new File(this.dir, "bin");
           
        Java java = createJavaForShutDown();
        java.setFork(true);

        Path classPath = java.createClasspath();
        classPath.createPathElement().setLocation(
            new File(binDir, "shutdown.jar"));

        java.setClassname("org.jboss.Shutdown");
       
        if (this.version.startsWith("3.2"))
        {
            java.createArg().setValue("--server=" + this.getServer() + ":"
                + this.getJndiPort());
            java.createArg().setValue("--shutdown");
        }
        else
        {
            java.createArg().setValue(this.getServer());
            java.createArg().setValue(String.valueOf(getPort()));
        }
        java.execute();
    }

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

    /**
     * @return the test context from JBoss's <code>jboss-web.xml</code> or null
     *         if none has been defined or if the file doesn't exist
     */
    private String getTestContextFromJBossWebXml()
    {
        String testContext = null;
       
        try
        {
            Document doc = getJBossWebXML();
            Element root = doc.getDocumentElement();
            Node context = root.getElementsByTagName("context-root").item(0);
            testContext = context.getFirstChild().getNodeValue();
        }
        catch (Exception e)
        {
            // no worries if we can't find what we are looking for (for now).
        }

        return testContext;
    }
   
    /**
     * Prepares a temporary installation of the container and deploys the
     * web-application.
     *
     * @param theDirName The name of the temporary container installation
     *        directory
     * @param theCustomServerDir the directory where the JBoss server
     *        configuration is to be deployed
     * @throws IOException If an I/O error occurs
     */
    private void prepare(String theDirName, File theCustomServerDir)
        throws IOException
    {
        FileUtils fileUtils = FileUtils.newFileUtils();

        // If the configDir property has not been set, let's default it to
        // the default JBoss server configuration directory.
        File computedConfigDir;
        if (this.configDir == null)
        {
            computedConfigDir = new File(this.dir, "server");
        }
        else
        {
            computedConfigDir = this.configDir;
        }
       
        // Copy the default JBoss server config directory into our custom
        // server directory.
        Copy copy = new Copy();
        copy.setTaskName("cactus");
        copy.setProject(getProject());
        copy.setTodir(theCustomServerDir);
        FileSet srcFiles = new FileSet();
        srcFiles.setDir(new File(computedConfigDir, this.config));
        copy.addFileset(srcFiles);
        copy.execute();
           
        // Deploy the web-app by copying the WAR file into the webapps
        // directory
        File deployDir = new File(theCustomServerDir, "/deploy");
        fileUtils.copyFile(getDeployableFile().getFile(),
            new File(deployDir, getDeployableFile().getFile().getName()),
            null, true);
    }

    /**
     * Returns the version of the JBoss installation.
     *
     * @param theDir The JBoss installation directory
     * @return The JBoss version, or <code>null</code> if the verion number
     *         could not be retrieved
     */
    private String getVersion(File theDir)
    {
        // Extract version information from the manifest in run.jar
        String retVal = null;
        try
        {
            JarFile runJar = new JarFile(new File(theDir, "bin/run.jar"));
            Manifest mf = runJar.getManifest();
            if (mf != null)
            {
                Attributes attrs = mf.getMainAttributes();
                retVal = attrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
            }
            else
            {
                getLog().warn("Couldn't find MANIFEST.MF in " + runJar);
            }
        }
        catch (IOException ioe)
        {
            getLog().warn("Couldn't retrieve JBoss version information", ioe);
        }
        return retVal;
    }

    /**
     * Get a Document object for the <code>jboss-web.xml</code> file.
     *
     * @return The parsed XML Document object or null if not found
     * @throws IOException If there is a problem reading files
     * @throws ParserConfigurationException If there is a problem w/ parser
     * @throws SAXException If there is a problem with parsing
     */
    private Document getJBossWebXML() throws
        IOException, ParserConfigurationException, SAXException
    {
        Document doc = null;
        File configDir = new File(this.dir, "server");
        File deployDir = new File(configDir, this.config + "/deploy");
        File warFile = new File(deployDir,
            getDeployableFile().getFile().getName());
        JarFile war = new JarFile(warFile);
        ZipEntry entry = war.getEntry("WEB-INF/jboss-web.xml");
        if (entry != null)
        {
            DocumentBuilderFactory factory =
                DocumentBuilderFactory.newInstance();
            factory.setValidating(false);
            factory.setNamespaceAware(false);
           
            DocumentBuilder builder = factory.newDocumentBuilder();
            builder.setEntityResolver(new EntityResolver()
            {
                public InputSource resolveEntity(String thePublicId,
                    String theSystemId) throws SAXException
                {
                    return new InputSource(new StringReader(""));
                }
            });
            doc = builder.parse(war.getInputStream(entry));
        }
        war.close();
        return doc;
    }
   
}
TOP

Related Classes of org.apache.cactus.integration.ant.container.jboss.JBoss3xContainer

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.