mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-06 08:35:26 +02:00
integration of Martin's ssh services
This commit is contained in:
parent
c4f9cd45b1
commit
08d25895ba
46 changed files with 2326 additions and 0 deletions
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
28
rse/plugins/org.eclipse.rse.connectorservice.ssh/.project
Normal file
28
rse/plugins/org.eclipse.rse.connectorservice.ssh/.project
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>org.eclipse.rse.connectorservice.ssh</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.pde.PluginNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
|
@ -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
|
|
@ -0,0 +1,4 @@
|
||||||
|
source.. = src/
|
||||||
|
output.. = bin/
|
||||||
|
bin.includes = META-INF/,\
|
||||||
|
.
|
|
@ -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
|
||||||
|
|
22
rse/plugins/org.eclipse.rse.connectorservice.ssh/plugin.xml
Normal file
22
rse/plugins/org.eclipse.rse.connectorservice.ssh/plugin.xml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
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
|
||||||
|
-->
|
||||||
|
<?eclipse version="3.1"?>
|
||||||
|
<plugin>
|
||||||
|
<extension point="org.eclipse.rse.core.systemTypes">
|
||||||
|
<systemType id="org.eclipse.rse.systemtype.ssh"
|
||||||
|
name="SSH Only"
|
||||||
|
description="%SshSystemDescription">
|
||||||
|
<property name="icon" value="icons/full/obj16/systemcommands_obj.gif"/>
|
||||||
|
<property name="iconLive" value="icons/full/obj16/systemcommandslive_obj.gif"/>
|
||||||
|
</systemType>
|
||||||
|
</extension>
|
||||||
|
</plugin>
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// <copied from org.eclipse.team.cvs.ssh2>
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
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) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// </copied from org.eclipse.team.cvs.ssh2>
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
7
rse/plugins/org.eclipse.rse.services.ssh/.classpath
Normal file
7
rse/plugins/org.eclipse.rse.services.ssh/.classpath
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
28
rse/plugins/org.eclipse.rse.services.ssh/.project
Normal file
28
rse/plugins/org.eclipse.rse.services.ssh/.project
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>org.eclipse.rse.services.ssh</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.pde.PluginNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
|
@ -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
|
28
rse/plugins/org.eclipse.rse.services.ssh/about.html
Normal file
28
rse/plugins/org.eclipse.rse.services.ssh/about.html
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
|
||||||
|
<title>About</title>
|
||||||
|
</head>
|
||||||
|
<body lang="EN-US">
|
||||||
|
<h2>About This Content</h2>
|
||||||
|
|
||||||
|
<p>May 2, 2006</p>
|
||||||
|
<h3>License</h3>
|
||||||
|
|
||||||
|
<p>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 <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
|
||||||
|
For purposes of the EPL, "Program" will mean the Content.</p>
|
||||||
|
|
||||||
|
<p>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 <a href="/">http://www.eclipse.org</a>.</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
10
rse/plugins/org.eclipse.rse.services.ssh/build.properties
Normal file
10
rse/plugins/org.eclipse.rse.services.ssh/build.properties
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
bin.includes = .classpath,\
|
||||||
|
.project,\
|
||||||
|
about.html,\
|
||||||
|
build.properties,\
|
||||||
|
icons/,\
|
||||||
|
META-INF/,\
|
||||||
|
plugin.properties,\
|
||||||
|
plugin.xml,\
|
||||||
|
readme.txt,\
|
||||||
|
src/
|
66
rse/plugins/org.eclipse.rse.services.ssh/readme.txt
Normal file
66
rse/plugins/org.eclipse.rse.services.ssh/readme.txt
Normal file
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package org.eclipse.rse.services.ssh;
|
||||||
|
|
||||||
|
import com.jcraft.jsch.Session;
|
||||||
|
|
||||||
|
public interface ISshSessionProvider
|
||||||
|
{
|
||||||
|
public Session getSession();
|
||||||
|
}
|
|
@ -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<vv.size(); ii++) {
|
||||||
|
Object obj=vv.elementAt(ii);
|
||||||
|
if(obj instanceof ChannelSftp.LsEntry){
|
||||||
|
ChannelSftp.LsEntry lsEntry = (ChannelSftp.LsEntry)obj;
|
||||||
|
String fileName = lsEntry.getFilename();
|
||||||
|
if (".".equals(fileName) || "..".equals(fileName)) { //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
//don't show the trivial names
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (filematcher.matches(fileName)) {
|
||||||
|
SftpHostFile node = makeHostFile(parentPath, fileName, lsEntry.getAttrs());
|
||||||
|
if (isRightType(fileType, node)) {
|
||||||
|
results.add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(Exception e) {
|
||||||
|
//TODO throw new SystemMessageException.
|
||||||
|
//We get a "2: No such file" exception when we try to get contents
|
||||||
|
//of a symbolic link that turns out to point to a file rather than
|
||||||
|
//a directory. In this case, the result is probably expected.
|
||||||
|
//We should try to classify symbolic links as "file" or "dir" correctly.
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return (IHostFile[])results.toArray(new IHostFile[results.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SftpHostFile makeHostFile(String parentPath, String fileName, SftpATTRS attrs) {
|
||||||
|
SftpHostFile node = new SftpHostFile(parentPath, fileName, attrs.isDir(), false, attrs.isLink(), attrs.getMTime(), attrs.getSize());
|
||||||
|
if (attrs.getExtended()!=null) {
|
||||||
|
node.setExtendedData(attrs.getExtended());
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSeparator() {
|
||||||
|
return "/"; //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean upload(IProgressMonitor monitor, File localFile, String remoteParent, String remoteFile, boolean isBinary, String srcEncoding, String hostEncoding)
|
||||||
|
{
|
||||||
|
//TODO what to do with isBinary?
|
||||||
|
try {
|
||||||
|
SftpProgressMonitor sftpMonitor=new MyProgressMonitor(monitor);
|
||||||
|
int mode=ChannelSftp.OVERWRITE;
|
||||||
|
String dst = remoteParent;
|
||||||
|
if( remoteFile!=null ) {
|
||||||
|
if (!dst.endsWith("/")) { //$NON-NLS-1$
|
||||||
|
dst += '/';
|
||||||
|
}
|
||||||
|
dst += remoteFile;
|
||||||
|
}
|
||||||
|
fChannelSftp.put(localFile.getAbsolutePath(), dst, sftpMonitor, mode);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
//TODO See download
|
||||||
|
//e.printStackTrace();
|
||||||
|
//throw new RemoteFileIOException(e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MyProgressMonitor implements SftpProgressMonitor
|
||||||
|
{
|
||||||
|
IProgressMonitor fMonitor;
|
||||||
|
|
||||||
|
public MyProgressMonitor(IProgressMonitor monitor) {
|
||||||
|
fMonitor = monitor;
|
||||||
|
}
|
||||||
|
public void init(int op, String src, String dest, long max){
|
||||||
|
String desc = ((op==SftpProgressMonitor.PUT)?
|
||||||
|
"put" : "get")+": "+src; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
//TODO avoid cast from long to int
|
||||||
|
fMonitor.beginTask(desc, (int)max);
|
||||||
|
}
|
||||||
|
public boolean count(long count){
|
||||||
|
fMonitor.worked((int)count);
|
||||||
|
return !(fMonitor.isCanceled());
|
||||||
|
}
|
||||||
|
public void end(){
|
||||||
|
fMonitor.done();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public boolean upload(IProgressMonitor monitor, InputStream stream, String remoteParent, String remoteFile, boolean isBinary, String hostEncoding) throws SystemMessageException
|
||||||
|
{
|
||||||
|
//TODO hack for now
|
||||||
|
try
|
||||||
|
{
|
||||||
|
BufferedInputStream bis = new BufferedInputStream(stream);
|
||||||
|
File tempFile = File.createTempFile("ftp", "temp"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
FileOutputStream os = new FileOutputStream(tempFile);
|
||||||
|
BufferedOutputStream bos = new BufferedOutputStream(os);
|
||||||
|
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int readCount;
|
||||||
|
while( (readCount = bis.read(buffer)) > 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
28
rse/plugins/org.eclipse.rse.subsystems.files.ssh/.project
Normal file
28
rse/plugins/org.eclipse.rse.subsystems.files.ssh/.project
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>org.eclipse.rse.subsystems.files.ssh</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.pde.PluginNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
|
@ -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
|
|
@ -0,0 +1,4 @@
|
||||||
|
source.. = src/
|
||||||
|
output.. = bin/
|
||||||
|
bin.includes = META-INF/,\
|
||||||
|
.
|
Binary file not shown.
After Width: | Height: | Size: 157 B |
Binary file not shown.
After Width: | Height: | Size: 224 B |
|
@ -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.
|
28
rse/plugins/org.eclipse.rse.subsystems.files.ssh/plugin.xml
Normal file
28
rse/plugins/org.eclipse.rse.subsystems.files.ssh/plugin.xml
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
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
|
||||||
|
-->
|
||||||
|
<?eclipse version="3.1"?>
|
||||||
|
<plugin>
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.rse.ui.subsystemConfiguration">
|
||||||
|
<configuration
|
||||||
|
systemTypes="Linux;Unix;AIX;SSH Only"
|
||||||
|
name="%SshFileSubsystemName"
|
||||||
|
description="%SshFileSubsystemDescription"
|
||||||
|
iconlive="icons/full/obj16/systemfileslive_obj.gif"
|
||||||
|
icon="icons/full/obj16/systemfiles_obj.gif"
|
||||||
|
category="files"
|
||||||
|
class="org.eclipse.rse.subsystems.files.ssh.SftpFileSubSystemConfiguration"
|
||||||
|
vendor="Wind River Systems, Inc."
|
||||||
|
id="ssh.files">
|
||||||
|
</configuration>
|
||||||
|
</extension>
|
||||||
|
</plugin>
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
28
rse/plugins/org.eclipse.rse.subsystems.shells.ssh/.project
Normal file
28
rse/plugins/org.eclipse.rse.subsystems.shells.ssh/.project
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>org.eclipse.rse.subsystems.shells.ssh</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.pde.PluginNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
|
@ -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
|
|
@ -0,0 +1,4 @@
|
||||||
|
source.. = src/
|
||||||
|
output.. = bin/
|
||||||
|
bin.includes = META-INF/,\
|
||||||
|
.
|
Binary file not shown.
After Width: | Height: | Size: 230 B |
Binary file not shown.
After Width: | Height: | Size: 246 B |
|
@ -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.
|
||||||
|
|
29
rse/plugins/org.eclipse.rse.subsystems.shells.ssh/plugin.xml
Normal file
29
rse/plugins/org.eclipse.rse.subsystems.shells.ssh/plugin.xml
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
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
|
||||||
|
-->
|
||||||
|
<?eclipse version="3.1"?>
|
||||||
|
<plugin>
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.rse.ui.subsystemConfiguration">
|
||||||
|
<configuration
|
||||||
|
systemTypes="Linux;Unix;AIX;SSH Only"
|
||||||
|
name="%SshShellSubsystemName"
|
||||||
|
description="%SshShellSubsystemDescription"
|
||||||
|
iconlive="icons/full/obj16/systemcommandslive_obj.gif"
|
||||||
|
icon="icons/full/obj16/systemcommands_obj.gif"
|
||||||
|
category="shells"
|
||||||
|
class="org.eclipse.rse.subsystems.shells.ssh.SshShellSubSystemConfiguration"
|
||||||
|
vendor="Wind River Systems, Inc."
|
||||||
|
id="ssh.shells">
|
||||||
|
</configuration>
|
||||||
|
</extension>
|
||||||
|
|
||||||
|
</plugin>
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue