From efeb6fc7bb2692b261d06a8404ea7812bcc3d0be Mon Sep 17 00:00:00 2001 From: Matthew Bastien Date: Wed, 22 Apr 2015 13:54:18 -0400 Subject: [PATCH] Bug 465212 - SSH should support command shell service Added JSchCommandShellService which creates a ChannelShell through JSch in order to open a remote terminal. Change-Id: Ib7ddeb3f9c964ab32130baf99a8d70d36605c3d8 Signed-off-by: Matthew Bastien --- .../internal/core/RemoteServicesManager.java | 2 +- .../org.eclipse.remote.jsch.core/plugin.xml | 5 ++ .../jsch/core/JSchCommandShellService.java | 52 +++++++++++++++++++ .../internal/jsch/core/JSchConnection.java | 17 ++++++ .../internal/jsch/core/JSchProcess.java | 14 +++-- .../jsch/core/JSchProcessBuilder.java | 26 +++++++--- 6 files changed, 104 insertions(+), 12 deletions(-) create mode 100644 bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchCommandShellService.java diff --git a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/RemoteServicesManager.java b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/RemoteServicesManager.java index c72b4aea2ea..678f23c194c 100644 --- a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/RemoteServicesManager.java +++ b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/RemoteServicesManager.java @@ -164,7 +164,7 @@ public class RemoteServicesManager implements IRemoteServicesManager { List connTypes = new ArrayList(); for (IRemoteConnectionType connType : getAllConnectionTypes()) { for (Class service : services) { - if (!connType.hasConnectionService(service)) { + if (connType.hasConnectionService(service)) { connTypes.add(connType); break; } diff --git a/bundles/org.eclipse.remote.jsch.core/plugin.xml b/bundles/org.eclipse.remote.jsch.core/plugin.xml index 70b0eb06389..154b3aec627 100644 --- a/bundles/org.eclipse.remote.jsch.core/plugin.xml +++ b/bundles/org.eclipse.remote.jsch.core/plugin.xml @@ -44,6 +44,11 @@ factory="org.eclipse.remote.internal.jsch.core.JSchConnection$Factory" service="org.eclipse.remote.internal.jsch.core.JSchConnection"> + + T getService(IRemoteConnection connection, Class service) { + if (IRemoteCommandShellService.class.equals(service)) { + return (T) new JSchCommandShellService(connection); + } + return null; + } + } +} diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java index 712fe4f7fc1..bf0b883e6d1 100644 --- a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java @@ -42,6 +42,7 @@ import org.eclipse.remote.internal.jsch.core.messages.Messages; import com.jcraft.jsch.Channel; import com.jcraft.jsch.ChannelExec; import com.jcraft.jsch.ChannelSftp; +import com.jcraft.jsch.ChannelShell; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import com.jcraft.jsch.UIKeyboardInteractive; @@ -541,6 +542,22 @@ public class JSchConnection implements IRemoteConnectionControlService, IRemoteC } } + /** + * Open a shell channel to the remote host. + * + * @return shell channel or null if the progress monitor was cancelled + * + * @throws RemoteConnectionException + * if a channel could not be opened + */ + public ChannelShell getShellChannel() throws RemoteConnectionException { + try { + return (ChannelShell) fSessions.get(0).openChannel("shell"); //$NON-NLS-1$ + } catch (JSchException e) { + throw new RemoteConnectionException(e.getMessage()); + } + } + public String getPassphrase() { return fRemoteConnection.getSecureAttribute(PASSPHRASE_ATTR); } diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchProcess.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchProcess.java index 7db09870f68..616b4c21dab 100644 --- a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchProcess.java +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchProcess.java @@ -22,7 +22,9 @@ import org.eclipse.remote.core.IRemoteProcessSignalService; import org.eclipse.remote.core.IRemoteProcessTerminalService; import org.eclipse.remote.core.exception.RemoteConnectionException; +import com.jcraft.jsch.Channel; import com.jcraft.jsch.ChannelExec; +import com.jcraft.jsch.ChannelShell; public class JSchProcess implements IRemoteProcessControlService, IRemoteProcessSignalService, IRemoteProcessTerminalService { @SuppressWarnings("nls") @@ -32,7 +34,7 @@ public class JSchProcess implements IRemoteProcessControlService, IRemoteProcess private static int WAIT_TIMEOUT = 1000; private static int refCount = 0; - private final ChannelExec fChannel; + private final Channel fChannel; private final IRemoteProcess fProcess; private InputStream fProcStdout; @@ -127,14 +129,14 @@ public class JSchProcess implements IRemoteProcessControlService, IRemoteProcess fProcStdout = new PipedInputStream(pipedOutput); fProcStderr = new NullInputStream(); - fStderrReader = new Thread(new ProcReader(fChannel.getErrStream(), pipedOutput)); + fStderrReader = new Thread(new ProcReader(fChannel.getExtInputStream(), pipedOutput)); fStdoutReader = new Thread(new ProcReader(fChannel.getInputStream(), pipedOutput)); fStderrReader.start(); fStdoutReader.start(); } else { fProcStdout = fChannel.getInputStream(); - fProcStderr = fChannel.getErrStream(); + fProcStderr = fChannel.getExtInputStream(); } } catch (IOException e) { Activator.log(e); @@ -237,7 +239,11 @@ public class JSchProcess implements IRemoteProcessControlService, IRemoteProcess */ @Override public void setTerminalSize(int cols, int rows, int width, int height) { - fChannel.setPtySize(cols, rows, width, height); + if (fChannel instanceof ChannelExec) { + ((ChannelExec) fChannel).setPtySize(cols, rows, width, height); + } else if (fChannel instanceof ChannelShell) { + ((ChannelShell) fChannel).setPtySize(cols, rows, width, height); + } } /* diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchProcessBuilder.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchProcessBuilder.java index 519c3158fc6..6c01b88c6f1 100644 --- a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchProcessBuilder.java +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchProcessBuilder.java @@ -32,7 +32,9 @@ import org.eclipse.remote.internal.core.RemoteDebugOptions; import org.eclipse.remote.internal.core.RemoteProcess; import org.eclipse.remote.internal.jsch.core.messages.Messages; +import com.jcraft.jsch.Channel; import com.jcraft.jsch.ChannelExec; +import com.jcraft.jsch.ChannelShell; import com.jcraft.jsch.JSchException; public class JSchProcessBuilder extends AbstractRemoteProcessBuilder { @@ -41,7 +43,7 @@ public class JSchProcessBuilder extends AbstractRemoteProcessBuilder { private final Map fRemoteEnv = new HashMap(); private final Set charSet = new HashSet(); - private ChannelExec fChannel; + private Channel fChannel; private Map fNewRemoteEnv; private boolean fPreamble = true; @@ -64,6 +66,10 @@ public class JSchProcessBuilder extends AbstractRemoteProcessBuilder { this(connection, Arrays.asList(command)); } + public JSchProcessBuilder(IRemoteConnection connection) { + this(connection, "shell"); //$NON-NLS-1$ + } + @Override public IFileStore directory() { IFileStore dir = super.directory(); @@ -155,13 +161,19 @@ public class JSchProcessBuilder extends AbstractRemoteProcessBuilder { } try { - fChannel = fConnection.getExecChannel(); - String command = buildCommand(remoteCmd, env, clearEnv); - fChannel.setCommand(command); - fChannel.setPty((flags & ALLOCATE_PTY) == ALLOCATE_PTY); + if (cmdArgs.size() == 1 && cmdArgs.get(0).equals("shell")) { //$NON-NLS-1$ + fChannel = fConnection.getShellChannel(); + ((ChannelShell) fChannel).setPty((flags & ALLOCATE_PTY) == ALLOCATE_PTY); + RemoteDebugOptions.trace(RemoteDebugOptions.DEBUG_REMOTE_COMMANDS, "executing command: shell"); //$NON-NLS-1$ + } else { + fChannel = fConnection.getExecChannel(); + String command = buildCommand(remoteCmd, env, clearEnv); + ((ChannelExec) fChannel).setCommand(command); + ((ChannelExec) fChannel).setPty((flags & ALLOCATE_PTY) == ALLOCATE_PTY); + RemoteDebugOptions.trace(RemoteDebugOptions.DEBUG_REMOTE_COMMANDS, "executing command: " + command); //$NON-NLS-1$ + } fChannel.setXForwarding((flags & FORWARD_X11) == FORWARD_X11); fChannel.connect(); - RemoteDebugOptions.trace(RemoteDebugOptions.DEBUG_REMOTE_COMMANDS, "executing command: " + command); //$NON-NLS-1$ return new RemoteProcess(getRemoteConnection(), this); } catch (RemoteConnectionException e) { throw new IOException(e.getMessage()); @@ -170,7 +182,7 @@ public class JSchProcessBuilder extends AbstractRemoteProcessBuilder { } } - public ChannelExec getChannel() { + public Channel getChannel() { return fChannel; }