Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt')
-rw-r--r--cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/Activator.java58
-rw-r--r--cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/IRemoteConnectionConfigurationConstants.java47
-rw-r--r--cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/IRemoteConnectionHostConstants.java33
-rw-r--r--cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/Messages.java76
-rw-r--r--cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteCDebuggerTab.java56
-rw-r--r--cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteCMainTab.java659
-rw-r--r--cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteGDBDebuggerPage.java141
-rw-r--r--cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteLaunchConfigurationTabGroup.java37
-rw-r--r--cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteRunLaunchDelegate.java409
-rw-r--r--cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/messages.properties51
10 files changed, 1567 insertions, 0 deletions
diff --git a/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/Activator.java b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/Activator.java
new file mode 100644
index 00000000000..bca462bd694
--- /dev/null
+++ b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/Activator.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2006 PalmSource, Inc.
+ * 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:
+ * Ewa Matejska (PalmSource)
+ *******************************************************************************/
+
+package org.eclipse.cdt.launch.remote;
+
+import org.eclipse.core.runtime.Plugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class Activator extends Plugin {
+
+ /* The shared instance */
+ private static Activator plugin;
+
+ /**
+ * The constructor.
+ */
+ public Activator() {
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.core.runtime.Plugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ plugin = null;
+ }
+
+ /**
+ * Returns the shared instance.
+ *
+ * @return the shared instance.
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+}
diff --git a/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/IRemoteConnectionConfigurationConstants.java b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/IRemoteConnectionConfigurationConstants.java
new file mode 100644
index 00000000000..e86581f185b
--- /dev/null
+++ b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/IRemoteConnectionConfigurationConstants.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 PalmSource, Inc. 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:
+ * Ewa Matejska (PalmSource) - Adapted from IGDBServerMILaunchConfigurationConstants
+ * Anna Dushistova (MontaVista) - [181517][usability] Specify commands to be run before remote application launch
+ *******************************************************************************/
+
+
+package org.eclipse.cdt.launch.remote;
+
+import org.eclipse.cdt.debug.mi.core.IGDBServerMILaunchConfigurationConstants;
+import org.eclipse.debug.core.DebugPlugin;
+
+public interface IRemoteConnectionConfigurationConstants extends
+ IGDBServerMILaunchConfigurationConstants {
+
+ public static final String ATTR_REMOTE_CONNECTION =
+ DebugPlugin.getUniqueIdentifier() + ".REMOTE_TCP"; //$NON-NLS-1$
+
+
+ public static final String ATTR_GDBSERVER_PORT =
+ DebugPlugin.getUniqueIdentifier() + ".ATTR_GDBSERVER_PORT"; //$NON-NLS-1$
+ public static final String ATTR_GDBSERVER_COMMAND =
+ DebugPlugin.getUniqueIdentifier() + ".ATTR_GDBSERVER_COMMAND"; //$NON-NLS-1$
+
+ public static final String ATTR_GDBSERVER_PORT_DEFAULT = "2345"; //$NON-NLS-1$
+ public static final String ATTR_GDBSERVER_COMMAND_DEFAULT = "gdbserver"; //$NON-NLS-1$
+
+ /*
+ * Generic Remote Path and Download options
+ * ATTR_REMOTE_PATH: Path of the binary on the remote.
+ * ATTR_SKIP_DOWNLOAD_TO_TARGET: true if download to remote is not desired.
+ */
+ public static final String ATTR_REMOTE_PATH =
+ DebugPlugin.getUniqueIdentifier() + ".ATTR_TARGET_PATH"; //$NON-NLS-1$
+ public static final String ATTR_SKIP_DOWNLOAD_TO_TARGET =
+ DebugPlugin.getUniqueIdentifier() + ".ATTR_SKIP_DOWNLOAD_TO_TARGET"; //$NON-NLS-1$
+
+
+ public static final String ATTR_PRERUN_COMMANDS = DebugPlugin.getUniqueIdentifier() + ".ATTR_PRERUN_CMDS"; //$NON-NLS-1$
+
+}
diff --git a/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/IRemoteConnectionHostConstants.java b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/IRemoteConnectionHostConstants.java
new file mode 100644
index 00000000000..1d7fdc6aac5
--- /dev/null
+++ b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/IRemoteConnectionHostConstants.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Wind River Systems, Inc.
+ * 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:
+ * Johann Draschwandtner (Wind River) - initial API and implementation
+ * Martin Oberhuber (Wind River) - [261486][api][cleanup] Mark @noimplement interfaces as @noextend
+ *******************************************************************************/
+package org.eclipse.cdt.launch.remote;
+
+/**
+ * Constants used for Remote CDT connection properties.
+ *
+ * <strong>EXPERIMENTAL</strong>. This class or interface has been added as part
+ * of a work in progress. There is no guarantee that this API will work or that
+ * it will remain the same. Please do not use this API without consulting with
+ * the <a href="http://www.eclipse.org/dsdp/tm/">Target Management</a> team.
+ * </p>
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ * @since org.eclipse.rse.remotecdt 2.1
+ */
+public interface IRemoteConnectionHostConstants {
+
+ public static final String PI_REMOTE_CDT = "org.eclipse.rse.remotecdt"; //$NON-NLS-1$
+
+ public static final String REMOTE_WS_ROOT = "remoteWsRoot"; //$NON-NLS-1$
+ public static final String DEFAULT_SKIP_DOWNLOAD = "defaultSkipDownload"; //$NON-NLS-1$
+}
diff --git a/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/Messages.java b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/Messages.java
new file mode 100644
index 00000000000..4d245044291
--- /dev/null
+++ b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/Messages.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 Wind River Systems, Inc. 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:
+ * Martin Oberhuber (Wind River) - initial API and implementation
+ * Ewa Matejska (PalmSource) - [158783] browse button for cdt remote path
+ * Johann Draschwandtner (Wind River) - [231827][remotecdt]Auto-compute default for Remote path
+ * Anna Dushistova (MontaVista) - [244173][remotecdt][nls] Externalize Strings in RemoteRunLaunchDelegate
+ * Anna Dushistova (MontaVista) - [181517][usability] Specify commands to be run before remote application launch
+ * Nikita Shulga (EmbeddedAlley) - [265236][remotecdt] Wait for RSE to initialize before querying it for host list
+ *******************************************************************************/
+package org.eclipse.cdt.launch.remote;
+
+import org.eclipse.osgi.util.NLS;
+
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.rse.internal.remotecdt.messages"; //$NON-NLS-1$
+
+ public static String Gdbserver_name_textfield_label;
+
+ public static String Gdbserver_Settings_Tab_Name;
+
+ public static String Port_number_textfield_label;
+
+ public static String Remote_GDB_Debugger_Options;
+
+ public static String RemoteCMainTab_Prerun;
+
+ public static String RemoteCMainTab_Program;
+
+ public static String RemoteCMainTab_Remote_Path_Browse_Button;
+
+ public static String RemoteCMainTab_Remote_Path_Browse_Button_Title;
+ public static String RemoteCMainTab_SkipDownload;
+ public static String RemoteCMainTab_ErrorNoProgram;
+ public static String RemoteCMainTab_ErrorNoConnection;
+ public static String RemoteCMainTab_Connection;
+ public static String RemoteCMainTab_New;
+ public static String RemoteCMainTab_Properties;
+ public static String RemoteCMainTab_Properties_title;
+ public static String RemoteCMainTab_Properties_Location;
+ public static String RemoteCMainTab_Properties_Skip_default;
+
+ public static String RemoteRunLaunchDelegate_0;
+
+ public static String RemoteRunLaunchDelegate_RemoteShell;
+ public static String RemoteRunLaunchDelegate_1;
+
+ public static String RemoteRunLaunchDelegate_10;
+
+ public static String RemoteRunLaunchDelegate_12;
+
+ public static String RemoteRunLaunchDelegate_13;
+
+ public static String RemoteRunLaunchDelegate_2;
+ public static String RemoteRunLaunchDelegate_3;
+ public static String RemoteRunLaunchDelegate_4;
+ public static String RemoteRunLaunchDelegate_5;
+ public static String RemoteRunLaunchDelegate_6;
+ public static String RemoteRunLaunchDelegate_7;
+ public static String RemoteRunLaunchDelegate_8;
+
+ public static String RemoteRunLaunchDelegate_9;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
diff --git a/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteCDebuggerTab.java b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteCDebuggerTab.java
new file mode 100644
index 00000000000..acb9458b282
--- /dev/null
+++ b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteCDebuggerTab.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2006 PalmSource, Inc.
+ * 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:
+ * Ewa Matejska (PalmSource)
+ *******************************************************************************/
+
+package org.eclipse.cdt.launch.remote;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.debug.core.CDebugCorePlugin;
+import org.eclipse.cdt.debug.core.ICDebugConfiguration;
+import org.eclipse.cdt.launch.ui.CDebuggerTab;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.PlatformUI;
+
+public class RemoteCDebuggerTab extends CDebuggerTab {
+
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
+ "org.eclipse.rse.internal.remotecdt.launchgroup"); //$NON-NLS-1$
+ }
+
+ static final private String REMOTE_GDB_DEBUGGER_NAME = "remote gdb/mi"; //$NON-NLS-1$
+
+ public RemoteCDebuggerTab(boolean attachMode) {
+ super(attachMode);
+ }
+
+ protected void loadDebuggerComboBox(ILaunchConfiguration config, String selection) {
+ ICDebugConfiguration[] debugConfigs = CDebugCorePlugin.getDefault().getDebugConfigurations();
+ String defaultSelection = selection;
+ List list = new ArrayList();
+ for(int i = 0; i < debugConfigs.length; i++) {
+ ICDebugConfiguration configuration = debugConfigs[i];
+ if(configuration.getName().equals(REMOTE_GDB_DEBUGGER_NAME)) {
+ list.add(configuration);
+ // Select as default selection
+ defaultSelection = configuration.getID();
+ break;
+ }
+ }
+ setInitializeDefault(defaultSelection.equals("") ? true : false); //$NON-NLS-1$
+ loadDebuggerCombo((ICDebugConfiguration[])list.toArray(
+ new ICDebugConfiguration[list.size()]), defaultSelection);
+ }
+
+}
diff --git a/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteCMainTab.java b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteCMainTab.java
new file mode 100644
index 00000000000..eed3c1ad8ad
--- /dev/null
+++ b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteCMainTab.java
@@ -0,0 +1,659 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 PalmSource, Inc. 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:
+ * Ewa Matejska (PalmSource) - initial API and implementation
+ * Martin Oberhuber (Wind River) - [186773] split ISystemRegistryUI from ISystemRegistry
+ * Martin Oberhuber (Wind River) - [196934] hide disabled system types in remotecdt combo
+ * Yu-Fen Kuo (MontaVista) - [190613] Fix NPE in Remotecdt when RSEUIPlugin has not been loaded
+ * Martin Oberhuber (Wind River) - [cleanup] Avoid using SystemStartHere in production code
+ * Johann Draschwandtner (Wind River) - [231827][remotecdt]Auto-compute default for Remote path
+ * Johann Draschwandtner (Wind River) - [233057][remotecdt]Fix button enablement
+ * Anna Dushistova (MontaVista) - [181517][usability] Specify commands to be run before remote application launch
+ * Anna Dushistova (MontaVista) - [223728] [remotecdt] connection combo is not populated until RSE is activated
+ *******************************************************************************/
+
+package org.eclipse.cdt.launch.remote;
+
+import org.eclipse.cdt.launch.ui.CMainTab;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.window.Window;
+import org.eclipse.rse.core.IRSESystemType;
+import org.eclipse.rse.core.RSECorePlugin;
+import org.eclipse.rse.core.model.IHost;
+import org.eclipse.rse.core.model.IPropertySet;
+import org.eclipse.rse.files.ui.dialogs.SystemRemoteFileDialog;
+import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile;
+import org.eclipse.rse.ui.actions.SystemNewConnectionAction;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+
+public class RemoteCMainTab extends CMainTab {
+
+ /* Labels and Error Messages */
+ private static final String REMOTE_PROG_LABEL_TEXT = Messages.RemoteCMainTab_Program;
+ private static final String SKIP_DOWNLOAD_BUTTON_TEXT = Messages.RemoteCMainTab_SkipDownload;
+ private static final String REMOTE_PROG_TEXT_ERROR = Messages.RemoteCMainTab_ErrorNoProgram;
+ private static final String CONNECTION_TEXT_ERROR = Messages.RemoteCMainTab_ErrorNoConnection;
+ private static final String PRE_RUN_LABEL_TEXT = Messages.RemoteCMainTab_Prerun;
+
+ /* Defaults */
+ private static final String REMOTE_PATH_DEFAULT = EMPTY_STRING;
+ private static final boolean SKIP_DOWNLOAD_TO_REMOTE_DEFAULT = false;
+
+ protected Button newRemoteConnectionButton;
+ protected Button remoteConnectionPropertiesButton;
+ protected Button remoteBrowseButton;
+ protected Label connectionLabel;
+ protected Combo connectionCombo;
+ protected Label remoteProgLabel;
+ protected Text remoteProgText;
+ protected Button skipDownloadButton;
+ protected Button useLocalPathButton;
+
+ SystemNewConnectionAction action = null;
+ private Text preRunText;
+ private Label preRunLabel;
+
+ public RemoteCMainTab(boolean terminalOption) {
+ super(terminalOption);
+ }
+
+ /*
+ * createControl
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl
+ */
+ public void createControl(Composite parent) {
+ Composite comp = new Composite(parent, SWT.NONE);
+ GridLayout topLayout = new GridLayout();
+ setControl(comp);
+ comp.setLayout(topLayout);
+
+ /* The RSE Connection dropdown with New button. */
+ createVerticalSpacer(comp, 1);
+ createRemoteConnectionGroup(comp, 4);
+
+ /* The Project and local binary location */
+ createVerticalSpacer(comp, 1);
+ createProjectGroup(comp, 1);
+ createBuildConfigCombo(comp, 1);
+ createExeFileGroup(comp, 1);
+
+ /* The remote binary location and skip download option */
+ createVerticalSpacer(comp, 1);
+ createTargetExePathGroup(comp);
+ createDownloadOption(comp);
+
+ /* If the local binary path changes, modify the remote binary location */
+ fProgText.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent evt) {
+ setLocalPathForRemotePath();
+ }
+ });
+
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
+ "org.eclipse.rse.internal.remotecdt.launchgroup"); //$NON-NLS-1$
+
+ // //No more needed according to
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=178832
+ // LaunchUIPlugin.setDialogShell(parent.getShell());
+ }
+
+ /*
+ * isValid
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#isValid
+ */
+ public boolean isValid(ILaunchConfiguration config) {
+ boolean retVal = super.isValid(config);
+ if (retVal == true) {
+ setErrorMessage(null);
+ int currentSelection = connectionCombo.getSelectionIndex();
+ String connection_name = currentSelection >= 0 ? connectionCombo
+ .getItem(currentSelection) : ""; //$NON-NLS-1$
+ if (connection_name.equals("")) { //$NON-NLS-1$
+ setErrorMessage(CONNECTION_TEXT_ERROR);
+ retVal = false;
+ }
+ if (retVal) {
+ String name = remoteProgText.getText().trim();
+ if (name.length() == 0) {
+ setErrorMessage(REMOTE_PROG_TEXT_ERROR);
+ retVal = false;
+ }
+ }
+ }
+ return retVal;
+ }
+
+ protected void createRemoteConnectionGroup(Composite parent, int colSpan) {
+ Composite projComp = new Composite(parent, SWT.NONE);
+ GridLayout projLayout = new GridLayout();
+ projLayout.numColumns = 4;
+ projLayout.marginHeight = 0;
+ projLayout.marginWidth = 0;
+ projComp.setLayout(projLayout);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = colSpan;
+ projComp.setLayoutData(gd);
+
+ connectionLabel = new Label(projComp, SWT.NONE);
+ connectionLabel.setText(Messages.RemoteCMainTab_Connection);
+ gd = new GridData();
+ gd.horizontalSpan = 1;
+ connectionLabel.setLayoutData(gd);
+
+ connectionCombo = new Combo(projComp, SWT.DROP_DOWN | SWT.READ_ONLY);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 1;
+ connectionCombo.setLayoutData(gd);
+ connectionCombo.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent e) {
+ setDirty(true);
+ updateLaunchConfigurationDialog();
+ useDefaultsFromConnection();
+ updatePropertiesButton();
+ }
+ });
+
+ newRemoteConnectionButton = createPushButton(projComp,
+ Messages.RemoteCMainTab_New, null);
+ newRemoteConnectionButton.addSelectionListener(new SelectionAdapter() {
+
+ public void widgetSelected(SelectionEvent evt) {
+ handleNewRemoteConnectionSelected();
+ updateLaunchConfigurationDialog();
+ updateConnectionPulldown();
+ }
+ });
+
+ remoteConnectionPropertiesButton = createPushButton(projComp,
+ Messages.RemoteCMainTab_Properties, null);
+ remoteConnectionPropertiesButton
+ .addSelectionListener(new SelectionAdapter() {
+
+ public void widgetSelected(SelectionEvent evt) {
+ handleRemoteConnectionPropertiesSelected();
+ }
+ });
+
+ updateConnectionPulldown();
+ }
+
+ /*
+ * createTargetExePath This creates the remote path user-editable textfield
+ * on the Main Tab.
+ */
+ protected void createTargetExePathGroup(Composite parent) {
+ Composite mainComp = new Composite(parent, SWT.NONE);
+ GridLayout mainLayout = new GridLayout();
+ mainLayout.numColumns = 2;
+ mainLayout.marginHeight = 0;
+ mainLayout.marginWidth = 0;
+ mainComp.setLayout(mainLayout);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ mainComp.setLayoutData(gd);
+
+ remoteProgLabel = new Label(mainComp, SWT.NONE);
+ remoteProgLabel.setText(REMOTE_PROG_LABEL_TEXT);
+ gd = new GridData();
+ gd.horizontalSpan = 2;
+ remoteProgLabel.setLayoutData(gd);
+
+ remoteProgText = new Text(mainComp, SWT.SINGLE | SWT.BORDER);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 1;
+ remoteProgText.setLayoutData(gd);
+ remoteProgText.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent evt) {
+ updateLaunchConfigurationDialog();
+ }
+ });
+
+ remoteBrowseButton = createPushButton(mainComp,
+ Messages.RemoteCMainTab_Remote_Path_Browse_Button, null);
+ remoteBrowseButton.addSelectionListener(new SelectionAdapter() {
+
+ public void widgetSelected(SelectionEvent evt) {
+ handleRemoteBrowseSelected();
+ updateLaunchConfigurationDialog();
+ }
+ });
+
+ // Commands to run before execution
+ preRunLabel = new Label(mainComp, SWT.NONE);
+ preRunLabel.setText(PRE_RUN_LABEL_TEXT);
+ gd = new GridData();
+ gd.horizontalSpan = 2;
+ preRunLabel.setLayoutData(gd);
+
+ preRunText = new Text(mainComp, SWT.MULTI | SWT.BORDER);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 2;
+ preRunText.setLayoutData(gd);
+ preRunText.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent evt) {
+ updateLaunchConfigurationDialog();
+ }
+ });
+
+ }
+
+ /*
+ * createDownloadOption This creates the skip download check button.
+ */
+ protected void createDownloadOption(Composite parent) {
+ Composite mainComp = new Composite(parent, SWT.NONE);
+ GridLayout mainLayout = new GridLayout();
+ mainLayout.marginHeight = 0;
+ mainLayout.marginWidth = 0;
+ mainComp.setLayout(mainLayout);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ mainComp.setLayoutData(gd);
+
+ skipDownloadButton = createCheckButton(mainComp,
+ SKIP_DOWNLOAD_BUTTON_TEXT);
+ skipDownloadButton.addSelectionListener(new SelectionAdapter() {
+
+ public void widgetSelected(SelectionEvent evt) {
+ updateLaunchConfigurationDialog();
+ }
+ });
+ skipDownloadButton.setEnabled(true);
+ }
+
+ /*
+ * performApply
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply
+ */
+ public void performApply(ILaunchConfigurationWorkingCopy config) {
+
+ int currentSelection = connectionCombo.getSelectionIndex();
+ config.setAttribute(
+ IRemoteConnectionConfigurationConstants.ATTR_REMOTE_CONNECTION,
+ currentSelection >= 0 ? connectionCombo
+ .getItem(currentSelection) : null);
+ config.setAttribute(
+ IRemoteConnectionConfigurationConstants.ATTR_REMOTE_PATH,
+ remoteProgText.getText());
+ config
+ .setAttribute(
+ IRemoteConnectionConfigurationConstants.ATTR_SKIP_DOWNLOAD_TO_TARGET,
+ skipDownloadButton.getSelection());
+ config.setAttribute(
+ IRemoteConnectionConfigurationConstants.ATTR_PRERUN_COMMANDS,
+ preRunText.getText());
+ super.performApply(config);
+ }
+
+ /*
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom
+ */
+ public void initializeFrom(ILaunchConfiguration config) {
+ String remoteConnection = null;
+ try {
+ remoteConnection = config
+ .getAttribute(
+ IRemoteConnectionConfigurationConstants.ATTR_REMOTE_CONNECTION,
+ ""); //$NON-NLS-1$
+ } catch (CoreException ce) {
+ // Ignore
+ }
+
+ String[] items = connectionCombo.getItems();
+ int i = 0;
+ for (i = 0; i < items.length; i++)
+ if (items[i].equals(remoteConnection))
+ break;
+ /*
+ * Select the last used connection in the connecion pulldown if it still
+ * exists.
+ */
+ if (i < items.length)
+ connectionCombo.select(i);
+ else if (items.length > 0)
+ connectionCombo.select(0);
+
+ super.initializeFrom(config);
+
+ updateTargetProgFromConfig(config);
+ updateSkipDownloadFromConfig(config);
+ updatePropertiesButton();
+ }
+
+ protected void handleNewRemoteConnectionSelected() {
+ if (action == null) {
+ action = new SystemNewConnectionAction(getControl().getShell(),
+ false, false, null);
+ }
+
+ try {
+ action.run();
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+
+ protected IHost getCurrentConnection() {
+ int currentSelection = connectionCombo.getSelectionIndex();
+ String remoteConnection = currentSelection >= 0 ? connectionCombo
+ .getItem(currentSelection) : null;
+ if (remoteConnection == null)
+ return null;
+ IHost[] connections = RSECorePlugin.getTheSystemRegistry().getHosts();
+ int i = 0;
+ for (i = 0; i < connections.length; i++)
+ if (connections[i].getAliasName().equals(remoteConnection))
+ break;
+ return connections[i];
+ }
+
+ protected void handleRemoteBrowseSelected() {
+ IHost currentConnectionSelected = getCurrentConnection();
+ SystemRemoteFileDialog dlg = new SystemRemoteFileDialog(getControl()
+ .getShell(),
+ Messages.RemoteCMainTab_Remote_Path_Browse_Button_Title,
+ currentConnectionSelected);
+ dlg.setBlockOnOpen(true);
+ if (dlg.open() == Window.OK) {
+ Object retObj = dlg.getSelectedObject();
+ if (retObj instanceof IRemoteFile) {
+ IRemoteFile selectedFile = (IRemoteFile) retObj;
+ remoteProgText.setText(selectedFile.getAbsolutePath());
+ }
+
+ }
+ }
+
+ protected void handleRemoteConnectionPropertiesSelected() {
+ class RemoteConnectionPropertyDialog extends Dialog {
+ private IHost fHost;
+ boolean fbLocalHost;
+ private Button fSkipDownloadBtn;
+ private Text fWSRoot;
+
+ public RemoteConnectionPropertyDialog(Shell parentShell,
+ String dialogTitle, IHost host) {
+ super(parentShell);
+ parentShell.setText(dialogTitle);
+ fHost = host;
+ fbLocalHost = fHost.getSystemType().isLocal();
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ // create composite
+ Composite composite = (Composite) super
+ .createDialogArea(parent);
+
+ Label label = new Label(composite, SWT.WRAP);
+ label.setText(Messages.RemoteCMainTab_Properties_Location);
+ GridData data = new GridData(GridData.GRAB_HORIZONTAL
+ | GridData.GRAB_VERTICAL
+ | GridData.HORIZONTAL_ALIGN_FILL
+ | GridData.VERTICAL_ALIGN_CENTER);
+ data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);
+ label.setLayoutData(data);
+ label.setFont(parent.getFont());
+ fWSRoot = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ fWSRoot.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
+ | GridData.HORIZONTAL_ALIGN_FILL));
+
+ fSkipDownloadBtn = new Button(composite, SWT.CHECK);
+ fSkipDownloadBtn
+ .setText(Messages.RemoteCMainTab_Properties_Skip_default);
+ if (!fbLocalHost) {
+ IPropertySet propertySet = fHost
+ .getPropertySet(IRemoteConnectionHostConstants.PI_REMOTE_CDT);
+ if (propertySet != null) {
+ String value = propertySet
+ .getPropertyValue(IRemoteConnectionHostConstants.REMOTE_WS_ROOT);
+ if (value != null) {
+ fWSRoot.setText(value);
+ }
+ fSkipDownloadBtn
+ .setSelection(Boolean
+ .valueOf(
+ propertySet
+ .getPropertyValue(IRemoteConnectionHostConstants.DEFAULT_SKIP_DOWNLOAD))
+ .booleanValue());
+ }
+ } else {
+ fSkipDownloadBtn.setEnabled(false);
+ fWSRoot.setEnabled(false);
+ }
+ applyDialogFont(composite);
+ return composite;
+ }
+
+ protected void buttonPressed(int buttonId) {
+ if (!fbLocalHost && (buttonId == IDialogConstants.OK_ID)) {
+ IPropertySet propertySet = fHost
+ .getPropertySet(IRemoteConnectionHostConstants.PI_REMOTE_CDT);
+ if (propertySet == null) {
+ propertySet = fHost
+ .createPropertySet(IRemoteConnectionHostConstants.PI_REMOTE_CDT);
+ }
+ propertySet.addProperty(
+ IRemoteConnectionHostConstants.REMOTE_WS_ROOT,
+ fWSRoot.getText());
+ propertySet
+ .addProperty(
+ IRemoteConnectionHostConstants.DEFAULT_SKIP_DOWNLOAD,
+ Boolean.toString(fSkipDownloadBtn
+ .getSelection()));
+ fHost.commit();
+ }
+ super.buttonPressed(buttonId);
+ }
+ }
+ IHost currentConnectionSelected = getCurrentConnection();
+ RemoteConnectionPropertyDialog dlg = new RemoteConnectionPropertyDialog(
+ getControl().getShell(),
+ Messages.RemoteCMainTab_Properties_title,
+ currentConnectionSelected);
+ dlg.setBlockOnOpen(true);
+ dlg.open();
+ }
+
+ protected void updateConnectionPulldown() {
+ if (!RSECorePlugin.isInitComplete(RSECorePlugin.INIT_MODEL))
+ try {
+ RSECorePlugin.waitForInitCompletion(RSECorePlugin.INIT_MODEL);
+ } catch (InterruptedException e) {
+ return;
+ }
+ // already initialized
+ connectionCombo.removeAll();
+ IHost[] connections = RSECorePlugin.getTheSystemRegistry()
+ .getHostsBySubSystemConfigurationCategory("shells"); //$NON-NLS-1$
+ for (int i = 0; i < connections.length; i++) {
+ IRSESystemType sysType = connections[i].getSystemType();
+ if (sysType != null && sysType.isEnabled()) {
+ connectionCombo.add(connections[i].getAliasName());
+ }
+ }
+
+ if (connections.length > 0) {
+ connectionCombo.select(connections.length - 1);
+ }
+ updatePropertiesButton();
+ }
+
+ private void updatePropertiesButton() {
+ if ((remoteConnectionPropertiesButton == null)
+ || remoteConnectionPropertiesButton.isDisposed()) {
+ return;
+ }
+ boolean bEnableProperties = false;
+ IHost currentConnectionSelected = getCurrentConnection();
+ if (currentConnectionSelected != null) {
+ IRSESystemType sysType = currentConnectionSelected.getSystemType();
+ if (sysType != null && sysType.isEnabled() && !sysType.isLocal()) {
+ bEnableProperties = true;
+ }
+ }
+ remoteConnectionPropertiesButton.setEnabled(bEnableProperties);
+ }
+
+ protected void updateTargetProgFromConfig(ILaunchConfiguration config) {
+ String targetPath = null;
+ try {
+ targetPath = config.getAttribute(
+ IRemoteConnectionConfigurationConstants.ATTR_REMOTE_PATH,
+ REMOTE_PATH_DEFAULT);
+ } catch (CoreException e) {
+ // Ignore
+ }
+ remoteProgText.setText(targetPath);
+
+ String prelaunchCmd = null;
+ try {
+ prelaunchCmd = config
+ .getAttribute(
+ IRemoteConnectionConfigurationConstants.ATTR_PRERUN_COMMANDS,
+ ""); //$NON-NLS-1$
+ } catch (CoreException e) {
+ // Ignore
+ }
+ preRunText.setText(prelaunchCmd);
+ }
+
+ protected void updateSkipDownloadFromConfig(ILaunchConfiguration config) {
+ boolean downloadToTarget = true;
+ try {
+ downloadToTarget = config
+ .getAttribute(
+ IRemoteConnectionConfigurationConstants.ATTR_SKIP_DOWNLOAD_TO_TARGET,
+ SKIP_DOWNLOAD_TO_REMOTE_DEFAULT);
+ } catch (CoreException e) {
+ // Ignore for now
+ }
+ skipDownloadButton.setSelection(downloadToTarget);
+ }
+
+ /*
+ * setLocalPathForRemotePath This function sets the remote path text field
+ * with the value of the local executable path.
+ */
+ private void setLocalPathForRemotePath() {
+ String programName = fProgText.getText().trim();
+ boolean bUpdateRemote = false;
+
+ String remoteName = remoteProgText.getText().trim();
+ String remoteWsRoot = getRemoteWSRoot();
+ if (remoteName.length() == 0) {
+ bUpdateRemote = true;
+ } else if (remoteWsRoot.length() != 0) {
+ bUpdateRemote = remoteName.equals(remoteWsRoot);
+ }
+
+ if (programName.length() != 0 && bUpdateRemote) {
+ IProject project = getCProject().getProject();
+ IPath exePath = new Path(programName);
+ if (!exePath.isAbsolute()) {
+ exePath = project.getFile(programName).getLocation();
+
+ IPath wsRoot = project.getWorkspace().getRoot().getLocation();
+ exePath = makeRelativeToWSRootLocation(exePath, remoteWsRoot,
+ wsRoot);
+ }
+ String path = exePath.toString();
+ remoteProgText.setText(path);
+ }
+ }
+
+ private void useDefaultsFromConnection() {
+ if ((remoteProgText != null) && !remoteProgText.isDisposed()) {
+ String remoteName = remoteProgText.getText().trim();
+ String remoteWsRoot = getRemoteWSRoot();
+ if (remoteName.length() == 0) {
+ remoteProgText.setText(remoteWsRoot);
+ } else {
+ // try to use remote path
+ IPath wsRoot = getCProject().getProject().getWorkspace()
+ .getRoot().getLocation();
+ IPath remotePath = makeRelativeToWSRootLocation(new Path(
+ remoteName), remoteWsRoot, wsRoot);
+ remoteProgText.setText(remotePath.toString());
+ }
+ }
+ if ((skipDownloadButton != null) && !skipDownloadButton.isDisposed()) {
+ skipDownloadButton.setSelection(getDefaultSkipDownload());
+ }
+ }
+
+ private IPath makeRelativeToWSRootLocation(IPath exePath,
+ String remoteWsRoot, IPath wsRoot) {
+ if (remoteWsRoot.length() != 0) {
+ // use remoteWSRoot instead of Workspace Root
+ if (wsRoot.isPrefixOf(exePath)) {
+ return new Path(remoteWsRoot).append(exePath
+ .removeFirstSegments(wsRoot.segmentCount()).setDevice(
+ null));
+ }
+ }
+ return exePath;
+ }
+
+ private String getRemoteWSRoot() {
+ IHost host = getCurrentConnection();
+ if (host != null) {
+ IPropertySet propertySet = host
+ .getPropertySet(IRemoteConnectionHostConstants.PI_REMOTE_CDT);
+ if (propertySet != null) {
+ String value = propertySet
+ .getPropertyValue(IRemoteConnectionHostConstants.REMOTE_WS_ROOT);
+ if (value != null) {
+ return value;
+ }
+ }
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ private boolean getDefaultSkipDownload() {
+ IHost host = getCurrentConnection();
+ if (host != null) {
+ IPropertySet propertySet = host
+ .getPropertySet(IRemoteConnectionHostConstants.PI_REMOTE_CDT);
+ if (propertySet != null) {
+ return Boolean
+ .valueOf(
+ propertySet
+ .getPropertyValue(IRemoteConnectionHostConstants.DEFAULT_SKIP_DOWNLOAD))
+ .booleanValue();
+ }
+ }
+ return SKIP_DOWNLOAD_TO_REMOTE_DEFAULT;
+ }
+}
diff --git a/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteGDBDebuggerPage.java b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteGDBDebuggerPage.java
new file mode 100644
index 00000000000..6162b92a7c2
--- /dev/null
+++ b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteGDBDebuggerPage.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2006 PalmSource, Inc.
+ * 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:
+ * Ewa Matejska (PalmSource)
+ *
+ * Referenced GDBDebuggerPage code to write this.
+ *******************************************************************************/
+
+package org.eclipse.cdt.launch.remote;
+
+import org.eclipse.cdt.debug.mi.internal.ui.GDBDebuggerPage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * The dynamic debugger tab for remote launches using gdb server.
+ * The gdbserver settings are used to start a gdbserver session on the
+ * remote and then to connect to it from the host. The DSDP-TM project is
+ * used to accomplish this.
+ */
+public class RemoteGDBDebuggerPage extends GDBDebuggerPage {
+
+ protected Text fGDBServerCommandText;
+
+ protected Text fGDBServerPortNumberText;
+
+ public String getName() {
+ return Messages.Remote_GDB_Debugger_Options;
+ }
+
+ public void setDefaults( ILaunchConfigurationWorkingCopy configuration ) {
+ super.setDefaults(configuration);
+ configuration.setAttribute( IRemoteConnectionConfigurationConstants.ATTR_GDBSERVER_COMMAND,
+ IRemoteConnectionConfigurationConstants.ATTR_GDBSERVER_COMMAND_DEFAULT );
+ configuration.setAttribute( IRemoteConnectionConfigurationConstants.ATTR_GDBSERVER_PORT,
+ IRemoteConnectionConfigurationConstants.ATTR_GDBSERVER_PORT_DEFAULT );
+ }
+
+ public void initializeFrom( ILaunchConfiguration configuration ) {
+ super.initializeFrom(configuration);
+ String gdbserverCommand = null;
+ String gdbserverPortNumber = null;
+ try {
+ gdbserverCommand = configuration.getAttribute( IRemoteConnectionConfigurationConstants.ATTR_GDBSERVER_COMMAND,
+ IRemoteConnectionConfigurationConstants.ATTR_GDBSERVER_COMMAND_DEFAULT);
+ }
+ catch( CoreException e ) {
+ }
+ try {
+ gdbserverPortNumber = configuration.getAttribute( IRemoteConnectionConfigurationConstants.ATTR_GDBSERVER_PORT,
+ IRemoteConnectionConfigurationConstants.ATTR_GDBSERVER_PORT_DEFAULT );
+ }
+ catch( CoreException e ) {
+ }
+ fGDBServerCommandText.setText( gdbserverCommand );
+ fGDBServerPortNumberText.setText( gdbserverPortNumber );
+ }
+
+ public void performApply( ILaunchConfigurationWorkingCopy configuration ) {
+ super.performApply(configuration);
+ String str = fGDBServerCommandText.getText();
+ str.trim();
+ configuration.setAttribute( IRemoteConnectionConfigurationConstants.ATTR_GDBSERVER_COMMAND, str );
+ str = fGDBServerPortNumberText.getText();
+ str.trim();
+ configuration.setAttribute( IRemoteConnectionConfigurationConstants.ATTR_GDBSERVER_PORT, str );
+ }
+
+ protected void createGdbserverSettingsTab( TabFolder tabFolder ) {
+ TabItem tabItem = new TabItem( tabFolder, SWT.NONE );
+ tabItem.setText( Messages.Gdbserver_Settings_Tab_Name );
+
+ Composite comp = new Composite(tabFolder, SWT.NULL);
+ comp.setLayout(new GridLayout(1, true));
+ comp.setLayoutData(new GridData(GridData.FILL_BOTH));
+ ((GridLayout)comp.getLayout()).makeColumnsEqualWidth = false;
+ comp.setFont( tabFolder.getFont() );
+ tabItem.setControl( comp );
+
+ Composite subComp = new Composite(comp, SWT.NULL);
+ subComp.setLayout(new GridLayout(2, true));
+ subComp.setLayoutData(new GridData(GridData.FILL_BOTH));
+ ((GridLayout)subComp.getLayout()).makeColumnsEqualWidth = false;
+ subComp.setFont( tabFolder.getFont() );
+
+ Label label = new Label(subComp, SWT.LEFT);
+ label.setText(Messages.Gdbserver_name_textfield_label);
+ GridData gd = new GridData();
+ label.setLayoutData( gd );
+
+
+ fGDBServerCommandText = new Text(subComp, SWT.SINGLE | SWT.BORDER);
+ GridData data = new GridData();
+ fGDBServerCommandText.setLayoutData(data);
+ fGDBServerCommandText.addModifyListener( new ModifyListener() {
+
+ public void modifyText( ModifyEvent evt ) {
+ updateLaunchConfigurationDialog();
+ }
+ } );
+ label = new Label(subComp, SWT.LEFT);
+ label.setText(Messages.Port_number_textfield_label);
+ gd = new GridData();
+ label.setLayoutData( gd );
+
+ fGDBServerPortNumberText = new Text(subComp, SWT.SINGLE | SWT.BORDER);
+ data = new GridData();
+ fGDBServerPortNumberText.setLayoutData(data);
+ fGDBServerPortNumberText.addModifyListener( new ModifyListener() {
+
+ public void modifyText( ModifyEvent evt ) {
+ updateLaunchConfigurationDialog();
+ }
+ } );
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.mi.internal.ui.GDBDebuggerPage#createTabs(org.eclipse.swt.widgets.TabFolder)
+ */
+ public void createTabs( TabFolder tabFolder ) {
+ super.createTabs( tabFolder );
+ createGdbserverSettingsTab( tabFolder );
+ }
+}
+
diff --git a/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteLaunchConfigurationTabGroup.java b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteLaunchConfigurationTabGroup.java
new file mode 100644
index 00000000000..8fe70b7166d
--- /dev/null
+++ b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteLaunchConfigurationTabGroup.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2006 PalmSource, Inc.
+ * 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:
+ * Ewa Matejska (PalmSource) - Adapted from LocalRunLaunchConfigurationTabGroup
+ *******************************************************************************/
+
+
+package org.eclipse.cdt.launch.remote;
+import org.eclipse.cdt.launch.ui.CArgumentsTab;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
+import org.eclipse.debug.ui.CommonTab;
+import org.eclipse.debug.ui.ILaunchConfigurationDialog;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+import org.eclipse.debug.ui.sourcelookup.SourceLookupTab;
+
+/**
+ * This class defines the tab group for the Remote C++ Launch
+ * Configuration.
+ */
+public class RemoteLaunchConfigurationTabGroup extends
+ AbstractLaunchConfigurationTabGroup {
+ public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
+ ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] {
+ new RemoteCMainTab(true),
+ new CArgumentsTab(),
+ new RemoteCDebuggerTab(false),
+ new SourceLookupTab(),
+ new CommonTab()
+ };
+ setTabs(tabs);
+ }
+} \ No newline at end of file
diff --git a/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteRunLaunchDelegate.java b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteRunLaunchDelegate.java
new file mode 100644
index 00000000000..f61daf31299
--- /dev/null
+++ b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/RemoteRunLaunchDelegate.java
@@ -0,0 +1,409 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 PalmSource, Inc. 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:
+ * Ewa Matejska (PalmSource) - Adapted from LocalRunLaunchDelegate
+ * Martin Oberhuber (Wind River) - [186128] Move IProgressMonitor last in all API
+ * Martin Oberhuber (Wind River) - [186773] split ISystemRegistryUI from ISystemRegistry
+ * Martin Oberhuber (Wind River) - [226301][api] IShellService should throw SystemMessageException on error
+ * Anna Dushistova (MontaVista) - [234490][remotecdt] Launching with disconnected target fails
+ * Anna Dushistova (MontaVista) - [235298][remotecdt] Further improve progress reporting and cancellation of Remote CDT Launch
+ * Anna Dushistova (MontaVista) - [244173][remotecdt][nls] Externalize Strings in RemoteRunLaunchDelegate
+ * Anna Dushistova (MontaVista) - [181517][usability] Specify commands to be run before remote application launch
+ * Nikita Shulga (EmbeddedAlley) - [265236][remotecdt] Wait for RSE to initialize before querying it for host list
+ *******************************************************************************/
+
+package org.eclipse.cdt.launch.remote;
+
+import java.io.File;
+
+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.ICDIDebugger2;
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.debug.core.cdi.CDIException;
+import org.eclipse.cdt.debug.core.cdi.ICDISession;
+import org.eclipse.cdt.debug.core.cdi.model.ICDITarget;
+import org.eclipse.cdt.debug.mi.core.GDBServerCDIDebugger2;
+import org.eclipse.cdt.debug.mi.core.IGDBServerMILaunchConfigurationConstants;
+import org.eclipse.cdt.launch.AbstractCLaunchDelegate;
+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.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+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.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.rse.core.RSECorePlugin;
+import org.eclipse.rse.core.model.IHost;
+import org.eclipse.rse.core.subsystems.ISubSystem;
+import org.eclipse.rse.services.IService;
+import org.eclipse.rse.services.clientserver.messages.SystemOperationCancelledException;
+import org.eclipse.rse.services.files.IFileService;
+import org.eclipse.rse.services.shells.HostShellProcessAdapter;
+import org.eclipse.rse.services.shells.IHostShell;
+import org.eclipse.rse.services.shells.IShellService;
+import org.eclipse.rse.subsystems.files.core.servicesubsystem.IFileServiceSubSystem;
+import org.eclipse.rse.subsystems.shells.core.subsystems.servicesubsystem.IShellServiceSubSystem;
+
+public class RemoteRunLaunchDelegate extends AbstractCLaunchDelegate {
+
+ private final static String SHELL_SERVICE = "shell.service"; //$NON-NLS-1$
+ private final static String FILE_SERVICE = "file.service"; //$NON-NLS-1$
+ private final static String EXIT_CMD = "exit"; //$NON-NLS-1$
+ private final static String CMD_DELIMITER = ";"; //$NON-NLS-1$
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.core.model.ILaunchConfigurationDelegate#launch
+ */
+ public void launch(ILaunchConfiguration config, String mode,
+ ILaunch launch, IProgressMonitor monitor) throws CoreException {
+
+ IBinaryObject exeFile = null;
+ IPath exePath = verifyProgramPath(config);
+ ICProject project = verifyCProject(config);
+ if (exePath != null) {
+ exeFile = verifyBinary(project, exePath);
+ String arguments = getProgramArguments(config);
+ String remoteExePath = config.getAttribute(
+ IRemoteConnectionConfigurationConstants.ATTR_REMOTE_PATH,
+ ""); //$NON-NLS-1$
+ String prelaunchCmd = config
+ .getAttribute(
+ IRemoteConnectionConfigurationConstants.ATTR_PRERUN_COMMANDS,
+ ""); //$NON-NLS-1$
+
+ if (monitor == null)
+ monitor = new NullProgressMonitor();
+
+ if (!RSECorePlugin.isInitComplete(RSECorePlugin.INIT_MODEL)) {
+ monitor.subTask(Messages.RemoteRunLaunchDelegate_10);
+ try {
+ RSECorePlugin.waitForInitCompletion(RSECorePlugin.INIT_MODEL);
+ } catch (InterruptedException e) {
+ throw new CoreException(new Status(IStatus.ERROR, getPluginID(),
+ IStatus.OK, e.getLocalizedMessage(), e));
+ }
+ }
+ if (mode.equals(ILaunchManager.DEBUG_MODE)) {
+ monitor.beginTask(Messages.RemoteRunLaunchDelegate_0, 100);
+ setDefaultSourceLocator(launch, config);
+ String debugMode = config
+ .getAttribute(
+ ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
+ ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN);
+ if (debugMode
+ .equals(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN)) {
+ Process remoteShellProcess = null;
+ ICDISession dsession = null;
+ try {
+ // Download the binary to the remote before debugging.
+ monitor.setTaskName(Messages.RemoteRunLaunchDelegate_2);
+ remoteFileDownload(config, launch, exePath.toString(),
+ remoteExePath, new SubProgressMonitor(monitor,
+ 80));
+
+ // Automatically start up the gdbserver. In the future
+ // this should be expanded to launch
+ // an arbitrary remote daemon.
+ String gdbserver_port_number = config
+ .getAttribute(
+ IRemoteConnectionConfigurationConstants.ATTR_GDBSERVER_PORT,
+ IRemoteConnectionConfigurationConstants.ATTR_GDBSERVER_PORT_DEFAULT);
+ String gdbserver_command = config
+ .getAttribute(
+ IRemoteConnectionConfigurationConstants.ATTR_GDBSERVER_COMMAND,
+ IRemoteConnectionConfigurationConstants.ATTR_GDBSERVER_COMMAND_DEFAULT);
+ String command_arguments = ":" + gdbserver_port_number + " " //$NON-NLS-1$ //$NON-NLS-2$
+ + spaceEscapify(remoteExePath);
+ if (arguments != null && !arguments.equals("")) //$NON-NLS-1$
+ command_arguments += " " + arguments; //$NON-NLS-1$
+ monitor.setTaskName(Messages.RemoteRunLaunchDelegate_9);
+ remoteShellProcess = remoteShellExec(config,
+ prelaunchCmd, gdbserver_command,
+ command_arguments, new SubProgressMonitor(
+ monitor, 5));
+ DebugPlugin.newProcess(launch, remoteShellProcess,
+ Messages.RemoteRunLaunchDelegate_RemoteShell);
+
+ // Pre-set configuration constants for the
+ // GDBSERVERCDIDebugger to indicate how the gdbserver
+ // was automatically started on the remote.
+ // GDBServerCDIDebugger uses these to figure out how
+ // to connect to the remote gdbserver.
+ ILaunchConfigurationWorkingCopy wc = config
+ .getWorkingCopy();
+ wc
+ .setAttribute(
+ IGDBServerMILaunchConfigurationConstants.ATTR_REMOTE_TCP,
+ true);
+ wc
+ .setAttribute(
+ IGDBServerMILaunchConfigurationConstants.ATTR_HOST,
+ getRemoteHostname(config));
+ wc
+ .setAttribute(
+ IGDBServerMILaunchConfigurationConstants.ATTR_PORT,
+ gdbserver_port_number);
+ wc.doSave();
+
+ // Default to using the GDBServerCDIDebugger.
+ GDBServerCDIDebugger2 debugger = new GDBServerCDIDebugger2();
+ dsession = ((ICDIDebugger2) debugger).createSession(
+ launch, exePath.toFile(),
+ new SubProgressMonitor(monitor, 15));
+
+ 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],
+ renderProcessLabel("gdbserver debugger"), //$NON-NLS-1$
+ iprocess, exeFile, true, false, stopSymbol,
+ true);
+ }
+ } catch (CoreException e) {
+ try {
+ if (dsession != null)
+ dsession.terminate();
+ if (remoteShellProcess != null)
+ remoteShellProcess.destroy();
+ } catch (CDIException e1) {
+ // ignore
+ }
+ throw e;
+ } finally {
+ monitor.done();
+ }
+ }
+
+ } else if (mode.equals(ILaunchManager.RUN_MODE)) {
+ monitor.beginTask(Messages.RemoteRunLaunchDelegate_0, 100);
+ Process remoteProcess = null;
+ try {
+ // Download the binary to the remote before debugging.
+ monitor.setTaskName(Messages.RemoteRunLaunchDelegate_2);
+ remoteFileDownload(config, launch, exePath.toString(),
+ remoteExePath, new SubProgressMonitor(monitor, 80));
+ // Use a remote shell to launch the binary.
+ monitor.setTaskName(Messages.RemoteRunLaunchDelegate_12);
+ remoteProcess = remoteShellExec(config, prelaunchCmd,
+ remoteExePath, arguments, new SubProgressMonitor(
+ monitor, 20));
+ DebugPlugin.newProcess(launch, remoteProcess,
+ renderProcessLabel(exePath.toOSString()));
+ } catch (CoreException e) {
+ throw e;
+ } finally {
+ monitor.done();
+ }
+
+ } else {
+ IStatus status = new Status(IStatus.ERROR, getPluginID(),
+ IStatus.OK, NLS.bind(
+ Messages.RemoteRunLaunchDelegate_1, mode), null);
+ throw new CoreException(status);
+ }
+ }
+ }
+
+ private String spaceEscapify(String inputString) {
+ if (inputString == null)
+ return null;
+
+ return inputString.replaceAll(" ", "\\\\ "); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ protected IHost getCurrentConnection(ILaunchConfiguration config)
+ throws CoreException {
+ String remoteConnection = config.getAttribute(
+ IRemoteConnectionConfigurationConstants.ATTR_REMOTE_CONNECTION,
+ ""); //$NON-NLS-1$
+
+ IHost[] connections = RSECorePlugin.getTheSystemRegistry().getHosts();
+ int i = 0;
+ for (i = 0; i < connections.length; i++)
+ if (connections[i].getAliasName().equals(remoteConnection))
+ break;
+ if (i >= connections.length) {
+ abort(Messages.RemoteRunLaunchDelegate_13, null,
+ ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR);
+ }
+ return connections[i];
+ }
+
+ protected IService getConnectedRemoteService(ILaunchConfiguration config,
+ String kindOfService, IProgressMonitor monitor)
+ throws CoreException {
+
+ // Check that the service requested is file or shell.
+ if (!kindOfService.equals(SHELL_SERVICE)
+ && !kindOfService.equals(FILE_SERVICE))
+ abort(Messages.RemoteRunLaunchDelegate_3, null,
+ ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR);
+
+ IHost currentConnection = getCurrentConnection(config);
+
+ ISubSystem[] subSystems = currentConnection.getSubSystems();
+ int i = 0;
+ for (i = 0; i < subSystems.length; i++) {
+ if (subSystems[i] instanceof IShellServiceSubSystem
+ && kindOfService.equals(SHELL_SERVICE))
+ break;
+ if (subSystems[i] instanceof IFileServiceSubSystem
+ && kindOfService.equals(FILE_SERVICE))
+ break;
+ }
+ if (i >= subSystems.length)
+ abort(Messages.RemoteRunLaunchDelegate_4, null,
+ ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR);
+
+ final ISubSystem subsystem = subSystems[i];
+ try {
+ subsystem.connect(monitor, false);
+ } catch (CoreException e) {
+ throw e;
+ } catch (OperationCanceledException e) {
+ throw new CoreException(Status.CANCEL_STATUS);
+ } catch (Exception e) {
+ throw new CoreException(new Status(IStatus.ERROR, getPluginID(),
+ IStatus.OK, e.getLocalizedMessage(), e));
+ }
+
+ if (!subsystem.isConnected())
+ abort(Messages.RemoteRunLaunchDelegate_5, null,
+ ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR);
+
+ if (kindOfService.equals(SHELL_SERVICE))
+ return ((IShellServiceSubSystem) subsystem).getShellService();
+ else
+ return ((IFileServiceSubSystem) subsystem).getFileService();
+ }
+
+ protected Process remoteFileDownload(ILaunchConfiguration config,
+ ILaunch launch, String localExePath, String remoteExePath,
+ IProgressMonitor monitor) throws CoreException {
+
+ boolean skipDownload = config
+ .getAttribute(
+ IRemoteConnectionConfigurationConstants.ATTR_SKIP_DOWNLOAD_TO_TARGET,
+ false);
+
+ if (skipDownload)
+ // Nothing to do. Download is skipped.
+ return null;
+ monitor.beginTask(Messages.RemoteRunLaunchDelegate_2, 100);
+ IFileService fileService = (IFileService) getConnectedRemoteService(
+ config, FILE_SERVICE, new SubProgressMonitor(monitor, 10));
+ File file = new File(localExePath);
+ Path remotePath = new Path(remoteExePath);
+ try {
+ fileService.upload(file, remotePath.removeLastSegments(1)
+ .toString(), remotePath.lastSegment(), true, null, null,
+ new SubProgressMonitor(monitor, 85));
+ // Need to change the permissions to match the original file
+ // permissions because of a bug in upload
+ Process p = remoteShellExec(
+ config,
+ "", "chmod", "+x " + spaceEscapify(remotePath.toString()), new SubProgressMonitor(monitor, 5)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ Thread.sleep(500);
+ p.destroy();
+ } catch (SystemOperationCancelledException e) {
+ cancel(e.getLocalizedMessage(), IStatus.CANCEL);
+ } catch (Exception e) {
+ abort(Messages.RemoteRunLaunchDelegate_6, e,
+ ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR);
+ } finally {
+ monitor.done();
+ }
+ return null;
+ }
+
+ protected String getRemoteHostname(ILaunchConfiguration config)
+ throws CoreException {
+ IHost currentConnection = getCurrentConnection(config);
+ return currentConnection.getHostName();
+ }
+
+ protected Process remoteShellExec(ILaunchConfiguration config,
+ String prelaunchCmd, String remoteCommandPath, String arguments,
+ IProgressMonitor monitor) throws CoreException {
+ // The exit command is called to force the remote shell to close after
+ // our command
+ // is executed. This is to prevent a running process at the end of the
+ // debug session.
+ // See Bug 158786.
+ monitor.beginTask(NLS.bind(Messages.RemoteRunLaunchDelegate_8,
+ remoteCommandPath, arguments), 10);
+ String real_remote_command = arguments == null ? spaceEscapify(remoteCommandPath)
+ : spaceEscapify(remoteCommandPath) + " " + arguments; //$NON-NLS-1$
+
+ String remote_command = real_remote_command + CMD_DELIMITER + EXIT_CMD;
+
+ if (!prelaunchCmd.trim().equals("")) //$NON-NLS-1$
+ remote_command = prelaunchCmd + CMD_DELIMITER + remote_command;
+
+ IShellService shellService = (IShellService) getConnectedRemoteService(
+ config, SHELL_SERVICE, new SubProgressMonitor(monitor, 7));
+
+ // This is necessary because runCommand does not actually run the
+ // command right now.
+ String env[] = new String[0];
+ Process p = null;
+ try {
+ IHostShell hostShell = shellService.launchShell(
+ "", env, new SubProgressMonitor(monitor, 3)); //$NON-NLS-1$
+ hostShell.writeToShell(remote_command);
+ p = new HostShellProcessAdapter(hostShell);
+ } catch (Exception e) {
+ if (p != null) {
+ p.destroy();
+ }
+ abort(Messages.RemoteRunLaunchDelegate_7, e,
+ ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR);
+ }
+ monitor.done();
+ return p;
+
+ }
+
+ protected String getPluginID() {
+ return "org.eclipse.rse.internal.remotecdt"; //$NON-NLS-1$
+ }
+}
diff --git a/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/messages.properties b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/messages.properties
new file mode 100644
index 00000000000..326545073b0
--- /dev/null
+++ b/cross/org.eclipse.cdt.launch.remote/src/org/eclipse/cdt/launch/remote/messages.properties
@@ -0,0 +1,51 @@
+################################################################################
+# Copyright (c) 2006, 2009 Wind River Systems, Inc. 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:
+# Martin Oberhuber (Wind River) - externalized strings
+# Ewa Matejska (PalmSource) - [158783] browse button for cdt remote path
+# Johann Draschwandtner (Wind River) - [231827][remotecdt]Auto-compute default for Remote path
+# Anna Dushistova (MontaVista) - [244173][remotecdt][nls] Externalize Strings in RemoteRunLaunchDelegate
+# Anna Dushistova (MontaVista) - [181517][usability] Specify commands to be run before remote application launch
+# Nikita Shulga (EmbeddedAlley) - [265236][remotecdt] Wait for RSE to initialize before querying it for host list
+################################################################################
+
+# NLS_MESSAGEFORMAT_VAR
+# NLS_ENCODING=UTF-8
+
+RemoteRunLaunchDelegate_0=Launching
+RemoteRunLaunchDelegate_RemoteShell=Remote Shell
+RemoteRunLaunchDelegate_1=Unidentified mode {0} passed to RemoteRunLaunchDelegate
+RemoteRunLaunchDelegate_10=Initializing RSE
+RemoteRunLaunchDelegate_12=Starting Debugger
+RemoteRunLaunchDelegate_13=Could not find the remote connection.
+RemoteRunLaunchDelegate_2=Downloading
+RemoteRunLaunchDelegate_3=Wrong service requested.
+RemoteRunLaunchDelegate_4=No subsystem found.\n
+RemoteRunLaunchDelegate_5=Could not connect to the remote system.
+RemoteRunLaunchDelegate_6=Error during file upload.
+RemoteRunLaunchDelegate_7=Could not create the hostShellProcess.\n
+RemoteRunLaunchDelegate_8=Executing {0} {1}
+RemoteRunLaunchDelegate_9=Starting Program
+
+RemoteCMainTab_Prerun=Commands to execute before application
+RemoteCMainTab_Program=Remote Absolute File Path for C/C++ Application:
+RemoteCMainTab_SkipDownload=Skip download to target path.
+Remote_GDB_Debugger_Options=Remote GDB Debugger Options
+RemoteCMainTab_ErrorNoProgram=Remote executable path is not specified.
+RemoteCMainTab_ErrorNoConnection=Remote Connection must be selected.
+RemoteCMainTab_Remote_Path_Browse_Button=Browse...
+RemoteCMainTab_Connection=Connection:
+RemoteCMainTab_New=New...
+Gdbserver_Settings_Tab_Name=Gdbserver Settings
+Gdbserver_name_textfield_label=Gdbserver name:
+Port_number_textfield_label=Port number:
+RemoteCMainTab_Remote_Path_Browse_Button_Title=Select Remote C/C++ Application File
+RemoteCMainTab_Properties=Properties...
+RemoteCMainTab_Properties_title=Properties
+RemoteCMainTab_Properties_Location=Remote workspace location:
+RemoteCMainTab_Properties_Skip_default=Skip download to target path by default

Back to the top