nl.tranquilizedquality.itest.cargo.AbstractInstalledContainerUtil.java Source code

Java tutorial

Introduction

Here is the source code for nl.tranquilizedquality.itest.cargo.AbstractInstalledContainerUtil.java

Source

/*
 * Copyright 2009 Salomo Petrus
 *
 * 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 nl.tranquilizedquality.itest.cargo;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import nl.tranquilizedquality.itest.cargo.exception.ConfigurationException;
import nl.tranquilizedquality.itest.cargo.exception.DeployException;
import nl.tranquilizedquality.itest.domain.DeployableLocationConfiguration;

import org.apache.ant.compress.taskdefs.Unzip;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.cargo.container.InstalledLocalContainer;
import org.codehaus.cargo.container.installer.ZipURLInstaller;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.beans.factory.annotation.Value;

/**
 * Base container class where every container should extend from. It contains
 * all the basic stuff which every container utility should have like cleaning
 * up the container before doing a fresh run.
 *
 * @author Salomo Petrus (sape)
 * @since 23 apr 2009
 *
 */
public abstract class AbstractInstalledContainerUtil implements ContainerUtil {

    /** Logger for this class */
    private static final Log LOGGER = LogFactory.getLog(AbstractInstalledContainerUtil.class);

    /** The name of the container. */
    private String containerName;

    /** The path where all configuration resource files are */
    protected String configResourcesPath;

    /**
     * The installedLocalContainer where the server application will be run in.
     */
    protected InstalledLocalContainer installedLocalContainer;

    /** The JVM arguments to use when starting up the installedLocalContainer */
    protected List<String> jvmArguments = new ArrayList<String>();

    /**
     * The path where the installedLocalContainer server is installed.
     */
    protected String containerHome;

    /**
     * The port where the container will run on. Use the property
     * ${cargo.server.port} to set the port dynamically and set the system
     * properties with this value.
     */
    protected Integer containerPort;

    /**
     * The path where the Cargo LOGGER files will be written to.
     */
    @Value("target/")
    protected String cargoLogFilePath;

    /** The system property that can be set to be used in the JVM. */
    protected Map<String, String> systemProperties;

    /** The URL where the container and configuration ZIP files are. */
    protected String remoteLocation;

    /** The ZIP file of the container to use i.e. jboss-4.0.4.GA.zip. */
    protected String containerFile;

    /** The deployable locations that will be used in the integration tests. */
    protected Map<String, String> deployableLocations;

    /**
     * The deployable location configurations that will be used in the
     * integration tests.
     */
    protected List<DeployableLocationConfiguration> deployableLocationConfigurations;

    /** The time the startup of a container may take before cargo times out. */
    protected Long deployTimeOut;

    /**
     * Determines if the extracted container in the temporary directory of the
     * OS should be cleaned up after the container was stopped.
     */
    private boolean cleanUpAfterContainerStopped = true;

    /** The root folder where the container will be extracted and started. */
    private String containerRootFolderName;

    /**
     * Default constructor.
     */
    public AbstractInstalledContainerUtil() {
        configResourcesPath = "src/test/resources/";
        deployTimeOut = 300000L;

        systemProperties = new HashMap<String, String>();
        deployableLocations = new LinkedHashMap<String, String>();
        deployableLocationConfigurations = new ArrayList<DeployableLocationConfiguration>();
    }

    /**
     * Cleans up the container if there is any to save disk space.
     */
    private void cleanUpContainer() {

        /*
         * Delete container directory.
         */
        try {
            FileUtils.deleteDirectory(new File(containerRootFolderName));
        } catch (final Exception exceptionOnDelete) {
            if (LOGGER.isErrorEnabled()) {
                LOGGER.error("Failed to delete the directory: " + containerHome + ".", exceptionOnDelete);
            }
        }
    }

    /**
     * Sets up the container home directory so the container can be extracted
     * and started there.
     */
    protected void setupContainerHome() {
        /*
         * Retrieve the operating system and current logged in user to create a
         * unique storage location for the container to start up in. This way
         * clashing of containers will be kept to the minimum.
         */
        final String operatingSystem = System.getProperty("os.name");
        final StringBuilder builder = new StringBuilder();
        if (operatingSystem != null && operatingSystem.startsWith("Windows")) {
            builder.append("C:/WINDOWS/Temp/");
        } else {
            builder.append("/tmp/");
        }

        /*
         * Get the time in millis so concurrent builds using the cargo-itest
         * utility can be executed without clashing with eachother.
         */
        final Long timeStamp = Calendar.getInstance().getTimeInMillis();
        builder.append(timeStamp);
        builder.append("/");
        containerRootFolderName = builder.toString();
        builder.append(containerName);
        builder.append("/");
        containerHome = builder.toString();

        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("Container HOME: " + containerHome);
        }
    }

    /**
     * Sets up the configuration needed for the deployable to be able to run
     * correctly.
     */
    protected abstract void setupConfiguration();

    /**
     * Installs the container and the application configuration. It also sets
     * some system properties so the container can startup properly. Finally it
     * sets up additional configuration like jndi.proprties files etc.
     */
    protected void setupContainer() {
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("Cleaning up " + containerName + "...");
        }

        // In windows the renaming causes problem when:
        // - The zip file has not the same name of the installed directory.
        // - The ZipURLInstaller fails.
        final String operatingSystem = System.getProperty("os.name");
        if (operatingSystem != null && !operatingSystem.startsWith("Windows")) {

            try {
                new File(containerHome).mkdir();
            } catch (final Exception exceptionOnMkDir) {
                if (LOGGER.isErrorEnabled()) {
                    LOGGER.error("Failed to create the directory: " + containerHome + ". Details: "
                            + exceptionOnMkDir.getMessage(), exceptionOnMkDir);
                }
                throw new ConfigurationException("Failed to create the directory: " + containerHome + ". Details: "
                        + exceptionOnMkDir.getMessage(), exceptionOnMkDir);
            }
        }

        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("Installing " + containerName + "...");
            LOGGER.info("Downloading container from: " + remoteLocation);
            LOGGER.info("Container file: " + containerFile);
        }

        /*
         * Download and configure the container.
         */
        final String installDir = StringUtils.substringBeforeLast(StringUtils.chomp(containerHome, "/"), "/");
        if (StringUtils.contains(this.remoteLocation, "http")) {

            try {
                final URL remoteLocationUrl = new URL(this.remoteLocation + containerFile);
                final ZipURLInstaller installer = new ZipURLInstaller(remoteLocationUrl, installDir, installDir);
                installer.install();
            } catch (final MalformedURLException e) {
                throw new DeployException("Failed to download container!", e);
            }

            /*
             * Rename the install directory to the container home directory so
             * it doesn't matter what the name is of the zip file and avoid case
             * sensitive issues on Linux.
             */
            final String containerDir = StringUtils.stripEnd(containerFile, ".zip");
            final File installedDir = new File(installDir + "/" + containerDir + "/");
            final File destenationDir = new File(containerHome);

            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("Renaming: " + installedDir.getPath());
                LOGGER.info("To: " + destenationDir.getPath());
            }

            final boolean renamed = installedDir.renameTo(destenationDir);

            if (!renamed) {
                final String msg = "Failed to rename container install directory to home directory name!";
                if (LOGGER.isErrorEnabled()) {
                    LOGGER.error(msg);
                }

                throw new ConfigurationException(msg);
            }

        } else {

            final Unzip unzipper = new Unzip();
            unzipper.setSrc(new File(this.remoteLocation + containerFile));
            unzipper.setDest(new File(containerHome));
            unzipper.execute();
        }

        /*
         * Setup the system properties.
         */
        systemProperties.put("cargo.server.port", containerPort.toString());

    }

    /**
     * Deploys the application to the correct
     */
    protected abstract void deploy();

    @Override
    public void start() {
        setupContainer();

        deploy();
    }

    @Override
    public void stop() {
        installedLocalContainer.stop();

        if (cleanUpAfterContainerStopped) {
            cleanUpContainer();
        }
    }

    /**
     * @param configResourcesPath
     *            the configResourcesPath to set
     */
    public void setConfigResourcesPath(final String configResourcesPath) {
        this.configResourcesPath = configResourcesPath;
    }

    /**
     * @return the configResourcesPath
     */
    public String getConfigResourcesPath() {
        return configResourcesPath;
    }

    /**
     * @param deployableLocations
     *            the deployableLocations to set
     */
    public void setDeployableLocations(final Map<String, String> deployableLocations) {
        this.deployableLocations = deployableLocations;
    }

    /**
     * @param locations
     *            the deployable configuration locations that will be set.
     */
    public void setDeployableLocationConfigurations(
            final List<DeployableLocationConfiguration> deployableLocationConfigurations) {
        this.deployableLocationConfigurations = deployableLocationConfigurations;
    }

    @Override
    public void addDeployableLocation(final String location, final String type) {
        this.deployableLocations.put(type, location);
    }

    @Override
    public Integer getContainerPort() {
        return containerPort;
    }

    /**
     * @param systemProperties
     *            the systemProperties to set
     */
    public void setSystemProperties(final Map<String, String> systemProperties) {
        this.systemProperties = systemProperties;
    }

    /**
     * Retrieves the JVM arguments
     *
     * @return Returns a unmodifiable list containing the current JVM arguments.
     */
    public List<String> getJvmArguments() {
        return Collections.unmodifiableList(jvmArguments);
    }

    /**
     * @param jvmArguments
     *            the jvmArguments to set
     */
    @Required
    public void setJvmArguments(final List<String> jvmArguments) {
        this.jvmArguments = new ArrayList<String>(jvmArguments);
    }

    @Required
    public void setCargoLogFilePath(final String cargoLogFilePath) {
        this.cargoLogFilePath = cargoLogFilePath;
    }

    /**
     * @param containerPort
     *            the containerPort to set
     */
    @Required
    public void setContainerPort(final Integer containerPort) {
        this.containerPort = containerPort;
    }

    /**
     * @param remoteLocation
     *            the remoteLocation to set
     */
    @Required
    public void setRemoteLocation(final String remoteLocation) {
        this.remoteLocation = remoteLocation;
    }

    /**
     * @param containerFile
     *            the containerFile to set
     */
    @Required
    public void setContainerFile(final String containerFile) {
        this.containerFile = containerFile;
    }

    public void setCleanUpAfterContainerStopped(final boolean cleanUpAfterContainerStopped) {
        this.cleanUpAfterContainerStopped = cleanUpAfterContainerStopped;
    }

    /**
     * @param deployTimeOut
     *            the deployTimeOut to set
     */
    public void setDeployTimeOut(final Long deployTimeOut) {
        this.deployTimeOut = deployTimeOut;
    }

    /**
     * @param containerName
     *            the containerName to set
     */
    protected void setContainerName(final String containerName) {
        this.containerName = containerName;
    }

}