blob: 990c8347c18e36ca6bd7022cd1f822fbd680383f [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2008, 2018 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.RConsoleRJLaunchDelegate.TIMEOUT;
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.nico.core.runtime.IToolEventHandler.LOGIN_USERNAME_FORCE_DATA_KEY;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.filesystem.IFileStore;
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.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.variables.IStringVariable;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchPage;
import com.jcraft.jsch.Session;
import org.eclipse.statet.jcommons.rmi.RMIAddress;
import org.eclipse.statet.jcommons.rmi.RMIUtils;
import org.eclipse.statet.ecommons.debug.core.util.LaunchUtils;
import org.eclipse.statet.ecommons.debug.core.util.OverlayLaunchConfiguration;
import org.eclipse.statet.ecommons.debug.ui.util.UnterminatedLaunchAlerter;
import org.eclipse.statet.ecommons.io.FileValidator;
import org.eclipse.statet.ecommons.net.resourcemapping.core.IResourceMappingManager;
import org.eclipse.statet.ecommons.net.resourcemapping.core.ResourceMappingUtils;
import org.eclipse.statet.ecommons.preferences.core.Preference;
import org.eclipse.statet.ecommons.preferences.core.Preference.StringPref;
import org.eclipse.statet.ecommons.preferences.core.util.PreferenceUtils;
import org.eclipse.statet.ecommons.ui.util.UIAccess;
import org.eclipse.statet.ecommons.variables.core.StringVariable;
import org.eclipse.statet.internal.r.console.ui.Messages;
import org.eclipse.statet.internal.r.console.ui.RConsoleUIPlugin;
import org.eclipse.statet.nico.core.runtime.IRemoteEngineController;
import org.eclipse.statet.nico.core.runtime.IToolEventHandler;
import org.eclipse.statet.nico.core.runtime.Queue;
import org.eclipse.statet.nico.core.runtime.ToolController.IToolStatusListener;
import org.eclipse.statet.nico.core.runtime.ToolProcess;
import org.eclipse.statet.nico.core.runtime.ToolRunner;
import org.eclipse.statet.nico.core.runtime.ToolStatus;
import org.eclipse.statet.nico.core.util.HistoryTrackingConfiguration;
import org.eclipse.statet.nico.core.util.TrackingConfiguration;
import org.eclipse.statet.nico.ui.NicoUITools;
import org.eclipse.statet.nico.ui.console.NIConsoleColorAdapter;
import org.eclipse.statet.nico.ui.util.LoginHandler;
import org.eclipse.statet.nico.ui.util.WorkbenchStatusHandler;
import org.eclipse.statet.r.console.core.RProcess;
import org.eclipse.statet.r.console.ui.RConsole;
import org.eclipse.statet.r.console.ui.launching.AbstractRConsoleLaunchDelegate;
import org.eclipse.statet.r.console.ui.launching.RConsoleLaunching;
import org.eclipse.statet.r.core.renv.IREnvConfiguration;
import org.eclipse.statet.r.launching.RRunDebugPreferenceConstants;
import org.eclipse.statet.r.launching.core.ILaunchDelegateAddon;
import org.eclipse.statet.r.launching.core.RLaunching;
import org.eclipse.statet.r.launching.ui.REnvTab;
import org.eclipse.statet.r.nico.impl.RjsController;
import org.eclipse.statet.r.nico.impl.RjsController.RjsConnection;
import org.eclipse.statet.r.nico.impl.RjsUtil;
import org.eclipse.statet.rj.server.RjsComConfig;
import org.eclipse.statet.rj.server.Server;
/**
*
*
* TODO: externalize error message strings
*/
public class RRemoteConsoleLaunchDelegate extends AbstractRConsoleLaunchDelegate {
public static final int DEFAULT_SSH_PORT= 22;
public static final IStringVariable WD_VARIABLE= new StringVariable(RLaunching.WORKING_DIRECTORY_VARNAME, "The configured R working directory (converted to remote path)");
private static final Pattern WD_PATTERN= Pattern.compile("\\Q${"+RLaunching.WORKING_DIRECTORY_VARNAME+"}\\E"); //$NON-NLS-1$ //$NON-NLS-2$
public static final String ADDRESS_VARIABLE_NAME= "address"; //$NON-NLS-1$;
public static final IStringVariable ADDRESS_VARIABLE= new StringVariable(ADDRESS_VARIABLE_NAME, "The address of the remote R engine");
private static final Pattern ADDRESS_PATTERN= Pattern.compile("\\Q${"+ADDRESS_VARIABLE_NAME+"}\\E"); //$NON-NLS-1$ //$NON-NLS-2$
public static final String NAME_VARIABLE_NAME= "name"; //$NON-NLS-1$;
public static final IStringVariable NAME_VARIABLE= new StringVariable(NAME_VARIABLE_NAME, "The name of the remote R engine (last segment of the address)");
private static final Pattern NAME_PATTERN= Pattern.compile("\\Q${"+NAME_VARIABLE_NAME+"}\\E"); //$NON-NLS-1$ //$NON-NLS-2$
public static final String DEFAULT_COMMAND;
private static final Preference<String> DEFAULT_COMMAND_PATH= new StringPref(
RRunDebugPreferenceConstants.CAT_RREMOTE_LAUNCHING_QUALIFIER,
"rj.startupscript.path"); //$NON-NLS-1$
static {
String path= PreferenceUtils.getInstancePrefs().getPreferenceValue(DEFAULT_COMMAND_PATH);
if (path == null || path.isEmpty()) {
path= "~/.RJServer/startup.sh"; //$NON-NLS-1$
}
DEFAULT_COMMAND= path
+ " \"${"+ADDRESS_VARIABLE_NAME+"}\"" //$NON-NLS-1$ //$NON-NLS-2$
+ " -wd=\"${"+RLaunching.WORKING_DIRECTORY_VARNAME+"}\""; //$NON-NLS-1$ //$NON-NLS-2$
}
private static final int TODO_START_SERVER= 1;
private static final int TODO_SETUP_CONSOLE= 2;
private static final int TODO_CONNECT= 3;
private ILaunchDelegateAddon addon;
public RRemoteConsoleLaunchDelegate() {
}
public RRemoteConsoleLaunchDelegate(final ILaunchDelegateAddon addon) {
this.addon= addon;
}
@Override
public void launch(final ILaunchConfiguration configuration, final String mode, final ILaunch launch,
final IProgressMonitor monitor) throws CoreException {
try {
if (monitor.isCanceled()) {
return;
}
final String type= configuration.getAttribute(RConsoleLaunching.ATTR_TYPE, "").trim(); //$NON-NLS-1$
if (type.equals(RConsoleLaunching.REMOTE_RJS) || type.equals(RConsoleLaunching.REMOTE_RJS_SSH)) {
launchRjsJriRemote(configuration, mode, launch, monitor);
return;
}
if (type.equals(RConsoleLaunching.REMOTE_RJS_RECONNECT)) {
if (configuration.hasAttribute(IRemoteEngineController.LAUNCH_RECONNECT_ATTRIBUTE)) {
launchRjsJriRemote(configuration, mode, launch, monitor);
return;
}
final AtomicReference<String> address= new AtomicReference<>();
final String username= configuration.getAttribute(RConsoleLaunching.ATTR_LOGIN_NAME, (String) null);
UIAccess.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
final RRemoteConsoleSelectionDialog dialog= new RRemoteConsoleSelectionDialog(null, true);
dialog.setUser(username);
if (dialog.open() == Dialog.OK) {
address.set((String) dialog.getFirstResult());
}
}
});
if (address.get() != null) {
final Map<String, Object> map= new HashMap<>();
map.put(IRemoteEngineController.LAUNCH_RECONNECT_ATTRIBUTE, Collections.EMPTY_MAP);
map.put(RConsoleLaunching.ATTR_ADDRESS, address.get());
launchRjsJriRemote(new OverlayLaunchConfiguration(configuration, map), mode, launch, monitor);
return;
}
throw new CoreException(new Status(IStatus.CANCEL, RConsoleUIPlugin.BUNDLE_ID, ""));
}
throw new CoreException(new Status(IStatus.ERROR, RConsoleUIPlugin.BUNDLE_ID, 0,
NLS.bind("R Remote Console launch type ''{0}'' is not available.", type),
null ));
}
finally {
monitor.done();
}
}
private void launchRjsJriRemote(final ILaunchConfiguration configuration, final String mode, final ILaunch launch,
final IProgressMonitor monitor) throws CoreException {
final SubMonitor m= LaunchUtils.initProgressMonitor(configuration, monitor, 25);
final long timestamp= System.currentTimeMillis();
final IWorkbenchPage page= UIAccess.getActiveWorkbenchPage(false);
final String type= configuration.getAttribute(RConsoleLaunching.ATTR_TYPE, (String) null).trim();
final String username= configuration.getAttribute(RConsoleLaunching.ATTR_LOGIN_NAME, (String) null);
m.worked(1);
if (m.isCanceled()) {
return;
}
IREnvConfiguration rEnv= null;
try {
rEnv= RLaunching.getREnvConfig(configuration, false);
}
catch (final Exception e) {}
// load tracking configurations
final List<TrackingConfiguration> trackingConfigs;
{ final List<String> trackingIds= configuration.getAttribute(RConsoleOptionsTab.TRACKING_ENABLED_IDS, Collections.EMPTY_LIST);
trackingConfigs= new ArrayList<>(trackingIds.size());
for (final String id : trackingIds) {
final TrackingConfiguration trackingConfig;
if (id.equals(HistoryTrackingConfiguration.HISTORY_TRACKING_ID)) {
trackingConfig= new HistoryTrackingConfiguration(id);
}
else {
trackingConfig= new TrackingConfiguration(id);
}
RConsoleOptionsTab.TRACKING_UTIL.load(trackingConfig, configuration);
trackingConfigs.add(trackingConfig);
}
}
m.worked(1);
if (m.isCanceled()) {
return;
}
final Map reconnect= configuration.getAttribute(IRemoteEngineController.LAUNCH_RECONNECT_ATTRIBUTE, (Map) null);
final ToolProcess prevProcess;
boolean prevProcessDisposeFinally= true;
if (reconnect != null) {
prevProcess= (ToolProcess) reconnect.get("process"); //$NON-NLS-1$
}
else {
prevProcess= null;
}
m.worked(1);
if (m.isCanceled()) {
return;
}
try {
// r env
// REnvConfiguration renv= REnvTab.getREnv(configuration);
// renv.validate();
//
// progress.worked(1);
// if (monitor.isCanceled()) {
// return;
// }
// arguments
String address;
if (reconnect != null && reconnect.containsKey("address")) { //$NON-NLS-1$
address= (String) reconnect.get("address"); //$NON-NLS-1$
}
else {
address= configuration.getAttribute(RConsoleLaunching.ATTR_ADDRESS, (String) null);
}
if (address == null || address.isEmpty()) {
throw new CoreException(new Status(IStatus.ERROR, RConsoleUIPlugin.BUNDLE_ID, 0,
Messages.LaunchDelegate_error_MissingAddress_message, null ));
}
if (!(address.startsWith("//") || address.startsWith("rmi:"))) { //$NON-NLS-1$ //$NON-NLS-2$
address= "//" + address; //$NON-NLS-1$
}
// Working directory
final FileValidator validator= REnvTab.getWorkingDirectoryValidator(configuration, false);
final IFileStore workingDirectory= (validator.validate(null).getSeverity() != IStatus.ERROR) ?
validator.getFileStore() : null;
{ // Replace variable in address
final Matcher matcher= WD_PATTERN.matcher(address);
if (matcher.find()) {
if (workingDirectory == null) {
throw new CoreException(validator.getStatus());
}
address= matcher.replaceAll(workingDirectory.getName());
}
}
final boolean sshTunnel= configuration.getAttribute(RConsoleLaunching.ATTR_SSH_TUNNEL_ENABLED, false);
final Map<String, Object> connectionInfo= new HashMap<>();
RMIAddress rmiAddress= null;
RMIClientSocketFactory socketFactory= null;
Session sshSession= null;
int todo= TODO_START_SERVER;
Exception todoException= null;
Registry registry= null;
boolean registryOK= false;
try {
m.subTask(Messages.LaunchDelegate_CheckingRegistry_subtask);
rmiAddress= new RMIAddress(address);
// init login data
connectionInfo.put(LOGIN_USERNAME_DATA_KEY, username);
if (type.equals(RConsoleLaunching.REMOTE_RJS_SSH)) {
connectionInfo.put(LOGIN_USERNAME_FORCE_DATA_KEY, true);
}
final int sshPort= configuration.getAttribute(RConsoleLaunching.ATTR_SSH_PORT, DEFAULT_SSH_PORT);
connectionInfo.put(LOGIN_SSH_HOST_DATA_KEY, rmiAddress.getHostAddress().getHostAddress());
connectionInfo.put(LOGIN_SSH_PORT_DATA_KEY, Integer.valueOf(sshPort));
final Remote remote;
if (sshTunnel) {
connectionInfo.put("protocol", "ssh");
if (sshSession == null) {
sshSession= RjsUtil.getSession(connectionInfo, m.newChild(5));
}
socketFactory= RjsUtil.createRMIOverSshClientSocketFactory(sshSession);
RjsComConfig.setRMIClientSocketFactory(socketFactory);
registry= LocateRegistry.getRegistry("127.0.0.1", rmiAddress.getPort().get(), //$NON-NLS-1$
socketFactory );
remote= registry.lookup(rmiAddress.getName());
registryOK= true;
}
else {
RMIUtils.checkRegistryAccess(rmiAddress);
RjsComConfig.setRMIClientSocketFactory(null);
registry= LocateRegistry.getRegistry(rmiAddress.getHost(), rmiAddress.getPort().get(),
socketFactory );
remote= registry.lookup(rmiAddress.getName());
registryOK= true;
}
if (remote instanceof Server) {
final Server server= (Server) remote;
final int state= server.getState();
if (state <= Server.S_NOT_STARTED) {
todo= TODO_SETUP_CONSOLE;
if (reconnect != null) {
throw new CoreException(new Status(IStatus.ERROR, RConsoleUIPlugin.BUNDLE_ID, 0,
NLS.bind("Cannot reconnect, the R engine at ''{0}'' is not yet started.", address),
null ));
}
}
else if (state == Server.S_CONNECTED) {
todo= TODO_CONNECT;
if (reconnect != null) {
}
else {
final Shell shell= page.getWorkbenchWindow().getShell();
final Display display= UIAccess.getDisplay(shell);
final String msg= NLS.bind("It seems, a client is already connected to the remote R engine (''{0}'').\n Do you want to disconnect this client and connect to the engine?", address);
final AtomicBoolean force= new AtomicBoolean(false);
display.syncExec(new Runnable() {
@Override
public void run() {
force.set(MessageDialog.openQuestion(shell, "Connect", msg));
}
});
if (!force.get()) {
monitor.setCanceled(true);
throw new CoreException(Status.CANCEL_STATUS);
}
}
}
else if (state <= Server.S_LOST) {
todo= TODO_CONNECT;
}
else if (state == Server.S_STOPPED) {
if (reconnect != null) {
throw new CoreException(new Status(IStatus.ERROR, RConsoleUIPlugin.BUNDLE_ID, 0,
NLS.bind("Cannot reconnect, the R engine at ''{0}'' is terminated.", address),
null ));
}
todo= TODO_START_SERVER;
}
else {
throw new IllegalStateException("Server state: " + state);
}
}
}
catch (final UnknownHostException e) {
throw new CoreException(new Status(IStatus.ERROR, RConsoleUIPlugin.BUNDLE_ID, 0,
Messages.LaunchDelegate_error_InvalidAddress_message, e ));
}
catch (final MalformedURLException e) {
throw new CoreException(new Status(IStatus.ERROR, RConsoleUIPlugin.BUNDLE_ID, 0,
Messages.LaunchDelegate_error_InvalidAddress_message, e ));
}
catch (final RemoteException e) {
if (!registryOK) {
registry= null;
}
todoException= e;
todo= TODO_START_SERVER;
}
catch (final NotBoundException e) {
todoException= e;
todo= TODO_START_SERVER;
}
m.worked(5);
if (m.isCanceled()) {
return;
}
final String[] args= LaunchUtils.getProcessArguments(configuration, RConsoleLaunching.ATTR_OPTIONS);
if (reconnect != null) {
final Map<String, String> reconnectData= (Map<String, String>) reconnect.get("connectionInfo"); //$NON-NLS-1$
if (reconnectData != null) {
connectionInfo.putAll(reconnectData);
}
}
String command= null;
if (todo == TODO_START_SERVER) {
m.subTask(Messages.LaunchDelegate_StartREngine_subtask);
m.setWorkRemaining(21);
if (type.equals(RConsoleLaunching.REMOTE_RJS_SSH)) {
command= configuration.getAttribute(RConsoleLaunching.ATTR_COMMAND, ""); //$NON-NLS-1$
if (command.isEmpty()) {
throw new CoreException(new Status(IStatus.ERROR, RConsoleUIPlugin.BUNDLE_ID, 0,
"Command to startup R over SSH is missing.", null )); //$NON-NLS-1$
}
final Matcher addressMatcher= ADDRESS_PATTERN.matcher(command);
if (addressMatcher.find()) {
command= addressMatcher.replaceAll(rmiAddress.getAddress());
}
final Matcher nameMatcher= NAME_PATTERN.matcher(command);
if (nameMatcher.find()) {
command= nameMatcher.replaceAll(rmiAddress.getName());
}
final Matcher wdMatcher= WD_PATTERN.matcher(command);
if (wdMatcher.find()) {
if (workingDirectory == null) {
throw new CoreException(validator.getStatus());
}
final IResourceMappingManager rmManager= ResourceMappingUtils.getManager();
final IPath path= (rmManager != null) ? rmManager
.mapFileStoreToRemoteResource(rmiAddress.getHostAddress().getHostAddress(), workingDirectory) :
null;
if (path == null) {
throw new CoreException(new Status(IStatus.ERROR, RConsoleUIPlugin.BUNDLE_ID,
NLS.bind("Cannot resolve working directory ''{0}'' to remote path.", workingDirectory.toString()) ));
}
command= wdMatcher.replaceAll(path.toString());
}
final Hashtable<String, String> envp= new Hashtable<>();
envp.put("LC_ALL", "C"); //$NON-NLS-1$ //$NON-NLS-2$
envp.put("LANG", "C"); //$NON-NLS-1$ //$NON-NLS-2$
envp.put("LC_NUMERIC", "C"); //$NON-NLS-1$ //$NON-NLS-2$
RjsUtil.startRemoteServerOverSsh(RjsUtil.getSession(connectionInfo, m.newChild(5)), command, envp, m.newChild(5));
m.subTask(Messages.LaunchDelegate_WaitForR_subtask);
final long t= System.nanoTime();
WAIT: for (int i= 0; true; i++) {
if (m.isCanceled()) {
throw new CoreException(Status.CANCEL_STATUS);
}
try {
if (registry == null) {
if (sshTunnel) {
if (sshSession == null) {
sshSession= RjsUtil.getSession(connectionInfo, m.newChild(5));
}
if (socketFactory == null) {
socketFactory= RjsUtil.createRMIOverSshClientSocketFactory(sshSession);
}
registry= LocateRegistry.getRegistry("127.0.0.1", rmiAddress.getPort().get(), //$NON-NLS-1$
socketFactory );
}
else {
RMIUtils.checkRegistryAccess(rmiAddress);
registryOK= true;
registry= LocateRegistry.getRegistry(rmiAddress.getHost(), rmiAddress.getPort().get());
}
}
final String[] list= registry.list();
registryOK= true;
for (final String entry : list) {
if (entry.equals(rmiAddress.getName())) {
break WAIT;
}
}
if (i > 1 && System.nanoTime() - t > TIMEOUT) {
break WAIT;
}
}
catch (final RemoteException e) {
if (i > 0 && System.nanoTime() - t > TIMEOUT / 3) {
if (registry == null) {
RjsController.lookup(null, e, rmiAddress);
}
break WAIT;
}
if (!registryOK) {
registry= null;
}
}
try {
Thread.sleep(333);
}
catch (final InterruptedException e) {
// continue, monitor is checked
}
}
m.worked(5);
todo= TODO_SETUP_CONSOLE;
}
else {
if (reconnect != null) {
throw new CoreException(new Status(IStatus.ERROR, RConsoleUIPlugin.BUNDLE_ID, 0,
NLS.bind("Cannot reconnect to server, no R engine is available at ''{0}''.", address),
todoException ));
}
else {
throw new CoreException(new Status(IStatus.ERROR, RConsoleUIPlugin.BUNDLE_ID, 0,
NLS.bind("Cannot start or reconnect to server, to R engine at ''{0}''. You have to restart the server (manually or using SSH automation).", address),
todoException ));
}
}
}
final RjsConnection connection= RjsController.lookup(registry, null, rmiAddress);
// create process
UnterminatedLaunchAlerter.registerLaunchType(RConsoleLaunching.R_REMOTE_CONSOLE_CONFIGURATION_TYPE_ID);
final boolean startup= (todo == TODO_SETUP_CONSOLE);
final RProcess process= new RProcess(launch, rEnv,
LaunchUtils.createLaunchPrefix(configuration),
((rEnv != null) ? rEnv.getName() : "-") + " / RJ " + rmiAddress.toString() + ' ' + LaunchUtils.createProcessTimestamp(timestamp), //$NON-NLS-1$ //$NON-NLS-2$
rmiAddress.toString(),
(workingDirectory != null) ? workingDirectory.toString() : null,
timestamp );
process.setAttribute(IProcess.ATTR_CMDLINE, rmiAddress.toString() + '\n'
+ ((startup) ? Arrays.toString(args) : "rjs-reconnect")); //$NON-NLS-1$
final HashMap<String, Object> rjsProperties= new HashMap<>();
rjsProperties.put(RjsComConfig.RJ_DATA_STRUCTS_LISTS_MAX_LENGTH_PROPERTY_ID,
configuration.getAttribute(RConsoleLaunching.ATTR_OBJECTDB_LISTS_MAX_LENGTH, 10000));
rjsProperties.put(RjsComConfig.RJ_DATA_STRUCTS_ENVS_MAX_LENGTH_PROPERTY_ID,
configuration.getAttribute(RConsoleLaunching.ATTR_OBJECTDB_ENVS_MAX_LENGTH, 10000));
rjsProperties.put("rj.session.startup.time", timestamp); //$NON-NLS-1$
final RjsController controller= new RjsController(process, rmiAddress, connection, connectionInfo,
(startup) ? RjsController.RJS_SETUP_CONSOLE : 0, args, rjsProperties, null,
RConsoleRJLaunchDelegate.createWorkspaceConfig(configuration), trackingConfigs);
// move all tasks, if started
if (reconnect != null && prevProcess != null) {
controller.addToolStatusListener(new IToolStatusListener() {
@Override
public void controllerStatusChanged(final ToolStatus oldStatus, final ToolStatus newStatus, final List<DebugEvent> eventCollection) {
if (newStatus != ToolStatus.TERMINATED) {
final Queue prevQueue= prevProcess.getQueue();
prevQueue.moveAll(process.getQueue());
}
prevProcess.restartCompleted(reconnect);
controller.removeToolStatusListener(this);
}
});
}
process.init(controller);
RConsoleLaunching.registerDefaultHandlerTo(controller);
controller.addCommandHandler(IToolEventHandler.LOGIN_REQUEST_EVENT_ID, new LoginHandler());
m.worked(5);
RConsoleRJLaunchDelegate.initConsoleOptions(controller, rEnv, configuration, mode,
startup );
if (this.addon != null) {
this.addon.init(configuration, mode, controller, monitor);
}
final RConsole console= new RConsole(process, new NIConsoleColorAdapter());
NicoUITools.startConsoleLazy(console, page,
configuration.getAttribute(RConsoleLaunching.ATTR_PIN_CONSOLE, false));
// start
new ToolRunner().runInBackgroundThread(process, new WorkbenchStatusHandler());
prevProcessDisposeFinally= false;
}
finally {
RjsComConfig.clearRMIClientSocketFactory();
if (prevProcessDisposeFinally && reconnect != null && prevProcess != null) {
prevProcess.restartCompleted(reconnect);
}
}
}
}