diff --git a/rse/plugins/org.eclipse.rse.connectorservice.telnet/src/org/eclipse/rse/internal/connectorservice/telnet/TelnetConnectorService.java b/rse/plugins/org.eclipse.rse.connectorservice.telnet/src/org/eclipse/rse/internal/connectorservice/telnet/TelnetConnectorService.java index fb4096a572f..ee49e03728e 100644 --- a/rse/plugins/org.eclipse.rse.connectorservice.telnet/src/org/eclipse/rse/internal/connectorservice/telnet/TelnetConnectorService.java +++ b/rse/plugins/org.eclipse.rse.connectorservice.telnet/src/org/eclipse/rse/internal/connectorservice/telnet/TelnetConnectorService.java @@ -7,18 +7,19 @@ * * Contributors: * Martin Oberhuber (Wind River) - initial API and implementation - * David Dykstal (IBM) - 168977: refactoring IConnectorService and ServerLauncher hierarchies - * Sheldon D'souza (Celunite) - adapted from SshConnectorService + * David Dykstal (IBM) - [168977] refactoring IConnectorService and ServerLauncher hierarchies + * Sheldon D'souza (Celunite) - adapted from SshConnectorService * Martin Oberhuber (Wind River) - apply refactorings for StandardConnectorService * 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 + * 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 - * Sheldon D'souza (Celunite) - [194464] fix create multiple telnet shells quickly + * Sheldon D'souza (Celunite) - [187301] support multiple telnet shells + * Sheldon D'souza (Celunite) - [194464] fix create multiple telnet shells quickly * Martin Oberhuber (Wind River) - [186761] make the port setting configurable * David McKnight (IBM) - [216252] [api][nls] Resource Strings specific to subsystems should be moved from rse.ui into files.ui / shells.ui / processes.ui where possible * David McKnight (IBM) - [220547] [api][breaking] SimpleSystemMessage needs to specify a message id and some messages should be shared + * Anna Dushistova (MontaVista) - [240523] [rseterminals] Provide a generic adapter factory that adapts any ITerminalService to an IShellService *******************************************************************************/ package org.eclipse.rse.internal.connectorservice.telnet; @@ -148,8 +149,12 @@ public class TelnetConnectorService extends StandardConnectorService implements return port; } - public TelnetClient makeNewTelnetClient( IProgressMonitor monitor ) throws Exception { + public TelnetClient makeNewTelnetClient(IProgressMonitor monitor ) throws Exception { TelnetClient client = new TelnetClient(); + return makeNewTelnetClient(client, monitor); + } + + public TelnetClient makeNewTelnetClient(TelnetClient client, IProgressMonitor monitor ) throws Exception { String host = getHostName(); String user = getUserId(); String password = ""; //$NON-NLS-1$ diff --git a/rse/plugins/org.eclipse.rse.services.telnet/META-INF/MANIFEST.MF b/rse/plugins/org.eclipse.rse.services.telnet/META-INF/MANIFEST.MF index 89d91d09b6e..62eab588b42 100644 --- a/rse/plugins/org.eclipse.rse.services.telnet/META-INF/MANIFEST.MF +++ b/rse/plugins/org.eclipse.rse.services.telnet/META-INF/MANIFEST.MF @@ -2,14 +2,15 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.rse.services.telnet -Bundle-Version: 1.1.100.qualifier +Bundle-Version: 1.2.0.qualifier Bundle-Activator: org.eclipse.rse.internal.services.telnet.Activator Bundle-Localization: plugin Require-Bundle: org.eclipse.core.runtime, org.eclipse.rse.services;bundle-version="[3.0.0,4.0.0)", org.apache.commons.net;bundle-version="[1.4.1,2.0.0)" 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" + org.eclipse.rse.internal.services.telnet.shell;x-friends:="org.eclipse.rse.connectorservice.telnet,org.eclipse.rse.subsystems.shells.telnet", + org.eclipse.rse.internal.services.telnet.terminal;x-friends:="org.eclipse.rse.subsystems.shells.telnet" Bundle-ActivationPolicy: lazy Eclipse-LazyStart: true Bundle-Vendor: %providerName diff --git a/rse/plugins/org.eclipse.rse.services.telnet/src/org/eclipse/rse/internal/services/telnet/ITelnetSessionProvider.java b/rse/plugins/org.eclipse.rse.services.telnet/src/org/eclipse/rse/internal/services/telnet/ITelnetSessionProvider.java index f17909a5780..c22e327d49b 100644 --- a/rse/plugins/org.eclipse.rse.services.telnet/src/org/eclipse/rse/internal/services/telnet/ITelnetSessionProvider.java +++ b/rse/plugins/org.eclipse.rse.services.telnet/src/org/eclipse/rse/internal/services/telnet/ITelnetSessionProvider.java @@ -12,8 +12,9 @@ * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. * * Contributors: - * Sheldon D'souza (Celunite) - adapted from ISshSessionProvider - * Sheldon D'souza (Celunite) - [187301] support multiple telnet shells + * Sheldon D'souza (Celunite) - adapted from ISshSessionProvider + * Sheldon D'souza (Celunite) - [187301] support multiple telnet shells + * Anna Dushistova (MontaVista) - [240523] [rseterminals] Provide a generic adapter factory that adapts any ITerminalService to an IShellService *******************************************************************************/ package org.eclipse.rse.internal.services.telnet; @@ -29,5 +30,14 @@ public interface ITelnetSessionProvider { * @throws Exception in case of any error */ public TelnetClient makeNewTelnetClient(IProgressMonitor monitor) throws Exception ; + + /** + * Initialize a new Commons.Net TelnetClient with a given ptyType. + * @param client telnet client already created + * @param monitor progress monitor + * @return authenticated client for the given connection + * @throws Exception in case of any error + */ + public TelnetClient makeNewTelnetClient(TelnetClient client, IProgressMonitor monitor) throws Exception ; } diff --git a/rse/plugins/org.eclipse.rse.services.telnet/src/org/eclipse/rse/internal/services/telnet/terminal/EOFDetectingInputStreamWrapper.java b/rse/plugins/org.eclipse.rse.services.telnet/src/org/eclipse/rse/internal/services/telnet/terminal/EOFDetectingInputStreamWrapper.java new file mode 100644 index 00000000000..7e63d744d11 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.services.telnet/src/org/eclipse/rse/internal/services/telnet/terminal/EOFDetectingInputStreamWrapper.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2008 MontaVista Software, 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: + * Anna Dushistova (MontaVista) - initial API and implementation + * Martin Oberhuber (Wind River) - [240523] [rseterminals] Provide a generic adapter factory that adapts any ITerminalService to an IShellService + *******************************************************************************/ + +package org.eclipse.rse.internal.services.telnet.terminal; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * @since 1.2 + */ +public class EOFDetectingInputStreamWrapper extends FilterInputStream { + + private boolean fEOF = false; + + public EOFDetectingInputStreamWrapper(InputStream origStream) { + super(origStream); + } + + public synchronized boolean isEOF() { + return fEOF; + } + + public synchronized void setEOF(boolean eof) { + fEOF = eof; + } + + public int read() throws IOException { + try { + int result = in.read(); + if (result < 0) { + setEOF(true); + } + return result; + } catch (IOException e) { + setEOF(true); + throw (e); + } + } + + /* + * (non-Javadoc) + * + * @see java.io.InputStream#close() + */ + public void close() throws IOException { + try { + in.close(); + } finally { + setEOF(true); + } + } + + /* + * (non-Javadoc) + * + * @see java.io.InputStream#read(byte[], int, int) + */ + public int read(byte[] b, int off, int len) throws IOException { + try { + int result = in.read(b, off, len); + if (result < 0) + setEOF(true); + return result; + } catch (IOException e) { + setEOF(true); + throw (e); + } + } +} diff --git a/rse/plugins/org.eclipse.rse.services.telnet/src/org/eclipse/rse/internal/services/telnet/terminal/TelnetTerminalService.java b/rse/plugins/org.eclipse.rse.services.telnet/src/org/eclipse/rse/internal/services/telnet/terminal/TelnetTerminalService.java new file mode 100644 index 00000000000..cd80329b0d3 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.services.telnet/src/org/eclipse/rse/internal/services/telnet/terminal/TelnetTerminalService.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2008 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 + * Anna Dushistova (MontaVista) - adapted from SshTerminalService + * Anna Dushistova (MontaVista) - [240523] [rseterminals] Provide a generic adapter factory that adapts any ITerminalService to an IShellService + *******************************************************************************/ + +package org.eclipse.rse.internal.services.telnet.terminal; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.rse.internal.services.shells.TerminalShellService; +import org.eclipse.rse.internal.services.telnet.ITelnetService; +import org.eclipse.rse.internal.services.telnet.ITelnetSessionProvider; +import org.eclipse.rse.internal.services.telnet.TelnetServiceResources; +import org.eclipse.rse.internal.services.terminals.AbstractTerminalService; +import org.eclipse.rse.internal.services.terminals.ITerminalShell; +import org.eclipse.rse.services.clientserver.messages.SystemMessageException; +import org.eclipse.rse.services.shells.IShellService; + +/** + * A Terminal Service for telnet. + * @since 1.2 + */ +public class TelnetTerminalService extends AbstractTerminalService implements ITelnetService { + + private final ITelnetSessionProvider fSessionProvider; + private IShellService fRelatedShellService; + + public TelnetTerminalService(ITelnetSessionProvider sessionProvider) { + fSessionProvider = sessionProvider; + } + + public ITelnetSessionProvider getSessionProvider() { + return fSessionProvider; + } + + public ITerminalShell launchTerminal(String ptyType, String encoding, String[] environment, String initialWorkingDirectory, String commandToRun, + IProgressMonitor monitor) throws SystemMessageException { + TelnetTerminalShell hostShell = new TelnetTerminalShell(fSessionProvider, ptyType, encoding, environment, initialWorkingDirectory, commandToRun); + return hostShell; + } + + /** + * Return an RSE IShellService related to this Terminal Service. + */ + protected synchronized IShellService getRelatedShellService() { + if (fRelatedShellService == null) { + fRelatedShellService = new TerminalShellService(this); + } + return fRelatedShellService; + } + + /** + * Adapt this terminal service to different (potentially contributed) + * interfaces, in order to provide additional functionality. + * + * Asks the adapter manager first whether it got any contributed adapter; if + * none is found contributed externally, try to adapt to an SshShellService. + * That way, clients can easily convert this ITerminalService into an + * IShellService: + * + *
+ * IShellService ss = (IShellService) myTerminalService.getAdapter(IShellService.class); + *+ * + * @see IAdaptable + * @see PlatformObject#getAdapter(Class) + */ + public Object getAdapter(Class adapter) { + // TODO I'm not sure if this is the right way doing things. First of + // all, we're holding on to the created terminal service forever if + // we're asked for it, thus needing extra memory. + // Second, by asking the adapter manager first, we might get no chance + // returning what we think is right. + Object o = super.getAdapter(adapter); + if (o==null && adapter.isAssignableFrom(IShellService.class)) { + return getRelatedShellService(); + } + return o; + } + + public String getName() { + return TelnetServiceResources.TelnetShellService_Name; + } + + public String getDescription() { + return TelnetServiceResources.TelnetShellService_Description; + } + +} diff --git a/rse/plugins/org.eclipse.rse.services.telnet/src/org/eclipse/rse/internal/services/telnet/terminal/TelnetTerminalShell.java b/rse/plugins/org.eclipse.rse.services.telnet/src/org/eclipse/rse/internal/services/telnet/terminal/TelnetTerminalShell.java new file mode 100644 index 00000000000..59d7a54f22c --- /dev/null +++ b/rse/plugins/org.eclipse.rse.services.telnet/src/org/eclipse/rse/internal/services/telnet/terminal/TelnetTerminalShell.java @@ -0,0 +1,274 @@ +/******************************************************************************* + * Copyright (c) 2008 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 + * Anna Dushistova (MontaVista) - [170910] Integrate the TM Terminal View with RSE + * Martin Oberhuber (Wind River) - [227320] Fix endless loop in TelnetTerminalShell + * Anna Dushistova (MontaVista) - [240523] [rseterminals] Provide a generic adapter factory that adapts any ITerminalService to an IShellService + *******************************************************************************/ + +package org.eclipse.rse.internal.services.telnet.terminal; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.io.Writer; + +import org.apache.commons.net.io.ToNetASCIIInputStream; +import org.apache.commons.net.telnet.EchoOptionHandler; +import org.apache.commons.net.telnet.SuppressGAOptionHandler; +import org.apache.commons.net.telnet.TelnetClient; +import org.apache.commons.net.telnet.TelnetOption; +import org.apache.commons.net.telnet.TerminalTypeOptionHandler; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.rse.internal.services.telnet.ITelnetSessionProvider; +import org.eclipse.rse.internal.services.terminals.AbstractTerminalShell; +import org.eclipse.rse.internal.services.terminals.ITerminalService; +import org.eclipse.rse.services.clientserver.PathUtility; +import org.eclipse.rse.services.clientserver.messages.SystemMessageException; +import org.eclipse.rse.services.files.RemoteFileException; + +/** + * A remote shell connection supporting Streams for I/O. + * + * @since 1.2 + */ +public class TelnetTerminalShell extends AbstractTerminalShell { + + private ITelnetSessionProvider fSessionProvider; + private TelnetClient fTelnetClient; + private String fEncoding; + private EOFDetectingInputStreamWrapper fInputStream; + private OutputStream fOutputStream; + private Writer fOutputStreamWriter; + private int fWidth = 0; + private int fHeight = 0; + private static String defaultEncoding = new java.io.InputStreamReader( + new java.io.ByteArrayInputStream(new byte[0])).getEncoding(); + + /** + * Construct a new Terminal connection. + * + * The SSH channel is immediately connected in the Constructor. + * + * @param sessionProvider + * SSH session provider + * @param ptyType + * Terminal type to set, or
null
if not relevant
+ * @param encoding
+ * The default encoding to use for initial command.
+ * @param environment
+ * Environment array to set, or null
if not
+ * relevant.
+ * @param initialWorkingDirectory
+ * initial directory to open the Terminal in. Use
+ * null
or empty String ("") to start in a default
+ * directory. Empty String will typically start in the home
+ * directory.
+ * @param commandToRun
+ * initial command to send.
+ * @throws SystemMessageException
+ * in case anything goes wrong. Channels and Streams are all
+ * cleaned up again in this case.
+ * @see ITerminalService
+ */
+ public TelnetTerminalShell(ITelnetSessionProvider sessionProvider,
+ String ptyType, String encoding, String[] environment,
+ String initialWorkingDirectory, String commandToRun)
+ throws SystemMessageException {
+ try {
+ fSessionProvider = sessionProvider;
+ boolean onUNIX = System.getProperty("os.name").toLowerCase()//$NON-NLS-1$
+ .startsWith("unix")//$NON-NLS-1$
+ || System.getProperty("os.name").toLowerCase().startsWith( //$NON-NLS-1$
+ "linux");//$NON-NLS-1$
+ fEncoding = encoding;
+ fTelnetClient = new TelnetClient(ptyType);
+ // request remote echo, but accept local if desired
+ fTelnetClient.addOptionHandler(new EchoOptionHandler(false, true,
+ true, true));
+ fTelnetClient.addOptionHandler(new SuppressGAOptionHandler(true,
+ true, true, true));
+ fTelnetClient.addOptionHandler(new TerminalTypeOptionHandler(
+ ptyType, true, true, true, true));
+ fTelnetClient = fSessionProvider.makeNewTelnetClient(fTelnetClient,
+ new NullProgressMonitor());
+ fOutputStream = fTelnetClient.getOutputStream();
+ if (onUNIX)
+ fInputStream = new EOFDetectingInputStreamWrapper(
+ new ToNetASCIIInputStream(fTelnetClient
+ .getInputStream()));
+ else
+ fInputStream = new EOFDetectingInputStreamWrapper(fTelnetClient
+ .getInputStream());
+ if (fEncoding != null) {
+ fOutputStreamWriter = new BufferedWriter(
+ new OutputStreamWriter(fOutputStream, encoding));
+ } else {
+ // default encoding == System.getProperty("file.encoding")
+ // TODO should try to determine remote encoding if possible
+ fOutputStreamWriter = new BufferedWriter(
+ new OutputStreamWriter(fOutputStream));
+ }
+
+ if (initialWorkingDirectory != null
+ && initialWorkingDirectory.length() > 0
+ && !initialWorkingDirectory.equals(".") //$NON-NLS-1$
+ && !initialWorkingDirectory.equals("Command Shell") //$NON-NLS-1$ //FIXME workaround for bug 153047
+ ) {
+ writeToShell("cd " + PathUtility.enQuoteUnix(initialWorkingDirectory)); //$NON-NLS-1$
+ }
+ if (commandToRun != null && commandToRun.length() > 0) {
+ writeToShell(commandToRun);
+ }
+ } catch (Exception e) {
+ throw new RemoteFileException("Error creating Terminal", e); //$NON-NLS-1$
+ } finally {
+ isActive();
+ }
+ }
+
+ public String getDefaultEncoding() {
+ return fEncoding;
+ }
+
+ /**
+ * Encode String with requested user encoding, in case it differs from
+ * Platform default encoding.
+ *
+ * @param s
+ * String to encode
+ * @param encoding
+ * Encoding to use
+ * @return encoded String
+ * @throws UnsupportedEncodingException
+ * in case the requested encoding is not supported
+ */
+ protected String recode(String s, String encoding)
+ throws UnsupportedEncodingException {
+ if (encoding == null) {
+ return s;
+ } else if (encoding.equals(defaultEncoding)) {
+ return s;
+ }
+ // what we want on the wire:
+ byte[] bytes = s.getBytes(encoding);
+ // what we need to tell Jsch to get this on the wire:
+ return new String(bytes, defaultEncoding);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ITerminalHostShell#getInputStream(Object)
+ */
+ public InputStream getInputStream() {
+ return fInputStream;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ITerminalHostShell#getOutputStream(Object)
+ */
+ public OutputStream getOutputStream() {
+ return fOutputStream;
+ }
+
+ /**
+ * Write a command to the shell, honoring specified Encoding. Can only be
+ * done before an outputStream is obtained, since these commands would
+ * interfere with the outputStream.
+ *
+ * @param command
+ * Command String to send, or "#break" to send a Ctrl+C command.
+ */
+ public void writeToShell(String command) throws IOException {
+ if (isActive()) {
+ if ("#break".equals(command)) { //$NON-NLS-1$
+ command = "\u0003"; // Unicode 3 == Ctrl+C //$NON-NLS-1$
+ } else {
+ command += "\r\n"; //$NON-NLS-1$
+ }
+ fOutputStreamWriter.write(command);
+ fOutputStreamWriter.flush();
+ }
+ }
+
+ public void exit() {
+ if (fTelnetClient != null) {
+ try {
+ try {
+ getInputStream().close();
+ } catch (IOException ioe) {
+ /* ignore */
+ }
+ try {
+ getOutputStream().close();
+ } catch (IOException ioe) {
+ /* ignore */
+ ioe.printStackTrace();
+ }
+ try {
+ // TODO disconnect should better be done via the
+ // ConnectorService!!
+ // Because like we do it here, the connector service is not
+ // notified!
+ synchronized (fTelnetClient) {
+ if (fTelnetClient.isConnected())
+ fTelnetClient.disconnect();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ } finally {
+ fTelnetClient = null;
+ isActive();
+ }
+ }
+ }
+
+ public boolean isActive() {
+ if (fTelnetClient != null && fTelnetClient.isConnected()
+ && !isDisconnected()) {
+ return true;
+ }
+ // shell is not active: check for session lost
+ exit();
+
+ // //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;
+ }
+
+ private boolean isDisconnected() {
+ return fInputStream.isEOF();
+ }
+
+ public boolean isLocalEcho() {
+ return fTelnetClient.getLocalOptionState(TelnetOption.ECHO);
+ }
+
+ public void setTerminalSize(int newWidth, int newHeight) {
+ if (fTelnetClient != null
+ && (newWidth != fWidth || newHeight != fHeight)) {
+ // avoid excessive communications due to change size requests by
+ // caching previous size
+ fWidth = newWidth;
+ fHeight = newHeight;
+ }
+ }
+
+}
diff --git a/rse/plugins/org.eclipse.rse.services/plugin.xml b/rse/plugins/org.eclipse.rse.services/plugin.xml
index 52d1ae933c3..4d596ae3c38 100644
--- a/rse/plugins/org.eclipse.rse.services/plugin.xml
+++ b/rse/plugins/org.eclipse.rse.services/plugin.xml
@@ -1,7 +1,27 @@
+
+ * ITerminalService ts = (ITerminalService) myShellService.getAdapter(ITerminalService.class); + *+ * + * @see IAdaptable + * @see PlatformObject#getAdapter(Class) + */ + public Object getAdapter(Class adapter) { + // TODO I'm not sure if this is the right way doing things. First of + // all, we're holding on to the created terminal service forever if + // we're asked for it, thus needing extra memory. + // Second, by asking the adapter manager first, we might get no chance + // returning what we think is right. + Object o = super.getAdapter(adapter); + if (o == null && adapter.isAssignableFrom(ITerminalService.class)) { + return fTerminalService; + } + return o; + } +} diff --git a/rse/plugins/org.eclipse.rse.subsystems.shells.telnet/src/org/eclipse/rse/internal/subsystems/shells/telnet/TelnetServiceCommandShell.java b/rse/plugins/org.eclipse.rse.subsystems.shells.telnet/src/org/eclipse/rse/internal/subsystems/shells/telnet/TelnetServiceCommandShell.java index c6ad7b60b22..6eef87790d1 100644 --- a/rse/plugins/org.eclipse.rse.subsystems.shells.telnet/src/org/eclipse/rse/internal/subsystems/shells/telnet/TelnetServiceCommandShell.java +++ b/rse/plugins/org.eclipse.rse.subsystems.shells.telnet/src/org/eclipse/rse/internal/subsystems/shells/telnet/TelnetServiceCommandShell.java @@ -13,8 +13,9 @@ * * Contributors: * Martin Oberhuber (Wind River) - Adapted from LocalServiceCommandShell - * Sheldon D'souza (Celunite) - Adapted from SshServiceCommandShell + * Sheldon D'souza (Celunite) - Adapted from SshServiceCommandShell * Martin Oberhuber (Wind River) - [225510][api] Fix OutputRefreshJob API leakage + * Anna Dushistova (MontaVista) - [240523] [rseterminals] Provide a generic adapter factory that adapts any ITerminalService to an IShellService *******************************************************************************/ package org.eclipse.rse.internal.subsystems.shells.telnet; @@ -25,6 +26,7 @@ import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.rse.core.subsystems.ISubSystem; +import org.eclipse.rse.internal.services.shells.TerminalServiceHostShell; import org.eclipse.rse.internal.services.telnet.shell.TelnetHostShell; import org.eclipse.rse.services.shells.IHostOutput; import org.eclipse.rse.services.shells.IHostShell; @@ -175,6 +177,9 @@ public class TelnetServiceCommandShell extends ServiceCommandShell { protected String getPromptCommand() { IHostShell shell = getHostShell(); //assert shell instanceof TelnetHostShell; + if (shell instanceof TerminalServiceHostShell) { + return ((TerminalServiceHostShell)shell).getPromptCommand(); + } if (shell instanceof TelnetHostShell) { return ((TelnetHostShell)shell).getPromptCommand(); } diff --git a/rse/plugins/org.eclipse.rse.subsystems.shells.telnet/src/org/eclipse/rse/subsystems/shells/telnet/TelnetShellSubSystemConfiguration.java b/rse/plugins/org.eclipse.rse.subsystems.shells.telnet/src/org/eclipse/rse/subsystems/shells/telnet/TelnetShellSubSystemConfiguration.java index c280a2af28c..ecf3515e36e 100644 --- a/rse/plugins/org.eclipse.rse.subsystems.shells.telnet/src/org/eclipse/rse/subsystems/shells/telnet/TelnetShellSubSystemConfiguration.java +++ b/rse/plugins/org.eclipse.rse.subsystems.shells.telnet/src/org/eclipse/rse/subsystems/shells/telnet/TelnetShellSubSystemConfiguration.java @@ -13,7 +13,8 @@ * * Contributors: * Martin Oberhuber (Wind River) - Adapted template for ssh service. - * Sheldon D'souza (Celunite) - Adapted template for telnet service + * Sheldon D'souza (Celunite) - Adapted template for telnet service + * Anna Dushistova (MontaVista) - [240523] [rseterminals] Provide a generic adapter factory that adapts any ITerminalService to an IShellService *******************************************************************************/ package org.eclipse.rse.subsystems.shells.telnet; @@ -23,7 +24,7 @@ import org.eclipse.rse.core.subsystems.ISubSystem; import org.eclipse.rse.internal.connectorservice.telnet.TelnetConnectorService; import org.eclipse.rse.internal.connectorservice.telnet.TelnetConnectorServiceManager; import org.eclipse.rse.internal.services.telnet.ITelnetService; -import org.eclipse.rse.internal.services.telnet.shell.TelnetShellService; +import org.eclipse.rse.internal.services.telnet.terminal.TelnetTerminalService; import org.eclipse.rse.internal.subsystems.shells.telnet.TelnetServiceCommandShell; import org.eclipse.rse.services.shells.IHostShell; import org.eclipse.rse.services.shells.IShellService; @@ -61,7 +62,7 @@ public class TelnetShellSubSystemConfiguration extends public IShellService createShellService(IHost host) { TelnetConnectorService cserv = (TelnetConnectorService)getConnectorService(host); - return new TelnetShellService(cserv); + return (IShellService) (new TelnetTerminalService(cserv)).getAdapter(IShellService.class); } public IConnectorService getConnectorService(IHost host) { diff --git a/rse/plugins/org.eclipse.rse.subsystems.terminals.core/build.properties b/rse/plugins/org.eclipse.rse.subsystems.terminals.core/build.properties index e4cf4a53ba3..f26a677c9d9 100644 --- a/rse/plugins/org.eclipse.rse.subsystems.terminals.core/build.properties +++ b/rse/plugins/org.eclipse.rse.subsystems.terminals.core/build.properties @@ -13,5 +13,6 @@ output.. = bin/ bin.includes = META-INF/,\ .,\ plugin.properties,\ - about.html + about.html,\ + plugin.xml src.includes = about.html diff --git a/rse/plugins/org.eclipse.rse.subsystems.terminals.core/icons/full/obj16/terminalcommands_obj.gif b/rse/plugins/org.eclipse.rse.subsystems.terminals.core/icons/full/obj16/terminalcommands_obj.gif new file mode 100644 index 00000000000..bbb6a9e153e Binary files /dev/null and b/rse/plugins/org.eclipse.rse.subsystems.terminals.core/icons/full/obj16/terminalcommands_obj.gif differ diff --git a/rse/plugins/org.eclipse.rse.subsystems.terminals.core/icons/full/obj16/terminalcommandslive_obj.gif b/rse/plugins/org.eclipse.rse.subsystems.terminals.core/icons/full/obj16/terminalcommandslive_obj.gif new file mode 100644 index 00000000000..be88df2b43e Binary files /dev/null and b/rse/plugins/org.eclipse.rse.subsystems.terminals.core/icons/full/obj16/terminalcommandslive_obj.gif differ diff --git a/rse/plugins/org.eclipse.rse.subsystems.terminals.core/plugin.properties b/rse/plugins/org.eclipse.rse.subsystems.terminals.core/plugin.properties index 5e3adf0f8dc..d1c92d2902b 100644 --- a/rse/plugins/org.eclipse.rse.subsystems.terminals.core/plugin.properties +++ b/rse/plugins/org.eclipse.rse.subsystems.terminals.core/plugin.properties @@ -14,3 +14,6 @@ pluginName = RSE Terminals Core (Incubation) providerName = Eclipse.org + +TerminalSubsystemName = Terminals +TerminalSubsystemDescription = Work with terminals and commands on remote systems. diff --git a/rse/plugins/org.eclipse.rse.subsystems.terminals.core/plugin.xml b/rse/plugins/org.eclipse.rse.subsystems.terminals.core/plugin.xml new file mode 100644 index 00000000000..3cbdb524980 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.subsystems.terminals.core/plugin.xml @@ -0,0 +1,30 @@ + + + +
null
if not found.
+ */
+ public static ISubSystem getSuitableSubSystem(IHost host) {
+ if (host == null)
+ return null;
+ ISubSystem[] subSystems = host.getSubSystems();
+ ITerminalService ssvc = null;
+ for (int i = 0; subSystems != null && i < subSystems.length; i++) {
+ IService svc = subSystems[i].getSubSystemConfiguration()
+ .getService(host);
+ if (svc != null) {
+ ssvc = (ITerminalService) svc
+ .getAdapter(ITerminalService.class);
+ if (ssvc != null) {
+ return subSystems[i];
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns ITerminalServiceSubSystem associated with the host.
+ *
+ * @param host
+ * the connection
+ * @return shell service subsystem, or null
if not found.
+ */
+ public static ITerminalServiceSubSystem getTerminalServiceSubSystem(
+ IHost host) {
+ if (host == null)
+ return null;
+ ISubSystem[] subSystems = host.getSubSystems();
+ for (int i = 0; subSystems != null && i < subSystems.length; i++) {
+ if (subSystems[i] instanceof ITerminalServiceSubSystem) {
+ return (ITerminalServiceSubSystem) subSystems[i];
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/rse/plugins/org.eclipse.rse.subsystems.terminals.core/src/org/eclipse/rse/subsystems/terminals/core/TerminalServiceSubSystem.java b/rse/plugins/org.eclipse.rse.subsystems.terminals.core/src/org/eclipse/rse/subsystems/terminals/core/TerminalServiceSubSystem.java
index 371824df9d8..5c1199b4426 100644
--- a/rse/plugins/org.eclipse.rse.subsystems.terminals.core/src/org/eclipse/rse/subsystems/terminals/core/TerminalServiceSubSystem.java
+++ b/rse/plugins/org.eclipse.rse.subsystems.terminals.core/src/org/eclipse/rse/subsystems/terminals/core/TerminalServiceSubSystem.java
@@ -6,10 +6,11 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Yu-Fen Kuo (MontaVista) - initial API and implementation
- * Yu-Fen Kuo (MontaVista) - [227572] RSE Terminal doesn't reset the "connected" state when the shell exits
- * Anna Dushistova (MontaVista) - [228577] [rseterminal] Clean up RSE Terminal impl
+ * Yu-Fen Kuo (MontaVista) - initial API and implementation
+ * Yu-Fen Kuo (MontaVista) - [227572] RSE Terminal doesn't reset the "connected" state when the shell exits
+ * Anna Dushistova (MontaVista) - [228577] [rseterminal] Clean up RSE Terminal impl
* Martin Oberhuber (Wind River) - [228577] [rseterminal] Further cleanup
+ * Anna Dushistova (MontaVista) - [227569] [rseterminal][api] Provide a "generic" Terminal subsystem
********************************************************************************/
package org.eclipse.rse.subsystems.terminals.core;
@@ -26,6 +27,7 @@ import org.eclipse.rse.core.model.ISystemRegistry;
import org.eclipse.rse.core.subsystems.CommunicationsEvent;
import org.eclipse.rse.core.subsystems.ICommunicationsListener;
import org.eclipse.rse.core.subsystems.IConnectorService;
+import org.eclipse.rse.core.subsystems.ISubSystemConfiguration;
import org.eclipse.rse.core.subsystems.SubSystem;
import org.eclipse.rse.internal.services.terminals.ITerminalService;
import org.eclipse.rse.subsystems.terminals.core.elements.TerminalElement;
@@ -35,39 +37,40 @@ import org.eclipse.swt.widgets.Display;
* A Subsystem that has terminal instances as children.
*/
public class TerminalServiceSubSystem extends SubSystem implements
- ITerminalServiceSubSystem, ICommunicationsListener {
+ ITerminalServiceSubSystem, ICommunicationsListener {
- private ITerminalService _hostService = null;
+ private ITerminalService _hostService = null;
- private ArrayList children = new ArrayList();
+ private ArrayList children = new ArrayList();
- /**
+ /**
* Constructor.
*/
- public TerminalServiceSubSystem(IHost host,
- IConnectorService connectorService, ITerminalService hostService) {
- super(host, connectorService);
- _hostService = hostService;
- }
+ public TerminalServiceSubSystem(IHost host,
+ IConnectorService connectorService, ITerminalService hostService) {
+ super(host, connectorService);
+ _hostService = hostService;
+ }
- private void fireAsyncRefresh(final Object target) {
+ private void fireAsyncRefresh(final Object target) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
ISystemRegistry registry = RSECorePlugin.getTheSystemRegistry();
- registry.fireEvent(new SystemResourceChangeEvent(target, ISystemResourceChangeEvents.EVENT_REFRESH, target));
+ registry.fireEvent(new SystemResourceChangeEvent(target,
+ ISystemResourceChangeEvents.EVENT_REFRESH, target));
}
});
}
- /**
+ /**
* Return the Terminal Service associated with this subsystem.
*/
- public ITerminalService getTerminalService() {
- return _hostService;
- }
+ public ITerminalService getTerminalService() {
+ return _hostService;
+ }
- public Class getServiceType() {
+ public Class getServiceType() {
return ITerminalService.class;
}
@@ -78,81 +81,81 @@ public class TerminalServiceSubSystem extends SubSystem implements
}
fireAsyncRefresh(this);
}
- }
+ }
- public void removeChild(TerminalElement element) {
- if(element!=null){
- synchronized (children) {
- children.remove(element);
- }
+ public void removeChild(TerminalElement element) {
+ if (element != null) {
+ synchronized (children) {
+ children.remove(element);
+ }
fireAsyncRefresh(this);
- }
- }
+ }
+ }
- public void removeChild(String terminalTitle) {
- removeChild(getChild(terminalTitle));
- }
+ public void removeChild(String terminalTitle) {
+ removeChild(getChild(terminalTitle));
+ }
- public TerminalElement getChild(String terminalTitle) {
- synchronized (children) {
+ public TerminalElement getChild(String terminalTitle) {
+ synchronized (children) {
for (Iterator it = children.iterator(); it.hasNext();) {
TerminalElement element = (TerminalElement) it.next();
if (element.getName().equals(terminalTitle))
return element;
}
}
- return null;
- }
+ return null;
+ }
- public Object[] getChildren() {
- synchronized (children) {
- return children.toArray();
- }
- }
+ public Object[] getChildren() {
+ synchronized (children) {
+ return children.toArray();
+ }
+ }
- public boolean hasChildren() {
- synchronized (children) {
- return !children.isEmpty();
- }
- }
+ public boolean hasChildren() {
+ synchronized (children) {
+ return !children.isEmpty();
+ }
+ }
- /**
+ /**
* Set the terminal service associated with this subsystem.
*/
- public void setTerminalService(ITerminalService service) {
- _hostService = service;
- }
+ public void setTerminalService(ITerminalService service) {
+ _hostService = service;
+ }
- public void communicationsStateChange(CommunicationsEvent e) {
- switch (e.getState()) {
- case CommunicationsEvent.AFTER_DISCONNECT:
- // no longer listen
- getConnectorService().removeCommunicationsListener(this);
- break;
+ public void communicationsStateChange(CommunicationsEvent e) {
+ switch (e.getState()) {
+ case CommunicationsEvent.AFTER_DISCONNECT:
+ // no longer listen
+ getConnectorService().removeCommunicationsListener(this);
+ break;
- case CommunicationsEvent.BEFORE_DISCONNECT:
- case CommunicationsEvent.CONNECTION_ERROR:
- Display.getDefault().asyncExec(new Runnable(){
- public void run() {
- cancelAllTerminals();
- }
- });
- break;
- default:
- break;
- }
+ case CommunicationsEvent.BEFORE_DISCONNECT:
+ case CommunicationsEvent.CONNECTION_ERROR:
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ cancelAllTerminals();
+ }
+ });
+ break;
+ default:
+ break;
+ }
- }
+ }
- public boolean isPassiveCommunicationsListener() {
- return true;
- }
+ public boolean isPassiveCommunicationsListener() {
+ return true;
+ }
- /**
+ /**
* Set the terminal service associated with this subsystem.
*/
- public void cancelAllTerminals() {
- Object[] terminals;
+ public void cancelAllTerminals() {
+ Object[] terminals;
synchronized (children) {
terminals = getChildren();
children.clear();
@@ -163,26 +166,32 @@ public class TerminalServiceSubSystem extends SubSystem implements
try {
removeTerminalElement(element);
} catch (Exception e) {
- RSECorePlugin.getDefault().getLogger().logError("Error removing terminal", e); //$NON-NLS-1$
+ RSECorePlugin.getDefault().getLogger().logError(
+ "Error removing terminal", e); //$NON-NLS-1$
}
}
fireAsyncRefresh(this);
}
- }
+ }
- private void removeTerminalElement(TerminalElement element) {
- element.getTerminalShell().exit();
- ISystemRegistry registry = RSECorePlugin.getTheSystemRegistry();
- registry.fireEvent(new SystemResourceChangeEvent(element, ISystemResourceChangeEvents.EVENT_COMMAND_SHELL_REMOVED, null));
- }
+ private void removeTerminalElement(TerminalElement element) {
+ element.getTerminalShell().exit();
+ ISystemRegistry registry = RSECorePlugin.getTheSystemRegistry();
+ registry.fireEvent(new SystemResourceChangeEvent(element,
+ ISystemResourceChangeEvents.EVENT_COMMAND_SHELL_REMOVED, null));
+ }
- public void initializeSubSystem(IProgressMonitor monitor) {
- super.initializeSubSystem(monitor);
- getConnectorService().addCommunicationsListener(this);
- }
+ public void initializeSubSystem(IProgressMonitor monitor) {
+ super.initializeSubSystem(monitor);
+ getConnectorService().addCommunicationsListener(this);
+ }
- public void uninitializeSubSystem(IProgressMonitor monitor) {
- getConnectorService().removeCommunicationsListener(this);
- super.uninitializeSubSystem(monitor);
- }
+ public void uninitializeSubSystem(IProgressMonitor monitor) {
+ getConnectorService().removeCommunicationsListener(this);
+ super.uninitializeSubSystem(monitor);
+ }
+
+ public boolean canSwitchTo(ISubSystemConfiguration configuration) {
+ return (configuration instanceof ITerminalServiceSubSystemConfiguration);
+ }
}
\ No newline at end of file
diff --git a/rse/plugins/org.eclipse.rse.subsystems.terminals.core/src/org/eclipse/rse/subsystems/terminals/core/TerminalServiceSubSystemConfiguration.java b/rse/plugins/org.eclipse.rse.subsystems.terminals.core/src/org/eclipse/rse/subsystems/terminals/core/TerminalServiceSubSystemConfiguration.java
index b74083a4179..95b920a0837 100644
--- a/rse/plugins/org.eclipse.rse.subsystems.terminals.core/src/org/eclipse/rse/subsystems/terminals/core/TerminalServiceSubSystemConfiguration.java
+++ b/rse/plugins/org.eclipse.rse.subsystems.terminals.core/src/org/eclipse/rse/subsystems/terminals/core/TerminalServiceSubSystemConfiguration.java
@@ -5,7 +5,8 @@
* available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Yu-Fen Kuo (MontaVista) - initial API and implementation
+ * Yu-Fen Kuo (MontaVista) - initial API and implementation
+ * Anna Dushistova (MontaVista) - [227569] [rseterminal][api] Provide a "generic" Terminal subsystem
********************************************************************************/
package org.eclipse.rse.subsystems.terminals.core;
@@ -18,21 +19,20 @@ import org.eclipse.rse.core.subsystems.SubSystemConfiguration;
import org.eclipse.rse.internal.services.terminals.ITerminalService;
import org.eclipse.rse.services.IService;
-
public abstract class TerminalServiceSubSystemConfiguration extends
- SubSystemConfiguration implements
- ITerminalServiceSubSystemConfiguration {
+ SubSystemConfiguration implements
+ ITerminalServiceSubSystemConfiguration {
private Map _services;
- protected TerminalServiceSubSystemConfiguration() {
- super();
- _services = new HashMap();
- }
+ protected TerminalServiceSubSystemConfiguration() {
+ super();
+ _services = new HashMap();
+ }
- public boolean supportsFilters() {
- return false;
- }
+ public boolean supportsFilters() {
+ return false;
+ }
public final ITerminalService getTerminalService(IHost host) {
ITerminalService service = (ITerminalService) _services.get(host);
@@ -51,4 +51,9 @@ public abstract class TerminalServiceSubSystemConfiguration extends
return ITerminalService.class;
}
+ public boolean isFactoryFor(Class subSystemType) {
+ boolean isFor = TerminalServiceSubSystem.class.equals(subSystemType);
+ return isFor;
+ }
+
}
diff --git a/rse/plugins/org.eclipse.rse.terminals.ui/src/org/eclipse/rse/internal/terminals/ui/TerminalServiceHelper.java b/rse/plugins/org.eclipse.rse.terminals.ui/src/org/eclipse/rse/internal/terminals/ui/TerminalServiceHelper.java
index 1dc17fee6a3..a1201c2eee4 100644
--- a/rse/plugins/org.eclipse.rse.terminals.ui/src/org/eclipse/rse/internal/terminals/ui/TerminalServiceHelper.java
+++ b/rse/plugins/org.eclipse.rse.terminals.ui/src/org/eclipse/rse/internal/terminals/ui/TerminalServiceHelper.java
@@ -5,9 +5,10 @@
* available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Yu-Fen Kuo (MontaVista) - initial API and implementation
- * Yu-Fen Kuo (MontaVista) - [227572] RSE Terminal doesn't reset the "connected" state when the shell exits
+ * Yu-Fen Kuo (MontaVista) - initial API and implementation
+ * Yu-Fen Kuo (MontaVista) - [227572] RSE Terminal doesn't reset the "connected" state when the shell exits
* Anna Dushistova (MontaVista) - [227535] [rseterminal][api] terminals.ui should not depend on files.core
+ * Anna Dushistova (MontaVista) - [227569] [rseterminal][api] Provide a "generic" Terminal subsystem
********************************************************************************/
package org.eclipse.rse.internal.terminals.ui;
@@ -42,8 +43,7 @@ public class TerminalServiceHelper {
ISystemRegistry systemRegistry = RSECorePlugin.getTheSystemRegistry();
ISubSystem[] subsystems = systemRegistry.getSubSystems(connection);
for (int i = 0; i < subsystems.length; i++) {
- if ("ssh.terminals".equals(subsystems[i]
- .getSubSystemConfiguration().getId())) {
+ if (subsystems[i] instanceof ITerminalServiceSubSystem) {
ITerminalServiceSubSystem subSystem = (ITerminalServiceSubSystem) subsystems[i];
return subSystem;
}
diff --git a/rse/tests/org.eclipse.rse.tests/META-INF/MANIFEST.MF b/rse/tests/org.eclipse.rse.tests/META-INF/MANIFEST.MF
index 8f53bad5d3b..af2532f56f3 100644
--- a/rse/tests/org.eclipse.rse.tests/META-INF/MANIFEST.MF
+++ b/rse/tests/org.eclipse.rse.tests/META-INF/MANIFEST.MF
@@ -25,7 +25,8 @@ Require-Bundle: org.junit,
org.eclipse.rse.files.ui,
org.eclipse.rse.efs,
org.eclipse.rse.tests.framework;bundle-version="[2.0.0,3.0.0)",
- org.apache.commons.net;bundle-version="[1.4.1,2.0.0)"
+ org.apache.commons.net;bundle-version="[1.4.1,2.0.0)",
+ org.eclipse.rse.subsystems.terminals.core;bundle-version="0.1.1"
Bundle-ActivationPolicy: lazy
Eclipse-LazyStart: true
Bundle-RequiredExecutionEnvironment: J2SE-1.4
diff --git a/rse/tests/org.eclipse.rse.tests/plugin.xml b/rse/tests/org.eclipse.rse.tests/plugin.xml
index daa60f3b3bf..19056624a25 100644
--- a/rse/tests/org.eclipse.rse.tests/plugin.xml
+++ b/rse/tests/org.eclipse.rse.tests/plugin.xml
@@ -96,6 +96,13 @@
value="true">
+