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

Java tutorial

Introduction

Here is the source code for org.deved.antlride.jdt.launch.AntlrJavaLauncher.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.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.regex.Matcher;

import org.deved.antlride.core.AntlrConstants;
import org.deved.antlride.core.build.AntlrBuildUnit;
import org.deved.antlride.core.build.AntlrDeployer;
import org.deved.antlride.core.launch.AntlrLauncher;
import org.deved.antlride.core.model.IGrammar;
import org.deved.antlride.core.model.IGrammarAction;
import org.deved.antlride.core.model.evaluation.AntlrResultListener;
import org.deved.antlride.core.model.evaluation.IEvalElement;
import org.deved.antlride.core.model.test.AntlrTestCase;
import org.deved.antlride.debug.model.event.AntlrDebugEvent;
import org.deved.antlride.debug.model.event.AntlrDebugEventFactory;
import org.deved.antlride.debug.ui.AntlrDebugParser;
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.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugPlugin;
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.launching.IRuntimeClasspathEntry;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.swt.widgets.Display;

public class AntlrJavaLauncher extends AntlrAbstractJavaLauncher implements AntlrLauncher {

    private AntlrResultListener listener;

    private int run(IProgressMonitor monitor, AntlrBuildUnit unit, AntlrTestCase test, IJavaProject javaProject,
            IRuntimeClasspathEntry[] classpath, IPath src, IPath classes)
            throws CoreException, InterruptedException {
        ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
        ILaunchConfigurationType type = manager.getLaunchConfigurationType(ID_JAVA_APPLICATION);

        ILaunchConfigurationWorkingCopy workingCopy = type.newInstance(null,
                new StringBuilder(test.getRule()).append(" ").append(test.getName()).toString());

        workingCopy.setAttribute(ATTR_PROJECT_NAME, javaProject.getElementName());

        workingCopy.setAttribute(ATTR_MAIN_TYPE_NAME, "org.deved.antlride.runtime.LaunchParser");
        workingCopy.setAttribute(ATTR_DEFAULT_CLASSPATH, false);

        IPath runtimePath = AntlrDeployer.RUNTIME_LOCATION;
        IRuntimeClasspathEntry runtimeEntry = JavaRuntime.newArchiveRuntimeClasspathEntry(runtimePath);
        runtimeEntry.setClasspathProperty(IRuntimeClasspathEntry.USER_CLASSES);

        IRuntimeClasspathEntry classesEntry = JavaRuntime.newArchiveRuntimeClasspathEntry(classes);
        classesEntry.setClasspathProperty(IRuntimeClasspathEntry.USER_CLASSES);
        classesEntry.setSourceAttachmentRootPath(src);

        String[] cp = new String[classpath.length + 2];
        cp[0] = runtimeEntry.getMemento();
        cp[1] = classesEntry.getMemento();
        for (int i = 0; i < classpath.length; i++) {
            cp[i + 2] = classpath[i].getMemento();
        }
        workingCopy.setAttribute(ATTR_CLASSPATH, Arrays.asList(cp));

        IGrammar grammar = unit.getGrammar();
        String grammarName = grammar.getElementName();
        String lexerPackage = getLexerJavaPackage(grammar);
        StringBuilder lexerClass = new StringBuilder(lexerPackage);

        String parserPackage = getParserJavaPackage(grammar);
        StringBuilder parserClass = new StringBuilder(parserPackage).append(grammarName);

        if (grammar.isCombinedGrammar()) {
            lexerClass.append(grammarName).append("Lexer");
            parserClass.append("Parser");
        } else {
            // it can only be a parser grammar
            lexerClass.append(grammar.getOption("tokenVocab"));
        }

        int port = findFreePort();
        StringBuilder programArgs = new StringBuilder();
        programArgs.append("-port").append(" ").append(port).append(" ");
        programArgs.append("-testCase").append(" ").append(safeArg(test.getPath().toOSString())).append(" ");
        programArgs.append("-lexer").append(" ").append(lexerClass).append(" ");
        programArgs.append("-parser").append(" ").append(parserClass).append(" ");
        programArgs.append("-ruleName").append(" ").append(test.getRule());
        // programArgs.append("").append(" ").append();
        // programArgs.append("").append(" ").append();
        // programArgs.append("").append(" ").append();
        // programArgs.append("").append(" ").append();
        // programArgs.append("").append(" ").append();

        workingCopy.setAttribute(ATTR_PROGRAM_ARGUMENTS, programArgs.toString());
        // create and run the launch configuration
        ILaunchConfiguration config = workingCopy.doSave();
        config.launch(ILaunchManager.RUN_MODE, monitor);
        // delete the configuration
        config.delete();

        return port;
    }

    public 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 {
        String[] classpath = new String[runtimeClassPath.length];

        for (int i = 0; i < runtimeClassPath.length; i++) {
            classpath[i] = runtimeClassPath[i].getMemento();
        }

        IGrammar grammar = unit.getGrammar();
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++
        // ++++++++++++++++++++ run
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++
        int port = run(monitor, unit, testCase, javaProject, runtimeClassPath, src, classes);
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++
        // ++++++++++++++++++++ start listener
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++
        startListener(grammar, port);
    }

    private void startListener(final IGrammar grammar, int port) throws UnknownHostException, IOException {
        try {
            // wait for debugger
            Thread.sleep(1000L);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        ;
        final Socket socket = new Socket("localhost", port);
        socket.setTcpNoDelay(true);
        final PrintWriter writer = createWriter(socket);
        final BufferedReader reader = createReader(socket);

        Job job = new Job("ANTLR Event Listener") {
            @Override
            protected IStatus run(IProgressMonitor monitor) {
                try {
                    String line = reader.readLine();
                    Collection<AntlrDebugEvent> events = new LinkedHashSet<AntlrDebugEvent>();
                    while (!"terminate".equals(line)) {
                        AntlrDebugEvent event = AntlrDebugEventFactory.createFromString(null, grammar, line);
                        events.add(event);
                        writer.println("ack");
                        writer.flush();
                        line = reader.readLine();
                    }
                    final IEvalElement element = AntlrDebugParser.createGraphModel(grammar, events);
                    Display.getDefault().asyncExec(new Runnable() {

                        public void run() {
                            listener.setResult(element);
                        }
                    });
                    reader.close();
                    writer.close();
                    socket.close();
                    events.clear();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return Status.OK_STATUS;
            }
        };
        job.schedule();
    }

    private static PrintWriter createWriter(Socket socket) throws IOException {
        OutputStream os = socket.getOutputStream();
        OutputStreamWriter osw = new OutputStreamWriter(os, "UTF8");
        return new PrintWriter(new BufferedWriter(osw));
    }

    private static BufferedReader createReader(Socket socket) throws IOException {
        return new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF8"));
    }

    private static int findFreePort() {
        ServerSocket socket = null;
        try {
            socket = new ServerSocket(0);
            return socket.getLocalPort();
        } catch (IOException e) {
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                }
            }
        }
        return 49153;
    }

    private static String getParserJavaPackage(IGrammar grammar) {
        if (grammar.isCombinedGrammar() || grammar.isParserGrammar() || grammar.isTreeParserGrammar()) {
            return extractJavaPackage(grammar, "header");
        }
        return "";
    }

    private static String getLexerJavaPackage(IGrammar grammar) {
        if (grammar.isCombinedGrammar()) {
            return extractJavaPackage(grammar, "lexer::header");
        }
        if (grammar.isParserGrammar() || grammar.isTreeParserGrammar()) {
            IGrammar tokenGrammar = grammar.getTokenVocab();
            if (tokenGrammar != null) {
                return extractJavaPackage(tokenGrammar, "header");
            }
        }
        if (grammar.isLexerGrammar()) {
            return extractJavaPackage(grammar, "header");
        }
        return "";
    }

    private static String extractJavaPackage(IGrammar grammar, String action) {
        IGrammarAction header = grammar.findAction(action);
        String packageName = "";
        if (header != null) {
            String headerText = header.toString();
            Matcher matcher = AntlrConstants.ANTLR_JAVA_PACKAGE_PATTERN.matcher(headerText);
            if (matcher.find()) {
                packageName = matcher.group(1) + ".";
            }
        }
        return packageName;
    }

    public void setResultListener(AntlrResultListener listener) {
        this.listener = listener;
    }
}