### Eclipse Workspace Patch 1.0 #P org.eclipse.rse.services.telnet Index: src/org/eclipse/rse/internal/services/telnet/ITelnetSessionProvider.java =================================================================== RCS file: /cvsroot/dsdp/org.eclipse.tm.rse/plugins/org.eclipse.rse.services.telnet/src/org/eclipse/rse/internal/services/telnet/ITelnetSessionProvider.java,v retrieving revision 1.1 diff -u -r1.1 ITelnetSessionProvider.java --- src/org/eclipse/rse/internal/services/telnet/ITelnetSessionProvider.java 11 May 2007 09:28:26 -0000 1.1 +++ src/org/eclipse/rse/internal/services/telnet/ITelnetSessionProvider.java 26 Jun 2007 17:39:57 -0000 @@ -13,15 +13,21 @@ * * Contributors: * Sheldon D'souza (Celunite) - adapted from ISshSessionProvider + * Sheldon D'souza (Celunite) - [187301] support multiple telnet shells *******************************************************************************/ package org.eclipse.rse.internal.services.telnet; import org.apache.commons.net.telnet.TelnetClient; +import org.eclipse.core.runtime.IProgressMonitor; public interface ITelnetSessionProvider { - public TelnetClient getTelnetClient(); + /** + * Create a new Commons.Net TelnetClient. + * @param monitor progress monitor + * @return a new Commons.Net TelnetClient for the given connection, already authenticated + * @throws Exception in case of any error + */ + public TelnetClient makeNewTelnetClient(IProgressMonitor monitor) throws Exception ; - /* Inform the connectorService that a session has been lost. */ - public void handleSessionLost(); } Index: src/org/eclipse/rse/internal/services/telnet/shell/TelnetHostShell.java =================================================================== RCS file: /cvsroot/dsdp/org.eclipse.tm.rse/plugins/org.eclipse.rse.services.telnet/src/org/eclipse/rse/internal/services/telnet/shell/TelnetHostShell.java,v retrieving revision 1.2 diff -u -r1.2 TelnetHostShell.java --- src/org/eclipse/rse/internal/services/telnet/shell/TelnetHostShell.java 11 May 2007 13:30:48 -0000 1.2 +++ src/org/eclipse/rse/internal/services/telnet/shell/TelnetHostShell.java 26 Jun 2007 17:39:57 -0000 @@ -14,6 +14,7 @@ * Contributors: * Martin Oberhuber (Wind River) - Adapted from LocalHostShell. * Sheldon D'souza (Celunite) - Adapted from SshHostShell + * Sheldon D'souza (Celunite) - [187301] support multiple telnet shells *******************************************************************************/ package org.eclipse.rse.internal.services.telnet.shell; @@ -25,6 +26,7 @@ import java.util.regex.Pattern; import org.apache.commons.net.telnet.TelnetClient; +import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.rse.internal.services.telnet.ITelnetSessionProvider; import org.eclipse.rse.services.clientserver.PathUtility; import org.eclipse.rse.services.shells.AbstractHostShell; @@ -39,15 +41,17 @@ private TelnetShellOutputReader fStdoutHandler; private TelnetShellOutputReader fStderrHandler; private TelnetShellWriterThread fShellWriter; + private TelnetClient fTelnetClient; public TelnetHostShell(ITelnetSessionProvider sessionProvider, String initialWorkingDirectory, String commandToRun, String encoding, String[] environment) { try { fSessionProvider = sessionProvider; + fTelnetClient = fSessionProvider.makeNewTelnetClient(new NullProgressMonitor()); - fStdoutHandler = new TelnetShellOutputReader(this, new BufferedReader(new InputStreamReader(sessionProvider.getTelnetClient().getInputStream())), false); + fStdoutHandler = new TelnetShellOutputReader(this, new BufferedReader(new InputStreamReader(fTelnetClient.getInputStream())), false); fStderrHandler = new TelnetShellOutputReader(this, null,true); - OutputStream outputStream = sessionProvider.getTelnetClient().getOutputStream(); + OutputStream outputStream = fTelnetClient.getOutputStream(); //TODO check if encoding or command to execute needs to be considered //If a command is given, it might be possible to do without a Thread //Charset cs = Charset.forName(encoding); @@ -85,11 +89,10 @@ try { //TODO disconnect should better be done via the ConnectorService!! //Because like we do it here, the connector service is not notified! - TelnetClient client = fSessionProvider.getTelnetClient(); - if (client!=null) { - synchronized(client) { - if (client.isConnected()) - client.disconnect(); + if (fTelnetClient!=null) { + synchronized(fTelnetClient) { + if (fTelnetClient.isConnected()) + fTelnetClient.disconnect(); } } } catch (IOException e) { @@ -106,16 +109,18 @@ } public boolean isActive() { - TelnetClient client = fSessionProvider.getTelnetClient(); - if (client!=null ) { + if (fTelnetClient!=null && fTelnetClient.isConnected()) { return true; } // shell is not active: check for session lost exit(); - if (client!=null && !client.isConnected()) { - fSessionProvider.handleSessionLost(); - } + ////MOB: Telnet sessions are really independent of each other. + ////So if one telnet session disconnects, it must not disconnect + ////the other sessions. + //if (fTelnetClient!=null && !fTelnetClient.isConnected()) { + // fSessionProvider.handleSessionLost(); + //} return false; } #P org.eclipse.rse.connectorservice.telnet Index: src/org/eclipse/rse/internal/connectorservice/telnet/TelnetConnectorService.java =================================================================== RCS file: /cvsroot/dsdp/org.eclipse.tm.rse/plugins/org.eclipse.rse.connectorservice.telnet/src/org/eclipse/rse/internal/connectorservice/telnet/TelnetConnectorService.java,v retrieving revision 1.11 diff -u -r1.11 TelnetConnectorService.java --- src/org/eclipse/rse/internal/connectorservice/telnet/TelnetConnectorService.java 16 May 2007 15:52:44 -0000 1.11 +++ src/org/eclipse/rse/internal/connectorservice/telnet/TelnetConnectorService.java 26 Jun 2007 17:39:58 -0000 @@ -14,12 +14,17 @@ * Sheldon D'souza (Celunite) - [186536] login and password should be configurable * Sheldon D'souza (Celunite) - [186570] handle invalid user id and password more gracefully * Martin Oberhuber (Wind River) - [187218] Fix error reporting for connect() + * Sheldon D'souza (Celunite) - [187301] support multiple telnet shells *******************************************************************************/ package org.eclipse.rse.internal.connectorservice.telnet; +import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import org.apache.commons.net.telnet.TelnetClient; import org.eclipse.core.runtime.IProgressMonitor; @@ -60,7 +65,7 @@ private static final int TELNET_DEFAULT_PORT = 23; // TODO Make configurable private static final int TELNET_CONNECT_TIMEOUT = 60; //seconds - TODO: Make configurable - private TelnetClient fTelnetClient = new TelnetClient(); + private List fTelnetClients = new ArrayList(); private SessionLostHandler fSessionLostHandler; private InputStream in; private PrintStream out; @@ -109,6 +114,27 @@ } protected void internalConnect(IProgressMonitor monitor) throws Exception { + try { + TelnetClient client = makeNewTelnetClient(monitor); + if( client != null ) { + synchronized(this) { + fTelnetClients.add(client); + if (fSessionLostHandler==null) { + fSessionLostHandler = new SessionLostHandler(this); + } + } + notifyConnection(); + } + }catch( Exception e) { + if( e instanceof SystemMessageException ) { + internalDisconnect( null ); + throw e; + } + } + } + + public TelnetClient makeNewTelnetClient( IProgressMonitor monitor ) throws Exception { + TelnetClient client = new TelnetClient(); String host = getHostName(); String user = getUserId(); String password = ""; //$NON-NLS-1$ @@ -116,14 +142,14 @@ Exception nestedException = null; try { Activator.trace("Telnet Service: Connecting....."); //$NON-NLS-1$ - fTelnetClient.connect(host, TELNET_DEFAULT_PORT); + client.connect(host, TELNET_DEFAULT_PORT); SystemSignonInformation ssi = getSignonInformation(); if (ssi != null) { password = ssi.getPassword(); } - in = fTelnetClient.getInputStream(); - out = new PrintStream(fTelnetClient.getOutputStream()); + in = client.getInputStream(); + out = new PrintStream(client.getOutputStream()); long millisToEnd = System.currentTimeMillis() + TELNET_CONNECT_TIMEOUT*1000; LoginThread checkLogin = new LoginThread(user, password); @@ -156,10 +182,13 @@ } finally { if (status == CONNECT_CANCELED) { Activator.trace("Telnet Service: Canceled"); //$NON-NLS-1$ - sessionDisconnect(); //will eventually destroy the LoginThread + try { + client.disconnect(); //will eventually destroy the LoginThread + } catch(Exception e) { + /*ignore on forced disconnect*/ + } + client = null; } else if (status == SUCCESS_CODE) { - fSessionLostHandler = new SessionLostHandler(this); - notifyConnection(); Activator.trace("Telnet Service: Connected"); //$NON-NLS-1$ } else { Activator.trace("Telnet Service: Connect failed"); //$NON-NLS-1$ @@ -173,10 +202,10 @@ msg = RSEUIPlugin.getPluginMessage(ISystemMessages.MSG_COMM_AUTH_FAILED); msg.makeSubstitution(getHost().getAliasName()); } - internalDisconnect(null); throw new SystemMessageException(msg); } } + return client; } /** @@ -185,18 +214,20 @@ */ private synchronized void sessionDisconnect() { Activator.trace("TelnetConnectorService.sessionDisconnect"); //$NON-NLS-1$ - try { - if (fTelnetClient != null) { - synchronized (fTelnetClient) { - if (fTelnetClient.isConnected()) - fTelnetClient.disconnect(); + Iterator it = fTelnetClients.iterator(); + while (it.hasNext()) { + TelnetClient client = (TelnetClient)it.next(); + if (client.isConnected()) { + try { + client.disconnect(); + } catch(IOException e) { + // Avoid NPE on disconnect shown in UI + // This is a non-critical exception so print only in debug mode + if (Activator.isTracingOn()) + e.printStackTrace(); } } - } catch (Exception e) { - // Avoid NPE on disconnect shown in UI - // This is a non-critical exception so print only in debug mode - if (Activator.isTracingOn()) - e.printStackTrace(); + it.remove(); } } @@ -267,10 +298,6 @@ notifyDisconnection(); } - public TelnetClient getTelnetClient() { - return fTelnetClient; - } - /** * Handle session-lost events. This is generic for any sort of connector * service. Most of this is extracted from dstore's @@ -514,18 +541,6 @@ } } - /* - * Notification from sub-services that our session was lost. Notify all - * subsystems properly. - * TODO allow user to try and reconnect? - */ - public void handleSessionLost() { - Activator.trace("TelnetConnectorService: handleSessionLost"); //$NON-NLS-1$ - if (fSessionLostHandler != null) { - fSessionLostHandler.sessionLost(); - } - } - protected static Display getStandardDisplay() { Display display = Display.getCurrent(); if (display == null) { @@ -535,17 +550,23 @@ } public boolean isConnected() { - boolean connected = false; - if (fTelnetClient != null) { - synchronized (fTelnetClient) { - connected = fTelnetClient.isConnected(); + boolean anyConnected = false; + synchronized(this) { + Iterator it = fTelnetClients.iterator(); + while (it.hasNext()) { + TelnetClient client = (TelnetClient)it.next(); + if (client.isConnected()) { + anyConnected = true; + } else { + it.remove(); + } } } - if (!connected && fSessionLostHandler != null) { + if (!anyConnected && fSessionLostHandler != null) { Activator.trace("TelnetConnectorService.isConnected: false -> sessionLost"); //$NON-NLS-1$ fSessionLostHandler.sessionLost(); } - return connected; + return anyConnected; } /**