diff --git a/rse/plugins/org.eclipse.rse.connectorservice.ssh/.classpath b/rse/plugins/org.eclipse.rse.connectorservice.ssh/.classpath
new file mode 100644
index 00000000000..751c8f2e504
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.connectorservice.ssh/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/rse/plugins/org.eclipse.rse.connectorservice.ssh/.project b/rse/plugins/org.eclipse.rse.connectorservice.ssh/.project
new file mode 100644
index 00000000000..dfdb5f84dd4
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.connectorservice.ssh/.project
@@ -0,0 +1,28 @@
+
+
+ org.eclipse.rse.connectorservice.ssh
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/rse/plugins/org.eclipse.rse.connectorservice.ssh/META-INF/MANIFEST.MF b/rse/plugins/org.eclipse.rse.connectorservice.ssh/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..5ee380b868f
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.connectorservice.ssh/META-INF/MANIFEST.MF
@@ -0,0 +1,19 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Ssh Plug-in
+Bundle-SymbolicName: org.eclipse.rse.connectorservice.ssh; singleton:=true
+Bundle-Version: 1.0.0
+Bundle-Activator: org.eclipse.rse.connectorservice.ssh.Activator
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.rse.services,
+ org.eclipse.rse.core,
+ org.eclipse.rse.ui,
+ com.jcraft.jsch,
+ org.eclipse.team.cvs.ssh,
+ org.eclipse.team.cvs.ssh2,
+ org.eclipse.team.cvs.ui,
+ org.eclipse.rse.services.ssh
+Eclipse-LazyStart: true
+Export-Package: org.eclipse.rse.connectorservice.ssh
diff --git a/rse/plugins/org.eclipse.rse.connectorservice.ssh/build.properties b/rse/plugins/org.eclipse.rse.connectorservice.ssh/build.properties
new file mode 100644
index 00000000000..34d2e4d2dad
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.connectorservice.ssh/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
diff --git a/rse/plugins/org.eclipse.rse.connectorservice.ssh/plugin.properties b/rse/plugins/org.eclipse.rse.connectorservice.ssh/plugin.properties
new file mode 100644
index 00000000000..d6e46520e8f
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.connectorservice.ssh/plugin.properties
@@ -0,0 +1,16 @@
+################################################################################
+# Copyright (c) 2006 Wind River Systems, Inc.
+# 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 - initial API and implementation
+################################################################################
+
+plugin.name = Ssh Connector Service Plugin
+
+SshSystemName=SSH Only
+SshSystemDescription=Connection for SSH access to remote hosts
+
diff --git a/rse/plugins/org.eclipse.rse.connectorservice.ssh/plugin.xml b/rse/plugins/org.eclipse.rse.connectorservice.ssh/plugin.xml
new file mode 100644
index 00000000000..1c088bcb81d
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.connectorservice.ssh/plugin.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rse/plugins/org.eclipse.rse.connectorservice.ssh/src/org/eclipse/rse/connectorservice/ssh/Activator.java b/rse/plugins/org.eclipse.rse.connectorservice.ssh/src/org/eclipse/rse/connectorservice/ssh/Activator.java
new file mode 100644
index 00000000000..e6ba9c4f63c
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.connectorservice.ssh/src/org/eclipse/rse/connectorservice/ssh/Activator.java
@@ -0,0 +1,61 @@
+package org.eclipse.rse.connectorservice.ssh;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.rse.connectorservice.ssh";
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns an image descriptor for the image file at the given
+ * plug-in relative path.
+ *
+ * @param path the path
+ * @return the image descriptor
+ */
+ public static ImageDescriptor getImageDescriptor(String path) {
+ return AbstractUIPlugin.imageDescriptorFromPlugin(PLUGIN_ID, path);
+ }
+}
diff --git a/rse/plugins/org.eclipse.rse.connectorservice.ssh/src/org/eclipse/rse/connectorservice/ssh/ISshSubSystem.java b/rse/plugins/org.eclipse.rse.connectorservice.ssh/src/org/eclipse/rse/connectorservice/ssh/ISshSubSystem.java
new file mode 100644
index 00000000000..ed716c1efd2
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.connectorservice.ssh/src/org/eclipse/rse/connectorservice/ssh/ISshSubSystem.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems, Inc.
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.rse.connectorservice.ssh;
+
+/**
+ * Markup Interface for subsystems using the SshConnectorService.
+ *
+ * By implementing this interface, subsystems can be recognized
+ * as being able to share a single ssh connector service between
+ * multiple different subsystems.
+ */
+public interface ISshSubSystem {
+
+}
\ No newline at end of file
diff --git a/rse/plugins/org.eclipse.rse.connectorservice.ssh/src/org/eclipse/rse/connectorservice/ssh/SshConnectorService.java b/rse/plugins/org.eclipse.rse.connectorservice.ssh/src/org/eclipse/rse/connectorservice/ssh/SshConnectorService.java
new file mode 100644
index 00000000000..951c698d0c8
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.connectorservice.ssh/src/org/eclipse/rse/connectorservice/ssh/SshConnectorService.java
@@ -0,0 +1,273 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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
+ *******************************************************************************/
+
+package org.eclipse.rse.connectorservice.ssh;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.rse.core.subsystems.AbstractConnectorService;
+import org.eclipse.rse.model.IHost;
+import org.eclipse.rse.services.files.IFileService;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.team.internal.ccvs.ssh2.CVSSSH2Plugin;
+import org.eclipse.team.internal.ccvs.ssh2.ISSHContants;
+import org.eclipse.team.internal.ccvs.ui.UserValidationDialog;
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.Session;
+import com.jcraft.jsch.UserInfo;
+import org.eclipse.rse.services.ssh.ISshSessionProvider;
+
+/**
+ * Create SSH connections.
+ */
+public class SshConnectorService extends AbstractConnectorService implements ISshSessionProvider
+{
+ private static final int SSH_DEFAULT_PORT = 22;
+ private static JSch jsch=new JSch();
+ private Session session;
+// protected SftpFileService _sftpFileService;
+
+ public SshConnectorService(IHost host) {
+ //TODO the port parameter doesnt really make sense here since
+ //it will be overridden when the subsystem initializes (through
+ //setPort() on our base class -- I assume the port is meant to
+ //be a local port.
+ super("SSH Connector Service", "SSH Connector Service Description", host, 0);
+ // _sftpFileService = new SftpFileService(this);
+ }
+
+ //----------------------------------------------------------------------
+ //
+ //----------------------------------------------------------------------
+ private static String current_ssh_home = null;
+ private static String current_pkeys = ""; //$NON-NLS-1$
+
+ static String SSH_HOME_DEFAULT = null;
+ static {
+ String ssh_dir_name = ".ssh"; //$NON-NLS-1$
+
+ // Windows doesn't like files or directories starting with a dot.
+ if (Platform.getOS().equals(Platform.OS_WIN32)) {
+ ssh_dir_name = "ssh"; //$NON-NLS-1$
+ }
+ SSH_HOME_DEFAULT = System.getProperty("user.home"); //$NON-NLS-1$
+ if (SSH_HOME_DEFAULT != null) {
+ SSH_HOME_DEFAULT = SSH_HOME_DEFAULT + java.io.File.separator + ssh_dir_name;
+ }
+ }
+
+ static void loadSshPrefs()
+ {
+ IPreferenceStore store = CVSSSH2Plugin.getDefault().getPreferenceStore();
+ String ssh_home = store.getString(ISSHContants.KEY_SSH2HOME);
+ String pkeys = store.getString(ISSHContants.KEY_PRIVATEKEY);
+
+ try {
+ if (ssh_home.length() == 0)
+ ssh_home = SSH_HOME_DEFAULT;
+
+ if (current_ssh_home == null || !current_ssh_home.equals(ssh_home)) {
+ loadKnownHosts(ssh_home);
+ current_ssh_home = ssh_home;
+ }
+
+ if (!current_pkeys.equals(pkeys)) {
+ java.io.File file;
+ String[] pkey = pkeys.split(","); //$NON-NLS-1$
+ String[] _pkey = current_pkeys.split(","); //$NON-NLS-1$
+ current_pkeys = ""; //$NON-NLS-1$
+ for (int i = 0; i < pkey.length; i++) {
+ file = new java.io.File(pkey[i]);
+ if (!file.isAbsolute()) {
+ file = new java.io.File(ssh_home, pkey[i]);
+ }
+ if (file.exists()) {
+ boolean notyet = true;
+ for (int j = 0; j < _pkey.length; j++) {
+ if (pkey[i].equals(_pkey[j])) {
+ notyet = false;
+ break;
+ }
+ }
+ if (notyet)
+ jsch.addIdentity(file.getPath());
+ if (current_pkeys.length() == 0) {
+ current_pkeys = pkey[i];
+ } else {
+ current_pkeys += ("," + pkey[i]); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ }
+
+ }
+
+ static void loadKnownHosts(String ssh_home){
+ try {
+ java.io.File file;
+ file=new java.io.File(ssh_home, "known_hosts"); //$NON-NLS-1$
+ jsch.setKnownHosts(file.getPath());
+ } catch (Exception e) {
+ }
+ }
+
+ //----------------------------------------------------------------------
+ //
+ //----------------------------------------------------------------------
+
+ protected void internalConnect(IProgressMonitor monitor) throws Exception
+ {
+ //TODO Set known hosts and identities from Preferences
+ //We could share the preferences from ssh2, or use RSE
+ //ConnectorService Properties / Server Launcher Properties
+
+ //jsch.setKnownHosts("/home/foo/.ssh/known_hosts");
+ loadSshPrefs();
+ String host = getHostName();
+ String user = getUserId();
+
+ session=jsch.getSession(user, host, SSH_DEFAULT_PORT);
+ session.setPassword(getPasswordInformation().getPassword());
+ //session.setPassword("your password");
+
+ // username and password will be given via UserInfo interface.
+ UserInfo ui=new MyUserInfo(user);
+ session.setUserInfo(ui);
+
+ //java.util.Hashtable config=new java.util.Hashtable();
+ //config.put("StrictHostKeyChecking", "no");
+ //session.setConfig(config);
+ session.connect(3000); // making connection with timeout.
+
+ //now also connect the sftpFileService. It's not very nice to force
+ //the connector service know about the file service, and connect it
+ //so early -- lazy connect inside the sftpFileService would be better.
+ //But the FileServiceSubsystem only calls internalConnect() on the
+ //connector service, and doesn't try to connect the file service
+ //individually.
+ //TODO: From the API point of view, it might be better if the file
+ //service had a connect() method and could decide itself if and how
+ //it wants to use the connector service.
+ //Or could we ensure that the FileService is instanciated only once
+ //it needs to be connected? - Currently this is not the case (it is
+ //instanciated very early by the subsystem).
+ // _sftpFileService.connect();
+ }
+
+ public void internalDisconnect(IProgressMonitor monitor)
+ {
+ //TODO: Check, Is disconnect being called because the network (connection) went down?
+ //TODO: Fire communication event (aboutToDisconnect) -- see DStoreConnectorService.internalDisconnect()
+ //TODO: Wrap exception in an InvocationTargetException -- see DStoreConnectorService.internalDisconnect()
+ // _sftpFileService.disconnect();
+ session.disconnect();
+ }
+
+ //TODO avoid having jsch type "Session" in the API.
+ //Could be done by instanciating SshShellService and SshFileService here,
+ //and implementing IShellService getShellService()
+ //and IFileService getFileService().
+ public Session getSession() {
+ return session;
+ }
+ /*
+ public IFileService getFileService() {
+ return _sftpFileService;
+ }
+ */
+
+ private static Display getStandardDisplay() {
+ Display display = Display.getCurrent();
+ if( display==null ) {
+ display = Display.getDefault();
+ }
+ return display;
+ }
+
+ private static class MyUserInfo implements UserInfo {
+ String fPassphrase;
+ String fPassword;
+ final String fUser;
+
+ public MyUserInfo(String user) {
+ fUser = user;
+ }
+ public String getPassword() {
+ return fPassword;
+ }
+ public boolean promptYesNo(final String str) {
+ //need to switch to UI thread for prompting
+ final boolean[] retval = new boolean[1];
+ getStandardDisplay().syncExec(new Runnable() {
+ public void run() {
+ retval[0] = MessageDialog.openQuestion(null, "Warning", str);
+ }
+ });
+ return retval[0];
+ }
+ private String promptString(final String message) {
+ final String[] retval = new String[1];
+ getStandardDisplay().syncExec(new Runnable() {
+ public void run() {
+ //TODO Write our own UserValidationDialog instead of re-using the internal one from team.ssh
+ UserValidationDialog uvd = new UserValidationDialog(null, null,
+ fUser, message);
+ uvd.setUsernameMutable(false);
+ if (uvd.open() == uvd.OK) {
+ retval[0] = uvd.getPassword();
+ } else {
+ retval[0] = null;
+ }
+ }
+ });
+ return retval[0];
+ }
+ public String getPassphrase() {
+ return fPassphrase;
+ }
+ public boolean promptPassphrase(String message) {
+ fPassphrase = promptString(message);
+ return (fPassphrase!=null);
+ }
+ public boolean promptPassword(final String message) {
+ fPassword = promptString(message);
+ return (fPassphrase!=null);
+ }
+ public void showMessage(final String message) {
+ getStandardDisplay().syncExec(new Runnable() {
+ public void run() {
+ MessageDialog.openInformation(null, "Info", message);
+ }
+ });
+ }
+ }
+
+ public boolean isConnected() {
+ return (session!=null && session.isConnected());
+ }
+
+ public boolean hasRemoteServerLauncherProperties() {
+ return false;
+ }
+
+ public boolean supportsRemoteServerLaunching() {
+ return false;
+ }
+
+ public boolean supportsServerLaunchProperties() {
+ return false;
+ }
+
+}
diff --git a/rse/plugins/org.eclipse.rse.connectorservice.ssh/src/org/eclipse/rse/connectorservice/ssh/SshConnectorServiceManager.java b/rse/plugins/org.eclipse.rse.connectorservice.ssh/src/org/eclipse/rse/connectorservice/ssh/SshConnectorServiceManager.java
new file mode 100644
index 00000000000..2c25e5cd976
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.connectorservice.ssh/src/org/eclipse/rse/connectorservice/ssh/SshConnectorServiceManager.java
@@ -0,0 +1,66 @@
+/********************************************************************************
+ * Copyright (c) 2006 IBM Corporation. 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
+ *
+ * Initial Contributors:
+ * The following IBM employees contributed to the Remote System Explorer
+ * component that contains this file: David McKnight, Kushal Munir,
+ * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,
+ * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
+ *
+ * Contributors:
+ * Martin Oberhuber (Wind River) - Adapted from LocalConnectorServiceManager.
+ ********************************************************************************/
+
+package org.eclipse.rse.connectorservice.ssh;
+
+import org.eclipse.rse.core.subsystems.AbstractConnectorServiceManager;
+import org.eclipse.rse.core.subsystems.IConnectorService;
+import org.eclipse.rse.core.subsystems.ISubSystem;
+import org.eclipse.rse.model.IHost;
+
+/**
+ * ConnectorService manager class.
+ *
+ * The job of this manager is to manage and return IConnectorService
+ * objects. It ensures there is only ever one per unique SystemConnection,
+* so that both the file and cmd subsystems can share the same
+* ConnectorService object.
+ */
+public class SshConnectorServiceManager extends AbstractConnectorServiceManager {
+
+ private static SshConnectorServiceManager fInstance;
+
+ private SshConnectorServiceManager() {
+ super();
+ }
+
+ /**
+ * Return singleton instance of this class
+ */
+ public static SshConnectorServiceManager getInstance()
+ {
+ if (fInstance == null)
+ fInstance = new SshConnectorServiceManager();
+ return fInstance;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.rse.core.subsystems.AbstractConnectorServiceManager#createConnectorService(org.eclipse.rse.model.IHost)
+ */
+ public IConnectorService createConnectorService(IHost host) {
+ IConnectorService service = new SshConnectorService(host);
+ return service;
+ }
+
+ public boolean sharesSystem(ISubSystem otherSubSystem) {
+ return (otherSubSystem instanceof ISshSubSystem);
+ }
+
+ public Class getSubSystemCommonInterface(ISubSystem subsystem) {
+ return ISshSubSystem.class;
+ }
+
+}
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/.classpath b/rse/plugins/org.eclipse.rse.services.ssh/.classpath
new file mode 100644
index 00000000000..751c8f2e504
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/.project b/rse/plugins/org.eclipse.rse.services.ssh/.project
new file mode 100644
index 00000000000..9c78ce6c12d
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/.project
@@ -0,0 +1,28 @@
+
+
+ org.eclipse.rse.services.ssh
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/META-INF/MANIFEST.MF b/rse/plugins/org.eclipse.rse.services.ssh/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..97d7c696e9f
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/META-INF/MANIFEST.MF
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %plugin.name
+Bundle-SymbolicName: org.eclipse.rse.services.ssh;singleton:=true
+Bundle-Version: 0.0.2
+Bundle-Activator: org.eclipse.rse.services.ssh.Activator
+Bundle-Vendor: Eclipse.org
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.rse.services,
+ com.jcraft.jsch,
+ org.eclipse.team.cvs.ui,
+ org.eclipse.team.cvs.ssh2
+Eclipse-LazyStart: true
+Export-Package: org.eclipse.rse.services.ssh,
+ org.eclipse.rse.services.ssh.files,
+ org.eclipse.rse.services.ssh.shell
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/about.html b/rse/plugins/org.eclipse.rse.services.ssh/about.html
new file mode 100644
index 00000000000..12a49f13a6d
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/about.html
@@ -0,0 +1,28 @@
+
+
+
+
+About
+
+
+About This Content
+
+May 2, 2006
+License
+
+The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
+at http://www.eclipse.org/legal/epl-v10.html.
+For purposes of the EPL, "Program" will mean the Content.
+
+If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at http://www.eclipse.org.
+
+
+
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/build.properties b/rse/plugins/org.eclipse.rse.services.ssh/build.properties
new file mode 100644
index 00000000000..4c0e8fb61e4
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/build.properties
@@ -0,0 +1,10 @@
+bin.includes = .classpath,\
+ .project,\
+ about.html,\
+ build.properties,\
+ icons/,\
+ META-INF/,\
+ plugin.properties,\
+ plugin.xml,\
+ readme.txt,\
+ src/
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/readme.txt b/rse/plugins/org.eclipse.rse.services.ssh/readme.txt
new file mode 100644
index 00000000000..4335f17a100
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/readme.txt
@@ -0,0 +1,66 @@
+Readme for RSE ssh service
+--------------------------
+
+The RSE ssh plugin allows to connect the RSE Remote Command View to
+a remote host through the secure shell (ssh) protocol.
+This plugin is meant as a proof-of-concept. The code does not have
+product quality yet, and there are lots of open issues (marked as
+TODO in the code). But it is functional for setting up an ssh shell
+connection.
+
+__Requirements:__
+The ssh service plugin has been tested with RSE M2 candidate
+(CVS HEAD as of May 09, 2006) and Eclipse 3.2 RC3.
+The Eclipse Platform Team / CVS feature is needed for the
+com.jcraft.jsh plugin and the org.eclipse.team.cvs.ui plugin.
+
+__Installation:__
+You need an Eclipse PDE Workspace with RSE.
+Then, choose File > Import > Existing Projects > Archive File,
+to import the ssh service archive.
+
+__Usage:__
+* Start RSE, create a new system of type "SSH Only".
+* If you store your ssh private keys in a non-standard place, use
+ Window > Preferences > Team > CVS > SSh2 Connection Method > General
+ to set the ssh home directory, and private key types to be used.
+* Select the "Shells" node and choose Contextmenu > Launch Shell.
+* Enter your username on the remote system. For the password, just
+ enter anything (this is not checked, since ssh has its own method
+ of acquiring password information).
+* When asked to accept remote host authenticity, press OK.
+* Enter the correct password for ssh on the remote system (this is only
+ necessary if you are not using a private key).
+
+__Known Limitations:__
+* Symbolic Links are not resolved (readlink not supported by jsch-0.1.28)
+* Ssh passwords can not be stored (no key ring; use private keys instead)
+* Ssh timeouts are not observed (no automatic reconnect)
+ - after auto-logout, shell just doesnt react to input any more
+* Password and passphrase internal handling has not been checked for
+ security against malicious reading from other Eclipse plugins.
+
+__Known Issues:__
+* A dummy password must be entered on initial connect (can be saved)
+* After some time, the connection may freeze and need to be
+ disconnected.
+* Command service should be provided in addition to the remote shell service.
+* Extremely long remote command output may lead to an Exception
+ due to memory exhaustion (ArrayIndexOutOfBoundsException)
+* "Break" can not be sent to the remote system in order to cancel
+ long-running jobs on the remote side.
+* Moving files with a space in the name doesn't currently work.
+ Renaming them works though.
+* Copy&paste, or drag&drop of remote files remotely does'nt currently work.
+* The plugin currently uses some "internal" classes from the
+ org.eclipse.team.cvs.ui plugin. This needs to be cleaned up.
+* For other internal coding issues, see TODO items in the code.
+
+__Changelog:__
+v0.2:
+* Re-use Team/CVS/ssh2 preferences for ssh2 home and private keys specification
+ Allows to do the ssh login without password if private/public key are set up.
+* Key management from Team/CVS/ssh2 Preferences can also be used
+* Add sftp files subsystem
+* Fix status after disconnect operation
+* Update about.html
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/Activator.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/Activator.java
new file mode 100644
index 00000000000..f4103701368
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/Activator.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems, Inc.
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.rse.services.ssh;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class Activator extends AbstractUIPlugin {
+
+ //The shared instance.
+ private static Activator plugin;
+
+ /**
+ * The constructor.
+ */
+ public Activator() {
+ plugin = this;
+ }
+
+ /**
+ * This method is called upon plug-in activation
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+// make sure files.ui is activated
+// org.eclipse.rse.files.ui.Activator.getDefault();
+ }
+
+ /**
+ * This method is called when the plug-in is stopped
+ */
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ plugin = null;
+ }
+
+ /**
+ * Returns the shared instance.
+ *
+ * @return the shared instance.
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns an image descriptor for the image file at the given
+ * plug-in relative path.
+ *
+ * @param path the path
+ * @return the image descriptor
+ */
+ public static ImageDescriptor getImageDescriptor(String path) {
+ return AbstractUIPlugin.imageDescriptorFromPlugin("org.eclipse.rse.services.ssh", path);
+ }
+}
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/ISshService.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/ISshService.java
new file mode 100644
index 00000000000..445a3a3354c
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/ISshService.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems, Inc.
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.rse.services.ssh;
+
+/**
+ * Markup Interface for services using the SshConnectorService.
+ *
+ * By implementing this interface, services can be recognized
+ * as operating against an SshConnectorService. The interface
+ * is used as the key in a table for looking up the connector
+ * service when needed.
+ */
+public interface ISshService {
+
+}
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/ISshSessionProvider.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/ISshSessionProvider.java
new file mode 100644
index 00000000000..9cfd1146f51
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/ISshSessionProvider.java
@@ -0,0 +1,8 @@
+package org.eclipse.rse.services.ssh;
+
+import com.jcraft.jsch.Session;
+
+public interface ISshSessionProvider
+{
+ public Session getSession();
+}
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/files/SftpFileService.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/files/SftpFileService.java
new file mode 100644
index 00000000000..2da95134cbd
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/files/SftpFileService.java
@@ -0,0 +1,451 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems, Inc.
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.rse.services.ssh.files;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.rse.services.clientserver.NamePatternMatcher;
+import org.eclipse.rse.services.clientserver.messages.SystemMessageException;
+import org.eclipse.rse.services.files.AbstractFileService;
+import org.eclipse.rse.services.files.IFileService;
+import org.eclipse.rse.services.files.IHostFile;
+import org.eclipse.rse.services.ssh.ISshService;
+import org.eclipse.rse.services.ssh.ISshSessionProvider;
+
+import com.jcraft.jsch.Channel;
+import com.jcraft.jsch.ChannelExec;
+import com.jcraft.jsch.ChannelSftp;
+import com.jcraft.jsch.Session;
+import com.jcraft.jsch.SftpATTRS;
+import com.jcraft.jsch.SftpProgressMonitor;
+
+public class SftpFileService extends AbstractFileService implements IFileService, ISshService
+{
+ //private SshConnectorService fConnector;
+ private ISshSessionProvider fSessionProvider;
+ private ChannelSftp fChannelSftp;
+ private String fUserHome;
+
+// public SftpFileService(SshConnectorService conn) {
+// fConnector = conn;
+// }
+
+ public SftpFileService(ISshSessionProvider sessionProvider) {
+ fSessionProvider = sessionProvider;
+ }
+
+ public String getName() {
+ return "Ssh / Sftp File Service";
+ }
+
+ public String getDescription() {
+ return "Access a remote file system via Ssh / Sftp protocol";
+ }
+
+ public void connect() throws Exception {
+ Session session = fSessionProvider.getSession();
+ Channel channel=session.openChannel("sftp"); //$NON-NLS-1$
+ channel.connect();
+ fChannelSftp=(ChannelSftp)channel;
+ fUserHome = fChannelSftp.pwd();
+ }
+
+ public void disconnect() {
+ fChannelSftp.disconnect();
+ fChannelSftp = null;
+ }
+
+ public IHostFile getFile(IProgressMonitor monitor, String remoteParent, String fileName)
+ {
+ //TODO getFile() must return a dummy even for non-existent files,
+ //or the move() operation will fail. This needs to be described in
+ //the API docs.
+ SftpHostFile node = null;
+ SftpATTRS attrs = null;
+ try {
+ attrs = fChannelSftp.stat(remoteParent+'/'+fileName);
+ } catch(Exception e) {}
+ if (attrs!=null) {
+ node = makeHostFile(remoteParent, fileName, attrs);
+ } else {
+ node = new SftpHostFile(remoteParent, fileName, false, false, false, 0, 0);
+ node.setExists(false);
+ }
+ return node;
+ }
+
+ public boolean isConnected() {
+ return fChannelSftp.isConnected();
+ }
+
+ protected IHostFile[] internalFetch(IProgressMonitor monitor, String parentPath, String fileFilter, int fileType)
+ {
+ if (fileFilter == null) {
+ fileFilter = "*"; //$NON-NLS-1$
+ }
+ NamePatternMatcher filematcher = new NamePatternMatcher(fileFilter, true, true);
+ List results = new ArrayList();
+ try {
+ java.util.Vector vv=fChannelSftp.ls(parentPath);
+ for(int ii=0; ii 0)
+ {
+ bos.write(buffer, 0, readCount);
+ }
+ bos.close();
+ upload(monitor, tempFile, remoteParent, remoteFile, isBinary, "", hostEncoding); //$NON-NLS-1$
+ }
+ catch (Exception e) {
+ //TODO See download
+ //e.printStackTrace();
+ //throw new RemoteFileIOException(e);
+ return false;
+ }
+ return true;
+ }
+
+ public boolean download(IProgressMonitor monitor, String remoteParent, String remoteFile, File localFile, boolean isBinary, String hostEncoding) throws SystemMessageException
+ {
+ try {
+ if (!localFile.exists()) {
+ File localParentFile = localFile.getParentFile();
+ if (!localParentFile.exists()) {
+ localParentFile.mkdirs();
+ }
+ //localFile.createNewFile();
+ }
+ //TODO Ascii/binary?
+ String remotePath = remoteParent+'/'+remoteFile;
+ int mode=ChannelSftp.OVERWRITE;
+ MyProgressMonitor sftpMonitor = new MyProgressMonitor(monitor);
+ fChannelSftp.get(remotePath, localFile.getAbsolutePath(), sftpMonitor, mode);
+ }
+ catch (Exception e) {
+ //TODO handle exception properly: happens e.g. when trying to download a symlink.
+ //Messages from Jsch are mostly not useful, especially when the server version is
+ //<=3 (e.g. "4: Failure"). therefore it is better for now to just return false.
+ //e.printStackTrace();
+ //throw new RemoteFileIOException(e);
+ return false;
+ }
+ return true;
+ }
+
+ public IHostFile getUserHome() {
+ //TODO assert: this is only called after we are connected
+ int lastSlash = fUserHome.lastIndexOf('/');
+ String name = fUserHome.substring(lastSlash + 1);
+ String parent = fUserHome.substring(0, lastSlash);
+ return getFile(null, parent, name);
+ }
+
+ public IHostFile[] getRoots(IProgressMonitor monitor) {
+ IHostFile root = new SftpHostFile("/", "/", true, true, false, 0, 0); //$NON-NLS-1$ //$NON-NLS-2$
+ return new IHostFile[] { root };
+ }
+
+ // TODO
+ /********************************************************
+ *
+ * The following APIs need to be implemented
+ *
+ ********************************************************/
+
+ public IHostFile createFile(IProgressMonitor monitor, String remoteParent, String fileName) throws SystemMessageException
+ {
+ IHostFile result = null;
+ try {
+ String fullPath = remoteParent + '/' + fileName;
+ OutputStream os = fChannelSftp.put(fullPath);
+ os.close();
+ SftpATTRS attrs = fChannelSftp.stat(fullPath);
+ result = makeHostFile(remoteParent, fileName, attrs);
+ } catch (Exception e) {
+ e.printStackTrace();
+ // DKM commenting out because services don't know about this class
+ // throw new RemoteFileIOException(e);
+ }
+ return result;
+ }
+
+ public IHostFile createFolder(IProgressMonitor monitor, String remoteParent, String folderName) throws SystemMessageException
+ {
+ IHostFile result = null;
+ try {
+ String fullPath = remoteParent + '/' + folderName;
+ fChannelSftp.mkdir(fullPath);
+ SftpATTRS attrs = fChannelSftp.stat(fullPath);
+ result = makeHostFile(remoteParent, folderName, attrs);
+ } catch (Exception e) {
+ e.printStackTrace();
+ // DKM commenting out because services don't know about this class
+ //throw new RemoteFileIOException(e);
+ }
+ return result;
+ }
+
+ public boolean delete(IProgressMonitor monitor, String remoteParent, String fileName) throws SystemMessageException
+ {
+ boolean ok=false;
+ try {
+ String fullPath = remoteParent + '/' + fileName;
+ SftpATTRS attrs = fChannelSftp.stat(fullPath);
+ if (attrs==null) {
+ //doesn't exist, nothing to do
+ } else if (attrs.isDir()) {
+ fChannelSftp.rmdir(fullPath);
+ } else {
+ fChannelSftp.rm(fullPath);
+ }
+ ok=true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ // DKM commenting out because services don't know about this class
+ //throw new RemoteFileIOException(e);
+ }
+ return ok;
+ }
+
+ public boolean rename(IProgressMonitor monitor, String remoteParent, String oldName, String newName) throws SystemMessageException
+ {
+ boolean ok=false;
+ try {
+ String fullPathOld = remoteParent + '/' + oldName;
+ String fullPathNew = remoteParent + '/' + newName;
+ fChannelSftp.rename(fullPathOld, fullPathNew);
+ ok=true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ // DKM commenting out because services don't know about this class
+ //throw new RemoteFileIOException(e);
+ }
+ return ok;
+ }
+
+ public boolean rename(IProgressMonitor monitor, String remoteParent, String oldName, String newName, IHostFile oldFile) throws SystemMessageException {
+ // TODO dont know how to update
+ return rename(monitor, remoteParent, oldName, newName);
+ }
+
+ private boolean progressWorked(IProgressMonitor monitor, int work) {
+ boolean cancelRequested = false;
+ if (monitor!=null) {
+ monitor.worked(work);
+ cancelRequested = monitor.isCanceled();
+ }
+ return cancelRequested;
+ }
+
+ public int runCommand(IProgressMonitor monitor, String command) throws SystemMessageException
+ {
+ int result = -1;
+ if (monitor!=null) {
+ monitor.beginTask(command, 20);
+ }
+ Channel channel = null;
+ try {
+ channel=fSessionProvider.getSession().openChannel("exec"); //$NON-NLS-1$
+ ((ChannelExec)channel).setCommand(command);
+
+ //No user input
+ channel.setInputStream(null);
+ //TODO capture error output for exception
+ ((ChannelExec)channel).setErrStream(System.err);
+ InputStream in=channel.getInputStream();
+ channel.connect();
+ byte[] tmp=new byte[1024];
+ while(!channel.isClosed()){
+ if( progressWorked(monitor,1) ) {
+ break;
+ }
+ while(in.available()>0){
+ int i=in.read(tmp, 0, 1024);
+ if(i<0)break;
+ //System.out.print(new String(tmp, 0, i));
+ }
+ try{Thread.sleep(1000);}catch(Exception ee){}
+ }
+ result = channel.getExitStatus();
+ } catch(Exception e) {
+ // DKM
+ // not visible to this plugin
+ // throw new RemoteFileIOException(e);
+ } finally {
+ if (monitor!=null) {
+ monitor.done();
+ }
+ if (channel!=null) {
+ channel.disconnect();
+ }
+ }
+ return result;
+ }
+
+ public boolean move(IProgressMonitor monitor, String srcParent, String srcName, String tgtParent, String tgtName) throws SystemMessageException
+ {
+ // move is not supported by sftp directly. Use the ssh shell instead.
+ // TODO check if newer versions of sftp support move directly
+ // TODO Interpret some error messages like "command not found" (use ren instead of mv on windows)
+ String fullPathOld = srcParent + '/' + srcName;
+ String fullPathNew = tgtParent + '/' + tgtName;
+ //TODO quote pathes if necessary
+ int rv = runCommand(monitor, "mv "+fullPathOld+' '+fullPathNew); //$NON-NLS-1$
+ return (rv==0);
+ }
+
+ public boolean copy(IProgressMonitor monitor, String srcParent, String srcName, String tgtParent, String tgtName) throws SystemMessageException {
+ // move is not supported by sftp directly. Use the ssh shell instead.
+ // TODO check if newer versions of sftp support move directly
+ // TODO Interpret some error messages like "command not found" (use (x)copy instead of cp on windows)
+ String fullPathOld = srcParent + '/' + srcName; //$NON-NLS-1$
+ String fullPathNew = tgtParent + '/' + tgtName; //$NON-NLS-1$
+ //TODO quote pathes if necessary
+ int rv = runCommand(monitor, "cp "+fullPathOld+' '+fullPathNew); //$NON-NLS-1$
+ return (rv==0);
+ }
+
+ public boolean copyBatch(IProgressMonitor monitor, String[] srcParents, String[] srcNames, String tgtParent) throws SystemMessageException
+ {
+ boolean ok = true;
+ for (int i = 0; i < srcParents.length; i++)
+ {
+ ok = ok && copy(monitor, srcParents[i], srcNames[i], tgtParent, srcNames[i]);
+ }
+ return ok;
+ }
+
+ public void initService(IProgressMonitor monitor) {
+ try
+ {
+ connect();
+ }
+ catch (Exception e)
+ {
+ }
+ }
+
+ public void uninitService(IProgressMonitor monitor) {
+ disconnect();
+ }
+
+ public boolean isCaseSensitive() {
+ //TODO find out whether remote is case sensitive or not
+ return true;
+ }
+
+}
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/files/SftpHostFile.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/files/SftpHostFile.java
new file mode 100644
index 00000000000..6c25c3b7828
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/files/SftpHostFile.java
@@ -0,0 +1,153 @@
+/********************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation. 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
+ *
+ * Initial Contributors:
+ * The following IBM employees contributed to the Remote System Explorer
+ * component that contains this file: David McKnight, Kushal Munir,
+ * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,
+ * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
+ *
+ * Contributors:
+ * Martin Oberhuber (Wind River) - Adapted from FTPHostFile.
+ ********************************************************************************/
+
+package org.eclipse.rse.services.ssh.files;
+
+import java.io.File;
+
+import org.eclipse.rse.services.clientserver.archiveutils.ArchiveHandlerManager;
+import org.eclipse.rse.services.files.IHostFile;
+
+public class SftpHostFile implements IHostFile {
+
+ private String fName;
+ private String fParentPath;
+ private boolean fIsDirectory = false;
+ private boolean fIsRoot = false;
+ private boolean fIsArchive = false;
+ private boolean fExists = true;
+ private long fLastModified = 0;
+ private long fSize = 0;
+ private boolean fIsLink = false;
+ private String[] fExtended = null;
+
+ //TODO just re-use or extend FTPHostFile instead of copying here?
+ public SftpHostFile(String parentPath, String name, boolean isDirectory, boolean isRoot, boolean isLink, long lastModified, long size) {
+ fParentPath = parentPath;
+ fName = name;
+ fIsDirectory = isDirectory;
+ fIsRoot = isRoot;
+ fLastModified = lastModified;
+ fSize = size;
+ fIsLink = isLink;
+ fIsArchive = internalIsArchive();
+ }
+
+ public String getName() {
+ return fName;
+ }
+
+ public boolean isHidden() {
+ String name = getName();
+ return name.charAt(0) == '.';
+ }
+
+ public String getParentPath() {
+ return fParentPath;
+ }
+
+ public boolean isDirectory() {
+ return fIsDirectory;
+ }
+
+ public boolean isFile() {
+ return !(fIsDirectory || fIsRoot || fIsLink);
+ }
+
+ public boolean isRoot() {
+ return fIsRoot;
+ }
+
+ public void setExists(boolean b) {
+ fExists = b;
+ }
+
+ public boolean exists() {
+ return fExists;
+ }
+
+ public String getAbsolutePath() {
+ if (isRoot()) {
+ return getName();
+ } else {
+ StringBuffer path = new StringBuffer(getParentPath());
+ if (!fParentPath.endsWith("/"))
+ {
+ path.append('/');
+ }
+ path.append(getName());
+ return path.toString();
+ }
+ }
+
+ public long getSize() {
+ return fSize;
+ }
+
+ public long getModifiedDate() {
+ return fLastModified;
+ }
+
+ public void renameTo(String newAbsolutePath) {
+ int i = newAbsolutePath.lastIndexOf("/");
+ if (i == -1) {
+ fName = newAbsolutePath;
+ }
+ else {
+ fParentPath = newAbsolutePath.substring(0, i);
+ fName = newAbsolutePath.substring(i+1);
+ }
+ fIsArchive = internalIsArchive();
+ }
+
+ protected boolean internalIsArchive() {
+ return ArchiveHandlerManager.getInstance().isArchive(new File(getAbsolutePath()))
+ && !ArchiveHandlerManager.isVirtual(getAbsolutePath());
+ }
+
+ public boolean isArchive() {
+ return fIsArchive;
+ }
+
+ public boolean isLink() {
+ return fIsLink;
+ }
+
+ /** Extended data: name:value pairs */
+ public void setExtendedData(String[] extended) {
+ fExtended = extended;
+ }
+
+ public String[] getExtendedData() {
+ return fExtended;
+ }
+
+ public String getClassification() {
+ //TODO: isExecutable(), shellscript vs. binary
+ String result;
+ if (isLink()) {
+ //TODO: read symbolic link target and its type to provide e.g. "symbolic link(directory):/export4/opt
+ result = "symbolic link"; //$NON-NLS-1$
+ } else if (isFile()) {
+ result = "file"; //$NON-NLS-1$
+ } else if (isDirectory()) {
+ result = "directory"; //$NON-NLS-1$
+ } else {
+ result = "unknown"; //default-fallback //$NON-NLS-1$
+ }
+ return result;
+ }
+}
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshHostShell.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshHostShell.java
new file mode 100644
index 00000000000..ec6b0edbe5a
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshHostShell.java
@@ -0,0 +1,87 @@
+/********************************************************************************
+ * Copyright (c) 2006 IBM Corporation. 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
+ *
+ * Initial Contributors:
+ * The following IBM employees contributed to the Remote System Explorer
+ * component that contains this file: David McKnight, Kushal Munir,
+ * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,
+ * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
+ *
+ * Contributors:
+ * Martin Oberhuber (Wind River) - Adapted from LocalHostShell.
+ ********************************************************************************/
+
+package org.eclipse.rse.services.ssh.shell;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+
+
+import org.eclipse.rse.services.shells.AbstractHostShell;
+import org.eclipse.rse.services.shells.IHostShellOutputReader;
+import org.eclipse.rse.services.ssh.ISshSessionProvider;
+
+import com.jcraft.jsch.Channel;
+import com.jcraft.jsch.Session;
+
+/**
+ * A Shell subsystem for SSH.
+ */
+public class SshHostShell extends AbstractHostShell {
+
+ private ISshSessionProvider fSessionProvider;
+ private Channel fChannel;
+ private SshShellOutputReader fStdoutHandler;
+ private SshShellOutputReader fStderrHandler;
+ private PrintWriter fStdinHandler;
+
+ public SshHostShell(ISshSessionProvider sessionProvider, String initialWorkingDirectory, String commandToRun, String encoding, String[] environment) {
+ try {
+ fSessionProvider = sessionProvider;
+ fChannel = fSessionProvider.getSession().openChannel("shell"); //$NON-NLS-1$
+
+ ////disable pty mode. This works in jsch-0.1.25 and later only.
+ ////By default, jsch always creates a vt100 connection sized
+ ////80x24 / 640x480 (dimensions can be changed).
+ ////I wonder whether jsch could give us a dumb terminal?
+ //if(fChannel instanceof ChannelShell) {
+ // ((ChannelShell)fChannel).setPty(false);
+ //}
+
+ fStdoutHandler = new SshShellOutputReader(this, new BufferedReader(new InputStreamReader(fChannel.getInputStream())), false);
+ fStderrHandler = new SshShellOutputReader(this, null,true);
+ fStdinHandler = new PrintWriter(fChannel.getOutputStream());
+
+ fChannel.connect();
+ } catch(Exception e) {
+ //TODO Forward exception to RSE properly
+ e.printStackTrace();
+ }
+ }
+
+ public boolean isActive() {
+ return !fChannel.isEOF();
+ }
+
+ public void writeToShell(String command) {
+ fStdinHandler.println(command);
+ fStdinHandler.flush();
+ }
+
+ public IHostShellOutputReader getStandardOutputReader() {
+ return fStdoutHandler;
+ }
+
+ public IHostShellOutputReader getStandardErrorReader() {
+ return fStderrHandler;
+ }
+
+ public void exit() {
+ fChannel.disconnect();
+ }
+
+}
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshShellOutputReader.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshShellOutputReader.java
new file mode 100644
index 00000000000..3c42c9eccfd
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshShellOutputReader.java
@@ -0,0 +1,126 @@
+/********************************************************************************
+ * Copyright (c) 2006 IBM Corporation. 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
+ *
+ * Initial Contributors:
+ * The following IBM employees contributed to the Remote System Explorer
+ * component that contains this file: David McKnight, Kushal Munir,
+ * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,
+ * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
+ *
+ * Contributors:
+ * Martin Oberhuber (Wind River) - Adapted from LocalShellOutputReader.
+ * Martin Oberhuber (Wind River) - Added vt100 escape sequence ignoring.
+ ********************************************************************************/
+
+package org.eclipse.rse.services.ssh.shell;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+
+import org.eclipse.rse.services.shells.AbstractHostShellOutputReader;
+import org.eclipse.rse.services.shells.IHostShell;
+import org.eclipse.rse.services.shells.IHostShellOutputReader;
+
+/**
+ * Listener to shell output. As io streams through, refresh events are sent out
+ * for the OutputChangeListener to respond to.
+ * VT100 terminal escape sequences are ignored.
+ */
+public class SshShellOutputReader extends AbstractHostShellOutputReader
+ implements IHostShellOutputReader {
+
+ protected BufferedReader fReader;
+
+ public SshShellOutputReader(IHostShell hostShell, BufferedReader reader,
+ boolean isErrorReader) {
+ super(hostShell, isErrorReader);
+ fReader = reader;
+ }
+
+ protected Object internalReadLine() {
+ if (fReader == null) {
+ //Our workaround sets the stderr reader to null, so we never give any stderr output.
+ //TODO Check if ssh supports some method of having separate stdout and stderr streams
+ return null;
+ }
+ StringBuffer theLine = new StringBuffer();
+ int ch;
+ int lastch = 0;
+ boolean done = false;
+ while (!done && !isFinished()) {
+ try {
+ ch = fReader.read();
+ switch (ch) {
+ case -1:
+ if (theLine.length() == 0) // End of Reader
+ return null;
+ done = true;
+ break;
+ case 65535:
+ if (theLine.length() == 0) // Check why I keep getting this!!!
+ return null;
+ done = true;
+ break;
+ case 10:
+ done = true; // Newline
+ break;
+ case 9:
+ //TODO Count characters and insert as many as needed to do a real tab
+ theLine.append(" "); // Tab //$NON-NLS-1$
+ break;
+ case 13:
+ break; // Carriage Return
+ default:
+ char tch = (char) ch;
+ if (!Character.isISOControl(tch)) {
+ theLine.append(tch); // Any other character
+ } else if (ch == 27) {
+ // Escape: ignore next char too
+ int nch = (char)fReader.read();
+ if (nch == 91) {
+ //vt100 escape sequence: read until end-of-command (skip digits and semicolon)
+ //e.g. \x1b;13;m --> ignore the entire command, including the trailing m
+ do {
+ nch = fReader.read();
+ } while (Character.isDigit((char)nch) || nch == ';');
+ }
+ }
+ }
+
+ boolean ready = fReader.ready();
+ //TODO Get rid of this to support UNIX and Mac? -- It appears that
+ //due to vt100 emulation we get CRLF even for UNIX connections.
+ if (ch == 10 && lastch == 13) {
+ return theLine.toString();
+ }
+ lastch = ch;
+
+ // Check to see if the BufferedReader is still ready which means
+ // there are more characters
+ // in the Buffer...If not, then we assume it is waiting for
+ // input.
+ if (!ready) {
+ // wait to make sure
+ try {
+ Thread.sleep(_waitIncrement);
+ } catch (InterruptedException e) {
+ }
+ if (!fReader.ready()) {
+ if (done) {
+ return theLine.toString().trim();
+ } else {
+ done = true;
+ }
+ }
+ }
+ } catch (IOException e) {
+ return null;
+ }
+ }
+ return theLine.toString();
+ }
+
+}
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshShellService.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshShellService.java
new file mode 100644
index 00000000000..5eaec06130f
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshShellService.java
@@ -0,0 +1,96 @@
+/********************************************************************************
+ * Copyright (c) 2006 IBM Corporation. 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
+ *
+ * Initial Contributors:
+ * The following IBM employees contributed to the Remote System Explorer
+ * component that contains this file: David McKnight, Kushal Munir,
+ * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,
+ * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
+ *
+ * Contributors:
+ * Martin Oberhuber (Wind River) - Adapted from LocalShellService.
+ ********************************************************************************/
+
+package org.eclipse.rse.services.ssh.shell;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.rse.services.clientserver.messages.SystemMessage;
+import org.eclipse.rse.services.shells.IHostShell;
+import org.eclipse.rse.services.shells.IShellService;
+import org.eclipse.rse.services.ssh.ISshService;
+import org.eclipse.rse.services.ssh.ISshSessionProvider;
+
+import com.jcraft.jsch.Session;
+
+/**
+ * A Shell Services for ssh.
+ * Adapted from LocalShellService.
+ */
+public class SshShellService implements ISshService, IShellService {
+
+ private static final String SHELL_INVOCATION = ">";
+ private ISshSessionProvider fSessionProvider;
+
+ public SshShellService(ISshSessionProvider sessionProvider) {
+ fSessionProvider = sessionProvider;
+ }
+
+ //TODO abstract base class should handle default encodings
+ public IHostShell launchShell(IProgressMonitor monitor,
+ String initialWorkingDirectory, String[] environment) {
+ String defaultEncoding = System.getProperty("file.encoding"); //$NON-NLS-1$
+ return launchShell(monitor, initialWorkingDirectory, defaultEncoding, environment);
+ }
+
+ public IHostShell launchShell(IProgressMonitor monitor,
+ String initialWorkingDirectory, String encoding,
+ String[] environment) {
+ SshHostShell hostShell = new SshHostShell(fSessionProvider, initialWorkingDirectory, SHELL_INVOCATION, encoding, environment);
+ return hostShell;
+ }
+
+ //TODO abstract base class should handle default encodings
+ public IHostShell runCommand(IProgressMonitor monitor,
+ String initialWorkingDirectory, String command, String[] environment) {
+ String defaultEncoding = System.getProperty("file.encoding"); //$NON-NLS-1$
+ return runCommand(monitor, initialWorkingDirectory, command, defaultEncoding, environment);
+ }
+
+ //TODO command is ignored by SshHostShell for now (just like DStoreHostShell).
+ public IHostShell runCommand(IProgressMonitor monitor,
+ String initialWorkingDirectory, String command, String encoding,
+ String[] environment) {
+ SshHostShell hostShell = new SshHostShell(fSessionProvider, initialWorkingDirectory, command, encoding, environment);
+ return hostShell;
+ }
+
+ public String[] getHostEnvironment() {
+ //TODO getHostEnvironment is not yet implemented for ssh (needs running remote command and parsing)
+ return new String[0];
+ }
+
+ public String getName() {
+ //TODO Externalize Strings
+ return "SSH Shell Service";
+ }
+
+ public String getDescription() {
+ return "SSH Shell Service Description";
+ }
+
+ public void initService(IProgressMonitor monitor) {
+ // nothing to do
+ }
+
+ public void uninitService(IProgressMonitor monitor) {
+ // nothing to do
+ }
+
+ public SystemMessage getMessage(String messageID) {
+ return null;
+ }
+
+}
diff --git a/rse/plugins/org.eclipse.rse.subsystems.files.ssh/.classpath b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/.classpath
new file mode 100644
index 00000000000..751c8f2e504
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/rse/plugins/org.eclipse.rse.subsystems.files.ssh/.project b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/.project
new file mode 100644
index 00000000000..bffdbdcd653
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/.project
@@ -0,0 +1,28 @@
+
+
+ org.eclipse.rse.subsystems.files.ssh
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/rse/plugins/org.eclipse.rse.subsystems.files.ssh/META-INF/MANIFEST.MF b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..aa1306e3e46
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/META-INF/MANIFEST.MF
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Ssh Plug-in
+Bundle-SymbolicName: org.eclipse.rse.subsystems.files.ssh; singleton:=true
+Bundle-Version: 1.0.0
+Bundle-Activator: org.eclipse.rse.subsystems.files.ssh.Activator
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.rse.services,
+ org.eclipse.rse.connectorservice.ssh,
+ org.eclipse.rse.services.ssh,
+ org.eclipse.rse.core,
+ org.eclipse.rse.subsystems.files.core,
+ com.jcraft.jsch,
+ org.eclipse.rse.ui
+Eclipse-LazyStart: true
+Export-Package: org.eclipse.rse.subsystems.files.ssh
diff --git a/rse/plugins/org.eclipse.rse.subsystems.files.ssh/build.properties b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/build.properties
new file mode 100644
index 00000000000..34d2e4d2dad
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
diff --git a/rse/plugins/org.eclipse.rse.subsystems.files.ssh/icons/full/obj16/systemfiles_obj.gif b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/icons/full/obj16/systemfiles_obj.gif
new file mode 100644
index 00000000000..874c9926215
Binary files /dev/null and b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/icons/full/obj16/systemfiles_obj.gif differ
diff --git a/rse/plugins/org.eclipse.rse.subsystems.files.ssh/icons/full/obj16/systemfileslive_obj.gif b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/icons/full/obj16/systemfileslive_obj.gif
new file mode 100644
index 00000000000..885b8a69e39
Binary files /dev/null and b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/icons/full/obj16/systemfileslive_obj.gif differ
diff --git a/rse/plugins/org.eclipse.rse.subsystems.files.ssh/plugin.properties b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/plugin.properties
new file mode 100644
index 00000000000..76d03d380f9
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/plugin.properties
@@ -0,0 +1,15 @@
+################################################################################
+# Copyright (c) 2006 Wind River Systems, Inc.
+# 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 - initial API and implementation
+################################################################################
+
+plugin.name = Ssh Files Plugin
+
+SshFileSubsystemName=Sftp Files
+SshFileSubsystemDescription=Show Sftp Files on remote host.
diff --git a/rse/plugins/org.eclipse.rse.subsystems.files.ssh/plugin.xml b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/plugin.xml
new file mode 100644
index 00000000000..04fabb1967f
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/plugin.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
diff --git a/rse/plugins/org.eclipse.rse.subsystems.files.ssh/src/org/eclipse/rse/subsystems/files/ssh/Activator.java b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/src/org/eclipse/rse/subsystems/files/ssh/Activator.java
new file mode 100644
index 00000000000..a2829b360c6
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/src/org/eclipse/rse/subsystems/files/ssh/Activator.java
@@ -0,0 +1,61 @@
+package org.eclipse.rse.subsystems.files.ssh;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.rse.subsystems.files.ssh";
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+ /**
+ * Returns an image descriptor for the image file at the given
+ * plug-in relative path.
+ *
+ * @param path the path
+ * @return the image descriptor
+ */
+ public static ImageDescriptor getImageDescriptor(String path) {
+ return AbstractUIPlugin.imageDescriptorFromPlugin(PLUGIN_ID, path);
+ }
+
+}
diff --git a/rse/plugins/org.eclipse.rse.subsystems.files.ssh/src/org/eclipse/rse/subsystems/files/ssh/SftpFileAdapter.java b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/src/org/eclipse/rse/subsystems/files/ssh/SftpFileAdapter.java
new file mode 100644
index 00000000000..214fd9d9969
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/src/org/eclipse/rse/subsystems/files/ssh/SftpFileAdapter.java
@@ -0,0 +1,63 @@
+/********************************************************************************
+ * Copyright (c) 2006 IBM Corporation. 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
+ *
+ * Initial Contributors:
+ * The following IBM employees contributed to the Remote System Explorer
+ * component that contains this file: David McKnight, Kushal Munir,
+ * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,
+ * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
+ *
+ * Contributors:
+ * Martin Oberhuber (Wind River) - Adapted from FTPFileAdapter.
+ ********************************************************************************/
+
+package org.eclipse.rse.subsystems.files.ssh;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.rse.services.files.IHostFile;
+import org.eclipse.rse.services.ssh.files.SftpHostFile;
+import org.eclipse.rse.subsystems.files.core.servicesubsystem.FileServiceSubSystem;
+import org.eclipse.rse.subsystems.files.core.subsystems.IHostFileToRemoteFileAdapter;
+import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile;
+import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileContext;
+import org.eclipse.rse.ui.ISystemPreferencesConstants;
+import org.eclipse.rse.ui.RSEUIPlugin;
+
+public class SftpFileAdapter implements IHostFileToRemoteFileAdapter {
+
+ public IRemoteFile[] convertToRemoteFiles(FileServiceSubSystem ss, IRemoteFileContext context, IRemoteFile parent, IHostFile[] nodes) {
+ boolean showHidden = RSEUIPlugin.getDefault().getPreferenceStore().getBoolean(ISystemPreferencesConstants.SHOWHIDDEN);
+
+ List results = new ArrayList();
+ for (int i = 0; i < nodes.length; i++) {
+ SftpHostFile node = (SftpHostFile)nodes[i];
+ if (showHidden || !node.isHidden()) {
+ IRemoteFile remoteFile = new SftpRemoteFile(ss, context, parent, node);
+ results.add(remoteFile);
+ ss.cacheRemoteFile(remoteFile);
+ }
+ }
+ return (IRemoteFile[])results.toArray(new IRemoteFile[results.size()]);
+ }
+
+ public IRemoteFile convertToRemoteFile(FileServiceSubSystem ss, IRemoteFileContext context, IRemoteFile parent, String name, boolean isDirectory, boolean isRoot) {
+ return null;
+ }
+
+ public IRemoteFile convertToRemoteFile(FileServiceSubSystem ss, IRemoteFileContext context, IRemoteFile parent, IHostFile node) {
+ IRemoteFile file = new SftpRemoteFile(ss, context, parent, (SftpHostFile)node);
+ ss.cacheRemoteFile(file);
+ return file;
+ }
+
+ public IRemoteFile convertToRemoteFile(FileServiceSubSystem ss, IRemoteFileContext context, IRemoteFile parent, Object object) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/rse/plugins/org.eclipse.rse.subsystems.files.ssh/src/org/eclipse/rse/subsystems/files/ssh/SftpFileSubSystemConfiguration.java b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/src/org/eclipse/rse/subsystems/files/ssh/SftpFileSubSystemConfiguration.java
new file mode 100644
index 00000000000..2db9495fff3
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/src/org/eclipse/rse/subsystems/files/ssh/SftpFileSubSystemConfiguration.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems, Inc.
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.rse.subsystems.files.ssh;
+
+import org.eclipse.rse.connectorservice.ssh.SshConnectorService;
+import org.eclipse.rse.connectorservice.ssh.SshConnectorServiceManager;
+import org.eclipse.rse.core.subsystems.IConnectorService;
+import org.eclipse.rse.core.subsystems.ISubSystem;
+import org.eclipse.rse.internal.subsystems.files.core.ILanguageUtilityFactory;
+import org.eclipse.rse.model.IHost;
+import org.eclipse.rse.services.clientserver.SystemSearchString;
+import org.eclipse.rse.services.files.IFileService;
+import org.eclipse.rse.services.search.IHostSearchResultConfiguration;
+import org.eclipse.rse.services.search.IHostSearchResultSet;
+import org.eclipse.rse.services.search.ISearchService;
+import org.eclipse.rse.services.ssh.ISshService;
+import org.eclipse.rse.services.ssh.ISshSessionProvider;
+import org.eclipse.rse.services.ssh.files.SftpFileService;
+import org.eclipse.rse.subsystems.files.core.servicesubsystem.FileServiceSubSystem;
+import org.eclipse.rse.subsystems.files.core.servicesubsystem.FileServiceSubSystemConfiguration;
+import org.eclipse.rse.subsystems.files.core.subsystems.IHostFileToRemoteFileAdapter;
+import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileSubSystem;
+
+import com.jcraft.jsch.Session;
+
+public class SftpFileSubSystemConfiguration extends FileServiceSubSystemConfiguration {
+
+ protected IHostFileToRemoteFileAdapter _hostFileAdapter;
+
+ public SftpFileSubSystemConfiguration() {
+ super();
+ setIsUnixStyle(true);
+ }
+
+ public boolean isFactoryFor(Class subSystemType) {
+ boolean isFor = FileServiceSubSystem.class.equals(subSystemType);
+ return isFor;
+ }
+
+ public boolean supportsArchiveManagement() {
+ return false;
+ }
+
+ public ISubSystem createSubSystemInternal(IHost host) {
+ SshConnectorService connectorService = (SshConnectorService)getConnectorService(host);
+ ISubSystem subsys = new FileServiceSubSystem(host, connectorService, getFileService(host), getHostFileAdapter(), getSearchService(host));
+ return subsys;
+ }
+
+ public boolean supportsFileTypes() {
+ return false;
+ }
+
+ public boolean supportsSearch() {
+ return false;
+ }
+
+ public boolean supportsEnvironmentVariablesPropertyPage() {
+ return false;
+ }
+
+ public boolean supportsFilters() {
+ return true;
+ }
+
+ public IConnectorService getConnectorService(IHost host) {
+ return SshConnectorServiceManager.getInstance().getConnectorService(host, getServiceImplType());
+ }
+
+ public void setConnectorService(IHost host, IConnectorService connectorService) {
+ SshConnectorServiceManager.getInstance().setConnectorService(host, getServiceImplType(), connectorService);
+ }
+
+ public IFileService createFileService(IHost host) {
+ SshConnectorService connectorService = (SshConnectorService)getConnectorService(host);
+ //return connectorService.getFileService();
+ //TODO We have to get the file service from the connector service in order to make
+ //sure the connector service can connect it when required. It might be better to
+ //create a new instance here, and have it connect lazily on demand instead.
+ //In fact, due to ssh timeouts, it might be necessary that we can re-connect
+ //on demand on any operation anyway.
+ return new SftpFileService((ISshSessionProvider)connectorService);
+ }
+
+ public ISearchService createSearchService(IHost host) {
+ // no search service supported for ssh/sftp at moment
+ return null;
+ }
+
+ public IHostFileToRemoteFileAdapter getHostFileAdapter() {
+ if (_hostFileAdapter == null) {
+ _hostFileAdapter = new SftpFileAdapter();
+ }
+ return _hostFileAdapter;
+ }
+
+ public IHostSearchResultConfiguration createSearchConfiguration(IHost host, IHostSearchResultSet resultSet, Object searchTarget, SystemSearchString searchString) {
+ return null;
+ }
+
+ public ILanguageUtilityFactory getLanguageUtilityFactory(IRemoteFileSubSystem ss) {
+ return null;
+ }
+
+ public Class getServiceImplType() {
+ return ISshService.class;
+ }
+
+}
diff --git a/rse/plugins/org.eclipse.rse.subsystems.files.ssh/src/org/eclipse/rse/subsystems/files/ssh/SftpRemoteFile.java b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/src/org/eclipse/rse/subsystems/files/ssh/SftpRemoteFile.java
new file mode 100644
index 00000000000..6a5c308bee2
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.files.ssh/src/org/eclipse/rse/subsystems/files/ssh/SftpRemoteFile.java
@@ -0,0 +1,47 @@
+/********************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation. 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
+ *
+ * Initial Contributors:
+ * The following IBM employees contributed to the Remote System Explorer
+ * component that contains this file: David McKnight, Kushal Munir,
+ * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,
+ * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
+ *
+ * Contributors:
+ * Martin Oberhuber (Wind River) - Adapted from FTPRemoteFile.
+ ********************************************************************************/
+
+package org.eclipse.rse.subsystems.files.ssh;
+
+import org.eclipse.rse.services.ssh.files.SftpHostFile;
+import org.eclipse.rse.subsystems.files.core.servicesubsystem.AbstractRemoteFile;
+import org.eclipse.rse.subsystems.files.core.servicesubsystem.FileServiceSubSystem;
+import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile;
+import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileContext;
+
+public class SftpRemoteFile extends AbstractRemoteFile {
+
+ public SftpRemoteFile(FileServiceSubSystem ss, IRemoteFileContext context, IRemoteFile parent, SftpHostFile hostFile) {
+ super(ss, context, parent, hostFile);
+ }
+
+ public SftpHostFile getSftpHostFile() {
+ return (SftpHostFile)getHostFile();
+ }
+
+ public boolean isVirtual() {
+ return false;
+ }
+
+ public String getCanonicalPath() {
+ return getAbsolutePath();
+ }
+
+ public String getClassification() {
+ return getSftpHostFile().getClassification();
+ }
+
+}
diff --git a/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/.classpath b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/.classpath
new file mode 100644
index 00000000000..751c8f2e504
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/.project b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/.project
new file mode 100644
index 00000000000..8762a137e8d
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/.project
@@ -0,0 +1,28 @@
+
+
+ org.eclipse.rse.subsystems.shells.ssh
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/META-INF/MANIFEST.MF b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..1c67ac0c02a
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/META-INF/MANIFEST.MF
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Ssh Plug-in
+Bundle-SymbolicName: org.eclipse.rse.subsystems.shells.ssh; singleton:=true
+Bundle-Version: 1.0.0
+Bundle-Activator: org.eclipse.rse.subsystems.shells.ssh.Activator
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.rse.services,
+ org.eclipse.rse.connectorservice.ssh,
+ org.eclipse.rse.services.ssh,
+ org.eclipse.rse.ui,
+ org.eclipse.rse.core,
+ org.eclipse.rse.subsystems.shells.core,
+ com.jcraft.jsch
+Eclipse-LazyStart: true
+Export-Package: org.eclipse.rse.subsystems.shells.ssh
diff --git a/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/build.properties b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/build.properties
new file mode 100644
index 00000000000..34d2e4d2dad
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
diff --git a/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/icons/full/obj16/systemcommands_obj.gif b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/icons/full/obj16/systemcommands_obj.gif
new file mode 100644
index 00000000000..061b6e226a9
Binary files /dev/null and b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/icons/full/obj16/systemcommands_obj.gif differ
diff --git a/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/icons/full/obj16/systemcommandslive_obj.gif b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/icons/full/obj16/systemcommandslive_obj.gif
new file mode 100644
index 00000000000..3faca447424
Binary files /dev/null and b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/icons/full/obj16/systemcommandslive_obj.gif differ
diff --git a/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/plugin.properties b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/plugin.properties
new file mode 100644
index 00000000000..a882b3df9b0
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/plugin.properties
@@ -0,0 +1,17 @@
+################################################################################
+# Copyright (c) 2006 Wind River Systems, Inc.
+# 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 - initial API and implementation
+################################################################################
+
+plugin.name = Ssh Shells Plugin
+
+
+SshShellSubsystemName=Shells
+SshShellSubsystemDescription=This configuration allows you to work with shells and commands on remote systems using the Secure Shell (ssh) protocol.
+
diff --git a/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/plugin.xml b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/plugin.xml
new file mode 100644
index 00000000000..45aa5f0861a
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/plugin.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/src/org/eclipse/rse/subsystems/shells/ssh/Activator.java b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/src/org/eclipse/rse/subsystems/shells/ssh/Activator.java
new file mode 100644
index 00000000000..fe10bfb5c70
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/src/org/eclipse/rse/subsystems/shells/ssh/Activator.java
@@ -0,0 +1,61 @@
+package org.eclipse.rse.subsystems.shells.ssh;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.rse.subsystems.shells.ssh";
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns an image descriptor for the image file at the given
+ * plug-in relative path.
+ *
+ * @param path the path
+ * @return the image descriptor
+ */
+ public static ImageDescriptor getImageDescriptor(String path) {
+ return AbstractUIPlugin.imageDescriptorFromPlugin(PLUGIN_ID, path);
+ }
+}
diff --git a/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/src/org/eclipse/rse/subsystems/shells/ssh/SshShellSubSystemConfiguration.java b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/src/org/eclipse/rse/subsystems/shells/ssh/SshShellSubSystemConfiguration.java
new file mode 100644
index 00000000000..294339b41d7
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/src/org/eclipse/rse/subsystems/shells/ssh/SshShellSubSystemConfiguration.java
@@ -0,0 +1,82 @@
+/********************************************************************************
+ * Copyright (c) 2006 IBM Corporation. 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
+ *
+ * Initial Contributors:
+ * The following IBM employees contributed to the Remote System Explorer
+ * component that contains this file: David McKnight, Kushal Munir,
+ * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,
+ * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
+ *
+ * Contributors:
+ * Martin Oberhuber (Wind River) - Adapted template for ssh service.
+ ********************************************************************************/
+
+package org.eclipse.rse.subsystems.shells.ssh;
+
+import org.eclipse.rse.connectorservice.ssh.SshConnectorService;
+import org.eclipse.rse.connectorservice.ssh.SshConnectorServiceManager;
+import org.eclipse.rse.core.subsystems.IConnectorService;
+import org.eclipse.rse.core.subsystems.ISubSystem;
+import org.eclipse.rse.internal.model.Host;
+import org.eclipse.rse.model.IHost;
+import org.eclipse.rse.services.shells.IShellService;
+import org.eclipse.rse.services.ssh.ISshService;
+import org.eclipse.rse.services.ssh.ISshSessionProvider;
+import org.eclipse.rse.services.ssh.shell.SshShellService;
+import org.eclipse.rse.subsystems.shells.core.subsystems.servicesubsystem.ShellServiceSubSystem;
+import org.eclipse.rse.subsystems.shells.core.subsystems.servicesubsystem.ShellServiceSubSystemConfiguration;
+
+public class SshShellSubSystemConfiguration extends
+ ShellServiceSubSystemConfiguration {
+
+ public SshShellSubSystemConfiguration() {
+ super();
+ }
+
+ public boolean supportsCommands() {
+ //TODO support commands in SshShellService.runCommand()
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.rse.core.subsystems.SubSystemConfiguration#isFactoryFor(java.lang.Class)
+ */
+ public boolean isFactoryFor(Class subSystemType) {
+ boolean isFor = ShellServiceSubSystem.class.equals(subSystemType);
+ return isFor;
+ }
+
+ /**
+ * Instantiate and return an instance of OUR subystem.
+ * Do not populate it yet though!
+ * @see org.eclipse.rse.core.subsystems.impl.SubSystemFactoryImpl#createSubSystemInternal(Host)
+ */
+ public ISubSystem createSubSystemInternal(IHost host)
+ {
+ SshConnectorService connectorService = (SshConnectorService)getConnectorService(host);
+ ISubSystem subsys = new ShellServiceSubSystem(host, connectorService, createShellService(host));
+ return subsys;
+ }
+
+ public IShellService createShellService(IHost host) {
+ SshConnectorService cserv = (SshConnectorService)getConnectorService(host);
+ return new SshShellService((ISshSessionProvider)cserv);
+ }
+
+ public IConnectorService getConnectorService(IHost host) {
+ return SshConnectorServiceManager.getInstance().getConnectorService(host, ISshService.class);
+ }
+
+ public void setConnectorService(IHost host,
+ IConnectorService connectorService) {
+ SshConnectorServiceManager.getInstance().setConnectorService(host, ISshService.class, connectorService);
+ }
+
+ public Class getServiceImplType() {
+ return ISshService.class;
+ }
+
+}