org.apache.cactus.eclipse.runner.containers.ant.AntContainerManager.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.cactus.eclipse.runner.containers.ant.AntContainerManager.java

Source

/* 
 * ========================================================================
 * 
 * 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.eclipse.runner.containers.ant;

import org.apache.cactus.eclipse.runner.containers.IContainerManager;
import org.apache.cactus.eclipse.runner.containers.IContainerProvider;
import org.apache.cactus.eclipse.runner.ui.CactusMessages;
import org.apache.cactus.eclipse.runner.ui.CactusPlugin;
import org.apache.cactus.eclipse.webapp.internal.WarBuilder;
import org.eclipse.core.boot.BootLoader;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.externaltools.internal.model.IExternalToolConstants;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Hashtable;
import java.util.Vector;

/**
 * Implementation of IContainerManager based on Ant.
 * 
 * @version $Id: AntContainerManager.java 238816 2004-02-29 16:36:46Z vmassol $
 */
public class AntContainerManager implements IContainerManager {
    /**
     * The progress monitor associated with the current action. 
     */
    private IProgressMonitor currentPM;

    /**
     * True if the provider has successfully been deployed. 
     */
    private boolean stateProviderDeployed = false;

    /**
     * True if the war has successfully been created. 
     */
    private boolean stateWarCreated = false;

    /**
     * True if the container has been prepared. 
     */
    private boolean prepared = false;

    /**
     * Provider currently used 
     */
    private AntContainerProvider provider;

    /**
     * Table containing all the information needed
     * (key = target mask & value = container home directory)
     * to call the scripts
     */
    private Hashtable containerHomes;

    /**
     * Ant arguments common to all container providers 
     */
    private Vector antArguments = new Vector();

    /**
     * Path to the Ant build file for the manager
     */
    private String buildFilePath;

    /**
     * Context path for the container provider
     */
    private String contextURLPath;

    /**
     * Reference to the War file so that we can delete it on tearDown()
     */
    private File war;

    /**
     * Constructor.
     * 
     * @param theBuildFilePath path to the Ant build file for this manager
     * @param thePort the port that will be used when setting up the containers
     * @param theTargetDir temporary directory to use for
     *     containers configuration
     * @param theHomes ContainerHome array for container config
     * @param theContextURLPath context path of the container provider
     * @throws CoreException if an argument is invalid 
     */
    public AntContainerManager(String theBuildFilePath, int thePort, String theTargetDir, Hashtable theHomes,
            String theContextURLPath) throws CoreException {
        this.buildFilePath = theBuildFilePath;
        init(thePort, theTargetDir, theHomes, theContextURLPath);
    }

    /**
     * Initializer.
     * 
     * @param thePort the port that will be used when setting up the containers
     * @param theTargetDir temporary directory to use for
     *     containers configuration
     * @param theHomes ContainerHome array for container config
     * @param theContextURLPath context path of the container provider 
     * @throws CoreException if an argument is invalid
     */
    public void init(int thePort, String theTargetDir, Hashtable theHomes, String theContextURLPath)
            throws CoreException {
        if (thePort <= 0) {
            throw CactusPlugin.createCoreException("CactusLaunch.message.invalidproperty.port", null);
        }
        if (theTargetDir.equalsIgnoreCase("")) {
            throw CactusPlugin.createCoreException("CactusLaunch.message.invalidproperty.tempdir", null);
        }
        if (theHomes.size() == 0) {
            throw CactusPlugin.createCoreException("CactusLaunch.message.invalidproperty.containers", null);
        }
        if (theContextURLPath.equalsIgnoreCase("")) {
            throw CactusPlugin.createCoreException("CactusLaunch.message.invalidproperty.contextpath", null);
        }
        this.contextURLPath = theContextURLPath;
        this.containerHomes = theHomes;
        antArguments.add("-Dcactus.port=" + thePort);
        antArguments.add("-Dcactus.target.dir=" + theTargetDir);
        // Avoid Ant console popups on win32 platforms
        if (BootLoader.getOS().equals(BootLoader.OS_WIN32)) {
            antArguments.add("-Dcactus.jvm=javaw");
        }
        this.provider = (AntContainerProvider) getContainerProviders()[0];
    }

    /**
     * @return an array of provider containers supported by the manager
     */
    private IContainerProvider[] getContainerProviders() {
        String[] ids = (String[]) containerHomes.keySet().toArray(new String[containerHomes.size()]);
        IContainerProvider[] providers = new IContainerProvider[ids.length];
        for (int i = 0; i < providers.length; i++) {
            providers[i] = new AntContainerProvider(this, ids[i], (String) containerHomes.get(ids[i]));
        }
        return providers;
    }

    /**
     * @param theTarget the Ant target to be called
     * @param theProviderArguments the Ant arguments specific for
     *     the container provider
     * @return a launch configuration copy for Ant build
     * @throws CoreException if the launch configuration cannot be created
     */
    public ILaunchConfigurationWorkingCopy createAntLaunchConfiguration(String[] theProviderArguments,
            String theTarget) throws CoreException {
        CactusPlugin thePlugin = CactusPlugin.getDefault();
        URL buildFileURL = thePlugin.find(new Path(buildFilePath));
        if (buildFileURL == null) {
            throw CactusPlugin.createCoreException("CactusLaunch.message.prepare.error.plugin.file",
                    " : " + buildFilePath, null);
        }
        File buildFileLocation = new File(buildFileURL.getPath());

        ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
        ILaunchConfigurationType antType = launchManager
                .getLaunchConfigurationType(IExternalToolConstants.ID_PROGRAM_LAUNCH_CONFIGURATION_TYPE); //ID_ANT_LAUNCH_CONFIGURATION_TYPE

        String name = "Cactus container start-up";
        String uniqueName = launchManager.generateUniqueLaunchConfigurationNameFrom(name);
        ILaunchConfigurationWorkingCopy antConfig = antType.newInstance(null, uniqueName);

        antConfig.setAttribute(IExternalToolConstants.ATTR_LOCATION, buildFileLocation.getAbsolutePath());
        antConfig.setAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS,
                getString(getAllAntArguments(theProviderArguments)));
        /*antConfig.setAttribute(
        IExternalToolConstants.ATTR_ANT_TARGETS,
        theTarget);
        antConfig.setAttribute(
        IExternalToolConstants.ATTR_RUN_IN_BACKGROUND,
        false);*/
        return antConfig;
    }

    /**
     * @param theStringArray an array of String
     * @return the concatenation of the String elements 
     */
    private String getString(String[] theStringArray) {
        String result = "";
        for (int i = 0; i < theStringArray.length; i++) {
            result += theStringArray[i] + " ";
        }
        return result;
    }

    /**
     * @param theProviderArguments the container provider specific arguments
     * @return an array of arguments for the container build
     */
    private String[] getAllAntArguments(String[] theProviderArguments) {
        String[] managerArguments = (String[]) antArguments.toArray(new String[antArguments.size()]);
        String[] allArguments = new String[theProviderArguments.length + managerArguments.length];
        System.arraycopy(theProviderArguments, 0, allArguments, 0, theProviderArguments.length);
        System.arraycopy(managerArguments, 0, allArguments, theProviderArguments.length, managerArguments.length);
        return allArguments;
    }

    /**
     * @see IContainerManager#prepare(org.eclipse.jdt.core.IJavaProject)
     */
    public void prepare(final IJavaProject theJavaProject) {
        this.prepared = false;
        CactusPlugin.log("Preparing cactus tests");
        new Thread(new Runnable() {
            public void run() {
                try {
                    prepareCactusTests(theJavaProject, new NullProgressMonitor(), provider);
                } catch (CoreException e) {
                    CactusPlugin.displayErrorMessage(CactusMessages.getString("CactusLaunch.message.prepare.error"),
                            e.getMessage(), null);
                    cancelPreparation(provider);
                    return;
                }
            }
        }).start();
        while (!prepared) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                CactusPlugin.log(e);
            }
        }
    }

    /**
     * Creates the war file, deploys and launches the container.
     * 
     * @param theJavaProject the Java file
     * @param thePM the progress monitor to report to
     * @param theProvider the provider to prepare
     * @throws CoreException if anything goes wrong during preparation
     */
    private void prepareCactusTests(IJavaProject theJavaProject, IProgressMonitor thePM,
            IContainerProvider theProvider) throws CoreException {
        this.currentPM = thePM;
        thePM.beginTask(CactusMessages.getString("CactusLaunch.message.prepare"), 10);
        try {
            URL warURL = createWar(theJavaProject, thePM);
            this.stateWarCreated = true;
            theProvider.deploy(this.contextURLPath, warURL, null, thePM);
            this.stateProviderDeployed = true;
            theProvider.start(null, thePM);
        } catch (MalformedURLException e) {
            CactusPlugin.log(e);
            throw CactusPlugin.createCoreException("CactusLaunch.message.war.malformed", e);
        }
        thePM.done();
    }

    /**
     * @param theJavaProject the project to build the war from
     * @param thePM monitor that tracks the progression
     * @return the URL to the war file
     * @throws JavaModelException if we cannot create the war
     * @throws CoreException if we cannot create the war
     * @throws MalformedURLException if we cannot create the war
     */
    private URL createWar(IJavaProject theJavaProject, IProgressMonitor thePM)
            throws JavaModelException, CoreException, MalformedURLException {
        WarBuilder newWar = new WarBuilder(theJavaProject);
        this.war = newWar.createWar(thePM);
        return war.toURL();
    }

    /**
     * Launches a new progress dialog for preparation cancellation.
     * 
     * @param theProvider the provider which preparation to cancel
     */
    private void cancelPreparation(final IContainerProvider theProvider) {
        ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell());
        IRunnableWithProgress tearDownRunnable = new IRunnableWithProgress() {
            public void run(IProgressMonitor thePM) throws InterruptedException {
                try {
                    teardownCactusTests(thePM, theProvider);
                } catch (CoreException e) {
                    throw new InterruptedException(e.getMessage());
                }
            }
        };
        try {
            dialog.run(true, true, tearDownRunnable);
        } catch (InvocationTargetException tearDownE) {
            CactusPlugin.displayErrorMessage(CactusMessages.getString("CactusLaunch.message.teardown.error"),
                    tearDownE.getTargetException().getMessage(), null);
        } catch (InterruptedException tearDownE) {
            CactusPlugin.displayErrorMessage(CactusMessages.getString("CactusLaunch.message.teardown.error"),
                    tearDownE.getMessage(), null);
        }
    }

    /**
     * Tears down the Cactus tests
     */
    public void tearDown() {
        CactusPlugin.log("Tearing down cactus tests");
        try {
            teardownCactusTests(new NullProgressMonitor(), provider);
        } catch (CoreException e) {
            CactusPlugin.displayErrorMessage(CactusMessages.getString("CactusLaunch.message.teardown.error"),
                    e.getMessage(), null);
            cancelPreparation(provider);
        }
    }

    /**
     * Stops the container and undeploys (cleans) it.
     * @param thePM a progress monitor that reflects progress made while tearing
     * down the container setup
     * @param theProvider the provider of the container to stop and undeploy
     * @throws CoreException if an error occurs when tearing down
     */
    private void teardownCactusTests(IProgressMonitor thePM, IContainerProvider theProvider) throws CoreException {
        thePM.beginTask(CactusMessages.getString("CactusLaunch.message.teardown"), 100);
        theProvider.stop(null, thePM);
        if (stateProviderDeployed) {
            theProvider.undeploy(null, null, thePM);
        }
        if (stateWarCreated) {
            this.war.delete();
        }
        thePM.done();
    }

    /**
     * Convenience method to get the active Shell.
     * @return the active shell 
     */
    protected Shell getShell() {
        return CactusPlugin.getActiveWorkbenchShell();
    }

    /**
     * @param theRunner the Eclipse runner to call when tests are done
     */
    public void setEclipseRunner(EclipseRunTests theRunner) {
        provider.setEclipseRunner(theRunner);
    }

    /**
     * Sets the prepared flag.
     */
    public void preparationDone() {
        this.prepared = true;
    }

}