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.IOException;
import java.net.ServerSocket;
import java.net.UnknownHostException;
import java.util.Arrays;
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.test.AntlrTestCase;
import org.deved.antlride.debug.AntlrDebugConstants;
import org.deved.antlride.debug.model.AntlrDebugTarget;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
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.launching.IRuntimeClasspathEntry;
import org.eclipse.jdt.launching.JavaRuntime;
public class AntlrJavaDebugLauncher extends AntlrAbstractJavaLauncher implements
AntlrLauncher {
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);// AntlrDebugConstants.ANTLR_LAUNCH_CONFIGURATION_TYPE);
ILaunchConfigurationWorkingCopy workingCopy = type.newInstance(null,
new StringBuilder(test.getRule()).append(" ").append(
test.getName()).toString());
workingCopy.setAttribute(ATTR_PROJECT_NAME, javaProject
.getElementName());
workingCopy.setAttribute(AntlrDebugConstants.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(
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());
workingCopy.setAttribute(AntlrDebugConstants.ATTR_ANTLR_PROGRAM, unit
.getFile().getProjectRelativePath().toPortableString());
// workingCopy.setAttribute(
// IJavaLaunchConfigurationConstants.ATTR_SOURCE_PATH_PROVIDER,
// "antlrJavaSourceLocator");
workingCopy.setAttribute(AntlrDebugConstants.JAVA_EXTERNAL_SOURCE_PATH,
src.toOSString());
workingCopy.setAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID,
"org.deved.antlride.jdt.sourceLocator");
// create and run the launch configuration
final ILaunchConfiguration config = workingCopy.doSave();
final ILaunch launch = config
.launch(ILaunchManager.DEBUG_MODE, monitor);
AntlrDebugTarget target = new AntlrDebugTarget(grammar, launch, launch
.getProcesses()[0], port);
launch.addDebugTarget(target);
new Thread(new Runnable() {
public void run() {
while (!launch.isTerminated()) {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
config.delete();
} catch (CoreException e) {
e.printStackTrace();
}
}
}).start();
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 {
// ++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++ run
// ++++++++++++++++++++++++++++++++++++++++++++++++++++
run(monitor, unit, testCase, javaProject, runtimeClassPath, src,
classes);
}
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) {
// do nothing
}
}