/** * */ package org.keplerproject.ldt.debug.core.launcher; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.net.ServerSocket; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; 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.DebugEvent; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.ILaunchConfigurationDelegate; import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.model.IStreamsProxy; import org.keplerproject.ldt.debug.core.LuaDebuggerPlugin; import org.keplerproject.ldt.debug.core.model.LuaDebugServer; import org.keplerproject.ldt.debug.core.model.LuaDebugTarget; import org.keplerproject.ldt.internal.launching.LuaInterpreter; import org.keplerproject.ldt.internal.launching.LuaRuntime; /** * @author jasonsantos */ public class LuaLaunchDelegate implements ILaunchConfigurationDelegate { /* * (non-Javadoc) * * @see org.eclipse.debug.core.model.ILaunchConfigurationDelegate#launch(org.eclipse.debug.core.ILaunchConfiguration, * java.lang.String, org.eclipse.debug.core.ILaunch, * org.eclipse.core.runtime.IProgressMonitor) */ public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException { String projectName = configuration.getAttribute( LuaDebuggerPlugin.LUA_PROJECT_ATTRIBUTE, (String) null); IWorkspaceRoot myWorkspaceRoot = ResourcesPlugin.getWorkspace() .getRoot(); IProject project = myWorkspaceRoot.getProject(projectName); boolean remoteDbgEnabled = configuration.getAttribute(LuaDebuggerPlugin.LUA_REMOTE_DBG_ENABLED_ATTRIBUTE, false); int remoteDbgPort = configuration.getAttribute(LuaDebuggerPlugin.LUA_REMOTE_DBG_PORT_ATTRIBUTE, 8171); // TODO obtain host and ports from configuration String controlHost = "localhost"; int controlPort = -1; int eventPort = -1; IProcess proc; if (remoteDbgEnabled) { controlPort = remoteDbgPort; eventPort = findFreePort(); if (controlPort == -1 || eventPort == -1) error("Could not allocate debug port", null); proc = new RemoteProcess(launch, "Remote Lua Debugger"); } else { String script = configuration.getAttribute( LuaDebuggerPlugin.LUA_SCRIPT_ATTRIBUTE, (String) null); String args = configuration.getAttribute( LuaDebuggerPlugin.LUA_ARGS_ATTRIBUTE, (String) null); IFile p = myWorkspaceRoot.getFile(new Path(script)); if (!p.exists()) { String msg = MessageFormat.format("Lua script {0} does not exist.", new String[] { p.getFullPath().toString() }, null); error(msg, new FileNotFoundException()); } String scriptPath = p.getLocation().toOSString(); List<String> commandList = new ArrayList<String>(); commandList.add(getLuaInterpreter(project)); commandList.add(getLuaDebugClient()); commandList.add("--prefix=" + getLuaModulesPath()); if (mode.equals(ILaunchManager.DEBUG_MODE)) { commandList.add("--debug"); controlPort = findFreePort(); eventPort = findFreePort(); if (controlPort == -1 || eventPort == -1) error("Could not allocate debug port", null); commandList.add("--host=" + controlHost); commandList.add("--port=" + controlPort); } commandList.add(scriptPath); String[] argList = DebugPlugin.parseArguments(args); for (String arg : argList) commandList.add(arg); String[] commandLine = commandList.toArray(new String[commandList .size()]); File scriptPathFile = new File(scriptPath).getParentFile(); Process process = DebugPlugin.exec(commandLine, scriptPathFile); proc = DebugPlugin.newProcess(launch, process, "Standard Lua Remdebug Engine"); } LuaDebugServer server = null; try { server = new LuaDebugServer(controlHost, controlPort, eventPort); } catch (IOException e) { throw new DebugException(new Status(IStatus.ERROR, DebugPlugin .getUniqueIdentifier(), "Could not connect to RemDebug", e)); } // if in debug mode, create a debug target if (mode.equals(ILaunchManager.DEBUG_MODE)) { IDebugTarget target = new LuaDebugTarget(launch, proc, server); launch.addDebugTarget(target); } } /** * Throws an error with a message * * @param msg * @throws CoreException */ private void error(String msg, Exception e) throws CoreException { throw new CoreException(new Status(IStatus.ERROR, LuaDebuggerPlugin.PLUGIN_ID, 0, msg, e)); } private String getLuaModulesPath() { File f = LuaDebuggerPlugin.getFileInPlugin(new Path("lua/5.1/")); if (f != null) return f.getAbsolutePath(); return null; } /** * Returns the absolute path of the remdebug client * * @return absolute path of the remdebug client */ private String getLuaDebugClient() throws DebugException { File f = LuaDebuggerPlugin.getFileInPlugin(new Path( "lua/5.1/debugger/client.lua")); if (f == null) throw new DebugException(new Status(IStatus.ERROR, DebugPlugin .getUniqueIdentifier(), "Could not locate remdebug eclipse client", new FileNotFoundException())); return f.getAbsolutePath(); } /** * Returns the name of the Lua Interpreter for the project * * @return * @throws CoreException */ private String getLuaInterpreter(IProject prj) throws CoreException { String interpreter; LuaInterpreter li = LuaRuntime.getDefault().getSelectedInterpreter(); interpreter = li.getFileName(); return interpreter; } public 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 -1; } } class RemoteProcess implements IProcess { private ILaunch launch; private HashMap<String,String> attrs = new HashMap<String,String>(); private String label; private boolean termintated; public RemoteProcess(ILaunch launch, String label) { this.launch = launch; this.label = label; launch.addProcess(this); } public String getAttribute(String key) { return attrs.get(key); } public int getExitValue() throws DebugException { if (!termintated) throw new DebugException(new Status(IStatus.ERROR, DebugPlugin .getUniqueIdentifier(), "Remote debugger not terminated")); return 0; } public String getLabel() { return label; } public ILaunch getLaunch() { return launch; } public IStreamsProxy getStreamsProxy() { return null; } public void setAttribute(String key, String value) { attrs.put(key, value); } public Object getAdapter(Class adapter) { return null; } public boolean canTerminate() { return !isTerminated(); } public boolean isTerminated() { return termintated; } public void terminate() throws DebugException { if (!termintated) { termintated = true; launch.terminate(); } } }