package intrace.ecl.ui.launching; import intrace.ecl.Activator; import intrace.ecl.Util; import intrace.ecl.ui.output.EditorInput; import intrace.ecl.ui.output.EditorInput.InputType; import java.io.IOException; import java.net.ServerSocket; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExecutableExtension; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.SubProgressMonitor; 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.debug.core.ILaunchesListener2; import org.eclipse.debug.core.model.ILaunchConfigurationDelegate; import org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate; import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.statushandlers.StatusManager; /** * Class which handles adding the InTrace JVM argument and launching the InTrace editor */ public class LaunchConfigurationDelegate extends AbstractJavaLaunchConfigurationDelegate implements IExecutableExtension { /** * Config key used to save the launch ID into an ILaunch object */ public static final String INTRACE_LAUNCHKEY = "INTRACE_LAUNCHKEY"; /** * Map of active launches */ public static final Map<Long, InTraceLaunch> intraceLaunches = new ConcurrentHashMap<Long, InTraceLaunch>(); /** * AtommicLong used to generate launch IDs */ private static final AtomicLong intraceLaunchId = new AtomicLong(); /** * The type of launch being handled. */ protected String launchtype; /** * The delegate which will do most of the work. */ protected ILaunchConfigurationDelegate launchdelegate; // IExecutableExtension interface: @Override public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { launchtype = config.getAttribute("type"); //$NON-NLS-1$ launchdelegate = getLaunchDelegate(launchtype); } @SuppressWarnings("deprecation") private ILaunchConfigurationDelegate getLaunchDelegate(String launchtype) throws CoreException { ILaunchConfigurationType type = DebugPlugin.getDefault().getLaunchManager() .getLaunchConfigurationType(launchtype); if (type == null) { throw new CoreException(Util.createErrorStatus("Unknown launch type", new Throwable())); } return type.getDelegate(ILaunchManager.RUN_MODE); } // ILaunchConfigurationDelegate interface: @Override public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException { try { // Create working copy launch config ILaunchConfigurationWorkingCopy wc = configuration.getWorkingCopy(); // Identify the main class String mainClass = wc.getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, ""); // Make sure main class will be instrumented String classIncludePattern = configuration.getAttribute(InTraceLaunchConfigTab.CLASS_INCL_ATTR, ""); if ("".equals(classIncludePattern)) { classIncludePattern = mainClass; ILaunchConfigurationWorkingCopy wc2 = configuration.getWorkingCopy(); wc2.setAttribute(InTraceLaunchConfigTab.CLASS_INCL_ATTR, classIncludePattern); wc2.doSave(); } // Prepare InTraceLaunch object to handle callback connection ServerSocket callbackServer = new ServerSocket(0); final InTraceLaunch intraceLaunch = new InTraceLaunch(mainClass, callbackServer, configuration); intraceLaunch.start(); // Save off launch object for later access Long connId = intraceLaunchId.getAndIncrement(); intraceLaunches.put(connId, intraceLaunch); launch.setAttribute(INTRACE_LAUNCHKEY, Long.toString(connId)); // Setup a launch listener to cleanup the intrace launch object ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); manager.addLaunchListener(new LaunchListener(launch, connId)); // Add VM arguments String vmArgs = wc.getAttribute( IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, ""); if (Activator.getDefault().baseAgentArg.length() > 0) { vmArgs += Activator.getDefault().baseAgentArg; vmArgs += "=[callbackport-"; vmArgs += Integer.toString(callbackServer.getLocalPort()); vmArgs += "[startwait"; } wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, vmArgs); // Launch editor final IWorkbench workbench = PlatformUI.getWorkbench(); Display display = workbench.getDisplay(); display.asyncExec(new Runnable() { @Override public void run() { try { IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); IWorkbenchPage page = window.getActivePage(); IDE.openEditor(page, new EditorInput(intraceLaunch, InputType.NEWCONNECTION), "intrace.ecl.plugin.ui.output.inTraceEditor"); } catch (PartInitException ex) { Util.handleStatus(Util.createErrorStatus("Failed to open InTrace Output", ex), StatusManager.SHOW); } } }); // Start launch launchdelegate.launch(wc, ILaunchManager.RUN_MODE, launch, new SubProgressMonitor(monitor, 1)); } catch (IOException e1) { Util.handleStatus(Util.createErrorStatus("InTrace launch failed", e1), StatusManager.SHOW); } } /** * Launch listener which handles the cleanup of entries in the intraceLaunches map */ private static class LaunchListener implements ILaunchesListener2 { public LaunchListener(ILaunch targetlaunch, Long intraceLaunchId) { this.targetlaunch = targetlaunch; this.intraceLaunchId = intraceLaunchId; } private final ILaunch targetlaunch; private final Long intraceLaunchId; @Override public void launchesRemoved(ILaunch[] launches) { // Do nothing } @Override public void launchesAdded(ILaunch[] launches) { // Do nothing } @Override public void launchesChanged(ILaunch[] launches) { // Do nothing } @Override public void launchesTerminated(ILaunch[] launches) { for (ILaunch launch : launches) { if (launch == targetlaunch) { InTraceLaunch intraceLaunch = intraceLaunches.remove(intraceLaunchId); if (intraceLaunch != null) { intraceLaunch.destroy(); } ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); manager.removeLaunchListener(this); } } } } }