blob: be8e357135e6abc1709520fb691ecdbbb243b3c9 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2008, 2019 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.internal.r.console.ui.launching;
import static org.eclipse.statet.internal.r.console.ui.launching.RRemoteConsoleLaunchDelegate.DEFAULT_SSH_PORT;
import static org.eclipse.statet.nico.core.runtime.IToolEventHandler.LOGIN_SSH_HOST_DATA_KEY;
import static org.eclipse.statet.nico.core.runtime.IToolEventHandler.LOGIN_SSH_PORT_DATA_KEY;
import static org.eclipse.statet.nico.core.runtime.IToolEventHandler.LOGIN_USERNAME_DATA_KEY;
import static org.eclipse.statet.r.console.ui.launching.RConsoleLaunching.REMOTE_RJS;
import static org.eclipse.statet.r.console.ui.launching.RConsoleLaunching.REMOTE_RJS_RECONNECT;
import static org.eclipse.statet.r.console.ui.launching.RConsoleLaunching.REMOTE_RJS_SSH;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.rmi.server.RMIClientSocketFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.IValueChangeListener;
import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.core.databinding.validation.MultiValidator;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.variables.IStringVariable;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.ui.StringVariableSelectionDialog;
import org.eclipse.jface.databinding.swt.typed.WidgetProperties;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import com.jcraft.jsch.Session;
import org.eclipse.statet.jcommons.rmi.RMIAddress;
import org.eclipse.statet.ecommons.databinding.core.validation.IntegerValidator;
import org.eclipse.statet.ecommons.ui.components.WidgetToolsButton;
import org.eclipse.statet.ecommons.ui.dialogs.DialogUtils;
import org.eclipse.statet.ecommons.ui.util.LayoutUtils;
import org.eclipse.statet.ecommons.ui.util.UIAccess;
import org.eclipse.statet.internal.r.console.ui.launching.RRemoteConsoleSelectionDialog.SpecialAddress;
import org.eclipse.statet.r.console.ui.IRConsoleHelpContextIds;
import org.eclipse.statet.r.console.ui.launching.RConsoleLaunching;
import org.eclipse.statet.r.nico.impl.RjsUtil;
public class RRemoteConsoleMainTab extends RConsoleMainTab {
private class UpdateJob extends Job implements IValueChangeListener<Object> {
private String user;
private String address;
private Integer sshPort;
public UpdateJob() {
super("Background Update for RRemoteConsoleMainTab");
setSystem(true);
setPriority(SHORT);
}
@Override
protected IStatus run(final IProgressMonitor monitor) {
final StringBuilder sb= new StringBuilder();
sb.setLength(0);
sb.append(this.user);
sb.append('@');
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
try {
final RMIAddress rmiAddress= new RMIAddress(this.address);
sb.append(rmiAddress.getHostAddress().getHostAddress());
}
catch (final UnknownHostException e) {
sb.append("<unknown>");
}
catch (final Exception e) {
}
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
final Integer port= this.sshPort;
if (port != null && port.intValue() != DEFAULT_SSH_PORT) {
sb.append(':');
sb.append(port.toString());
}
final String s= sb.toString();
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
RRemoteConsoleMainTab.this.sshAddressValue.getRealm().asyncExec(new Runnable() {
@Override
public void run() {
RRemoteConsoleMainTab.this.sshAddressValue.setValue(s);
}
});
return Status.OK_STATUS;
}
@Override
public void handleValueChange(final ValueChangeEvent<?> event) {
cancel();
this.user= RRemoteConsoleMainTab.this.userValue.getValue();
this.address= RRemoteConsoleMainTab.this.addressValue.getValue();
this.sshPort= RRemoteConsoleMainTab.this.sshPortValue.getValue();
schedule(100);
}
}
private final IObservableValue<String> addressValue;
private final IObservableValue<String> userValue;
private final IObservableValue<Integer> sshPortValue;
private final IObservableValue<Boolean> sshTunnelValue;
private final IObservableValue<String> commandValue;
private final IObservableValue<String> sshAddressValue;
private Text addressControl;
private List<Control> addressControls;
private RRemoteConsoleSelectionDialog remoteEngineSelectionDialog;
private Text usernameControl;
private List <Control> loginControls;
private Label usernameInfo;
private Text sshPortControl;
private Text sshAddress;
private Button sshTunnelControl;
private List<Control> sshControls;
private Text commandControl;
private List<Control> commandControls;
private UpdateJob updateJob;
public RRemoteConsoleMainTab() {
final Realm realm= getRealm();
this.addressValue= new WritableValue<>(realm, "", String.class); //$NON-NLS-1$
this.userValue= new WritableValue<>(realm, "", String.class); //$NON-NLS-1$
this.sshPortValue= new WritableValue<>(realm, null, Integer.class);
this.sshTunnelValue= new WritableValue<>(realm, false, Boolean.TYPE);
this.commandValue= new WritableValue<>(realm, "", String.class); //$NON-NLS-1$
this.sshAddressValue= new WritableValue<>(realm, "", String.class); //$NON-NLS-1$
}
@Override
protected RConsoleType[] loadTypes() {
final List<RConsoleType> types= new ArrayList<>();
types.add(new RConsoleType("RJ (RMI/JRI) - Manual", REMOTE_RJS, false, true, false));
types.add(new RConsoleType("RJ (RMI/JRI) - Start over SSH", REMOTE_RJS_SSH, false, true, false));
types.add(new RConsoleType("RJ (RMI/JRI) - Quick Reconnect", REMOTE_RJS_RECONNECT, false, true, false));
return types.toArray(new RConsoleType[types.size()]);
}
@Override
public void createControl(final Composite parent) {
this.updateJob= new UpdateJob();
super.createControl(parent);
PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
IRConsoleHelpContextIds.R_REMOTE_CONSOLE_LAUNCH);
}
@Override
public void dispose() {
super.dispose();
if (this.updateJob != null) {
this.updateJob.cancel();
this.updateJob= null;
}
}
@Override
protected Composite createTypeDetailGroup(final Composite parent) {
final Group group= new Group(parent, SWT.NONE);
group.setLayout(LayoutUtils.newGroupGrid(4));
group.setText("Connection:");
this.addressControls= new ArrayList<>(8);
this.loginControls= new ArrayList<>(8);
this.sshControls= new ArrayList<>(8);
this.commandControls= new ArrayList<>(8);
{ // Address:
final Label label= new Label(group, SWT.NONE);
label.setText("&Address: ");
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
final Composite composite= new Composite(group, SWT.NONE);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1));
composite.setLayout(LayoutUtils.newCompositeGrid(2));
this.addressControl= new Text(composite, SWT.LEFT | SWT.BORDER);
this.addressControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
final Button addressButton= new Button(composite, SWT.PUSH);
addressButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
addressButton.setText("Browse...");
addressButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent event) {
final boolean newDialog= (RRemoteConsoleMainTab.this.remoteEngineSelectionDialog == null);
if (newDialog) {
RRemoteConsoleMainTab.this.remoteEngineSelectionDialog= new RRemoteConsoleSelectionDialog(getShell(), false);
}
else {
RRemoteConsoleMainTab.this.remoteEngineSelectionDialog.clearAdditionaAddress(true);
}
String userName= RRemoteConsoleMainTab.this.userValue.getValue();
if (userName != null && userName.isEmpty()) {
userName= null;
}
final String text= RRemoteConsoleMainTab.this.addressControl.getText();
if (text.length() > 0) {
try {
final RMIAddress rmiAddress= new RMIAddress(text);
final StringBuilder sb= new StringBuilder();
sb.append(rmiAddress.getHost());
if (rmiAddress.getPort() != RMIAddress.DEFAULT_PORT) {
sb.append(':').append(rmiAddress.getPort());
}
final String address= sb.toString();
RRemoteConsoleMainTab.this.remoteEngineSelectionDialog.addAdditionalAddress(address, null);
if (newDialog) {
RRemoteConsoleMainTab.this.remoteEngineSelectionDialog.setInitialAddress(address);
}
if (RRemoteConsoleMainTab.this.sshTunnelControl.isEnabled() && RRemoteConsoleMainTab.this.sshTunnelControl.getSelection()
&& userName != null) {
final Map<String, Object> loginData= new HashMap<>();
loginData.put(LOGIN_SSH_HOST_DATA_KEY, rmiAddress.getHost());
final Object sshPort= RRemoteConsoleMainTab.this.sshPortValue.getValue();
loginData.put(LOGIN_SSH_PORT_DATA_KEY, (sshPort instanceof Integer) ?
((Integer) sshPort).intValue() : DEFAULT_SSH_PORT );
loginData.put(LOGIN_USERNAME_DATA_KEY, userName);
final SpecialAddress special= new SpecialAddress(
rmiAddress, "127.0.0.1" ) {
@Override
public RMIClientSocketFactory getSocketFactory(
final IProgressMonitor monitor) throws CoreException {
final Session session= RjsUtil.getSession(loginData, monitor);
return RjsUtil.createRMIOverSshClientSocketFactory(session);
}
};
final String label= rmiAddress.getHost() + " through SSH tunnel";
RRemoteConsoleMainTab.this.remoteEngineSelectionDialog.addAdditionalAddress(label, special);
RRemoteConsoleMainTab.this.remoteEngineSelectionDialog.setInitialAddress(label);
}
}
catch (final Exception e) {}
}
RRemoteConsoleMainTab.this.remoteEngineSelectionDialog.setUser(userName);
if (RRemoteConsoleMainTab.this.remoteEngineSelectionDialog.open() == Dialog.OK) {
final String result= (String) RRemoteConsoleMainTab.this.remoteEngineSelectionDialog.getFirstResult();
RRemoteConsoleMainTab.this.addressValue.setValue(result);
}
}
});
this.addressControls.add(label);
this.addressControls.add(composite);
}
{ // Username:
{ final Label label= new Label(group, SWT.NONE);
label.setText("&Username: ");
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
final Composite composite= new Composite(group, SWT.NONE);
composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
composite.setLayout(LayoutUtils.newCompositeGrid(2));
this.usernameControl= new Text(composite, SWT.LEFT | SWT.BORDER);
final GridData gd= new GridData(SWT.FILL, SWT.CENTER, false, false);
gd.widthHint= gd.minimumWidth= LayoutUtils.hintWidth(this.usernameControl, 20);
this.usernameControl.setLayoutData(gd);
this.usernameInfo= new Label(composite, SWT.LEFT);
this.usernameInfo.setText("");
this.usernameInfo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
this.loginControls.add(label);
this.loginControls.add(this.usernameControl);
this.loginControls.add(this.usernameInfo);
}
{ final Label label= new Label(group, SWT.NONE);
label.setText("&SSH Port: ");
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
this.sshPortControl= new Text(group, SWT.LEFT | SWT.BORDER);
final GridData gd= new GridData(SWT.LEFT, SWT.CENTER, true, false);
gd.widthHint= LayoutUtils.hintWidth(this.sshPortControl, 6);
this.sshPortControl.setLayoutData(gd);
this.sshControls.add(label);
this.sshControls.add(this.sshPortControl);
}
}
{ // Ext SSH:
{ final Label label= new Label(group, SWT.NONE);
label.setText("SSH Options: ");
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
this.sshTunnelControl= new Button(group, SWT.CHECK);
this.sshTunnelControl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
this.sshTunnelControl.setText("&Tunnel connections to R engine through SSH");
this.sshControls.add(label);
this.sshControls.add(this.sshTunnelControl);
}
{ final Label label= new Label(group, SWT.LEFT);
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
label.setText("SSH Address:");
this.sshAddress= new Text(group, SWT.LEFT | SWT.BORDER);
this.sshAddress.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
this.sshAddress.setEditable(false);
this.sshControls.add(label);
this.sshControls.add(this.sshAddress);
}
}
{ // Remote Command:
final Label label= new Label(group, SWT.NONE);
label.setText("Re&mote Command: ");
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
final Composite composite= new Composite(group, SWT.NONE);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1));
composite.setLayout(LayoutUtils.newCompositeGrid(2));
this.commandControl= new Text(composite, SWT.LEFT | SWT.BORDER);
this.commandControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
final WidgetToolsButton toolsButton= new WidgetToolsButton(this.commandControl) {
@Override
protected void fillMenu(final Menu menu) {
final MenuItem item= new MenuItem(menu, SWT.PUSH);
item.setText("Insert &Variable...");
item.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final StringVariableSelectionDialog dialog= new StringVariableSelectionDialog(getShell()) {
@Override
public void setElements(final Object[] elements) {
super.setElements(new IStringVariable[] {
RRemoteConsoleLaunchDelegate.ADDRESS_VARIABLE,
RRemoteConsoleLaunchDelegate.NAME_VARIABLE,
RRemoteConsoleLaunchDelegate.WD_VARIABLE,
});
}
};
if (dialog.open() != Dialog.OK) {
return;
}
final String variable= dialog.getVariableExpression();
if (variable == null) {
return;
}
RRemoteConsoleMainTab.this.commandControl.insert(variable);
RRemoteConsoleMainTab.this.commandControl.setFocus();
}
});
}
};
toolsButton.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1));
this.commandControls.add(label);
this.commandControls.add(this.commandControl);
this.commandControls.add(toolsButton);
}
return group;
}
@Override
protected void createFooter(final Composite composite) {
final Link link= new Link(composite, SWT.NONE);
link.setText("Global preferences: "
+ "<a href=\"org.eclipse.statet.nico.preferencePages.ResourceMappings\">Folder Mapping</a>, "
+ "<a href=\"org.eclipse.jsch.ui.SSHPreferences\">SSH2 Options (Key Management)</a>.");
composite.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, false));
link.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final PreferenceDialog dialog= org.eclipse.ui.dialogs.PreferencesUtil.createPreferenceDialogOn(null, e.text, null, null);
if (dialog != null) {
dialog.open();
}
}
});
super.createFooter(composite);
}
@Override
protected void addBindings(final DataBindingContext dbc, final Realm realm) {
super.addBindings(dbc, realm);
final MultiValidator validator= new MultiValidator() {
@Override
protected IStatus validate() {
// Calculate the validation status
if (!getType().getId().equals(REMOTE_RJS_RECONNECT)) {
final String text= RRemoteConsoleMainTab.this.addressValue.getValue();
if (text == null || text.isEmpty()) {
return ValidationStatus.error("Missing address for R remote engine ('//host[:port]/rsessionname').");
}
try {
RMIAddress.validate(text);
}
catch (final MalformedURLException e) {
return ValidationStatus.error("Invalid address for R remote engine: "+e.getLocalizedMessage());
}
}
return ValidationStatus.ok();
}
};
final WritableValue<String> addressValue1= new WritableValue<>("", String.class); //$NON-NLS-1$
dbc.bindValue(
WidgetProperties.text(SWT.Modify)
.observe(this.addressControl),
addressValue1 );
validator.observeValidatedValue(addressValue1);
dbc.bindValue(
addressValue1,
this.addressValue );
dbc.bindValue(
WidgetProperties.text(SWT.Modify)
.observe(this.usernameControl),
this.userValue );
dbc.bindValue(
WidgetProperties.text(SWT.Modify)
.observe(this.sshPortControl),
this.sshPortValue,
new UpdateValueStrategy<String, Integer>()
.setAfterGetValidator(new IntegerValidator(0, 65535, true,
"Invalid SSH port number specified (0-65535)." )),
null );
dbc.bindValue(
WidgetProperties.buttonSelection()
.observe(this.sshTunnelControl),
this.sshTunnelValue );
dbc.bindValue(
WidgetProperties.text(SWT.Modify)
.observe(this.commandControl),
this.commandValue );
dbc.bindValue(
WidgetProperties.text(SWT.Modify)
.observe(this.sshAddress),
this.sshAddressValue );
this.addressValue.addValueChangeListener(this.updateJob);
this.userValue.addValueChangeListener(this.updateJob);
this.sshPortValue.addValueChangeListener(this.updateJob);
dbc.addValidationStatusProvider(validator);
validator.observeValidatedValue(getTypeValue());
}
@Override
protected void updateType(final RConsoleType type) {
if (REMOTE_RJS.equals(type.getId())) {
DialogUtils.setEnabled(this.addressControls, null, true);
DialogUtils.setEnabled(getArgumentComposite(), null, true);
DialogUtils.setEnabled(this.loginControls, null, true);
this.usernameInfo.setText("(optional)");
DialogUtils.setVisible(this.sshControls, null, true);
DialogUtils.setVisible(this.commandControls, null, false);
}
else if (REMOTE_RJS_SSH.equals(type.getId())) {
DialogUtils.setEnabled(this.addressControls, null, true);
DialogUtils.setEnabled(getArgumentComposite(), null, true);
DialogUtils.setEnabled(this.loginControls, null, true);
this.usernameInfo.setText("(required)");
DialogUtils.setVisible(this.sshControls, null, true);
DialogUtils.setVisible(this.commandControls, null, true);
UIAccess.getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
if (RRemoteConsoleMainTab.this.userValue.getValue() == null || RRemoteConsoleMainTab.this.userValue.getValue().isEmpty()) {
RRemoteConsoleMainTab.this.userValue.setValue(System.getProperty("user.name"));
}
if (RRemoteConsoleMainTab.this.sshPortValue.getValue() == null) {
RRemoteConsoleMainTab.this.sshPortValue.setValue(22);
}
if (RRemoteConsoleMainTab.this.commandValue.getValue() == null || RRemoteConsoleMainTab.this.commandValue.getValue().isEmpty()) {
RRemoteConsoleMainTab.this.commandValue.setValue(RRemoteConsoleLaunchDelegate.DEFAULT_COMMAND);
}
}
});
}
else {
DialogUtils.setEnabled(this.addressControls, null, false);
DialogUtils.setEnabled(getArgumentComposite(), null, false);
DialogUtils.setEnabled(this.loginControls, null, true);
this.usernameInfo.setText("");
DialogUtils.setVisible(this.sshControls, null, false);
DialogUtils.setVisible(this.commandControls, null, false);
}
}
@Override
public void setDefaults(final ILaunchConfigurationWorkingCopy configuration) {
super.setDefaults(configuration);
configuration.setAttribute(RConsoleLaunching.ATTR_ADDRESS, "//host/rsessionname"); //$NON-NLS-1$
}
@Override
protected void doInitialize(final ILaunchConfiguration configuration) {
super.doInitialize(configuration);
this.addressValue.setValue(readAttribute(configuration,
RConsoleLaunching.ATTR_ADDRESS,
"" )); //$NON-NLS-1$
this.userValue.setValue(readAttribute(configuration,
RConsoleLaunching.ATTR_LOGIN_NAME,
"" )); //$NON-NLS-1$
this.sshPortValue.setValue(readAttribute(configuration,
RConsoleLaunching.ATTR_SSH_PORT,
DEFAULT_SSH_PORT ));
this.sshTunnelValue.setValue(readAttribute(configuration,
RConsoleLaunching.ATTR_SSH_TUNNEL_ENABLED,
false ));
this.commandValue.setValue(readAttribute(configuration,
RConsoleLaunching.ATTR_COMMAND,
"" ));
}
@Override
protected void doSave(final ILaunchConfigurationWorkingCopy configuration) {
super.doSave(configuration);
if (this.addressControl.isEnabled()) {
configuration.setAttribute(RConsoleLaunching.ATTR_ADDRESS, this.addressValue.getValue());
}
else {
configuration.removeAttribute(RConsoleLaunching.ATTR_ADDRESS);
}
final String user= this.userValue.getValue();
if (user != null && user.length() > 0) {
configuration.setAttribute(RConsoleLaunching.ATTR_LOGIN_NAME, user);
}
else {
configuration.removeAttribute(RConsoleLaunching.ATTR_LOGIN_NAME);
}
final Integer port= this.sshPortValue.getValue();
if (!getType().getId().equals(REMOTE_RJS_RECONNECT) && port != null) {
configuration.setAttribute(RConsoleLaunching.ATTR_SSH_PORT, port.intValue());
}
else {
configuration.removeAttribute(RConsoleLaunching.ATTR_SSH_PORT);
}
final Boolean tunnel= this.sshTunnelValue.getValue();
if (!getType().getId().equals(REMOTE_RJS_RECONNECT) && tunnel != null) {
configuration.setAttribute(RConsoleLaunching.ATTR_SSH_TUNNEL_ENABLED, tunnel.booleanValue());
}
else {
configuration.removeAttribute(RConsoleLaunching.ATTR_SSH_TUNNEL_ENABLED);
}
final String command= this.commandValue.getValue();
if (getType().getId().equals(REMOTE_RJS_SSH) && command != null) {
configuration.setAttribute(RConsoleLaunching.ATTR_COMMAND, command);
}
else {
configuration.removeAttribute(RConsoleLaunching.ATTR_COMMAND);
}
}
}