### Eclipse Workspace Patch 1.0 #P org.eclipse.rse.services.telnet 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 18 May 2007 13:38:35 -0000 @@ -19,12 +19,18 @@ import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.io.PrintStream; import java.io.PrintWriter; +import java.util.Random; import java.util.regex.Pattern; import org.apache.commons.net.telnet.TelnetClient; +import org.eclipse.rse.core.model.IPropertySet; + +import org.eclipse.rse.internal.services.telnet.Activator; import org.eclipse.rse.internal.services.telnet.ITelnetSessionProvider; import org.eclipse.rse.services.clientserver.PathUtility; import org.eclipse.rse.services.shells.AbstractHostShell; @@ -39,15 +45,48 @@ private TelnetShellOutputReader fStdoutHandler; private TelnetShellOutputReader fStderrHandler; private TelnetShellWriterThread fShellWriter; + private TelnetClient thisShellsClient = null; + private String host; + private String password; + private String shellId = "Shell." + String.valueOf( new Random().nextInt() ); //$NON-NLS-1$ + private IPropertySet sessionProperties; + private InputStream in; + private PrintStream out; + + public static final String PROPERTY_SET_NAME = "Telnet Settings"; //$NON-NLS-1$ + public static final String PROPERTY_LOGIN_REQUIRED = "Login.Required"; //$NON-NLS-1$ + public static final String PROPERTY_LOGIN_PROMPT = "Login.Prompt"; //$NON-NLS-1$ + public static final String PROPERTY_PASSWORD_PROMPT = "Password.Prompt"; //$NON-NLS-1$ + public static final String PROPERTY_COMMAND_PROMPT = "Command.Prompt"; //$NON-NLS-1$ + private static final int ERROR_CODE = 100; // filed error code + private static final int SUCCESS_CODE = 150; // login pass code + private static final int CONNECT_CLOSED = 200; // code for end of login attempts public TelnetHostShell(ITelnetSessionProvider sessionProvider, String initialWorkingDirectory, String commandToRun, String encoding, String[] environment) { try { fSessionProvider = sessionProvider; + host = fSessionProvider.getSessionHostName(); + password = fSessionProvider.getSessionPassword(); + sessionProperties = fSessionProvider.getSessionPropertySet(); - - fStdoutHandler = new TelnetShellOutputReader(this, new BufferedReader(new InputStreamReader(sessionProvider.getTelnetClient().getInputStream())), false); + TelnetClient perShellClient = new TelnetClient(); + perShellClient.connect(host); + setThisShellsClient(perShellClient); + + + fSessionProvider.addShellsTelnetClient(perShellClient, getShellId() ); + + in = perShellClient.getInputStream(); + out = new PrintStream(perShellClient.getOutputStream()); + + LoginThread checkLogin = new LoginThread( fSessionProvider.getSessionUsername(), password); + checkLogin.start(); + checkLogin.join(); + int status = checkLogin.getLoginStatus(); + + fStdoutHandler = new TelnetShellOutputReader(this, new BufferedReader(new InputStreamReader(perShellClient.getInputStream())), false); fStderrHandler = new TelnetShellOutputReader(this, null,true); - OutputStream outputStream = sessionProvider.getTelnetClient().getOutputStream(); + OutputStream outputStream = perShellClient.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); @@ -76,22 +115,35 @@ } } + public String getShellId() { + return this.shellId; + } + public String getPromptCommand() { return "echo $PWD'>'"; //$NON-NLS-1$ } + private void setThisShellsClient( TelnetClient client) { + this.thisShellsClient = client; + } + + private TelnetClient getThisShellsClient( ) { + return this.thisShellsClient; + } + public void exit() { fShellWriter.stopThread(); 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(); + TelnetClient client = getThisShellsClient();//fSessionProvider.getTelnetClient(); if (client!=null) { synchronized(client) { if (client.isConnected()) client.disconnect(); } } + fSessionProvider.removeShellsTelnetClient( getShellId() ); } catch (IOException e) { } @@ -106,7 +158,7 @@ } public boolean isActive() { - TelnetClient client = fSessionProvider.getTelnetClient(); + TelnetClient client = getThisShellsClient();//fSessionProvider.getTelnetClient(); if (client!=null ) { return true; } @@ -136,5 +188,98 @@ } } + + /* + * A Login Thread to catch errors during login into telnet session + */ + + private class LoginThread extends Thread { + + private String user; + private String passwd; + private int status = SUCCESS_CODE; + + public LoginThread(String username, String password) { + this.user = username; + this.passwd = password; + } + + public void run() { + + String login_required = sessionProperties + .getPropertyValue(PROPERTY_LOGIN_REQUIRED); + String login_prompt = sessionProperties + .getPropertyValue(PROPERTY_LOGIN_PROMPT); + String password_prompt = sessionProperties + .getPropertyValue(PROPERTY_PASSWORD_PROMPT); + String command_prompt = sessionProperties + .getPropertyValue(PROPERTY_COMMAND_PROMPT); + + if (Boolean.valueOf(login_required).booleanValue()) { + status = SUCCESS_CODE; + if (login_prompt != null && login_prompt.length() > 0) { + status = readUntil(login_prompt); + write(user); + } + if (status == SUCCESS_CODE && password_prompt != null && password_prompt.length() > 0) { + status = readUntil(password_prompt); + write(passwd); + } + if (status == SUCCESS_CODE && command_prompt != null && command_prompt.length() > 0) { + status = readUntil(command_prompt); + } + } else { + if (command_prompt != null && command_prompt.length() > 0) { + status = readUntil(command_prompt); + } + } + } + + public int getLoginStatus() { + return this.status; + } + } + public int readUntil(String pattern) { + try { + char lastChar = pattern.charAt(pattern.length() - 1); + StringBuffer sb = new StringBuffer(); + int ch = in.read(); + while (ch >= 0) { + char tch = (char) ch; + if (Activator.isTracingOn()) + System.out.print(tch); + sb.append(tch); + if (tch=='t' && sb.indexOf("incorrect") >= 0) { //$NON-NLS-1$ + return ERROR_CODE; + } + if (tch=='d' && sb.indexOf("closed") >= 0) { //$NON-NLS-1$ + return CONNECT_CLOSED; + } + if (tch == lastChar) { + if (sb.toString().endsWith(pattern)) { + return SUCCESS_CODE; + } + } + ch = in.read(); + } + } catch (Exception e) { + } + return CONNECT_CLOSED; + } + + public void write(String value) { + try { + out.println(value); + out.flush(); + if (Activator.isTracingOn()) { + // Avoid printing password to stdout + // Activator.trace("write: "+value ); //$NON-NLS-1$ + int len = value.length() + 6; + Activator.trace("write: ******************".substring(0, len <= 24 ? len : 24)); //$NON-NLS-1$ + } + } catch (Exception e) { + e.printStackTrace(); + } + } } 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 18 May 2007 13:38:34 -0000 @@ -16,12 +16,26 @@ *******************************************************************************/ package org.eclipse.rse.internal.services.telnet; + import org.apache.commons.net.telnet.TelnetClient; +import org.eclipse.rse.core.model.IPropertySet; public interface ITelnetSessionProvider { public TelnetClient getTelnetClient(); + public void addShellsTelnetClient( TelnetClient client, String shellId ); + + public void removeShellsTelnetClient( String shellId ); + + public String getSessionHostName(); + + public String getSessionPassword(); + + public String getSessionUsername(); + + public IPropertySet getSessionPropertySet() ; + /* Inform the connectorService that a session has been lost. */ public void handleSessionLost(); } Index: src/org/eclipse/rse/internal/services/telnet/Activator.java =================================================================== RCS file: /cvsroot/dsdp/org.eclipse.tm.rse/plugins/org.eclipse.rse.services.telnet/src/org/eclipse/rse/internal/services/telnet/Activator.java,v retrieving revision 1.1 diff -u -r1.1 Activator.java --- src/org/eclipse/rse/internal/services/telnet/Activator.java 11 May 2007 09:28:26 -0000 1.1 +++ src/org/eclipse/rse/internal/services/telnet/Activator.java 18 May 2007 13:38:34 -0000 @@ -10,8 +10,13 @@ *******************************************************************************/ package org.eclipse.rse.internal.services.telnet; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.osgi.util.NLS; import org.eclipse.ui.plugin.AbstractUIPlugin; @@ -52,6 +57,38 @@ super.stop(context); } + private static Boolean fTracingOn = null; + public static boolean isTracingOn() { + if (fTracingOn==null) { + String id = plugin.getBundle().getSymbolicName(); + String val = Platform.getDebugOption(id + "/debug"); //$NON-NLS-1$ + if ("true".equals(val)) { //$NON-NLS-1$ + fTracingOn = Boolean.TRUE; + } else { + fTracingOn = Boolean.FALSE; + } + } + return fTracingOn.booleanValue(); + } + public static String getTimestamp() { + try { + DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //$NON-NLS-1$ + return formatter.format(new Date()); + } catch (Exception e) { + // If there were problems writing out the date, ignore and + // continue since that shouldn't stop us from logging the rest + // of the information + } + return Long.toString(System.currentTimeMillis()); + } + public static void trace(String msg) { + if (isTracingOn()) {Date + String fullMsg = getTimestamp() + " | " + Thread.currentThread().getName() + " | " + msg; //$NON-NLS-1$ //$NON-NLS-2$ + System.out.println(fullMsg); + System.out.flush(); + } + } + /** * Returns the shared instance * Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/dsdp/org.eclipse.tm.rse/plugins/org.eclipse.rse.services.telnet/META-INF/MANIFEST.MF,v retrieving revision 1.1 diff -u -r1.1 MANIFEST.MF --- META-INF/MANIFEST.MF 11 May 2007 09:28:26 -0000 1.1 +++ META-INF/MANIFEST.MF 18 May 2007 13:38:34 -0000 @@ -9,7 +9,8 @@ org.eclipse.core.runtime, org.eclipse.rse.services, org.apache.commons.net, - org.eclipse.rse.services.files.ftp + org.eclipse.rse.services.files.ftp, + org.eclipse.rse.core Export-Package: org.eclipse.rse.internal.services.telnet;x-friends:="org.eclipse.rse.connectorservice.telnet,org.eclipse.rse.subsystems.files.telnet,org.eclipse.rse.subsystems.shells.telnet", org.eclipse.rse.internal.services.telnet.shell;x-friends:="org.eclipse.rse.connectorservice.telnet,org.eclipse.rse.subsystems.shells.telnet" Eclipse-LazyStart: true #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 18 May 2007 13:38:37 -0000 @@ -13,13 +13,20 @@ * Martin Oberhuber (Wind River) - [178606] fix endless loop in readUntil() * 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() *******************************************************************************/ package org.eclipse.rse.internal.connectorservice.telnet; +import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; +import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Vector; import org.apache.commons.net.telnet.TelnetClient; import org.eclipse.core.runtime.IProgressMonitor; @@ -28,6 +35,7 @@ import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.rse.core.RSECorePlugin; +import org.eclipse.rse.core.SystemBasePlugin; import org.eclipse.rse.core.model.IHost; import org.eclipse.rse.core.model.IPropertySet; import org.eclipse.rse.core.model.ISystemRegistry; @@ -41,7 +49,6 @@ import org.eclipse.rse.services.clientserver.messages.SystemMessageException; import org.eclipse.rse.ui.ISystemMessages; import org.eclipse.rse.ui.RSEUIPlugin; -import org.eclipse.rse.ui.SystemBasePlugin; import org.eclipse.rse.ui.messages.SystemMessageDialog; import org.eclipse.rse.ui.subsystems.StandardConnectorService; import org.eclipse.swt.widgets.Display; @@ -57,13 +64,18 @@ public static final String PROPERTY_LOGIN_PROMPT = "Login.Prompt"; //$NON-NLS-1$ public static final String PROPERTY_PASSWORD_PROMPT = "Password.Prompt"; //$NON-NLS-1$ public static final String PROPERTY_COMMAND_PROMPT = "Command.Prompt"; //$NON-NLS-1$ - - private static final int TELNET_DEFAULT_PORT = 23; // TODO Make configurable + public static final String PROPERTY_TELNET_CONNECT_TIMEOUT = "Telnet.timeout"; //$NON-NLS-1$ private static final int TELNET_CONNECT_TIMEOUT = 60; //seconds - TODO: Make configurable + + private static final int TELNET_DEFAULT_PORT = 23; private TelnetClient fTelnetClient = new TelnetClient(); + private Map fTelnetShellClients = new HashMap(); + private Vector shellSessionId = new Vector(); private SessionLostHandler fSessionLostHandler; private InputStream in; private PrintStream out; + private String sessionHostName ; + private String sessionPassword; private IPropertySet telnetPropertySet = null; private static final int ERROR_CODE = 100; // filed error code private static final int SUCCESS_CODE = 150; // login pass code @@ -99,6 +111,9 @@ "assword: ", PropertyType.getStringPropertyType()); //$NON-NLS-1$ telnetSet.addProperty(PROPERTY_COMMAND_PROMPT, "$", PropertyType.getStringPropertyType()); //$NON-NLS-1$ + telnetSet.addProperty(PROPERTY_TELNET_CONNECT_TIMEOUT, + "60", PropertyType.getStringPropertyType()); //$NON-NLS-1$ + } return telnetSet; } @@ -112,6 +127,7 @@ String host = getHostName(); String user = getUserId(); String password = ""; //$NON-NLS-1$ + int status = ERROR_CODE; Exception nestedException = null; try { @@ -122,10 +138,15 @@ password = ssi.getPassword(); } + telnetPropertySet = getTelnetPropertySet(); + + String time_out = telnetPropertySet.getPropertyValue(PROPERTY_TELNET_CONNECT_TIMEOUT); + this.sessionHostName = host; + this.sessionPassword = password; in = fTelnetClient.getInputStream(); out = new PrintStream(fTelnetClient.getOutputStream()); - long millisToEnd = System.currentTimeMillis() + TELNET_CONNECT_TIMEOUT*1000; + long millisToEnd = System.currentTimeMillis() + Integer.valueOf( time_out ).intValue()*1000; LoginThread checkLogin = new LoginThread(user, password); checkLogin.start(); while (checkLogin.isAlive() && System.currentTimeMillis()