From 437d707cd93edf1398ef7f9d3dd77d76297fb336 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Thu, 16 Feb 2012 21:39:37 -0500 Subject: [PATCH] Bug 362039: Default directory for "post mortem" debug, as well as handling the use of variables in core/trace file specification. --- .../gdb/internal/ui/launching/CMainTab.java | 29 ++++- .../ui/launching/CoreFilePrompter.java | 9 +- .../gdb/launching/LaunchMessages.properties | 4 +- .../gdb/service/DebugNewProcessSequence.java | 121 ++++++++++++------ .../eclipse/cdt/dsf/gdb/service/Messages.java | 31 +++++ .../cdt/dsf/gdb/service/Messages.properties | 14 ++ 6 files changed, 159 insertions(+), 49 deletions(-) create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CMainTab.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CMainTab.java index 93a56874be6..73e8e3983b3 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CMainTab.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CMainTab.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2010 QNX Software Systems and others. + * Copyright (c) 2008, 2012 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 @@ -10,9 +10,13 @@ * Ken Ryall (Nokia) - bug 178731 * Ericsson - Support for tracepoint post-mortem debugging * IBM Corporation + * Marc Khouzam (Ericsson) - Support setting the path in which the core file + * dialog should start (Bug 362039) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.ui.launching; +import java.io.File; + import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.model.IBinary; import org.eclipse.cdt.core.model.ICElement; @@ -30,6 +34,7 @@ import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; +import org.eclipse.core.variables.VariablesPlugin; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.ui.DebugUITools; @@ -485,15 +490,25 @@ public class CMainTab extends CAbstractMainTab { String coreName = fCoreText.getText().trim(); // We accept an empty string. This should trigger a prompt to the user // This allows to re-use the launch, with a different core file. + // We also accept an absolute or workspace-relative path, including variables. + // This allows the user to indicate in which directory the prompt will start (Bug 362039) if (!coreName.equals(EMPTY_STRING)) { - if (coreName.equals(".") || coreName.equals("..")) { //$NON-NLS-1$ //$NON-NLS-2$ - setErrorMessage(LaunchMessages.getString("CMainTab.File_does_not_exist")); //$NON-NLS-1$ + try { + // Replace the variables + coreName = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(coreName, false); + } catch (CoreException e) { + setErrorMessage(e.getMessage()); return false; } - IPath corePath = new Path(coreName); - if (!corePath.toFile().exists()) { - setErrorMessage(LaunchMessages.getString("CMainTab.File_does_not_exist")); //$NON-NLS-1$ - return false; + + coreName = coreName.trim(); + File filePath = new File(coreName); + if (!filePath.isDirectory()) { + IPath corePath = new Path(coreName); + if (!corePath.toFile().exists()) { + setErrorMessage(LaunchMessages.getString("CMainTab.File_does_not_exist")); //$NON-NLS-1$ + return false; + } } } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CoreFilePrompter.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CoreFilePrompter.java index 6d00780f285..5d1e62e484c 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CoreFilePrompter.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CoreFilePrompter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 Ericsson and others. + * Copyright (c) 2009, 2012 Ericsson 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: * Ericsson - initial API and implementation + * Marc Khouzam (Ericsson) - Set path in which the dialog should start (Bug 362039) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.ui.launching; @@ -46,6 +47,12 @@ public class CoreFilePrompter implements IStatusHandler { FileDialog dialog = new FileDialog(shell); dialog.setText(LaunchMessages.getString("CoreFileLaunchDelegate.Select_Corefile")); //$NON-NLS-1$ + + String initialPath = (String)params; + if (initialPath != null && initialPath.length() != 0) { + dialog.setFilterPath(initialPath); + } + String res = dialog.open(); if (res != null) { File file = new File(res); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchMessages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchMessages.properties index 305a41c9e17..472f9ef646a 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchMessages.properties +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchMessages.properties @@ -92,8 +92,8 @@ CMainTab.&ProjectColon=&Project: CMainTab.C/C++_Application=C/C++ Application: CMainTab.CoreFile_type=Core file CMainTab.TraceFile_type=Trace file -CMainTab.CoreFile_path=Core file (leave blank to trigger prompt): -CMainTab.TraceFile_path=Trace data file (leave blank to trigger prompt): +CMainTab.CoreFile_path=Core file (leave blank or select root directory to trigger prompt): +CMainTab.TraceFile_path=Trace data file (leave blank or select root directory to trigger prompt): CMainTab.Search...=Searc&h Project... CMainTab.Choose_program_to_run=Choose a &program to run: CMainTab.Choose_program_to_run_from_NAME=Choose a program to run from {0}: diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/DebugNewProcessSequence.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/DebugNewProcessSequence.java index e296382dcea..be4fe2d0da3 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/DebugNewProcessSequence.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/DebugNewProcessSequence.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 Ericsson and others. + * Copyright (c) 2011, 2012 Ericsson 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,9 +7,12 @@ * * Contributors: * Ericsson - initial API and implementation + * Marc Khouzam (Ericsson) - Support setting the path in which the core file + * dialog should start (Bug 362039) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.service; +import java.io.File; import java.util.Map; import java.util.Properties; @@ -40,8 +43,10 @@ import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.variables.VariablesPlugin; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.IStatusHandler; @@ -256,10 +261,21 @@ public class DebugNewProcessSequence extends ReflectionSequence { /** @since 4.0 */ protected static class PromptForCoreJob extends Job { + /** + * The initial path that should be used in the prompt for the core file + * @since 4.1 + */ + protected String fInitialPath; protected DataRequestMonitor fRequestMonitor; public PromptForCoreJob(String name, DataRequestMonitor rm) { + this(name, null, null, rm); + } + + /** @since 4.1 */ + public PromptForCoreJob(String name, String coreType, String initialPath, DataRequestMonitor rm) { super(name); + fInitialPath = initialPath; fRequestMonitor = rm; } @@ -281,7 +297,7 @@ public class DebugNewProcessSequence extends ReflectionSequence { } try { - Object result = prompter.handleStatus(filePrompt, null); + Object result = prompter.handleStatus(filePrompt, fInitialPath); if (result == null) { fRequestMonitor.cancel(); } else if (result instanceof String) { @@ -314,14 +330,46 @@ public class DebugNewProcessSequence extends ReflectionSequence { String coreFile = CDebugUtils.getAttribute( fAttributes, ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, ""); //$NON-NLS-1$ + + try { + // Support variable substitution for the core file path + // Bug 362039 + coreFile = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(coreFile, false); + } catch (CoreException e) { + // Ignore and use core file string as is. + // This should not happen because the dialog will + // prevent the user from making such mistakes + } + final String coreType = CDebugUtils.getAttribute( fAttributes, IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_POST_MORTEM_TYPE, IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TYPE_DEFAULT); - if (coreFile.length() == 0) { + // We handle three cases: + // 1- Core file specified, in which case we use it + // 2- Nothing specified, in which case we prompt for a core file path + // 3- Path to a directory, in which case we prompt for a core file starting at the specified path + boolean shouldPrompt = false; + coreFile = coreFile.trim(); + if (coreFile.length() == 0) { + shouldPrompt = true; + } else { + File filePath = new File(coreFile); + if (filePath.isDirectory()) { + // The user provided a directory. We need to prompt for an actual + // core file, but we'll start off in the specified directory + // Bug 362039 + shouldPrompt = true; + } + // else not a directory but an actual core file: use it. + } + + if (shouldPrompt) { new PromptForCoreJob( "Prompt for post mortem file", //$NON-NLS-1$ + coreType, + coreFile, new DataRequestMonitor(getExecutor(), rm) { @Override protected void handleCancel() { @@ -332,53 +380,48 @@ public class DebugNewProcessSequence extends ReflectionSequence { protected void handleSuccess() { String newCoreFile = getData(); if (newCoreFile == null || newCoreFile.length()== 0) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get post mortem file path", null)); //$NON-NLS-1$ + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, Messages.Cannot_get_post_mortem_file_path_error, null)); rm.done(); } else { - if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) { - fCommandControl.queueCommand( - fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), newCoreFile), - new DataRequestMonitor(getExecutor(), rm)); - } 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, rm); - } else { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Tracing not supported", null)); - rm.done(); - } - } else { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Invalid post-mortem type", null)); - rm.done(); - } + targetSelectFile(coreType, newCoreFile, rm); } } }).schedule(); } else { - if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) { - fCommandControl.queueCommand( - fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), coreFile), - new DataRequestMonitor(getExecutor(), rm)); - } 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, rm); - } else { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Tracing not supported", null)); - rm.done(); - } - } else { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Invalid post-mortem type", null)); - rm.done(); - } + // The user specified something that was not a directory, + // it therefore should be the core file itself. Let's use it. + + // First convert to absolute path so that things work even if the user + // specifies a relative path. The reason we do this is that GDB + // may not be using the same root path as Eclipse. + String absoluteCoreFile = new Path(coreFile).toFile().getAbsolutePath(); + targetSelectFile(coreType, absoluteCoreFile, rm); } } else { rm.done(); } } + private void targetSelectFile(String coreType, String file, RequestMonitor rm) { + if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) { + fCommandControl.queueCommand( + fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), file), + new DataRequestMonitor(getExecutor(), rm)); + } 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, file, rm); + } else { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, Messages.Tracing_not_supported_error, null)); + rm.done(); + } + } else { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, Messages.Invalid_post_mortem_type_error, null)); + rm.done(); + } + } + /** * Start tracking the breakpoints. Note that for remote debugging * we should first connect to the target. @@ -435,4 +478,4 @@ public class DebugNewProcessSequence extends ReflectionSequence { fTracker = null; rm.done(); } -} \ No newline at end of file +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java new file mode 100644 index 00000000000..a35539cb469 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson 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: + * Marc Khouzam (Ericsson) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.service; + +import org.eclipse.osgi.util.NLS; + +/** + * Preference strings. + * @since 4.1 + */ +class Messages extends NLS { + public static String Tracing_not_supported_error; + public static String Invalid_post_mortem_type_error; + public static String Cannot_get_post_mortem_file_path_error; + + static { + // initialize resource bundle + NLS.initializeMessages(Messages.class.getName(), Messages.class); + } + + private Messages() { + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties new file mode 100644 index 00000000000..ff882bec4ee --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties @@ -0,0 +1,14 @@ +############################################################################### +# Copyright (c) 2012 Ericsson 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: +# Marc Khouzam (Ericsson) - initial API and implementation +############################################################################### + +Tracing_not_supported_error=Tracing not supported +Invalid_post_mortem_type_error=Invalid post-mortem type +Cannot_get_post_mortem_file_path_error=Cannot get post mortem file path \ No newline at end of file