/*******************************************************************************
* Copyright (c) 2005, 2010 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* QNX Software Systems - initial API and implementation
*******************************************************************************/
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.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.internal.ui.LaunchMessages;
import org.eclipse.cdt.launch.internal.ui.LaunchUIPlugin;
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.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 {
public void launch(ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException {
IBinaryObject exeFile = null;
if (monitor == null) {
monitor = new NullProgressMonitor();
}
monitor.beginTask(LaunchMessages.LocalRunLaunchDelegate_Launching_Local_C_Application, 10);
// check for cancellation
if (monitor.isCanceled()) {
return;
}
try {
monitor.worked(1);
IPath exePath = CDebugUtils.verifyProgramPath(config);
ICProject project = CDebugUtils.verifyCProject(config);
if (exePath != null) {
exeFile = verifyBinary(project, exePath);
}
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<String> command = new ArrayList<String>(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]));
}
} 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
* <code>ERR_WORKING_DIRECTORY_NOT_SUPPORTED</code> is queried to see if
* the exec should be re-executed without specifying a working directory.
*
* @param cmdLine
* the command line
* @param workingDirectory
* the working directory, or <code>null</code>
* @return the resulting process or <code>null</code> if the exec is
* cancelled
* @see Runtime
*/
protected Process exec(String[] cmdLine, String[] environ, File workingDirectory, boolean usePty) throws CoreException {
Process p = null;
try {
if (workingDirectory == null) {
p = ProcessFactory.getFactory().exec(cmdLine, environ);
} else {
if (usePty && PTY.isSupported()) {
p = ProcessFactory.getFactory().exec(cmdLine, environ, workingDirectory, new PTY());
} else {
p = 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);
}
}
}
return p;
}
protected String getPluginID() {
return LaunchUIPlugin.getUniqueIdentifier();
}
}