From bd66f35865127f4a748113c3c47601b11e5307ee Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Wed, 15 Apr 2015 09:12:51 -0400 Subject: [PATCH] Bug 464636 - Modernize Run launch Change-Id: I1c7a4cbbcd00f3967fe9cdbc1fc4b6e0b4d4d14f Signed-off-by: Marc Khouzam --- .../org.eclipse.cdt.dsf.gdb/plugin.properties | 4 +- launch/org.eclipse.cdt.launch/plugin.xml | 2 +- .../cdt/launch/AbstractCLaunchDelegate2.java | 77 ++++++- .../internal/LocalCDILaunchDelegate.java | 39 +--- .../internal/LocalRunLaunchDelegate.java | 206 ++++++------------ .../org/eclipse/cdt/launch/ui/CMainTab2.java | 5 +- 6 files changed, 158 insertions(+), 175 deletions(-) diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/plugin.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb/plugin.properties index e09faf24aea..dc6822f9b5d 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/plugin.properties +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/plugin.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2006, 2012 Wind River Systems and others. +# Copyright (c) 2006, 2015 Wind River Systems and others. # 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 @@ -13,7 +13,7 @@ pluginName=GDB DSF Debugger Integration Core providerName=Eclipse CDT -launchDelegate.localApplication.name=GDB (DSF) Create Process +launchDelegate.localApplication.name=GDB (DSF) Debug Process launchDelegate.localApplication.description=Start new application under control of GDB debugger integrated using the Debugger Services Framework (DSF). launchDelegate.remoteApplication.name=GDB (DSF) Manual Remote Debugging launchDelegate.remoteApplication.description=Debug a new application that was manually started on a remote system under control of GDB debugger integrated using the Debugger Services Framework (DSF). diff --git a/launch/org.eclipse.cdt.launch/plugin.xml b/launch/org.eclipse.cdt.launch/plugin.xml index ad8f5b7e3a7..d387219bfc0 100644 --- a/launch/org.eclipse.cdt.launch/plugin.xml +++ b/launch/org.eclipse.cdt.launch/plugin.xml @@ -193,7 +193,7 @@ id="org.eclipse.cdt.cdi.launch.runApplicationLaunch.mainTab" group="org.eclipse.cdt.launch.applicationRunLaunchTabGroup" name="%MainLaunchTab.name" - class="org.eclipse.cdt.launch.ui.CMainTab"> + class="org.eclipse.cdt.launch.ui.CMainTab2"> null if a working directory is not + * specified. + * + * @param configuration launch configuration + * @return an absolute path to a directory, or null if unspecified + * @throws CoreException if unable to retrieve the associated launch + * configuration attribute or if unable to resolve any variables + * + * @since 7.3 + */ + protected IPath getWorkingDirectoryPath(ILaunchConfiguration config) throws CoreException { + String location = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, (String)null); + if (location != null) { + String expandedLocation = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(location);; + if (!expandedLocation.isEmpty()) { + return new Path(expandedLocation); + } + } + return null; + } + + /** + * Verifies the working directory specified by the given launch + * configuration exists, and returns that working directory, or + * null if none is specified. + * + * @param configuration + * launch configuration + * @return the working directory specified by the given launch + * configuration, or null if none + * @exception CoreException + * if unable to retrieve the attribute + * @since 7.3 + */ + protected File verifyWorkingDirectory(ILaunchConfiguration configuration) throws CoreException { + IPath path = getWorkingDirectoryPath(configuration); + if (path == null) { + // default working dir is the project if this config has a project + ICProject cp = CDebugUtils.getCProject(configuration); + if (cp == null) { + return null; + } + + IProject p = cp.getProject(); + return p.getLocation().toFile(); + } + + if (path.isAbsolute()) { + File dir = new File(path.toOSString()); + if (dir.isDirectory()) { + return dir; + } + } else { + IResource res = ResourcesPlugin.getWorkspace().getRoot().findMember(path); + if (res instanceof IContainer && res.exists()) { + return res.getLocation().toFile(); + } + } + + abort(LaunchMessages.AbstractCLaunchDelegate_Working_directory_does_not_exist, + new FileNotFoundException( + NLS.bind(LaunchMessages.AbstractCLaunchDelegate_WORKINGDIRECTORY_PATH_not_found, + path.toOSString())), + ICDTLaunchConfigurationConstants.ERR_WORKING_DIRECTORY_DOES_NOT_EXIST); + return null; + } + /** * @return the ID of the plugin hosting the launch delegate. It's used to * create {@link IStatus} objects. diff --git a/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/LocalCDILaunchDelegate.java b/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/LocalCDILaunchDelegate.java index 7be45a8ce08..10605efdb15 100644 --- a/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/LocalCDILaunchDelegate.java +++ b/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/LocalCDILaunchDelegate.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2010 QNX Software Systems and others. + * Copyright (c) 2004, 2015 QNX Software Systems and others. * 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 @@ -9,18 +9,17 @@ * QNX Software Systems - Initial API and implementation * Anton Leherbauer (Wind River Systems) - bugs 205108, 212632, 224187 * Ken Ryall (Nokia) - bug 188116 + * Marc Khouzam (Ericsson) - Modernize Run launch (bug 464636) *******************************************************************************/ package org.eclipse.cdt.launch.internal; import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.IBinaryParser.IBinaryObject; import org.eclipse.cdt.core.IProcessInfo; import org.eclipse.cdt.core.IProcessList; -import org.eclipse.cdt.core.IBinaryParser.IBinaryObject; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.debug.core.CDIDebugModel; import org.eclipse.cdt.debug.core.CDebugUtils; @@ -68,40 +67,16 @@ public class LocalCDILaunchDelegate extends AbstractCLaunchDelegate { monitor = new NullProgressMonitor(); } if (mode.equals(ILaunchManager.RUN_MODE)) { - runLocalApplication(config, launch, monitor); + // We plan on splitting the Run delegate from the Debug one. + // For now, to keep backwards-compatibility, we need to keep the same delegate (to keep its id) + // However, we can just call the new delegate class + new LocalRunLaunchDelegate().launch(config, mode, launch, monitor); } if (mode.equals(ILaunchManager.DEBUG_MODE)) { launchDebugger(config, launch, monitor); } } - private void runLocalApplication(ILaunchConfiguration config, ILaunch launch, IProgressMonitor monitor) throws CoreException { - monitor.beginTask(LaunchMessages.LocalCDILaunchDelegate_0, 10); - if (monitor.isCanceled()) { - return; - } - monitor.worked(1); - try { - IPath exePath = CDebugUtils.verifyProgramPath(config); - File wd = getWorkingDirectory(config); - if (wd == null) { - wd = new File(System.getProperty("user.home", ".")); //$NON-NLS-1$ //$NON-NLS-2$ - } - String arguments[] = getProgramArgumentsArray(config); - ArrayList command = new ArrayList(1 + arguments.length); - command.add(exePath.toOSString()); - command.addAll(Arrays.asList(arguments)); - String[] commandArray = (String[])command.toArray(new String[command.size()]); - boolean usePty = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_USE_TERMINAL, ICDTLaunchConfigurationConstants.USE_TERMINAL_DEFAULT); - monitor.worked(2); - Process process = exec(commandArray, getEnvironment(config), wd, usePty); - monitor.worked(6); - DebugPlugin.newProcess(launch, process, renderProcessLabel(commandArray[0])); - } finally { - monitor.done(); - } - } - private void launchDebugger(ILaunchConfiguration config, ILaunch launch, IProgressMonitor monitor) throws CoreException { monitor.beginTask(LaunchMessages.LocalCDILaunchDelegate_1, 10); if (monitor.isCanceled()) { diff --git a/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/LocalRunLaunchDelegate.java b/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/LocalRunLaunchDelegate.java index 57a608c8d37..57219d3dc37 100644 --- a/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/LocalRunLaunchDelegate.java +++ b/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/LocalRunLaunchDelegate.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2010 QNX Software Systems and others. + * Copyright (c) 2005, 2015 QNX Software Systems and others. * 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 @@ -7,6 +7,7 @@ * * Contributors: * QNX Software Systems - initial API and implementation + * Marc Khouzam (Ericsson) - Modified to only handle Run mode and modernized (Bug 464636) *******************************************************************************/ package org.eclipse.cdt.launch.internal; @@ -14,187 +15,118 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; -import org.eclipse.cdt.core.IBinaryParser.IBinaryObject; -import org.eclipse.cdt.core.model.ICProject; -import org.eclipse.cdt.debug.core.CDIDebugModel; import org.eclipse.cdt.debug.core.CDebugUtils; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; -import org.eclipse.cdt.debug.core.ICDebugConfiguration; -import org.eclipse.cdt.debug.core.cdi.CDIException; -import org.eclipse.cdt.debug.core.cdi.ICDISession; -import org.eclipse.cdt.debug.core.cdi.model.ICDIRuntimeOptions; -import org.eclipse.cdt.debug.core.cdi.model.ICDITarget; -import org.eclipse.cdt.launch.AbstractCLaunchDelegate; +import org.eclipse.cdt.launch.AbstractCLaunchDelegate2; import org.eclipse.cdt.launch.internal.ui.LaunchMessages; import org.eclipse.cdt.launch.internal.ui.LaunchUIPlugin; +import org.eclipse.cdt.utils.CommandLineUtil; import org.eclipse.cdt.utils.pty.PTY; import org.eclipse.cdt.utils.spawner.ProcessFactory; 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.NullProgressMonitor; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.core.variables.VariablesPlugin; 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.IStatusHandler; -import org.eclipse.debug.core.model.IProcess; -public class LocalRunLaunchDelegate extends AbstractCLaunchDelegate { +import com.ibm.icu.text.DateFormat; +/** + * The launch delegate for Run mode. + */ +public class LocalRunLaunchDelegate extends AbstractCLaunchDelegate2 +{ + public LocalRunLaunchDelegate() { + super(false); + } + @Override - public void launch(ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException { - IBinaryObject exeFile = null; - if (monitor == null) { + public void launch( ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor ) throws CoreException { + // This delegate is only for Run mode + assert mode.equals(ILaunchManager.RUN_MODE); + + if ( monitor == null ) { monitor = new NullProgressMonitor(); } - monitor.beginTask(LaunchMessages.LocalRunLaunchDelegate_Launching_Local_C_Application, 10); - // check for cancellation + if ( mode.equals(ILaunchManager.RUN_MODE ) ) { + runLocalApplication( config, launch, monitor ); + } + } + + private void runLocalApplication(ILaunchConfiguration config, ILaunch launch, IProgressMonitor monitor) throws CoreException { + monitor.beginTask(LaunchMessages.LocalCDILaunchDelegate_0, 10); if (monitor.isCanceled()) { return; } + monitor.worked(1); try { - monitor.worked(1); IPath exePath = CDebugUtils.verifyProgramPath(config); - ICProject project = CDebugUtils.verifyCProject(config); - if (exePath != null) { - exeFile = verifyBinary(project, exePath); + + File wd = verifyWorkingDirectory(config); + if (wd == null) { + wd = new File(System.getProperty("user.home", ".")); //$NON-NLS-1$ //$NON-NLS-2$ } - String arguments[] = getProgramArgumentsArray(config); - - // set the default source locator if required - setDefaultSourceLocator(launch, config); - - if (mode.equals(ILaunchManager.DEBUG_MODE)) { - ICDebugConfiguration debugConfig = getDebugConfig(config); - ICDISession dsession = null; - String debugMode = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, - ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN); - if (debugMode.equals(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN)) { - dsession = debugConfig.createDebugger().createDebuggerSession(launch, exeFile, - new SubProgressMonitor(monitor, 8)); - try { - try { - ICDITarget[] dtargets = dsession.getTargets(); - for (int i = 0; i < dtargets.length; ++i) { - ICDIRuntimeOptions opt = dtargets[i].getRuntimeOptions(); - opt.setArguments(arguments); - File wd = getWorkingDirectory(config); - if (wd != null) { - opt.setWorkingDirectory(wd.getAbsolutePath()); - } - opt.setEnvironment(getEnvironmentAsProperty(config)); - } - } catch (CDIException e) { - abort(LaunchMessages.LocalRunLaunchDelegate_Failed_setting_runtime_option_though_debugger, e, - ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR); - } - monitor.worked(1); - boolean stopInMain = config.getAttribute( - ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false); - String stopSymbol = null; - if (stopInMain) { - stopSymbol = launch.getLaunchConfiguration().getAttribute( - ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, - ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT); - } - - ICDITarget[] targets = dsession.getTargets(); - for (int i = 0; i < targets.length; i++) { - Process process = targets[i].getProcess(); - IProcess iprocess = null; - if (process != null) { - iprocess = DebugPlugin.newProcess(launch, process, renderProcessLabel(exePath.toOSString()), getDefaultProcessMap()); - } - CDIDebugModel.newDebugTarget(launch, project.getProject(), targets[i], renderTargetLabel(debugConfig), - iprocess, exeFile, true, false, stopSymbol, true); - } - } catch (CoreException e) { - try { - dsession.terminate(); - } catch (CDIException e1) { - // ignore - } - throw e; - } - } - } else { - File wd = getWorkingDirectory(config); - if (wd == null) { - wd = new File(System.getProperty("user.home", ".")); //$NON-NLS-1$ //$NON-NLS-2$ - } - ArrayList command = new ArrayList(1 + arguments.length); - command.add(exePath.toOSString()); - command.addAll(Arrays.asList(arguments)); - String[] commandArray = command.toArray(new String[command.size()]); - boolean usePty = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_USE_TERMINAL, - ICDTLaunchConfigurationConstants.USE_TERMINAL_DEFAULT); - monitor.worked(5); - Process process = exec(commandArray, getEnvironment(config), wd, usePty); - monitor.worked(3); - DebugPlugin.newProcess(launch, process, renderProcessLabel(commandArray[0])); + + String args = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, ""); //$NON-NLS-1$ + if (args.length() != 0) { + args = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(args); } + + String[] arguments = CommandLineUtil.argumentsToArray(args); + ArrayList command = new ArrayList<>(1 + arguments.length); + command.add(exePath.toOSString()); + command.addAll(Arrays.asList(arguments)); + monitor.worked(2); + + String[] commandArray = command.toArray(new String[command.size()]); + String[] environment = DebugPlugin.getDefault().getLaunchManager().getEnvironment(config); + Process process = exec(commandArray, environment, wd); + monitor.worked(6); + + String timestamp = DateFormat.getInstance().format(new Date(System.currentTimeMillis())); + String processLabel = String.format("%s (%s)", commandArray[0], timestamp); //$NON-NLS-1$ + DebugPlugin.newProcess(launch, process, processLabel); } finally { monitor.done(); - } + } } /** * Performs a runtime exec on the given command line in the context of the - * specified working directory, and returns the resulting process. If the - * current runtime does not support the specification of a working - * directory, the status handler for error code - * ERR_WORKING_DIRECTORY_NOT_SUPPORTED is queried to see if - * the exec should be re-executed without specifying a working directory. + * specified working directory, and returns the resulting process. * * @param cmdLine * the command line + * @param environ * @param workingDirectory * the working directory, or null - * @return the resulting process or null if the exec is - * cancelled + * @return the resulting process or null if the exec is cancelled * @see Runtime + * @since 4.7 */ - protected Process exec(String[] cmdLine, String[] environ, File workingDirectory, boolean usePty) throws CoreException { - Process p = null; + protected Process exec(String[] cmdLine, String[] environ, File workingDirectory) throws CoreException { try { - if (workingDirectory == null) { - p = ProcessFactory.getFactory().exec(cmdLine, environ); + if (PTY.isSupported()) { + return ProcessFactory.getFactory().exec(cmdLine, environ, workingDirectory, new PTY()); } else { - if (usePty && PTY.isSupported()) { - p = ProcessFactory.getFactory().exec(cmdLine, environ, workingDirectory, new PTY()); - } else { - p = ProcessFactory.getFactory().exec(cmdLine, environ, workingDirectory); - } + return ProcessFactory.getFactory().exec(cmdLine, environ, workingDirectory); } } catch (IOException e) { - if (p != null) { - p.destroy(); - } - abort(LaunchMessages.LocalRunLaunchDelegate_Error_starting_process, e, - ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR); - } catch (NoSuchMethodError e) { - //attempting launches on 1.2.* - no ability to set working - // directory - - IStatus status = new Status(IStatus.ERROR, LaunchUIPlugin.getUniqueIdentifier(), - ICDTLaunchConfigurationConstants.ERR_WORKING_DIRECTORY_NOT_SUPPORTED, - LaunchMessages.LocalRunLaunchDelegate_Does_not_support_working_dir, - e); - IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler(status); - - if (handler != null) { - Object result = handler.handleStatus(status, this); - if (result instanceof Boolean && ((Boolean) result).booleanValue()) { - p = exec(cmdLine, environ, null, usePty); - } - } + abort(LaunchMessages.LocalCDILaunchDelegate_8, e, ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR); } - return p; + return null; + } + + + @Override + public boolean preLaunchCheck(ILaunchConfiguration config, String mode, IProgressMonitor monitor) throws CoreException { + return super.preLaunchCheck(config, mode, monitor); } @Override diff --git a/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/ui/CMainTab2.java b/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/ui/CMainTab2.java index c158be86c3b..16f615b8647 100644 --- a/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/ui/CMainTab2.java +++ b/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/ui/CMainTab2.java @@ -76,7 +76,8 @@ public class CMainTab2 extends CAbstractMainTab { * org.eclipse.debug.ui.launchConfigurationTabs * extension point. */ - public static final String TAB_ID = "org.eclipse.cdt.launch.mainTab2"; //$NON-NLS-1$ + // Keep the same id as the original Run launch main tab for backwards-compatibility + public static final String TAB_ID = "org.eclipse.cdt.cdi.launch.mainTab"; //$NON-NLS-1$ private static final String CORE_FILE = LaunchMessages.CMainTab2_CoreFile_type; private static final String TRACE_FILE = LaunchMessages.CMainTab2_TraceFile_type; @@ -441,7 +442,7 @@ public class CMainTab2 extends CAbstractMainTab { } IPath exePath = new Path(programName); if (exePath.isAbsolute()) { - // For absolute paths, we don't need a project, we can debug the binary directly + // For absolute paths, we don't need a project, we can debug or run the binary directly // as long as it exists File executable = exePath.toFile(); if (!executable.exists()) {