com.legstar.eclipse.plugin.common.wizards.AbstractWizardRunnable.java Source code

Java tutorial

Introduction

Here is the source code for com.legstar.eclipse.plugin.common.wizards.AbstractWizardRunnable.java

Source

/*******************************************************************************
 * Copyright (c) 2010 LegSem.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v2.1
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     LegSem - initial API and implementation
 ******************************************************************************/
package com.legstar.eclipse.plugin.common.wizards;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IStreamsProxy;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.osgi.util.NLS;

import com.legstar.codegen.CodeGenMakeException;
import com.legstar.codegen.models.IAntBuildModel;
import com.legstar.eclipse.ant.AntLaunchException;
import com.legstar.eclipse.ant.AntLaunchHelper;
import com.legstar.eclipse.plugin.common.Activator;
import com.legstar.eclipse.plugin.common.Messages;
import com.legstar.eclipse.plugin.common.preferences.PreferenceConstants;

/**
 * Abstract backend task. Provides common ant launcher capabilities.
 */
public abstract class AbstractWizardRunnable implements IRunnableWithProgress {

    /** The model to build from. */
    private IAntBuildModel _antBuildModel;

    /** The target project. */
    private IProject _targetProject;

    /** The target ant file name (without path). */
    private String _targetAntFileName;

    /** Probe files prefixes. */
    private static final String PROBE_FILE_PREFIX = "probe";

    /** Probe files suffixes. */
    private static final String PROBE_FILE_SUFFIX = "tmp";

    /**
     * Instantiate this runnable from UI items. It is important not to attempt
     * access to UI elements from the background thread.
     * 
     * @param antBuildModel the model object to be passed to velocity templates
     * @param targetContainerRelativePathName where generated objects are stored
     * @param targetAntFileName the name (no path) of the ant file
     * @throws InvocationTargetException if runnable cannot be instantiated
     */
    public AbstractWizardRunnable(final IAntBuildModel antBuildModel, final String targetContainerRelativePathName,
            final String targetAntFileName) throws InvocationTargetException {
        this(antBuildModel, getProject(targetContainerRelativePathName), targetAntFileName);
    }

    /**
     * Instantiate this runnable from UI items. It is important not to attempt
     * access to UI elements from the background thread.
     * 
     * @param antBuildModel the model object to be passed to velocity templates
     * @param project the Eclipse project
     * @param targetAntFileName the name (no path) of the ant file
     * @throws InvocationTargetException if runnable cannot be instantiated
     */
    public AbstractWizardRunnable(final IAntBuildModel antBuildModel, final IProject project,
            final String targetAntFileName) throws InvocationTargetException {
        _antBuildModel = antBuildModel;
        _targetProject = project;
        _targetAntFileName = targetAntFileName;
    }

    /**
     * Create a new ANT script file (replace existing one). We create this
     * one directly under the target container. The process also creates
     * a temporary probe file expected to be deleted by the ant script on
     * successful completion. This serves as a general purpose mechanism to
     * determine whether the ant run was successful or not.
     * 
     * @param monitor the current monitor
     * @param scale the scale of progress
     * @throws InvocationTargetException if creation fails
     */
    protected void createBuild(final IProgressMonitor monitor, final int scale) throws InvocationTargetException {
        monitor.setTaskName(Messages.ant_generating_task_label);
        try {
            File antFile = getAntFile();
            _antBuildModel.setProbeFile(getProbeFile());
            _antBuildModel.generateBuild(antFile);
            monitor.worked(1 * scale);
        } catch (CodeGenMakeException e) {
            throw new InvocationTargetException(e);
        }
    }

    /**
     * Execute an ant build monitoring its progress.
     * 
     * @param monitor the current monitor
     * @param scale the scale of progress
     * @throws InvocationTargetException execution fails
     */
    protected void runBuild(final IProgressMonitor monitor, final int scale) throws InvocationTargetException {

        monitor.setTaskName(Messages.ant_running_task_label);
        try {
            getTargetProject().refreshLocal(IResource.DEPTH_INFINITE, null);
            IFile antFile = getGeneratedAntFile();
            AntLaunchHelper antHelper = new AntLaunchHelper(getGeneratedAntFile());
            ILaunch launch = antHelper.execute(new SubProgressMonitor(monitor, 1 * scale));
            /* Wait until the async process is finished */
            for (IProcess process : launch.getProcesses()) {
                if (!process.getLaunch().equals(launch)) {
                    continue;
                }
                while (!process.isTerminated()) {
                    if (monitor.isCanceled()) {
                        return;
                    }
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e1) {
                        return;
                    }
                }
                IStreamsProxy streamsProxy = process.getStreamsProxy();
                if (streamsProxy != null) {
                    String errorMessage = streamsProxy.getErrorStreamMonitor().getContents();
                    if (errorMessage != null && errorMessage.length() > 0) {
                        Throwable th = new AntLaunchException(
                                NLS.bind(Messages.ant_failure_stream_msg, antFile.getName(), errorMessage));
                        throw new InvocationTargetException(th);
                    }
                }
                if (process.getExitValue() != 0) {
                    Throwable th = new AntLaunchException(
                            NLS.bind(Messages.ant_failure_retcode_msg, antFile.getName(), process.getExitValue()));
                    throw new InvocationTargetException(th);
                }
            }

            /* Check that the probe file was successfully removed */
            getTargetProject().refreshLocal(IResource.DEPTH_INFINITE, null);
            if (!checkProbeFile()) {
                Throwable th = new AntLaunchException(
                        NLS.bind(Messages.ant_failure_console_msg, antFile.getName()));
                throw new InvocationTargetException(th);
            }

        } catch (CoreException e) {
            throw new InvocationTargetException(e);
        } finally {
            monitor.worked(1 * scale);
        }
    }

    /**
     * @return the ant file as a file system object
     */
    protected File getAntFile() {
        File antFile = new File(
                getTargetAntScriptLocation().toOSString() + File.separatorChar + getTargetAntFileName());
        return antFile;
    }

    /**
     * Create a temporary probe file.
     * 
     * @return the probe file
     * @throws CodeGenMakeException if file cannot be created
     */
    protected File getProbeFile() throws CodeGenMakeException {
        try {
            return File.createTempFile(PROBE_FILE_PREFIX, PROBE_FILE_SUFFIX);
        } catch (IOException e) {
            throw new CodeGenMakeException(e);
        }
    }

    /**
     * @return true if the probe file was successfully deleted false otherwise
     */
    protected boolean checkProbeFile() {
        File probeFile = _antBuildModel.getProbeFile();
        if (probeFile != null) {
            if (probeFile.exists()) {
                return false;
            }
        }
        return true;
    }

    /**
     * The generated script goes into the target project under a specific
     * ant folder.
     * If the ant folder does not yet exist, it is created
     * 
     * @return the location for the ant script
     */
    protected IPath getTargetAntScriptLocation() {
        IPath antFolder = getAntFolderAbsolutePath();
        mkDir(antFolder);
        return antFolder;
    }

    /**
     * @return the folder where ant scripts need to be stored.
     */
    protected IPath getAntFolderRelativePath() {
        IPath projectPath = _targetProject.getFullPath();
        IPath containerPath = projectPath.append(getPreferenceAntFolder());
        return containerPath;
    }

    /**
     * @return the folder where ant scripts need to be stored.
     */
    protected IPath getAntFolderAbsolutePath() {
        IPath projectPath = _targetProject.getLocation();
        IPath containerPath = projectPath.append(getPreferenceAntFolder());
        return containerPath;
    }

    /**
     * @return the ant file relative path (relative to the workspace root)
     */
    protected IPath getAntFileRelativePath() {
        IPath containerPath = getAntFolderRelativePath();
        return containerPath.append(getTargetAntFileName());
    }

    /**
     * Once the ant file is generated it is retrieved as an IFile.
     * 
     * @return the generated ant script file ready to be launched
     */
    protected IFile getGeneratedAntFile() {
        IPath filePath = getAntFileRelativePath();
        IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
        IResource resource = root.findMember(filePath);
        return (IFile) resource;
    }

    /**
     * Make sure a folder physically exists.
     * 
     * @param path a path to the folder (must be absolute)
     */
    protected void mkDir(final IPath path) {
        File folder = new File(path.toOSString());
        if (!folder.exists()) {
            folder.mkdirs();
        }
    }

    /**
     * @return the preferred ant script sub folder relative to projects.
     */
    public String getPreferenceAntFolder() {
        IPreferenceStore store = Activator.getDefault().getPreferenceStore();
        String antScriptsFolder = store.getString(PreferenceConstants.ANT_SCRIPTS_FOLDER);
        if (antScriptsFolder == null) {
            return "";
        } else {
            return antScriptsFolder;
        }
    }

    /**
     * Retrieve the parent project from a resource relative path name.
     * 
     * @param relativePathName relative to workspace root
     * @return the parent project
     */
    public static IProject getProject(final String relativePathName) {
        IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
        IResource resource = root.findMember(relativePathName);
        if (resource == null) {
            return null;
        }
        return resource.getProject();
    }

    /**
     * @return the target project
     */
    protected IProject getTargetProject() {
        return _targetProject;
    }

    /**
     * @return the target ant file same (not a path)
     */
    protected String getTargetAntFileName() {
        return _targetAntFileName;
    }

    /**
     * @return the model to build from
     */
    public IAntBuildModel getAntBuildModel() {
        return _antBuildModel;
    }

    /**
     * @param antBuildModel the model to build from to set
     */
    public void setAntBuildModel(final IAntBuildModel antBuildModel) {
        _antBuildModel = antBuildModel;
    }

}