package intrace.ecl.ui.launching; import intrace.ecl.Util; import intrace.ecl.ui.output.InTraceEditor; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Map; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.jface.action.IAction; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.statushandlers.StatusManager; import org.intrace.shared.AgentConfigConstants; /** * This class wraps the state associated with a single InTrace enabled launch. */ public class InTraceLaunch implements Runnable { /** * Server socket used for callback connection from InTrace agent */ private final ServerSocket callbackserver; /** * Active connection established as part of InTrace callback */ private Socket clientConnection = null; /** * Server port which the InTrace agent is listening on */ public String agentServerPort = null; /** * Currently active InTrace editor */ private InTraceEditor editor = null; /** * Action which opens the InTrace editor */ private IAction openeditoraction = null; /** * Main class being launched */ public final String mainClass; /** * Associated launch configuration */ public final ILaunchConfiguration configuration; /** * Construct an instance to listen on a provided ServerSocket * @param xiMainClass * @param xiServer * @param xiConfiguration */ public InTraceLaunch(String xiMainClass, ServerSocket xiServer, ILaunchConfiguration xiConfiguration) { this.mainClass = xiMainClass; this.callbackserver = xiServer; this.configuration = xiConfiguration; } @SuppressWarnings("unchecked") @Override public void run() { try { // Listen for incoming callback connection clientConnection = callbackserver.accept(); // Connected! Time to discover the server port. ObjectOutputStream out = new ObjectOutputStream(clientConnection.getOutputStream()); out.writeObject("getsettings"); out.flush(); // Read the returned settings, discard any instrumentation status messages ObjectInputStream in; while (agentServerPort == null) { in = new ObjectInputStream(clientConnection.getInputStream()); Object obj = in.readObject(); if (obj instanceof Map<?,?>) { Map<String,String> settingsMap = (Map<String,String>)obj; agentServerPort = settingsMap.get(AgentConfigConstants.SERVER_PORT); } } // Notify the UI that we have got a connection notifyClientConnection(); } catch (Throwable th) { Util.handleStatus(Util.createErrorStatus("Error during InTrace launch", th), StatusManager.SHOW | StatusManager.LOG); } } /** * Mark that a connection is ready */ private synchronized void notifyClientConnection() { this.notifyAll(); } /** * Start the callback connection thread */ public void start() { Thread callbackConnectionThread = new Thread(this); callbackConnectionThread.setDaemon(true); callbackConnectionThread.setName("InTrace-Launch-CallbackHandler"); callbackConnectionThread.start(); } /** * @return The active connection. * @throws InterruptedException */ public synchronized Socket getClientConnection() throws InterruptedException { while (clientConnection == null) { this.wait(); } return clientConnection; } public synchronized InTraceEditor getEditor() { return editor; } public synchronized void setEditor(InTraceEditor editor) { this.editor = editor; } public synchronized void setOpeneditoraction(IAction openeditoraction) { this.openeditoraction = openeditoraction; } public synchronized void destroy() { final IAction action = openeditoraction; if (action != null) { // Disable action final IWorkbench workbench = PlatformUI.getWorkbench(); Display display = workbench.getDisplay(); display.asyncExec(new Runnable() { @Override public void run() { action.setEnabled(false); } }); } this.openeditoraction = null; } }