org.deved.antlride.jdt.launch.AntlrAbstractJavaLauncher.java Source code

Java tutorial

Introduction

Here is the source code for org.deved.antlride.jdt.launch.AntlrAbstractJavaLauncher.java

Source

/*******************************************************************************
 * Copyright (c) 2007, 2008 Edgar Espina.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
     
 *******************************************************************************/

package org.deved.antlride.jdt.launch;

import static org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants.ATTR_CLASSPATH;
import static org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH;
import static org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME;
import static org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS;
import static org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME;
import static org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.UnknownHostException;
import java.util.Arrays;

import org.deved.antlride.core.AntlrCore;
import org.deved.antlride.core.build.AntlrBuildUnit;
import org.deved.antlride.core.build.AntlrDeployer;
import org.deved.antlride.core.build.AntlrDeployerRepository;
import org.deved.antlride.core.launch.AntlrLauncher;
import org.deved.antlride.core.model.IGrammar;
import org.deved.antlride.core.model.test.AntlrTestCase;
import org.deved.antlride.core.util.AntlrCoreHelper;
import org.deved.antlride.integration.jdt.AntlrJDT;
import org.deved.antlride.integration.jdt.AntlrJavaTargetService;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
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.JavaCore;
import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Display;
import org.osgi.framework.Bundle;

public abstract class AntlrAbstractJavaLauncher implements AntlrLauncher {

    public AntlrAbstractJavaLauncher() {
    }

    public final void launch(final boolean rebuild, final AntlrBuildUnit unit, final AntlrTestCase testCase)
            throws CoreException {
        try {
            final IJavaProject javaProject = JavaCore.create(unit.getFile().getProject());
            if (javaProject != null /* && javaProject.exists() */) {
                ProgressMonitorDialog dialog = new ProgressMonitorDialog(null);
                dialog.run(true, true, new IRunnableWithProgress() {

                    public void run(IProgressMonitor monitor)
                            throws InvocationTargetException, InterruptedException {
                        try {
                            AntlrDeployer deployer = AntlrDeployerRepository.createDeployer();
                            deployer.deployRuntime();

                            IPath compilerPath = deployCompiler();
                            IGrammar grammar = unit.getGrammar();
                            IPath src = getFolder(grammar, "src", false);
                            IPath classes = getFolder(grammar, "classes", rebuild);

                            final IJavaProject javaProject = JavaCore.create(unit.getFile().getProject());

                            IRuntimeClasspathEntry[] runtimeClassPath;
                            if (javaProject.exists()) {
                                runtimeClassPath = AntlrJavaTargetService
                                        .computeDefaultRuntimeClassPath(javaProject);
                            } else {
                                runtimeClassPath = new IRuntimeClasspathEntry[0];
                            }

                            runtimeClassPath = AntlrJavaTargetService.mergeClasspath(monitor, unit,
                                    runtimeClassPath);

                            String[] classpath = AntlrJavaTargetService.getMementoClassPath(runtimeClassPath);
                            // ++++++++++++++++++++++++++++++++++++++++++++++++++++
                            // ++++++++++++++++++++ generate code
                            // ++++++++++++++++++++++++++++++++++++++++++++++++++++
                            if (rebuild) {
                                generateCode(monitor, unit, javaProject, classpath, src);
                                // ++++++++++++++++++++++++++++++++++++++++++++++++++++
                                // ++++++++++++++++++++ compile
                                // ++++++++++++++++++++++++++++++++++++++++++++++++++++
                                compile(monitor, unit, javaProject, runtimeClassPath, compilerPath, src, classes);
                            }

                            doLaunch(monitor, javaProject, runtimeClassPath, rebuild, unit, testCase, compilerPath,
                                    src, classes);
                        } catch (CoreException e) {
                            showError(e.getStatus());
                        } catch (UnknownHostException e) {
                            showError(createFailStatus(e));
                        } catch (IOException e) {
                            showError(createFailStatus(e));
                        }

                    }
                });
            }
        } catch (Exception ex) {
            showError(createFailStatus(ex));
        }
    }

    private static void showError(final IStatus status) {
        Display.getDefault().asyncExec(new Runnable() {

            public void run() {
                ErrorDialog.openError(null, "Launch problem", "Execution was cancelled", status);
            }
        });

    }

    private static IStatus createFailStatus(Exception ex) {
        IStatus status = new Status(IStatus.ERROR, AntlrJDT.PLUGIN_ID, ex.getMessage(), ex);
        return status;
    }

    protected abstract void doLaunch(IProgressMonitor monitor, IJavaProject javaProject,
            IRuntimeClasspathEntry[] runtimeClassPath, boolean rebuild, AntlrBuildUnit unit, AntlrTestCase testCase,
            IPath compilerPath, IPath src, IPath classes)
            throws CoreException, InterruptedException, UnknownHostException, IOException;

    protected String safeArg(String arg) {
        String[] tokens = arg.split(" ");
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < tokens.length - 1; i++) {
            builder.append(tokens[i]).append("\" \"");
        }
        builder.append(tokens[tokens.length - 1]);
        return builder.toString();
    }

    protected void generateCode(IProgressMonitor monitor, AntlrBuildUnit unit, IJavaProject javaProject,
            String[] classpath, IPath src) throws CoreException, InterruptedException {
        ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
        ILaunchConfigurationType type = manager.getLaunchConfigurationType(ID_JAVA_APPLICATION);
        ILaunchConfigurationWorkingCopy cgwc = type.newInstance(null,
                "Generating Code for " + unit.getGrammar().getElementName());
        cgwc.setAttribute(ATTR_PROJECT_NAME, javaProject.getElementName());
        cgwc.setAttribute(ATTR_MAIN_TYPE_NAME, "org.antlr.Tool");
        cgwc.setAttribute(ATTR_DEFAULT_CLASSPATH, false);
        cgwc.setAttribute(ATTR_CLASSPATH, Arrays.asList(classpath));
        // program arguments
        StringBuilder programArgs = new StringBuilder();
        programArgs.append("-verbose ");
        programArgs.append("-debug ");
        programArgs.append("-o ");
        programArgs.append(safeArg(src.toOSString()));
        programArgs.append(" ");
        IGrammar grammar = unit.getGrammar();
        if (grammar.isParserGrammar()) {
            String lexerGrammarName = grammar.getOption("tokenVocab");
            IPath lexerFile = unit.getAbsoluteLibraryPath().append(lexerGrammarName).addFileExtension("g");
            programArgs.append(safeArg(lexerFile.toOSString())).append(" ");
        }
        programArgs.append(safeArg(unit.getAbsolutePath().toOSString()));

        cgwc.setAttribute(ATTR_PROGRAM_ARGUMENTS, programArgs.toString());
        // create and run the launch configuration
        ILaunchConfiguration config = cgwc.doSave();
        ILaunch launch = config.launch(ILaunchManager.RUN_MODE, monitor);
        while (!launch.isTerminated()) {
            Thread.sleep(500L);
        }
        // delete the configuration
        config.delete();
        int exitValue = launch.getProcesses()[0].getExitValue();
        if (exitValue != 0) {
            throw new CoreException(new Status(IStatus.ERROR, AntlrJDT.PLUGIN_ID, "Code generation fails"));
        }
    }

    protected void compile(IProgressMonitor monitor, AntlrBuildUnit unit, IJavaProject javaProject,
            IRuntimeClasspathEntry[] classpath, IPath compilerPath, IPath src, IPath classes)
            throws CoreException, InterruptedException {
        ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
        ILaunchConfigurationType type = manager.getLaunchConfigurationType(ID_JAVA_APPLICATION);

        ILaunchConfigurationWorkingCopy workingCopy = type.newInstance(null,
                "Compiling " + unit.getGrammar().getElementName());

        workingCopy.setAttribute(ATTR_PROJECT_NAME, javaProject.getElementName());
        workingCopy.setAttribute(ATTR_MAIN_TYPE_NAME, "org.eclipse.jdt.internal.compiler.batch.Main");
        workingCopy.setAttribute(ATTR_DEFAULT_CLASSPATH, false);

        IRuntimeClasspathEntry compilerEntry = JavaRuntime.newArchiveRuntimeClasspathEntry(compilerPath);
        compilerEntry.setClasspathProperty(IRuntimeClasspathEntry.USER_CLASSES);

        workingCopy.setAttribute(ATTR_CLASSPATH, Arrays.asList(compilerEntry.getMemento()));

        StringBuilder compilerArgs = new StringBuilder();
        compilerArgs.append("-showversion ");
        compilerArgs.append("-cp ");
        for (IRuntimeClasspathEntry rcp : classpath) {
            compilerArgs.append(safeArg(rcp.getLocation()));
            compilerArgs.append(File.pathSeparator);
        }
        compilerArgs.setLength(compilerArgs.length() - 1);
        String sourceLevel = "-" + javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true);
        compilerArgs.append(" -nowarn ");
        compilerArgs.append(sourceLevel);
        compilerArgs.append(" -d ");
        compilerArgs.append(safeArg(classes.toOSString()));
        compilerArgs.append(" ");
        compilerArgs.append(safeArg(src.toOSString()));

        workingCopy.setAttribute(ATTR_PROGRAM_ARGUMENTS, compilerArgs.toString());
        // create and run the launch configuration
        ILaunchConfiguration config = workingCopy.doSave();
        ILaunch launch = config.launch(ILaunchManager.RUN_MODE, monitor);
        while (!launch.isTerminated()) {
            Thread.sleep(500L);
        }
        // delete the configuration
        config.delete();
        int exitValue = launch.getProcesses()[0].getExitValue();
        if (exitValue != 0) {
            throw new CoreException(new Status(IStatus.ERROR, AntlrJDT.PLUGIN_ID, "Compilation fails"));
        }
    }

    private static IPath deployCompiler() {
        IPath root = AntlrJDT.getDefault().getStateLocation().append("jars");
        IPath lib = Path.fromPortableString("lib");
        String jarFileName = "org.eclipse.jdt.core_3.4.0.jar";
        IPath compilerJar = root.append(jarFileName);
        try {
            File file = compilerJar.toFile();
            File container = file.getParentFile();
            if (!container.exists()) {
                container.mkdirs();
            }
            if (!file.exists()) {
                Bundle bundle = AntlrJDT.getDefault().getBundle();
                String bundleFile = lib.append(jarFileName).toPortableString();
                AntlrCoreHelper.copyFileFromBundle(bundle, bundleFile, file);
            }
        } catch (IOException e) {
            AntlrCore.error(e);
        }

        return compilerJar;
    }

    private static IPath getFolder(IGrammar grammar, String name, boolean clean) {
        IPath path = getDeployHome(grammar).append(grammar.getElementName()).append(name);
        File folder = path.toFile();
        if (!folder.exists()) {
            folder.mkdirs();
        } else if (clean) {
            clean(folder);
        }
        return path;
    }

    private static IPath getDeployHome(IGrammar grammar) {
        return AntlrCore.getDefault().getStateLocation().append("java").append(grammar.getFolder());
    }

    private static void clean(File dir) {
        File[] files = dir.listFiles();
        if (files != null && files.length > 0) {
            for (File file : files) {
                if (file.isDirectory()) {
                    clean(file);
                }
                file.delete();
            }
        }
    }
}