Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/FinalLaunchSequence.java1194
-rw-r--r--dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/concurrent/ReflectionSequence.java264
-rw-r--r--dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/concurrent/DsfSequenceTests.java177
3 files changed, 1060 insertions, 575 deletions
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/FinalLaunchSequence.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/FinalLaunchSequence.java
index 8947b514c9..df43b455dc 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/FinalLaunchSequence.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/FinalLaunchSequence.java
@@ -19,8 +19,8 @@ import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.ReflectionSequence;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
-import org.eclipse.cdt.dsf.concurrent.Sequence;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.DataModelInitializedEvent;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
@@ -49,580 +49,624 @@ import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IStatusHandler;
-public class FinalLaunchSequence extends Sequence {
-
- Step[] fSteps = new Step[] {
- new Step() { @Override
- public void execute(RequestMonitor requestMonitor) {
- fTracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), fLaunch.getSession().getId());
- requestMonitor.done();
- }
- @Override
- public void rollBack(RequestMonitor requestMonitor) {
- if (fTracker != null) fTracker.dispose();
- fTracker = null;
- requestMonitor.done();
- }},
-
- /*
- * Fetch the GDBBackend, CommandControl and Process services for later use
- */
- new Step() { @Override
- public void execute(RequestMonitor requestMonitor) {
- fGDBBackend = fTracker.getService(IGDBBackend.class);
- if (fGDBBackend == null) {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot obtain GDBBackend service", null)); //$NON-NLS-1$
- requestMonitor.done();
- return;
- }
-
- fCommandControl = fTracker.getService(IGDBControl.class);
- if (fCommandControl == null) {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot obtain control service", null)); //$NON-NLS-1$
- requestMonitor.done();
- return;
- }
-
- fCommandFactory = fCommandControl.getCommandFactory();
-
- fProcService = fTracker.getService(IMIProcesses.class);
- if (fProcService == null) {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot obtain process service", null)); //$NON-NLS-1$
- requestMonitor.done();
- return;
- }
-
- requestMonitor.done();
- }},
- /*
- * Specify GDB's working directory
- */
- new Step() { @Override
- public void execute(final RequestMonitor requestMonitor) {
- IPath dir = null;
- try {
- dir = fGDBBackend.getGDBWorkingDirectory();
- } catch (CoreException e) {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get working directory", e)); //$NON-NLS-1$
- requestMonitor.done();
- return;
- }
-
- if (dir != null) {
- fCommandControl.queueCommand(
- fCommandFactory.createMIEnvironmentCD(fCommandControl.getContext(), dir.toPortableString()),
- new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
- } else {
- requestMonitor.done();
- }
- }},
- /*
- * Source the gdbinit file specified in the launch
- */
- new Step() { @Override
- public void execute(final RequestMonitor requestMonitor) {
- try {
- final String gdbinitFile = fGDBBackend.getGDBInitFile();
-
- if (gdbinitFile != null && gdbinitFile.length() > 0) {
- fCommandControl.queueCommand(
- fCommandFactory.createCLISource(fCommandControl.getContext(), gdbinitFile),
- new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
- @Override
- protected void handleCompleted() {
- // If the gdbinitFile is the default, then it may not exist and we
- // should not consider this an error.
- // If it is not the default, then the user must have specified it and
- // we want to warn the user if we can't find it.
- if (!gdbinitFile.equals(IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT )) {
- requestMonitor.setStatus(getStatus());
- }
- requestMonitor.done();
- }
- });
- } else {
- requestMonitor.done();
- }
- } catch (CoreException e) {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get gdbinit option", e)); //$NON-NLS-1$
- requestMonitor.done();
- }
- }},
- /*
- * Specify environment variables if needed
- */
- new Step() { @Override
- public void execute(final RequestMonitor requestMonitor) {
- boolean clear = false;
- Properties properties = new Properties();
- try {
- clear = fGDBBackend.getClearEnvironment();
- properties = fGDBBackend.getEnvironmentVariables();
- } catch (CoreException e) {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get environment information", e)); //$NON-NLS-1$
- requestMonitor.done();
- return;
- }
-
- if (clear == true || properties.size() > 0) {
- fCommandControl.setEnvironment(properties, clear, requestMonitor);
- } else {
- requestMonitor.done();
- }
- }},
- /*
- * Specify the executable file to be debugged and read the symbol table.
- */
- new Step() { @Override
- public void execute(final RequestMonitor requestMonitor) {
- boolean noFileCommand = IGDBLaunchConfigurationConstants.DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP_DEFAULT;
- try {
- noFileCommand = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP,
- IGDBLaunchConfigurationConstants.DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP_DEFAULT);
- } catch (CoreException e) {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot read use solib symbols for app options", e)); //$NON-NLS-1$
- requestMonitor.done();
- return;
- }
-
- final IPath execPath = fGDBBackend.getProgramPath();
- if (!noFileCommand && execPath != null && !execPath.isEmpty()) {
- fCommandControl.queueCommand(
- fCommandFactory.createMIFileExecAndSymbols(fCommandControl.getContext(),
- execPath.toPortableString()),
- new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
- } else {
- requestMonitor.done();
- }
- }},
- /*
- * Specify the arguments to the executable file
- */
- new Step() { @Override
- public void execute(final RequestMonitor requestMonitor) {
- try {
- String args = fGDBBackend.getProgramArguments();
-
- if (args != null) {
- fCommandControl.queueCommand(
- fCommandFactory.createMIGDBSetArgs(fCommandControl.getContext(), args),
- new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
- } else {
- requestMonitor.done();
- }
- } catch (CoreException e) {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get inferior arguments", e)); //$NON-NLS-1$
- requestMonitor.done();
- }
- }},
- /*
- * Enable non-stop mode if necessary
- */
- new Step() { @Override
- public void execute(final RequestMonitor requestMonitor) {
- boolean isNonStop = false;
- try {
- isNonStop = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
- IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
- } catch (CoreException e) {
- }
-
- // GDBs that don't support non-stop don't allow you to set it to false.
- // We really should set it to false when GDB supports it though.
- // Something to fix later.
- if (isNonStop) {
- fCommandControl.queueCommand(
- fCommandFactory.createMIGDBSetTargetAsync(fCommandControl.getContext(), true),
- new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
- @Override
- protected void handleSuccess() {
- fCommandControl.queueCommand(
- fCommandFactory.createMIGDBSetPagination(fCommandControl.getContext(), false),
- new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
- @Override
- protected void handleSuccess() {
- fCommandControl.queueCommand(
- fCommandFactory.createMIGDBSetNonStop(fCommandControl.getContext(), true),
- new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
- }
- });
- }
+public class FinalLaunchSequence extends ReflectionSequence {
+
+ private GdbLaunch fLaunch;
+ private SessionType fSessionType;
+ private boolean fAttach;
+
+ private IGDBControl fCommandControl;
+ private IGDBBackend fGDBBackend;
+ private IMIProcesses fProcService;
+ private CommandFactory fCommandFactory;
+
+ private DsfServicesTracker fTracker;
+
+ public FinalLaunchSequence(DsfExecutor executor, GdbLaunch launch, SessionType sessionType, boolean attach, IProgressMonitor pm) {
+ super(executor, pm, LaunchMessages.getString("FinalLaunchSequence.0"), LaunchMessages.getString("FinalLaunchSequence.1")); //$NON-NLS-1$ //$NON-NLS-2$
+ fLaunch = launch;
+ fSessionType = sessionType;
+ fAttach = attach;
+ }
+
+ @Override
+ protected String[] getExecutionOrder(String group) {
+ if (GROUP_TOP_LEVEL.equals(group)) {
+ return new String[] {
+ "stepInitializeFinalLaunchSequence", //$NON-NLS-1$
+ "stepSetEnvironmentDirectory", //$NON-NLS-1$
+ "stepSourceGDBInitFile", //$NON-NLS-1$
+ "stepSetEnvironmentVariables", //$NON-NLS-1$
+ "stepSetExecutable", //$NON-NLS-1$
+ "stepSetArguments", //$NON-NLS-1$
+ "stepSetNonStop", //$NON-NLS-1$
+ "stepSetAutoLoadSharedLibrarySymbols", //$NON-NLS-1$
+ "stepSetSharedLibraryPaths", //$NON-NLS-1$
+ "stepSetSourceLookupPath", //$NON-NLS-1$
+ "stepSpecifyCoreFile", //$NON-NLS-1$
+ "stepRemoteConnection", //$NON-NLS-1$
+ "stepAttachToProcess", //$NON-NLS-1$
+ "stepStartTrackingBreakpoints", //$NON-NLS-1$
+ "stepStartExecution", //$NON-NLS-1$
+ "stepDataModelInitializationComplete", //$NON-NLS-1$
+ "stepCleanup", //$NON-NLS-1$
+ };
+ }
+ return null;
+ }
+
+ /**
+ * Initialize the members of the {@link FinalLaunchSequence} class.
+ * This step is mandatory for the rest fo the sequence to complete.
+ * @since 4.0
+ */
+ @Execute
+ public void stepInitializeFinalLaunchSequence(RequestMonitor requestMonitor) {
+ fTracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), fLaunch.getSession().getId());
+ fGDBBackend = fTracker.getService(IGDBBackend.class);
+ if (fGDBBackend == null) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot obtain GDBBackend service", null)); //$NON-NLS-1$
+ requestMonitor.done();
+ return;
+ }
+
+ fCommandControl = fTracker.getService(IGDBControl.class);
+ if (fCommandControl == null) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot obtain control service", null)); //$NON-NLS-1$
+ requestMonitor.done();
+ return;
+ }
+
+ fCommandFactory = fCommandControl.getCommandFactory();
+
+ fProcService = fTracker.getService(IMIProcesses.class);
+ if (fProcService == null) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot obtain process service", null)); //$NON-NLS-1$
+ requestMonitor.done();
+ return;
+ }
+
+ requestMonitor.done();
+ }
+
+ /**
+ * Rollback method for {@link #stepInitializeFinalLaunchSequence()}
+ * @since 4.0
+ */
+ @RollBack("stepInitializeFinalLaunchSequence")
+ public void rollBackInitializeFinalLaunchSequence(RequestMonitor requestMonitor) {
+ if (fTracker != null) fTracker.dispose();
+ fTracker = null;
+ requestMonitor.done();
+ }
+
+ /**
+ * Specify GDB's working directory.
+ * @since 4.0
+ */
+ @Execute
+ public void stepSetEnvironmentDirectory(final RequestMonitor requestMonitor) {
+ IPath dir = null;
+ try {
+ dir = fGDBBackend.getGDBWorkingDirectory();
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get working directory", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ return;
+ }
+
+ if (dir != null) {
+ fCommandControl.queueCommand(
+ fCommandFactory.createMIEnvironmentCD(fCommandControl.getContext(), dir.toPortableString()),
+ new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
+ } else {
+ requestMonitor.done();
+ }
+ }
+
+ /**
+ * Source the gdbinit file specified in the launch.
+ * @since 4.0
+ */
+ @Execute
+ public void stepSourceGDBInitFile(final RequestMonitor requestMonitor) {
+ try {
+ final String gdbinitFile = fGDBBackend.getGDBInitFile();
+
+ if (gdbinitFile != null && gdbinitFile.length() > 0) {
+ fCommandControl.queueCommand(
+ fCommandFactory.createCLISource(fCommandControl.getContext(), gdbinitFile),
+ new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleCompleted() {
+ // If the gdbinitFile is the default, then it may not exist and we
+ // should not consider this an error.
+ // If it is not the default, then the user must have specified it and
+ // we want to warn the user if we can't find it.
+ if (!gdbinitFile.equals(IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT )) {
+ requestMonitor.setStatus(getStatus());
+ }
+ requestMonitor.done();
+ }
+ });
+ } else {
+ requestMonitor.done();
+ }
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get gdbinit option", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ }
+ }
+
+ /**
+ * Specify environment variables if needed
+ * @since 4.0
+ */
+ @Execute
+ public void stepSetEnvironmentVariables(final RequestMonitor requestMonitor) {
+ boolean clear = false;
+ Properties properties = new Properties();
+ try {
+ clear = fGDBBackend.getClearEnvironment();
+ properties = fGDBBackend.getEnvironmentVariables();
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get environment information", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ return;
+ }
+
+ if (clear == true || properties.size() > 0) {
+ fCommandControl.setEnvironment(properties, clear, requestMonitor);
+ } else {
+ requestMonitor.done();
+ }
+ }
+
+ /**
+ * Specify the executable file to be debugged and read the symbol table.
+ * @since 4.0
+ */
+ @Execute
+ public void stepSetExecutable(final RequestMonitor requestMonitor) {
+ boolean noFileCommand = IGDBLaunchConfigurationConstants.DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP_DEFAULT;
+ try {
+ noFileCommand = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP,
+ IGDBLaunchConfigurationConstants.DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP_DEFAULT);
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot read use solib symbols for app options", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ return;
+ }
+
+ final IPath execPath = fGDBBackend.getProgramPath();
+ if (!noFileCommand && execPath != null && !execPath.isEmpty()) {
+ fCommandControl.queueCommand(
+ fCommandFactory.createMIFileExecAndSymbols(fCommandControl.getContext(),
+ execPath.toPortableString()),
+ new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
+ } else {
+ requestMonitor.done();
+ }
+ }
+
+ /**
+ * Specify the arguments to the executable file.
+ * @since 4.0
+ */
+ @Execute
+ public void stepSetArguments(final RequestMonitor requestMonitor) {
+ try {
+ String args = fGDBBackend.getProgramArguments();
+
+ if (args != null) {
+ fCommandControl.queueCommand(
+ fCommandFactory.createMIGDBSetArgs(fCommandControl.getContext(), args),
+ new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
+ } else {
+ requestMonitor.done();
+ }
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get inferior arguments", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ }
+ }
+
+ /**
+ * Enable non-stop mode if requested.
+ * @since 4.0
+ */
+ @Execute
+ public void stepSetNonStop(final RequestMonitor requestMonitor) {
+ boolean isNonStop = false;
+ try {
+ isNonStop = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
+ IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
+ } catch (CoreException e) {
+ }
+
+ // GDBs that don't support non-stop don't allow you to set it to false.
+ // We really should set it to false when GDB supports it though.
+ // Something to fix later.
+ if (isNonStop) {
+ fCommandControl.queueCommand(
+ fCommandFactory.createMIGDBSetTargetAsync(fCommandControl.getContext(), true),
+ new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ fCommandControl.queueCommand(
+ fCommandFactory.createMIGDBSetPagination(fCommandControl.getContext(), false),
+ new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ fCommandControl.queueCommand(
+ fCommandFactory.createMIGDBSetNonStop(fCommandControl.getContext(), true),
+ new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
+ }
+ });
+ }
});
- } else {
- requestMonitor.done();
- }
- }},
- /*
- * Tell GDB to automatically load or not the shared library symbols
- */
- new Step() { @Override
- public void execute(RequestMonitor requestMonitor) {
- try {
- boolean autolib = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_AUTO_SOLIB,
- IGDBLaunchConfigurationConstants.DEBUGGER_AUTO_SOLIB_DEFAULT);
- fCommandControl.queueCommand(
- fCommandFactory.createMIGDBSetAutoSolib(fCommandControl.getContext(), autolib),
- new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
- } catch (CoreException e) {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot set shared library option", e)); //$NON-NLS-1$
- requestMonitor.done();
- }
- }},
- /*
- * Set the shared library paths
- */
- new Step() { @Override
- public void execute(final RequestMonitor requestMonitor) {
- try {
- List<String> p = fGDBBackend.getSharedLibraryPaths();
-
- if (p.size() > 0) {
- String[] paths = p.toArray(new String[p.size()]);
- fCommandControl.queueCommand(
- fCommandFactory.createMIGDBSetSolibSearchPath(fCommandControl.getContext(), paths),
- new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
- @Override
- protected void handleSuccess() {
-// Sysroot is not available in GDB6.6 and will make the launch fail in that case.
-// Let's remove it for now
- requestMonitor.done();
-// // If we are able to set the solib-search-path,
-// // we should disable the sysroot variable, as indicated
-// // in the GDB documentation. This is to avoid the sysroot
-// // variable finding libraries that were not meant to be found.
-// fCommandControl.queueCommand(
-// new MIGDBSetSysroot(fCommandControl.getContext()),
-// new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
- };
- });
- } else {
- requestMonitor.done();
- }
- } catch (CoreException e) {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot set share library paths", e)); //$NON-NLS-1$
- requestMonitor.done();
- }
- }},
- /*
- * Setup the source paths
- */
- new Step() { @Override
- public void execute(RequestMonitor requestMonitor) {
- CSourceLookup sourceLookup = fTracker.getService(CSourceLookup.class);
- CSourceLookupDirector locator = (CSourceLookupDirector)fLaunch.getSourceLocator();
- ISourceLookupDMContext sourceLookupDmc = (ISourceLookupDMContext)fCommandControl.getContext();
-
- sourceLookup.setSourceLookupPath(sourceLookupDmc, locator.getSourceContainers(), requestMonitor);
- }},
- /*
- * Specify the core file to be debugged if we are launching such a debug session.
- */
- new Step() {
- // Need a job because prompter.handleStatus will block
- class PromptForCoreJob extends Job {
- DataRequestMonitor<String> fRequestMonitor;
-
- public PromptForCoreJob(String name, DataRequestMonitor<String> rm) {
- super(name);
- fRequestMonitor = rm;
- }
-
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- final IStatus promptStatus = new Status(IStatus.INFO, "org.eclipse.debug.ui", 200/*STATUS_HANDLER_PROMPT*/, "", null); //$NON-NLS-1$//$NON-NLS-2$
- final IStatus filePrompt = new Status(IStatus.INFO, "org.eclipse.cdt.dsf.gdb.ui", 1001, "", null); //$NON-NLS-1$//$NON-NLS-2$
- // consult a status handler
- final IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler(promptStatus);
-
- final Status NO_CORE_STATUS = new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1,
- LaunchMessages.getString("LocalCDILaunchDelegate.6"), //$NON-NLS-1$
- null);
-
- if (prompter == null) {
- fRequestMonitor.setStatus(NO_CORE_STATUS);
- fRequestMonitor.done();
- return Status.OK_STATUS;
- }
-
- try {
- Object result = prompter.handleStatus(filePrompt, null);
- if (result instanceof String) {
- fRequestMonitor.setData((String)result);
- } else {
- fRequestMonitor.setStatus(NO_CORE_STATUS);
- }
- } catch (CoreException e) {
- fRequestMonitor.setStatus(NO_CORE_STATUS);
- }
- fRequestMonitor.done();
-
- return Status.OK_STATUS;
- }
- };
- @Override
- public void execute(final RequestMonitor requestMonitor) {
- if (fSessionType == SessionType.CORE) {
- try {
- String coreFile = fLaunch.getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, ""); //$NON-NLS-1$
- final String coreType = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_POST_MORTEM_TYPE,
- IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TYPE_DEFAULT);
- if (coreFile.length() == 0) {
- new PromptForCoreJob(
- "Prompt for post mortem file", //$NON-NLS-1$
- new DataRequestMonitor<String>(getExecutor(), requestMonitor) {
- @Override
- protected void handleSuccess() {
- String newCoreFile = getData();
- if (newCoreFile == null || newCoreFile.length()== 0) {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get post mortem file path", null)); //$NON-NLS-1$
- requestMonitor.done();
- } else {
- if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) {
- fCommandControl.queueCommand(
- fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), newCoreFile),
- new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
- } else if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE)) {
- IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class);
- if (traceControl != null) {
- ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(fCommandControl.getContext(), ITraceTargetDMContext.class);
- traceControl.loadTraceData(targetDmc, newCoreFile, requestMonitor);
- } else {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Tracing not supported", null));
- requestMonitor.done();
- }
- } else {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Invalid post-mortem type", null));
- requestMonitor.done();
- }
- }
- }
- }).schedule();
- } else {
- if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) {
- fCommandControl.queueCommand(
- fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), coreFile),
- new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
- } else if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE)) {
- IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class);
- if (traceControl != null) {
- ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(fCommandControl.getContext(), ITraceTargetDMContext.class);
- traceControl.loadTraceData(targetDmc, coreFile, requestMonitor);
- } else {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Tracing not supported", null));
- requestMonitor.done();
- }
- } else {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Invalid post-mortem type", null));
- requestMonitor.done();
- }
- }
- } catch (CoreException e) {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get post mortem file path", e));
- requestMonitor.done();
- }
- } else {
- requestMonitor.done();
- }
- }
- },
- /*
- * If remote debugging, connect to target.
- */
- new Step() {
- private boolean fTcpConnection;
- private String fRemoteTcpHost;
- private String fRemoteTcpPort;
- private String fSerialDevice;
-
- private boolean checkConnectionType(RequestMonitor requestMonitor) {
- try {
- fTcpConnection = fLaunch.getLaunchConfiguration().getAttribute(
- IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP,
- false);
- } catch (CoreException e) {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve connection mode", e)); //$NON-NLS-1$
- requestMonitor.done();
- return false;
- }
- return true;
- }
-
- private boolean getSerialDevice(RequestMonitor requestMonitor) {
- try {
- fSerialDevice = fLaunch.getLaunchConfiguration().getAttribute(
- IGDBLaunchConfigurationConstants.ATTR_DEV, "invalid"); //$NON-NLS-1$
- } catch (CoreException e) {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve serial device", e)); //$NON-NLS-1$
- requestMonitor.done();
- return false;
- }
- return true;
- }
-
- private boolean getTcpHost(RequestMonitor requestMonitor) {
- try {
- fRemoteTcpHost = fLaunch.getLaunchConfiguration().getAttribute(
- IGDBLaunchConfigurationConstants.ATTR_HOST, "invalid"); //$NON-NLS-1$
- } catch (CoreException e) {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve remote TCP host", e)); //$NON-NLS-1$
- requestMonitor.done();
- return false;
- }
- return true;
- }
-
- private boolean getTcpPort(RequestMonitor requestMonitor) {
- try {
- fRemoteTcpPort = fLaunch.getLaunchConfiguration().getAttribute(
- IGDBLaunchConfigurationConstants.ATTR_PORT, "invalid"); //$NON-NLS-1$
- } catch (CoreException e) {
- requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve remote TCP port", e)); //$NON-NLS-1$
- requestMonitor.done();
- return false;
- }
- return true;
- }
-
- @Override
- public void execute(final RequestMonitor requestMonitor) {
- if (fSessionType == SessionType.REMOTE) {
- if (!checkConnectionType(requestMonitor)) return;
-
- if (fTcpConnection) {
- if (!getTcpHost(requestMonitor)) return;
- if (!getTcpPort(requestMonitor)) return;
-
- fCommandControl.queueCommand(
- fCommandFactory.createMITargetSelect(fCommandControl.getContext(),
- fRemoteTcpHost, fRemoteTcpPort, fAttach),
- new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
- } else {
- if (!getSerialDevice(requestMonitor)) return;
-
- fCommandControl.queueCommand(
- fCommandFactory.createMITargetSelect(fCommandControl.getContext(),
- fSerialDevice, fAttach),
- new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
- }
- } else {
- requestMonitor.done();
- }
- }
- },
- /*
- * If attach session, perform the attach.
- */
- new Step() {
- @Override
- public void execute(final RequestMonitor requestMonitor) {
- // A local attach can figure out the binary from the attach
- // command. This allows the user not to specify the binary
- // in the launch. But for breakpoints to work, we must do the
- // attach before we set the breakpoints, i.e., here.
- // On the other hand, for a remote attach, we need to specify
- // the binary anyway, or use the solib command. In both cases,
- // breakpoints can be set before we attach. Therefore, we don't
- // force an attach here, but wait for the user to decide to connect
- // using the connect action.
- if (fAttach && fSessionType != SessionType.REMOTE) {
- // If we are attaching, get the process id.
- int pid = -1;
- try {
- // have we already been given the pid (maybe from a JUnit test launch or something)
- pid = fLaunch.getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_ATTACH_PROCESS_ID, -1);
- } catch (CoreException e) {
- // do nothing and fall to below
- }
-
- if (pid != -1) {
- fProcService.attachDebuggerToProcess(
- fProcService.createProcessContext(fCommandControl.getContext(), Integer.toString(pid)),
- new DataRequestMonitor<IDMContext>(getExecutor(), requestMonitor));
- } else {
- IConnect connectCommand = (IConnect)fLaunch.getSession().getModelAdapter(IConnect.class);
- if (connectCommand != null) {
- connectCommand.connect(requestMonitor);
- } else {
- requestMonitor.done();
- }
- }
- } else {
- requestMonitor.done();
- }
- }
- },
- /*
- * Start tracking the breakpoints once we know we are connected to the target (necessary for remote debugging)
- */
- new Step() { @Override
- public void execute(final RequestMonitor requestMonitor) {
- if (fSessionType != SessionType.CORE) {
- MIBreakpointsManager bpmService = fTracker.getService(MIBreakpointsManager.class);
- IBreakpointsTargetDMContext breakpointDmc = (IBreakpointsTargetDMContext)fCommandControl.getContext();
-
- bpmService.startTrackingBreakpoints(breakpointDmc, requestMonitor);
- } else {
- requestMonitor.done();
- }
- }},
- /*
- * Start the program.
- */
- new Step() {
- @Override
- public void execute(final RequestMonitor requestMonitor) {
- if (fSessionType != SessionType.CORE) {
- fCommandControl.start(fLaunch, requestMonitor);
- } else {
- requestMonitor.done();
- }
- }
- },
- /*
- * Indicate that the Data Model has been filled. This will trigger the Debug view to expand.
- */
- new Step() {
- @Override
- public void execute(final RequestMonitor requestMonitor) {
- fLaunch.getSession().dispatchEvent(new DataModelInitializedEvent(fCommandControl.getContext()),
- fCommandControl.getProperties());
- requestMonitor.done();
- }
- },
- /*
- * Cleanup
- */
- new Step() {
- @Override
- public void execute(final RequestMonitor requestMonitor) {
- fTracker.dispose();
- fTracker = null;
- requestMonitor.done();
- }
- },
- };
-
- GdbLaunch fLaunch;
- SessionType fSessionType;
- boolean fAttach;
-
- private IGDBControl fCommandControl;
- private IGDBBackend fGDBBackend;
- private IMIProcesses fProcService;
- private CommandFactory fCommandFactory;
-
- DsfServicesTracker fTracker;
-
- public FinalLaunchSequence(DsfExecutor executor, GdbLaunch launch, SessionType sessionType, boolean attach, IProgressMonitor pm) {
- super(executor, pm, LaunchMessages.getString("FinalLaunchSequence.0"), LaunchMessages.getString("FinalLaunchSequence.1")); //$NON-NLS-1$ //$NON-NLS-2$
- fLaunch = launch;
- fSessionType = sessionType;
- fAttach = attach;
- }
-
- @Override
- public Step[] getSteps() {
- return fSteps;
- }
+ } else {
+ requestMonitor.done();
+ }
+ }
+
+ /**
+ * Tell GDB to automatically load or not the shared library symbols
+ * @since 4.0
+ */
+ @Execute
+ public void stepSetAutoLoadSharedLibrarySymbols(RequestMonitor requestMonitor) {
+ try {
+ boolean autolib = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_AUTO_SOLIB,
+ IGDBLaunchConfigurationConstants.DEBUGGER_AUTO_SOLIB_DEFAULT);
+ fCommandControl.queueCommand(
+ fCommandFactory.createMIGDBSetAutoSolib(fCommandControl.getContext(), autolib),
+ new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot set shared library option", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ }
+ }
+
+ /**
+ * Set the shared library paths.
+ * @since 4.0
+ */
+ @Execute
+ public void stepSetSharedLibraryPaths(final RequestMonitor requestMonitor) {
+ try {
+ List<String> p = fGDBBackend.getSharedLibraryPaths();
+
+ if (p.size() > 0) {
+ String[] paths = p.toArray(new String[p.size()]);
+ fCommandControl.queueCommand(
+ fCommandFactory.createMIGDBSetSolibSearchPath(fCommandControl.getContext(), paths),
+ new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ // Sysroot is not available in GDB6.6 and will make the launch fail in that case.
+ // Let's remove it for now
+ requestMonitor.done();
+ // // If we are able to set the solib-search-path,
+ // // we should disable the sysroot variable, as indicated
+ // // in the GDB documentation. This is to avoid the sysroot
+ // // variable finding libraries that were not meant to be found.
+ // fCommandControl.queueCommand(
+ // new MIGDBSetSysroot(fCommandControl.getContext()),
+ // new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
+ };
+ });
+ } else {
+ requestMonitor.done();
+ }
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot set share library paths", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ }
+ }
+
+ /**
+ * Setup the source paths.
+ * @since 4.0
+ */
+ @Execute
+ public void stepSetSourceLookupPath(RequestMonitor requestMonitor) {
+ CSourceLookup sourceLookup = fTracker.getService(CSourceLookup.class);
+ CSourceLookupDirector locator = (CSourceLookupDirector)fLaunch.getSourceLocator();
+ ISourceLookupDMContext sourceLookupDmc = (ISourceLookupDMContext)fCommandControl.getContext();
+
+ sourceLookup.setSourceLookupPath(sourceLookupDmc, locator.getSourceContainers(), requestMonitor);
+ }
+
+ /** @since 4.0 */
+ protected class PromptForCoreJob extends Job {
+ protected DataRequestMonitor<String> fRequestMonitor;
+
+ public PromptForCoreJob(String name, DataRequestMonitor<String> rm) {
+ super(name);
+ fRequestMonitor = rm;
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ final IStatus promptStatus = new Status(IStatus.INFO, "org.eclipse.debug.ui", 200/*STATUS_HANDLER_PROMPT*/, "", null); //$NON-NLS-1$//$NON-NLS-2$
+ final IStatus filePrompt = new Status(IStatus.INFO, "org.eclipse.cdt.dsf.gdb.ui", 1001, "", null); //$NON-NLS-1$//$NON-NLS-2$
+ // consult a status handler
+ final IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler(promptStatus);
+
+ final Status NO_CORE_STATUS = new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1,
+ LaunchMessages.getString("LocalCDILaunchDelegate.6"), //$NON-NLS-1$
+ null);
+
+ if (prompter == null) {
+ fRequestMonitor.setStatus(NO_CORE_STATUS);
+ fRequestMonitor.done();
+ return Status.OK_STATUS;
+ }
+
+ try {
+ Object result = prompter.handleStatus(filePrompt, null);
+ if (result instanceof String) {
+ fRequestMonitor.setData((String)result);
+ } else {
+ fRequestMonitor.setStatus(NO_CORE_STATUS);
+ }
+ } catch (CoreException e) {
+ fRequestMonitor.setStatus(NO_CORE_STATUS);
+ }
+ fRequestMonitor.done();
+
+ return Status.OK_STATUS;
+ }
+ };
+
+ /**
+ * If we are dealing with a post-mortem debug session, specify the core file.
+ * @since 4.0
+ */
+ @Execute
+ public void stepSpecifyCoreFile(final RequestMonitor requestMonitor) {
+ if (fSessionType == SessionType.CORE) {
+ try {
+ String coreFile = fLaunch.getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, ""); //$NON-NLS-1$
+ final String coreType = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_POST_MORTEM_TYPE,
+ IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TYPE_DEFAULT);
+ if (coreFile.length() == 0) {
+ new PromptForCoreJob(
+ "Prompt for post mortem file", //$NON-NLS-1$
+ new DataRequestMonitor<String>(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ String newCoreFile = getData();
+ if (newCoreFile == null || newCoreFile.length()== 0) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get post mortem file path", null)); //$NON-NLS-1$
+ requestMonitor.done();
+ } else {
+ if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) {
+ fCommandControl.queueCommand(
+ fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), newCoreFile),
+ new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
+ } else if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE)) {
+ IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class);
+ if (traceControl != null) {
+ ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(fCommandControl.getContext(), ITraceTargetDMContext.class);
+ traceControl.loadTraceData(targetDmc, newCoreFile, requestMonitor);
+ } else {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Tracing not supported", null));
+ requestMonitor.done();
+ }
+ } else {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Invalid post-mortem type", null));
+ requestMonitor.done();
+ }
+ }
+ }
+ }).schedule();
+ } else {
+ if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) {
+ fCommandControl.queueCommand(
+ fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), coreFile),
+ new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
+ } else if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE)) {
+ IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class);
+ if (traceControl != null) {
+ ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(fCommandControl.getContext(), ITraceTargetDMContext.class);
+ traceControl.loadTraceData(targetDmc, coreFile, requestMonitor);
+ } else {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Tracing not supported", null));
+ requestMonitor.done();
+ }
+ } else {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Invalid post-mortem type", null));
+ requestMonitor.done();
+ }
+ }
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get post mortem file path", e));
+ requestMonitor.done();
+ }
+ } else {
+ requestMonitor.done();
+ }
+ }
+
+
+ private boolean fTcpConnection;
+ private String fRemoteTcpHost;
+ private String fRemoteTcpPort;
+ private String fSerialDevice;
+
+ private boolean checkConnectionType(RequestMonitor requestMonitor) {
+ try {
+ fTcpConnection = fLaunch.getLaunchConfiguration().getAttribute(
+ IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP,
+ false);
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve connection mode", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ return false;
+ }
+ return true;
+ }
+
+ private boolean getSerialDevice(RequestMonitor requestMonitor) {
+ try {
+ fSerialDevice = fLaunch.getLaunchConfiguration().getAttribute(
+ IGDBLaunchConfigurationConstants.ATTR_DEV, "invalid"); //$NON-NLS-1$
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve serial device", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ return false;
+ }
+ return true;
+ }
+
+ private boolean getTcpHost(RequestMonitor requestMonitor) {
+ try {
+ fRemoteTcpHost = fLaunch.getLaunchConfiguration().getAttribute(
+ IGDBLaunchConfigurationConstants.ATTR_HOST, "invalid"); //$NON-NLS-1$
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve remote TCP host", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ return false;
+ }
+ return true;
+ }
+
+ private boolean getTcpPort(RequestMonitor requestMonitor) {
+ try {
+ fRemoteTcpPort = fLaunch.getLaunchConfiguration().getAttribute(
+ IGDBLaunchConfigurationConstants.ATTR_PORT, "invalid"); //$NON-NLS-1$
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve remote TCP port", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * If we are dealing with a remote debugging session, connect to the target.
+ * @since 4.0
+ */
+ @Execute
+ public void stepRemoteConnection(final RequestMonitor requestMonitor) {
+ if (fSessionType == SessionType.REMOTE) {
+ if (!checkConnectionType(requestMonitor)) return;
+
+ if (fTcpConnection) {
+ if (!getTcpHost(requestMonitor)) return;
+ if (!getTcpPort(requestMonitor)) return;
+
+ fCommandControl.queueCommand(
+ fCommandFactory.createMITargetSelect(fCommandControl.getContext(),
+ fRemoteTcpHost, fRemoteTcpPort, fAttach),
+ new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
+ } else {
+ if (!getSerialDevice(requestMonitor)) return;
+
+ fCommandControl.queueCommand(
+ fCommandFactory.createMITargetSelect(fCommandControl.getContext(),
+ fSerialDevice, fAttach),
+ new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
+ }
+ } else {
+ requestMonitor.done();
+ }
+ }
+
+ /**
+ * If we are dealing with an attach debugging session, perform the attach.
+ * @since 4.0
+ */
+ @Execute
+ public void stepAttachToProcess(final RequestMonitor requestMonitor) {
+ // A local attach can figure out the binary from the attach
+ // command. This allows the user not to specify the binary
+ // in the launch. But for breakpoints to work, we must do the
+ // attach before we set the breakpoints, i.e., here.
+ // On the other hand, for a remote attach, we need to specify
+ // the binary anyway, or use the solib command. In both cases,
+ // breakpoints can be set before we attach. Therefore, we don't
+ // force an attach here, but wait for the user to decide to connect
+ // using the connect action.
+ if (fAttach && fSessionType != SessionType.REMOTE) {
+ // If we are attaching, get the process id.
+ int pid = -1;
+ try {
+ // have we already been given the pid (maybe from a JUnit test launch or something)
+ pid = fLaunch.getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_ATTACH_PROCESS_ID, -1);
+ } catch (CoreException e) {
+ // do nothing and fall to below
+ }
+
+ if (pid != -1) {
+ fProcService.attachDebuggerToProcess(
+ fProcService.createProcessContext(fCommandControl.getContext(), Integer.toString(pid)),
+ new DataRequestMonitor<IDMContext>(getExecutor(), requestMonitor));
+ } else {
+ IConnect connectCommand = (IConnect)fLaunch.getSession().getModelAdapter(IConnect.class);
+ if (connectCommand != null) {
+ connectCommand.connect(requestMonitor);
+ } else {
+ requestMonitor.done();
+ }
+ }
+ } else {
+ requestMonitor.done();
+ }
+ }
+
+ /**
+ * Start tracking the breakpoints. Note that for remote debugging
+ * we should first connect to the target.
+ * @since 4.0
+ */
+ @Execute
+ public void stepStartTrackingBreakpoints(final RequestMonitor requestMonitor) {
+ if (fSessionType != SessionType.CORE) {
+ MIBreakpointsManager bpmService = fTracker.getService(MIBreakpointsManager.class);
+ IBreakpointsTargetDMContext breakpointDmc = (IBreakpointsTargetDMContext)fCommandControl.getContext();
+
+ bpmService.startTrackingBreakpoints(breakpointDmc, requestMonitor);
+ } else {
+ requestMonitor.done();
+ }
+ }
+
+ /**
+ * Start executing the program.
+ * @since 4.0
+ */
+ @Execute
+ public void stepStartExecution(final RequestMonitor requestMonitor) {
+ if (fSessionType != SessionType.CORE) {
+ fCommandControl.start(fLaunch, requestMonitor);
+ } else {
+ requestMonitor.done();
+ }
+ }
+
+ /**
+ * Indicate that the Data Model has been filled. This will trigger the Debug view to expand.
+ * @since 4.0
+ */
+ @Execute
+ public void stepDataModelInitializationComplete(final RequestMonitor requestMonitor) {
+ fLaunch.getSession().dispatchEvent(new DataModelInitializedEvent(fCommandControl.getContext()),
+ fCommandControl.getProperties());
+ requestMonitor.done();
+ }
+
+ /**
+ * Cleanup now that the sequence has been run.
+ * @since 4.0
+ */
+ @Execute
+ public void stepCleanup(final RequestMonitor requestMonitor) {
+ fTracker.dispose();
+ fTracker = null;
+ requestMonitor.done();
+ }
}
diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/concurrent/ReflectionSequence.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/concurrent/ReflectionSequence.java
new file mode 100644
index 0000000000..0cec06ff28
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/concurrent/ReflectionSequence.java
@@ -0,0 +1,264 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.concurrent;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.cdt.dsf.internal.DsfPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * A type of {@link Sequence} which uses reflection and annotations to
+ * declare its different {@link Sequence.Step}. It can be used to make
+ * larger DSF sequences more readable and easier to override.
+ *
+ * The order of execution of the {@code @Execute} methods is determined by
+ * the {@link #getExecutionOrder()} method.
+ *
+ * {@code @Execute} methods can be grouped in a hierarchical set of groups,
+ * which should be included in the result of {@link #getExecutionOrder()}.
+ * Using groups can make overriding slightly simpler.
+ *
+ * A usage example follows: <code><pre>
+ * public class MyReflectionSequence extends ReflectionSequence {
+ *
+ * public MyReflectionSequence(DsfExecutor executor) {
+ * super(executor);
+ * }
+ *
+ * protected static final String GROUP_INIT = "GROUP_INIT";
+ *
+ * {@code @Override}
+ * protected String[] getExecutionOrder(String group) {
+ * if (GROUP_TOP_LEVEL.equals(group)) {
+ * // This is the top level group which contains
+ * // all sub-groups, or steps that are not in
+ * // other groups.
+ * return new String[] { GROUP_INIT, "step3", "step4" };
+ * }
+ *
+ * // Now deal with the content of sub-groups
+ * if (GROUP_INIT.equals(group)) {
+ * return new String[] { "step1", "step2" };
+ * }
+ *
+ * // An invalid group was requested
+ * return null;
+ * }
+ *
+ * {@code @Execute}
+ * public void step1(RequestMonitor rm) {
+ * // Do something
+ * rm.done();
+ * }
+ *
+ * {@code @RollBack("step1")}
+ * public void rollBack1(RequestMonitor rm) {
+ * // Rollback what was done in step1()
+ * rm.done();
+ * }
+ *
+ * {@code @Execute}
+ * public void step2(RequestMonitor rm) {
+ * // Do something else
+ * rm.done();
+ * }
+ *
+ * {@code @Execute}
+ * public void step3(RequestMonitor rm) {
+ * // Do something else
+ * rm.done();
+ * }
+ *
+ * {@code @Execute}
+ * public void step4(RequestMonitor rm) {
+ * // Do something else
+ * rm.done();
+ * }
+ * }
+ * </pre></code>
+ *
+ * @since 2.2
+ */
+abstract public class ReflectionSequence extends Sequence {
+
+ /**
+ * The top-level group in which all sub-groups or steps that
+ * are not part of any sub-groups are contained. This group
+ * identifier is the one that will be used in the first call to
+ * {@link #getExecutionOrder()}.
+ */
+ public static final String GROUP_TOP_LEVEL = "GROUP_TOP_LEVEL"; //$NON-NLS-1$
+
+ private Step[] fReflectionSteps;
+
+ /**
+ * Annotation used to indicate that a method corresponds to an
+ * {@link Sequence.Step#execute()} method of a {@link Sequence.Step}.
+ * The annotated method must be declared public.
+ */
+ @Inherited
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.METHOD)
+ public static @interface Execute {}
+
+ /**
+ * Annotation used to indicate that a method corresponds to a
+ * {@link Sequence.Step#rollBack()} method of a {@link Sequence.Step}.
+ * Declaring such a method is optional. If declared, the annotated
+ * method must be declared public.
+ */
+ @Inherited
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.METHOD)
+ public static @interface RollBack {
+ /**
+ * Name of the method tagged with the {@link Execute} annotation that this method rolls back.
+ */
+ String value();
+ }
+
+ private class ReflectionStep extends Step {
+ final private Method fExecuteMethod;
+ final private Method fRollbackMethod;
+
+ private ReflectionStep(Method executeMethod, Method rollbackMethod) {
+ assert executeMethod != null;
+
+ fExecuteMethod = executeMethod;;
+ fRollbackMethod = rollbackMethod;
+ }
+
+ @Override
+ public void execute(RequestMonitor rm) {
+ try {
+ fExecuteMethod.invoke(ReflectionSequence.this, rm);
+ } catch (Exception e) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Error executing step execute method: " + fExecuteMethod.getName(), e)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ @Override
+ public void rollBack(RequestMonitor rm) {
+ if (fRollbackMethod == null) {
+ super.rollBack(rm);
+ } else {
+ try {
+ fRollbackMethod.invoke(ReflectionSequence.this, rm);
+ } catch (Exception e) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Error executing step rollback method: " + fRollbackMethod.getName(), e)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+ }
+ }
+
+ public ReflectionSequence(DsfExecutor executor) {
+ super(executor);
+ }
+
+ public ReflectionSequence(DsfExecutor executor, RequestMonitor rm) {
+ super(executor, rm);
+ }
+
+ public ReflectionSequence(DsfExecutor executor, IProgressMonitor pm, String taskName, String rollbackTaskName) {
+ super(executor, pm, taskName, rollbackTaskName);
+ }
+
+ public ReflectionSequence(DsfExecutor executor, RequestMonitorWithProgress rm, String taskName, String rollbackTaskName) {
+ super(executor, rm, taskName, rollbackTaskName);
+ }
+
+ /**
+ * This method must return the execution order of {@code @Execute} methods and/or groups.
+ *
+ * @param groupName The name of a group for which the list of {@code @Execute} methods
+ * or sub-groups should be returned in the order they should be executed.
+ * If the concept of groups is not used, then this parameter can be ignored,
+ * at the top-level ordering should be returned.
+ *
+ * @return An array containing the list of @Execute methods and groups in the order
+ * they should be executed, or null if the specified groupName is unknown.
+ */
+ abstract protected String[] getExecutionOrder(String groupName);
+
+ @Override
+ public Step[] getSteps() {
+ if (fReflectionSteps == null) {
+ Map<String, Method> executeMethods = getAnnotatedMethods(Execute.class);
+ Map<String, Method> rollBackMethods = getAnnotatedMethods(RollBack.class);
+ List<Step> steps = getGroupSteps(GROUP_TOP_LEVEL, executeMethods, rollBackMethods);
+ fReflectionSteps = steps.toArray(new ReflectionStep[steps.size()]);
+ }
+ return fReflectionSteps;
+ }
+
+ private List<Step> getGroupSteps(String groupId, Map<String, Method> executeMethods, Map<String, Method> rollBackMethods) {
+ List<Step> steps = new ArrayList<Step>(executeMethods.size());
+
+ String[] order = getExecutionOrder(groupId);
+ if (order == null) {
+ throw new RuntimeException("Unknown group in sequence: " + groupId); //$NON-NLS-1$
+ }
+
+ for (String name : order) {
+ Method executeMethod = executeMethods.get(name);
+ if (executeMethod == null) {
+ // name is a group id
+ steps.addAll(getGroupSteps(name, executeMethods, rollBackMethods));
+ } else {
+ steps.add(new ReflectionStep(executeMethod, rollBackMethods.get(executeMethod.getName())));
+ }
+ }
+ return steps;
+ }
+
+ private Map<String, Method> getAnnotatedMethods(Class<? extends Annotation> annotationType) {
+ Map<String, Method> retVal = new HashMap<String, Method>();
+ try {
+ Method[] methods = getClass().getMethods();
+ for (Method method : methods) {
+ if (method.isAnnotationPresent(annotationType)) {
+ Class<?>[] paramTypes = method.getParameterTypes();
+ if (paramTypes.length != 1) { // must have one and only param, the RequestMonitor
+ throw new IllegalArgumentException("Method " + //$NON-NLS-1$
+ method.getDeclaringClass().getSimpleName() + "#" + method.getName() + //$NON-NLS-1$
+ " must have a single parameter"); //$NON-NLS-1$
+ } else {
+ if (annotationType.equals(Execute.class)) {
+ retVal.put(method.getName(), method);
+ } else {// @Rollback
+ retVal.put(method.getAnnotation(RollBack.class).value(), method);
+ }
+ }
+ }
+ }
+ } catch(SecurityException e) {
+ throw new IllegalArgumentException("No permission to access ReflectionSequence method"); //$NON-NLS-1$
+ }
+ return retVal;
+ }
+
+
+}
diff --git a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/concurrent/DsfSequenceTests.java b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/concurrent/DsfSequenceTests.java
index d8ac41785a..e9019429db 100644
--- a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/concurrent/DsfSequenceTests.java
+++ b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/concurrent/DsfSequenceTests.java
@@ -17,6 +17,7 @@ import java.util.concurrent.TimeUnit;
import junit.framework.Assert;
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.concurrent.ReflectionSequence;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Sequence;
import org.eclipse.cdt.tests.dsf.DsfTestPlugin;
@@ -93,6 +94,55 @@ public class DsfSequenceTests {
Assert.assertTrue(sequence.isDone());
Assert.assertTrue(!sequence.isCancelled());
}
+
+
+ public class SimpleReflectionSequence extends ReflectionSequence {
+
+ public int fStepCounter;
+
+ public SimpleReflectionSequence() {
+ super(fExecutor);
+ }
+
+ @Override
+ protected String[] getExecutionOrder(String groupName) {
+ return new String[] { "step1", "step2"};
+ }
+
+ @Execute()
+ public void step1(RequestMonitor rm) {
+ fStepCounter++;
+ rm.done();
+ }
+
+ @Execute()
+ public void step2(RequestMonitor rm) {
+ fStepCounter++;
+ rm.done();
+ }
+ }
+
+ @Test
+ public void simpleReflectionTest() throws InterruptedException, ExecutionException {
+
+ // Create, start, and wait for the sequence.
+ SimpleReflectionSequence sequence = new SimpleReflectionSequence();
+
+ //Sequence sequence = new SimpleReflectionSequence();
+ Assert.assertTrue(!sequence.isDone());
+ Assert.assertTrue(!sequence.isCancelled());
+
+ fExecutor.execute(sequence);
+ sequence.get();
+
+ // Check the count
+ Assert.assertTrue(sequence.fStepCounter == 2);
+
+ // Check post conditions
+ Assert.assertTrue(sequence.isDone());
+ Assert.assertTrue(!sequence.isCancelled());
+ }
+
@Test (expected = ExecutionException.class)
public void rollbackTest() throws InterruptedException, ExecutionException {
@@ -149,6 +199,133 @@ public class DsfSequenceTests {
Assert.assertTrue("Exception should have been thrown", false); //$NON-NLS-1$
}
+
+ public class RollBackReflectionSequence extends ReflectionSequence {
+
+ public int fStepCounter;
+ public int fRollBackCounter;
+
+ public RollBackReflectionSequence() {
+ super(fExecutor);
+ }
+
+ @Override
+ protected String[] getExecutionOrder(String groupName) {
+ return new String[] { "step1", "step2"};
+ }
+
+ @Execute()
+ public void step1(RequestMonitor rm) {
+ fStepCounter++;
+ rm.done();
+ }
+
+ @RollBack("step1")
+ public void rollBack1(RequestMonitor rm) {
+ fRollBackCounter++;
+ rm.done();
+ }
+
+ @Execute()
+ public void step2(RequestMonitor rm) {
+ fStepCounter++;
+ rm.setStatus(new Status(IStatus.ERROR, DsfTestPlugin.PLUGIN_ID, -1, "", null)); //$NON-NLS-1$
+ rm.done();
+ }
+
+ @RollBack("step2")
+ public void rollBack2(RequestMonitor rm) {
+ fRollBackCounter++;
+ rm.done();
+ }
+ }
+
+ @Test (expected = ExecutionException.class)
+ public void rollbackReflectionTest() throws InterruptedException, ExecutionException {
+ // Create and start.
+ RollBackReflectionSequence sequence = new RollBackReflectionSequence();
+ fExecutor.execute(sequence);
+
+ // Block and wait for sequence to complete.
+ try {
+ sequence.get();
+ } finally {
+ // Both steps should be performed
+ Assert.assertEquals(2, sequence.fStepCounter);
+ // Only one step is rolled back, the first one.
+ Assert.assertEquals(1, sequence.fRollBackCounter);
+
+ // Check state from Future interface
+ Assert.assertTrue(sequence.isDone());
+ Assert.assertTrue(!sequence.isCancelled());
+ }
+ Assert.assertTrue("Exception should have been thrown", false); //$NON-NLS-1$
+ }
+
+ public class RollBackReflectionSequence2 extends ReflectionSequence {
+
+ public int fStepCounter;
+ public int fRollBackCounter;
+
+ public RollBackReflectionSequence2() {
+ super(fExecutor);
+ }
+
+ @Override
+ protected String[] getExecutionOrder(String groupName) {
+ return new String[] { "step1", "step2", "step3" };
+ }
+
+ @Execute()
+ public void step1(RequestMonitor rm) {
+ fStepCounter++;
+ rm.done();
+ }
+
+ @RollBack("step1")
+ public void rollBack1(RequestMonitor rm) {
+ fRollBackCounter++;
+ rm.done();
+ }
+ @Execute()
+
+ public void step2(RequestMonitor rm) {
+ fStepCounter++;
+ rm.done();
+ }
+
+ @Execute()
+ public void step3(RequestMonitor rm) {
+ fStepCounter++;
+ rm.setStatus(new Status(IStatus.ERROR, DsfTestPlugin.PLUGIN_ID, -1, "", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ @Test (expected = ExecutionException.class)
+ public void rollbackReflectionWithoutRollBackMethodTest() throws InterruptedException, ExecutionException {
+ // Create and start.
+ RollBackReflectionSequence2 sequence = new RollBackReflectionSequence2();
+ fExecutor.execute(sequence);
+
+ // Block and wait for sequence to complete.
+ try {
+ sequence.get();
+ } finally {
+ // All three steps should be performed
+ Assert.assertEquals(3, sequence.fStepCounter);
+ // Two steps are rolled back, but only the first one has
+ // a rollback method.
+ Assert.assertEquals(1, sequence.fRollBackCounter);
+
+ // Check state from Future interface
+ Assert.assertTrue(sequence.isDone());
+ Assert.assertTrue(!sequence.isCancelled());
+ }
+ Assert.assertTrue("Exception should have been thrown", false); //$NON-NLS-1$
+ }
+
+
/**
* The goal of this test it to check that if an exception is thrown within
* the Step.execute(), the step will return from the Future.get() method.

Back to the top