1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-18 13:45:45 +02:00

[224799] Fix JSch encoding problems with arabic UTF-8 file names

This commit is contained in:
Martin Oberhuber 2008-04-02 21:00:03 +00:00
parent 94f38246c5
commit 69c14379e8
2 changed files with 441 additions and 419 deletions

View file

@ -1,14 +1,14 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2006, 2008 Wind River Systems, Inc. and others. * Copyright (c) 2006, 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* Martin Oberhuber (Wind River) - initial API and implementation * Martin Oberhuber (Wind River) - initial API and implementation
* David Dykstal (IBM) - 168977: refactoring IConnectorService and ServerLauncher hierarchies * David Dykstal (IBM) - 168977: refactoring IConnectorService and ServerLauncher hierarchies
* Martin Oberhuber (Wind River) - [175686] Adapted to new IJSchService API * Martin Oberhuber (Wind River) - [175686] Adapted to new IJSchService API
* - copied code from org.eclipse.team.cvs.ssh2/JSchSession (Copyright IBM) * - copied code from org.eclipse.team.cvs.ssh2/JSchSession (Copyright IBM)
* Martin Oberhuber (Wind River) - [186773] split ISystemRegistryUI from ISystemRegistry * Martin Oberhuber (Wind River) - [186773] split ISystemRegistryUI from ISystemRegistry
* Martin Oberhuber (Wind River) - [186761] make the port setting configurable * Martin Oberhuber (Wind River) - [186761] make the port setting configurable
@ -65,21 +65,21 @@ import org.eclipse.rse.ui.SystemBasePlugin;
import org.eclipse.rse.ui.messages.SystemMessageDialog; import org.eclipse.rse.ui.messages.SystemMessageDialog;
import org.eclipse.rse.ui.subsystems.StandardConnectorService; import org.eclipse.rse.ui.subsystems.StandardConnectorService;
/** /**
* Create SSH connections. * Create SSH connections.
*/ */
public class SshConnectorService extends StandardConnectorService implements ISshSessionProvider public class SshConnectorService extends StandardConnectorService implements ISshSessionProvider
{ {
private static final int SSH_DEFAULT_PORT = 22; private static final int SSH_DEFAULT_PORT = 22;
private static final int CONNECT_DEFAULT_TIMEOUT = 60; //seconds private static final int CONNECT_DEFAULT_TIMEOUT = 60; //seconds
/** Property Keys. These are API because they are stored persistently. */ /** Property Keys. These are API because they are stored persistently. */
private static final String PROPERTY_SET_SSH_SETTINGS = "SSH Settings"; //$NON-NLS-1$ private static final String PROPERTY_SET_SSH_SETTINGS = "SSH Settings"; //$NON-NLS-1$
private static final String PROPERTY_KEY_TIMEOUT = "timeout(sec)"; //$NON-NLS-1$ private static final String PROPERTY_KEY_TIMEOUT = "timeout(sec)"; //$NON-NLS-1$
private static final String PROPERTY_KEY_KEEPALIVE = "keepalive(sec)"; //$NON-NLS-1$ private static final String PROPERTY_KEY_KEEPALIVE = "keepalive(sec)"; //$NON-NLS-1$
private Session session; private Session session;
private SessionLostHandler fSessionLostHandler; private SessionLostHandler fSessionLostHandler;
/** Indicates the default string encoding on this platform */ /** Indicates the default string encoding on this platform */
private static String _defaultEncoding = new java.io.InputStreamReader(new java.io.ByteArrayInputStream(new byte[0])).getEncoding(); private static String _defaultEncoding = new java.io.InputStreamReader(new java.io.ByteArrayInputStream(new byte[0])).getEncoding();
@ -100,46 +100,46 @@ public class SshConnectorService extends StandardConnectorService implements ISs
* the Jsch config (for instance, in order to switch off strict * the Jsch config (for instance, in order to switch off strict
* host key checking or in order to add specific ciphers). * host key checking or in order to add specific ciphers).
*/ */
protected Session createSession(String username, String password, String hostname, int port, UserInfo wrapperUI, IProgressMonitor monitor) throws JSchException { protected Session createSession(String username, String password, String hostname, int port, UserInfo wrapperUI, IProgressMonitor monitor) throws JSchException {
IJSchService service = Activator.getDefault().getJSchService(); IJSchService service = Activator.getDefault().getJSchService();
if (service == null) if (service == null)
return null; return null;
Session session = service.createSession(hostname, port, username); Session session = service.createSession(hostname, port, username);
IPropertySet propertySet = getPropertySet(); IPropertySet propertySet = getPropertySet();
String timeoutStr = propertySet.getPropertyValue(PROPERTY_KEY_TIMEOUT); String timeoutStr = propertySet.getPropertyValue(PROPERTY_KEY_TIMEOUT);
int timeout = 0; //default is never timeout int timeout = 0; //default is never timeout
try { try {
int value = Integer.parseInt(timeoutStr); int value = Integer.parseInt(timeoutStr);
if (value > 0) { if (value > 0) {
timeout = value * 1000; timeout = value * 1000;
} }
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
//wrong input - should never happen because property type is Integer //wrong input - should never happen because property type is Integer
} }
session.setTimeout(timeout); session.setTimeout(timeout);
int keepalive = 300000; //default is 5 minutes int keepalive = 300000; //default is 5 minutes
String keepaliveStr = propertySet.getPropertyValue(PROPERTY_KEY_KEEPALIVE); String keepaliveStr = propertySet.getPropertyValue(PROPERTY_KEY_KEEPALIVE);
try { try {
int value = Integer.parseInt(keepaliveStr); int value = Integer.parseInt(keepaliveStr);
if (value >= 0) { if (value >= 0) {
keepalive = value * 1000; keepalive = value * 1000;
} }
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
//wrong input - should never happen because property type is Integer //wrong input - should never happen because property type is Integer
} }
if (keepalive > 0) { if (keepalive > 0) {
session.setServerAliveInterval(keepalive); session.setServerAliveInterval(keepalive);
} }
session.setServerAliveCountMax(6); //give up after 6 tries (remote will be dead after 30 min) session.setServerAliveCountMax(6); //give up after 6 tries (remote will be dead after 30 min)
if (password != null) if (password != null)
session.setPassword(password); session.setPassword(password);
session.setUserInfo(wrapperUI); session.setUserInfo(wrapperUI);
return session; return session;
} }
static void shutdown() { static void shutdown() {
//TODO: Store all Jsch sessions in a pool and disconnect them on shutdown //TODO: Store all Jsch sessions in a pool and disconnect them on shutdown
@ -159,45 +159,45 @@ public class SshConnectorService extends StandardConnectorService implements ISs
} }
protected void internalConnect(IProgressMonitor monitor) throws Exception protected void internalConnect(IProgressMonitor monitor) throws Exception
{ {
// Fire comm event to signal state about to change // Fire comm event to signal state about to change
fireCommunicationsEvent(CommunicationsEvent.BEFORE_CONNECT); fireCommunicationsEvent(CommunicationsEvent.BEFORE_CONNECT);
String host = getHostName(); String host = getHostName();
String user = getUserId(); String user = getUserId();
String password=""; //$NON-NLS-1$ String password=""; //$NON-NLS-1$
SystemSignonInformation ssi = getSignonInformation(); SystemSignonInformation ssi = getSignonInformation();
if (ssi!=null) { if (ssi!=null) {
password = getSignonInformation().getPassword(); password = getSignonInformation().getPassword();
} }
MyUserInfo userInfo = new MyUserInfo(user, password); MyUserInfo userInfo = new MyUserInfo(user, password);
userInfo.aboutToConnect(); userInfo.aboutToConnect();
try {
session = createSession(user, password, host, getSshPort(),
userInfo, monitor);
//java.util.Hashtable config=new java.util.Hashtable(); try {
//config.put("StrictHostKeyChecking", "no"); session = createSession(user, password, host, getSshPort(),
//session.setConfig(config); userInfo, monitor);
userInfo.aboutToConnect();
Activator.trace("SshConnectorService.connecting..."); //$NON-NLS-1$ //java.util.Hashtable config=new java.util.Hashtable();
//wait for 60 sec maximum during connect //config.put("StrictHostKeyChecking", "no");
session.connect(CONNECT_DEFAULT_TIMEOUT * 1000); //session.setConfig(config);
Activator.trace("SshConnectorService.connected"); //$NON-NLS-1$ userInfo.aboutToConnect();
} catch (JSchException e) {
Activator.trace("SshConnectorService.connect failed: "+e.toString()); //$NON-NLS-1$ Activator.trace("SshConnectorService.connecting..."); //$NON-NLS-1$
sessionDisconnect(); //wait for 60 sec maximum during connect
session.connect(CONNECT_DEFAULT_TIMEOUT * 1000);
Activator.trace("SshConnectorService.connected"); //$NON-NLS-1$
} catch (JSchException e) {
Activator.trace("SshConnectorService.connect failed: "+e.toString()); //$NON-NLS-1$
sessionDisconnect();
if(e.toString().indexOf("Auth cancel")>=0) { //$NON-NLS-1$ if(e.toString().indexOf("Auth cancel")>=0) { //$NON-NLS-1$
throw new OperationCanceledException(); throw new OperationCanceledException();
} }
throw e; throw e;
} }
userInfo.connectionMade(); userInfo.connectionMade();
fSessionLostHandler = new SessionLostHandler(this); fSessionLostHandler = new SessionLostHandler(this);
notifyConnection(); notifyConnection();
} }
/** /**
* Disconnect the ssh session. * Disconnect the ssh session.
@ -205,21 +205,21 @@ public class SshConnectorService extends StandardConnectorService implements ISs
* quickly in succession. * quickly in succession.
*/ */
private synchronized void sessionDisconnect() { private synchronized void sessionDisconnect() {
Activator.trace("SshConnectorService.sessionDisconnect"); //$NON-NLS-1$ Activator.trace("SshConnectorService.sessionDisconnect"); //$NON-NLS-1$
try { try {
if (session.isConnected()) if (session.isConnected())
session.disconnect(); session.disconnect();
} catch(Exception e) { } catch(Exception e) {
//Bug 175328: NPE on disconnect shown in UI //Bug 175328: NPE on disconnect shown in UI
//This is a non-critical exception so print only in debug mode //This is a non-critical exception so print only in debug mode
if (Activator.isTracingOn()) e.printStackTrace(); if (Activator.isTracingOn()) e.printStackTrace();
} }
} }
protected void internalDisconnect(IProgressMonitor monitor) throws Exception protected void internalDisconnect(IProgressMonitor monitor) throws Exception
{ {
//TODO Will services like the sftp service be disconnected too? Or notified? //TODO Will services like the sftp service be disconnected too? Or notified?
Activator.trace("SshConnectorService.disconnect"); //$NON-NLS-1$ Activator.trace("SshConnectorService.disconnect"); //$NON-NLS-1$
try try
{ {
if (session != null) { if (session != null) {
@ -230,13 +230,13 @@ public class SshConnectorService extends StandardConnectorService implements ISs
// handle events // handle events
if (sessionLost) { if (sessionLost) {
notifyError(); notifyError();
} }
else { else {
// Fire comm event to signal state about to change // Fire comm event to signal state about to change
fireCommunicationsEvent(CommunicationsEvent.BEFORE_DISCONNECT); fireCommunicationsEvent(CommunicationsEvent.BEFORE_DISCONNECT);
} }
sessionDisconnect(); sessionDisconnect();
// Fire comm event to signal state changed // Fire comm event to signal state changed
notifyDisconnection(); notifyDisconnection();
//TODO MOB - keep the session to avoid NPEs in services (disables gc for the session!) //TODO MOB - keep the session to avoid NPEs in services (disables gc for the session!)
@ -253,43 +253,42 @@ public class SshConnectorService extends StandardConnectorService implements ISs
} }
//TODO avoid having jsch type "Session" in the API. //TODO avoid having jsch type "Session" in the API.
//Could be done by instanciating SshShellService and SshFileService here, // Could be done by instantiating SshShellService and SshFileService here,
//and implementing IShellService getShellService() //and implementing IShellService getShellService()
//and IFileService getFileService(). //and IFileService getFileService().
public Session getSession() { public Session getSession() {
return session; return session;
} }
public String getControlEncoding() { public String getControlEncoding() {
//TODO this code should be in IHost //TODO this code should be in IHost
String encoding = getHost().getDefaultEncoding(false); String encoding = getHost().getDefaultEncoding(true);
if (encoding==null) encoding = getHost().getDefaultEncoding(true);
if (encoding==null) encoding = _defaultEncoding; if (encoding==null) encoding = _defaultEncoding;
//</code to be in IHost> //</code to be in IHost>
return encoding; return encoding;
} }
/** /**
* Handle session-lost events. * Handle session-lost events.
* This is generic for any sort of connector service. * This is generic for any sort of connector service.
* Most of this is extracted from dstore's ConnectionStatusListener. * Most of this is extracted from dstore's ConnectionStatusListener.
* *
* TODO should be refactored to make it generally available, and allow * TODO should be refactored to make it generally available, and allow
* dstore to derive from it. * dstore to derive from it.
*/ */
public static class SessionLostHandler implements Runnable, IRunnableWithProgress public static class SessionLostHandler implements Runnable, IRunnableWithProgress
{ {
private IConnectorService _connection; private IConnectorService _connection;
private boolean fSessionLost; private boolean fSessionLost;
public SessionLostHandler(IConnectorService cs) public SessionLostHandler(IConnectorService cs)
{ {
_connection = cs; _connection = cs;
fSessionLost = false; fSessionLost = false;
} }
/** /**
* Notify that the connection has been lost. This may be called * Notify that the connection has been lost. This may be called
* multiple times from multiple subsystems. The SessionLostHandler * multiple times from multiple subsystems. The SessionLostHandler
* ensures that actual user feedback and disconnect actions are * ensures that actual user feedback and disconnect actions are
* done only once, on the first invocation. * done only once, on the first invocation.
@ -309,11 +308,11 @@ public class SshConnectorService extends StandardConnectorService implements ISs
Display.getDefault().asyncExec(this); Display.getDefault().asyncExec(this);
} }
} }
public synchronized boolean isSessionLost() { public synchronized boolean isSessionLost() {
return fSessionLost; return fSessionLost;
} }
public void run() public void run()
{ {
Shell shell = getShell(); Shell shell = getShell();
@ -321,9 +320,9 @@ public class SshConnectorService extends StandardConnectorService implements ISs
//TODO allow users to reconnect from this dialog //TODO allow users to reconnect from this dialog
//SystemMessage msg = RSEUIPlugin.getPluginMessage(ISystemMessages.MSG_CONNECT_UNKNOWNHOST); //SystemMessage msg = RSEUIPlugin.getPluginMessage(ISystemMessages.MSG_CONNECT_UNKNOWNHOST);
SystemMessage msg = new SimpleSystemMessage(Activator.PLUGIN_ID, SystemMessage msg = new SimpleSystemMessage(Activator.PLUGIN_ID,
ICommonMessageIds.MSG_CONNECT_CANCELED, IStatus.CANCEL, ICommonMessageIds.MSG_CONNECT_CANCELED, IStatus.CANCEL,
NLS.bind(CommonMessages.MSG_CONNECT_CANCELED, NLS.bind(CommonMessages.MSG_CONNECT_CANCELED,
_connection.getHost().getAliasName())); _connection.getHost().getAliasName()));
SystemMessageDialog dialog = new SystemMessageDialog(getShell(), msg); SystemMessageDialog dialog = new SystemMessageDialog(getShell(), msg);
@ -334,23 +333,23 @@ public class SshConnectorService extends StandardConnectorService implements ISs
//But what about error messages? //But what about error messages?
IRunnableContext runnableContext = getRunnableContext(getShell()); IRunnableContext runnableContext = getRunnableContext(getShell());
// will do this.run(IProgressMonitor mon) // will do this.run(IProgressMonitor mon)
//runnableContext.run(false,true,this); // inthread, cancellable, IRunnableWithProgress //runnableContext.run(false,true,this); // inthread, cancellable, IRunnableWithProgress
runnableContext.run(true,true,this); // fork, cancellable, IRunnableWithProgress runnableContext.run(true,true,this); // fork, cancellable, IRunnableWithProgress
_connection.reset(); _connection.reset();
ISystemRegistry sr = RSECorePlugin.getTheSystemRegistry(); ISystemRegistry sr = RSECorePlugin.getTheSystemRegistry();
sr.connectedStatusChange(_connection.getPrimarySubSystem(), false, true, true); sr.connectedStatusChange(_connection.getPrimarySubSystem(), false, true, true);
}
catch (InterruptedException exc) // user cancelled
{
if (shell != null)
showDisconnectCancelledMessage(shell, _connection.getHostName(), _connection.getPort());
}
catch (java.lang.reflect.InvocationTargetException invokeExc) // unexpected error
{
Exception exc = (Exception)invokeExc.getTargetException();
if (shell != null)
showDisconnectErrorMessage(shell, _connection.getHostName(), _connection.getPort(), exc);
} }
catch (InterruptedException exc) // user cancelled
{
if (shell != null)
showDisconnectCancelledMessage(shell, _connection.getHostName(), _connection.getPort());
}
catch (java.lang.reflect.InvocationTargetException invokeExc) // unexpected error
{
Exception exc = (Exception)invokeExc.getTargetException();
if (shell != null)
showDisconnectErrorMessage(shell, _connection.getHostName(), _connection.getPort(), exc);
}
catch (Exception e) catch (Exception e)
{ {
SystemBasePlugin.logError(SshConnectorResources.SshConnectorService_ErrorDisconnecting, e); SystemBasePlugin.logError(SshConnectorResources.SshConnectorService_ErrorDisconnecting, e);
@ -358,7 +357,7 @@ public class SshConnectorService extends StandardConnectorService implements ISs
} }
public void run(IProgressMonitor monitor) public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException throws InvocationTargetException, InterruptedException
{ {
String message = null; String message = null;
message = SubSystemConfiguration.getDisconnectingMessage( message = SubSystemConfiguration.getDisconnectingMessage(
@ -391,7 +390,7 @@ public class SshConnectorService extends StandardConnectorService implements ISs
} }
if (window == null) { if (window == null) {
IWorkbenchWindow[] windows = PlatformUI.getWorkbench() IWorkbenchWindow[] windows = PlatformUI.getWorkbench()
.getWorkbenchWindows(); .getWorkbenchWindows();
if (windows != null && windows.length > 0) { if (windows != null && windows.length > 0) {
return windows[0].getShell(); return windows[0].getShell();
} }
@ -402,7 +401,7 @@ public class SshConnectorService extends StandardConnectorService implements ISs
return null; return null;
} }
/** /**
* Get the progress monitor dialog for this operation. We try to use one * Get the progress monitor dialog for this operation. We try to use one
* for all phases of a single operation, such as connecting and * for all phases of a single operation, such as connecting and
* resolving. * resolving.
@ -413,11 +412,11 @@ public class SshConnectorService extends StandardConnectorService implements ISs
IWorkbenchWindow win = SystemBasePlugin.getActiveWorkbenchWindow(); IWorkbenchWindow win = SystemBasePlugin.getActiveWorkbenchWindow();
if (win != null) { if (win != null) {
Shell winShell = RSEUIPlugin.getDefault().getWorkbench() Shell winShell = RSEUIPlugin.getDefault().getWorkbench()
.getActiveWorkbenchWindow().getShell(); .getActiveWorkbenchWindow().getShell();
if (winShell != null && !winShell.isDisposed() if (winShell != null && !winShell.isDisposed()
&& winShell.isVisible()) { && winShell.isVisible()) {
SystemBasePlugin SystemBasePlugin
.logInfo("Using active workbench window as runnable context"); //$NON-NLS-1$ .logInfo("Using active workbench window as runnable context"); //$NON-NLS-1$
shell = winShell; shell = winShell;
return win; return win;
} else { } else {
@ -426,69 +425,69 @@ public class SshConnectorService extends StandardConnectorService implements ISs
} }
if (shell == null || shell.isDisposed() || !shell.isVisible()) { if (shell == null || shell.isDisposed() || !shell.isVisible()) {
SystemBasePlugin SystemBasePlugin
.logInfo("Using progress monitor dialog with given shell as parent"); //$NON-NLS-1$ .logInfo("Using progress monitor dialog with given shell as parent"); //$NON-NLS-1$
shell = rshell; shell = rshell;
} }
IRunnableContext dlg = new ProgressMonitorDialog(rshell); IRunnableContext dlg = new ProgressMonitorDialog(rshell);
return dlg; return dlg;
} }
/** /**
* Show an error message when the disconnection fails. Shows a common * Show an error message when the disconnection fails. Shows a common
* message by default. Overridable. * message by default. Overridable.
*/ */
protected void showDisconnectErrorMessage(Shell shell, String hostName, int port, Exception exc) protected void showDisconnectErrorMessage(Shell shell, String hostName, int port, Exception exc)
{ {
//SystemMessage.displayMessage(SystemMessage.MSGTYPE_ERROR,shell,RSEUIPlugin.getResourceBundle(), //SystemMessage.displayMessage(SystemMessage.MSGTYPE_ERROR,shell,RSEUIPlugin.getResourceBundle(),
// ISystemMessages.MSG_DISCONNECT_FAILED, // ISystemMessages.MSG_DISCONNECT_FAILED,
// hostName, exc.getMessage()); // hostName, exc.getMessage());
//RSEUIPlugin.logError("Disconnect failed",exc); // temporary //RSEUIPlugin.logError("Disconnect failed",exc); // temporary
SystemMessage msg = new SimpleSystemMessage(Activator.PLUGIN_ID, ICommonMessageIds.MSG_DISCONNECT_FAILED, IStatus.ERROR, NLS.bind(CommonMessages.MSG_DISCONNECT_FAILED, hostName), exc); SystemMessage msg = new SimpleSystemMessage(Activator.PLUGIN_ID, ICommonMessageIds.MSG_DISCONNECT_FAILED, IStatus.ERROR, NLS.bind(CommonMessages.MSG_DISCONNECT_FAILED, hostName), exc);
SystemMessageDialog msgDlg = new SystemMessageDialog(shell, msg); SystemMessageDialog msgDlg = new SystemMessageDialog(shell, msg);
msgDlg.setException(exc); msgDlg.setException(exc);
msgDlg.open(); msgDlg.open();
} }
/** /**
* Show an error message when the user cancels the disconnection. * Show an error message when the user cancels the disconnection.
* Shows a common message by default. * Shows a common message by default.
* Overridable. * Overridable.
*/ */
protected void showDisconnectCancelledMessage(Shell shell, String hostName, int port) protected void showDisconnectCancelledMessage(Shell shell, String hostName, int port)
{ {
//SystemMessage.displayMessage(SystemMessage.MSGTYPE_ERROR, shell, RSEUIPlugin.getResourceBundle(), //SystemMessage.displayMessage(SystemMessage.MSGTYPE_ERROR, shell, RSEUIPlugin.getResourceBundle(),
// ISystemMessages.MSG_DISCONNECT_CANCELED, hostName) // ISystemMessages.MSG_DISCONNECT_CANCELED, hostName)
SystemMessage msg = new SimpleSystemMessage(Activator.PLUGIN_ID, ICommonMessageIds.MSG_DISCONNECT_CANCELED, IStatus.CANCEL, NLS.bind(CommonMessages.MSG_DISCONNECT_CANCELED, hostName)); SystemMessage msg = new SimpleSystemMessage(Activator.PLUGIN_ID, ICommonMessageIds.MSG_DISCONNECT_CANCELED, IStatus.CANCEL, NLS.bind(CommonMessages.MSG_DISCONNECT_CANCELED, hostName));
SystemMessageDialog msgDlg = new SystemMessageDialog(shell,msg); SystemMessageDialog msgDlg = new SystemMessageDialog(shell,msg);
msgDlg.open(); msgDlg.open();
} }
} }
/** /**
* Notification from sub-services that our session was lost. * Notification from sub-services that our session was lost.
* Notify all subsystems properly. * Notify all subsystems properly.
* TODO allow user to try and reconnect? * TODO allow user to try and reconnect?
*/ */
public void handleSessionLost() { public void handleSessionLost() {
Activator.trace("SshConnectorService: handleSessionLost"); //$NON-NLS-1$ Activator.trace("SshConnectorService: handleSessionLost"); //$NON-NLS-1$
if (fSessionLostHandler!=null) { if (fSessionLostHandler!=null) {
fSessionLostHandler.sessionLost(); fSessionLostHandler.sessionLost();
} }
} }
protected static Display getStandardDisplay() { protected static Display getStandardDisplay() {
Display display = Display.getCurrent(); Display display = Display.getCurrent();
if( display==null ) { if( display==null ) {
display = Display.getDefault(); display = Display.getDefault();
} }
return display; return display;
} }
private static class MyUserInfo implements UserInfo, UIKeyboardInteractive { private static class MyUserInfo implements UserInfo, UIKeyboardInteractive {
private String fPassphrase; private String fPassphrase;
private String fPassword; private String fPassword;
private int fAttemptCount; private int fAttemptCount;
private final String fUser; private final String fUser;
public MyUserInfo(String user, String password) { public MyUserInfo(String user, String password) {
fUser = user; fUser = user;
@ -502,10 +501,10 @@ public class SshConnectorService extends StandardConnectorService implements ISs
final boolean[] retval = new boolean[1]; final boolean[] retval = new boolean[1];
getStandardDisplay().syncExec(new Runnable() { getStandardDisplay().syncExec(new Runnable() {
public void run() { public void run() {
retval[0] = MessageDialog.openQuestion(null, SshConnectorResources.SshConnectorService_Warning, str); retval[0] = MessageDialog.openQuestion(null, SshConnectorResources.SshConnectorService_Warning, str);
} }
}); });
return retval[0]; return retval[0];
} }
private String promptSecret(final String message) { private String promptSecret(final String message) {
final String[] retval = new String[1]; final String[] retval = new String[1];
@ -546,57 +545,57 @@ public class SshConnectorService extends StandardConnectorService implements ISs
} }
}); });
} }
public String[] promptKeyboardInteractive(final String destination, public String[] promptKeyboardInteractive(final String destination,
final String name, final String instruction, final String name, final String instruction,
final String[] prompt, final boolean[] echo) final String[] prompt, final boolean[] echo)
{ {
if (prompt.length == 0) { if (prompt.length == 0) {
// No need to prompt, just return an empty String array // No need to prompt, just return an empty String array
return new String[0]; return new String[0];
} }
try{ try{
if (fAttemptCount == 0 && fPassword != null && prompt.length == 1 && prompt[0].trim().equalsIgnoreCase("password:")) { //$NON-NLS-1$ if (fAttemptCount == 0 && fPassword != null && prompt.length == 1 && prompt[0].trim().equalsIgnoreCase("password:")) { //$NON-NLS-1$
// Return the provided password the first time but always prompt on subsequent tries // Return the provided password the first time but always prompt on subsequent tries
fAttemptCount++; fAttemptCount++;
return new String[] { fPassword }; return new String[] { fPassword };
} }
final String[][] finResult = new String[1][]; final String[][] finResult = new String[1][];
getStandardDisplay().syncExec(new Runnable() { getStandardDisplay().syncExec(new Runnable() {
public void run() { public void run() {
KeyboardInteractiveDialog dialog = new KeyboardInteractiveDialog(null, KeyboardInteractiveDialog dialog = new KeyboardInteractiveDialog(null,
null, destination, name, instruction, prompt, echo); null, destination, name, instruction, prompt, echo);
dialog.open(); dialog.open();
finResult[0]=dialog.getResult(); finResult[0]=dialog.getResult();
} }
}); });
String[] result=finResult[0]; String[] result=finResult[0];
if (result == null) if (result == null)
return null; // canceled return null; // canceled
if (result.length == 1 && prompt.length == 1 && prompt[0].trim().equalsIgnoreCase("password:")) { //$NON-NLS-1$ if (result.length == 1 && prompt.length == 1 && prompt[0].trim().equalsIgnoreCase("password:")) { //$NON-NLS-1$
fPassword = result[0]; fPassword = result[0];
} }
fAttemptCount++; fAttemptCount++;
return result; return result;
} }
catch(OperationCanceledException e){ catch(OperationCanceledException e){
return null; return null;
} }
} }
/** /**
* Callback to indicate that a connection is about to be attempted * Callback to indicate that a connection is about to be attempted
*/ */
public void aboutToConnect() { public void aboutToConnect() {
fAttemptCount = 0; fAttemptCount = 0;
} }
/** /**
* Callback to indicate that a connection was made * Callback to indicate that a connection was made
*/ */
public void connectionMade() { public void connectionMade() {
fAttemptCount = 0; fAttemptCount = 0;
} }
} }
public boolean isConnected() { public boolean isConnected() {
if (session!=null) { if (session!=null) {
if (session.isConnected()) { if (session.isConnected()) {
@ -608,15 +607,15 @@ public class SshConnectorService extends StandardConnectorService implements ISs
} }
return false; return false;
} }
public boolean requiresPassword() { public boolean requiresPassword() {
return false; return false;
} }
public boolean requiresUserId() { public boolean requiresUserId() {
return false; return false;
} }
private IPropertySet getPropertySet() private IPropertySet getPropertySet()
{ {
IPropertySet propertySet = getPropertySet(PROPERTY_SET_SSH_SETTINGS); IPropertySet propertySet = getPropertySet(PROPERTY_SET_SSH_SETTINGS);

View file

@ -1,14 +1,14 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2006, 2008 Wind River Systems, Inc. and others. * Copyright (c) 2006, 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* Martin Oberhuber (Wind River) - initial API and implementation * Martin Oberhuber (Wind River) - initial API and implementation
* David Dykstal (IBM) - fixing bug 162510: correctly process filter strings * David Dykstal (IBM) - fixing bug 162510: correctly process filter strings
* Kushal Munir (IBM) - for API bug * Kushal Munir (IBM) - for API bug
* Martin Oberhuber (Wind River) - [186128] Move IProgressMonitor last in all API * Martin Oberhuber (Wind River) - [186128] Move IProgressMonitor last in all API
* Martin Oberhuber (Wind River) - [192724] Fixed logic to filter folders if FILE_TYPE_FOLDERS * Martin Oberhuber (Wind River) - [192724] Fixed logic to filter folders if FILE_TYPE_FOLDERS
* Martin Oberhuber (Wind River) - [199548] Avoid touching files on setReadOnly() if unnecessary * Martin Oberhuber (Wind River) - [199548] Avoid touching files on setReadOnly() if unnecessary
@ -23,6 +23,7 @@
* David McKnight (IBM) - [209593] [api] add support for "file permissions" and "owner" properties for unix files * David McKnight (IBM) - [209593] [api] add support for "file permissions" and "owner" properties for unix files
* Martin Oberhuber (Wind River) - [216343] immediate link targets and canonical paths for Sftp * Martin Oberhuber (Wind River) - [216343] immediate link targets and canonical paths for Sftp
* David McKnight (IBM) - [216252] [api][nls] Resource Strings specific to subsystems should be moved from rse.ui into files.ui / shells.ui / processes.ui where possible * David McKnight (IBM) - [216252] [api][nls] Resource Strings specific to subsystems should be moved from rse.ui into files.ui / shells.ui / processes.ui where possible
* Martin Oberhuber (Wind River) - [224799] Fix JSch encoding problems with Arabic filenames
*******************************************************************************/ *******************************************************************************/
package org.eclipse.rse.internal.services.ssh.files; package org.eclipse.rse.internal.services.ssh.files;
@ -82,9 +83,9 @@ public class SftpFileService extends AbstractFileService implements IFileService
{ {
private static class SftpBufferedInputStream extends BufferedInputStream { private static class SftpBufferedInputStream extends BufferedInputStream {
private ChannelSftp channel; private ChannelSftp channel;
/** /**
* Creates a BufferedInputStream and saves its argument, the input stream, for later use. An internal buffer array is created. * Creates a BufferedInputStream and saves its argument, the input stream, for later use. An internal buffer array is created.
* @param in the underlying input stream. * @param in the underlying input stream.
@ -115,11 +116,11 @@ public class SftpFileService extends AbstractFileService implements IFileService
channel.disconnect(); channel.disconnect();
} }
} }
private static class SftpBufferedOutputStream extends BufferedOutputStream { private static class SftpBufferedOutputStream extends BufferedOutputStream {
private ChannelSftp channel; private ChannelSftp channel;
/** /**
* Creates a new buffered output stream to write data to the specified underlying output stream with a default 512-byte buffer size. * Creates a new buffered output stream to write data to the specified underlying output stream with a default 512-byte buffer size.
* @param out the underlying output stream. * @param out the underlying output stream.
@ -150,7 +151,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
channel.disconnect(); channel.disconnect();
} }
} }
//private SshConnectorService fConnector; //private SshConnectorService fConnector;
private ISshSessionProvider fSessionProvider; private ISshSessionProvider fSessionProvider;
private ChannelSftp fChannelSftp; private ChannelSftp fChannelSftp;
@ -161,19 +162,37 @@ public class SftpFileService extends AbstractFileService implements IFileService
private String fControlEncoding = null; private String fControlEncoding = null;
/** Indicates the default string encoding on this platform */ /** Indicates the default string encoding on this platform */
private static String defaultEncoding = new java.io.InputStreamReader(new java.io.ByteArrayInputStream(new byte[0])).getEncoding(); private static String defaultEncoding = new java.io.InputStreamReader(new java.io.ByteArrayInputStream(new byte[0])).getEncoding();
/** Indicates the encoding that our JSch channel uses */
// public SftpFileService(SshConnectorService conn) { private String fJSchChannelEncoding = defaultEncoding;
// fConnector = conn;
// } // public SftpFileService(SshConnectorService conn) {
// fConnector = conn;
// }
public SftpFileService(ISshSessionProvider sessionProvider) { public SftpFileService(ISshSessionProvider sessionProvider) {
fSessionProvider = sessionProvider; fSessionProvider = sessionProvider;
} }
public void setControlEncoding(String encoding) { public void setControlEncoding(String encoding) throws SystemMessageException {
try {
fChannelSftp.setFilenameEncoding(encoding);
fJSchChannelEncoding = encoding;
} catch (NoSuchMethodError e) {
// Fallback for JSch < 0.1.34: use recode() for encoding conversion
fControlEncoding = encoding;
fJSchChannelEncoding = defaultEncoding;
} catch (SftpException e) {
try {
fChannelSftp.setFilenameEncoding("UTF-8"); //$NON-NLS-1$
fJSchChannelEncoding = "UTF-8"; //$NON-NLS-1$
} catch (SftpException enest) {
// should not happen, are we not connected?
throw makeSystemMessageException(enest);
}
}
fControlEncoding = encoding; fControlEncoding = encoding;
} }
/** /**
* Encode String with requested user encoding, in case it differs from Platform default encoding. * Encode String with requested user encoding, in case it differs from Platform default encoding.
* @param s String to encode * @param s String to encode
@ -183,22 +202,24 @@ public class SftpFileService extends AbstractFileService implements IFileService
protected String recode(String s) throws SystemMessageException { protected String recode(String s) throws SystemMessageException {
if (fControlEncoding==null) { if (fControlEncoding==null) {
return s; return s;
} else if (fControlEncoding.equals(defaultEncoding)) { } else if (fControlEncoding.equals(fJSchChannelEncoding)) {
return s; return s;
} }
try { try {
byte[] bytes = s.getBytes(fControlEncoding); //what we want on the wire byte[] bytes = s.getBytes(fControlEncoding); //what we want on the wire
return new String(bytes); //what we need to tell Jsch to get this on the wire return new String(bytes, fJSchChannelEncoding); // what we need to
// tell Jsch to get
// this on the wire
} catch(UnsupportedEncodingException e) { } catch(UnsupportedEncodingException e) {
throw makeSystemMessageException(e); throw makeSystemMessageException(e);
} }
} }
/** /**
* Recode String, and check that no information is lost. * Recode String, and check that no information is lost.
* Throw an exception in case the desired Unicode String can not be expressed * Throw an exception in case the desired Unicode String can not be expressed
* by the current encodings. Also enquotes result characters '?' and '*' for * by the current encodings. Also enquotes result characters '?' and '*' for
* Jsch if necessary. * Jsch if necessary.
* @param s String to recode * @param s String to recode
* @return recoded String * @return recoded String
* @throws SystemMessageException if information is lost * @throws SystemMessageException if information is lost
@ -206,38 +227,38 @@ public class SftpFileService extends AbstractFileService implements IFileService
protected String recodeSafe(String s) throws SystemMessageException { protected String recodeSafe(String s) throws SystemMessageException {
try { try {
String recoded = recode(s); String recoded = recode(s);
byte[] bytes = recoded.getBytes(defaultEncoding); byte[] bytes = recoded.getBytes(fJSchChannelEncoding);
String decoded = decode(new String(bytes)); String decoded = decode(new String(bytes, fJSchChannelEncoding));
if (!s.equals(decoded)) { if (!s.equals(decoded)) {
int i=0; int i=0;
int lmax = Math.min(s.length(), decoded.length()); int lmax = Math.min(s.length(), decoded.length());
while( (i<lmax) && (s.charAt(i)==decoded.charAt(i))) { while( (i<lmax) && (s.charAt(i)==decoded.charAt(i))) {
i++; i++;
} }
//String sbad=s.substring(Math.max(i-2,0), Math.min(i+2,lmax)); //String sbad=s.substring(Math.max(i-2,0), Math.min(i+2,lmax));
char sbad = s.charAt(i); char sbad = s.charAt(i);
String msg = "Cannot express character \'"+sbad+"\'(0x"+Integer.toHexString(sbad) +") with "; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ String msg = "Cannot express character \'"+sbad+"\'(0x"+Integer.toHexString(sbad) +") with "; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
if (fControlEncoding==null || fControlEncoding.equals(defaultEncoding)) { if (fControlEncoding == null || fControlEncoding.equals(fJSchChannelEncoding)) {
msg += "default encoding \""+defaultEncoding+"\". "; //$NON-NLS-1$ //$NON-NLS-2$ msg += "default encoding \"" + fJSchChannelEncoding + "\". "; //$NON-NLS-1$ //$NON-NLS-2$
} else { } else {
msg += "encoding \""+fControlEncoding+"\" over local default encoding \""+defaultEncoding+"\". "; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ msg += "encoding \"" + fControlEncoding + "\" over local default encoding \"" + fJSchChannelEncoding + "\". "; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
} }
msg += "Please specify a different encoding in host properties."; //$NON-NLS-1$ msg += "Please specify a different encoding in host properties."; //$NON-NLS-1$
throw new UnsupportedEncodingException(msg); throw new UnsupportedEncodingException(msg);
} }
//Quote ? and * characters for Jsch //Quote ? and * characters for Jsch
//FIXME bug 204705: this does not work properly for commands like ls(), due to a Jsch bug //FIXME bug 204705: this does not work properly for commands like ls(), due to a Jsch bug
return quoteForJsch(recoded); return quoteForJsch(recoded);
} catch(UnsupportedEncodingException e) { } catch(UnsupportedEncodingException e) {
//SystemMessage msg = new SystemMessage("RSE","F","9999",'E',e.getMessage(),"Please specify a different encoding in host properties."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //SystemMessage msg = new SystemMessage("RSE","F","9999",'E',e.getMessage(),"Please specify a different encoding in host properties."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
SystemMessage msg = new SystemMessage("RSE","F","9999",'E',e.getMessage(),""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ SystemMessage msg = new SystemMessage("RSE","F","9999",'E',e.getMessage(),""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
//throw new RemoteFileIOException(new SystemMessageException(msg)); //throw new RemoteFileIOException(new SystemMessageException(msg));
throw new SystemMessageException(msg); throw new SystemMessageException(msg);
} }
} }
/** /**
* Decode String (sftp result) with requested user encoding, in case it differs from Platform default encoding. * Decode String (sftp result) with requested user encoding, in case it differs from Platform default encoding.
* @param s String to decode * @param s String to decode
@ -247,11 +268,13 @@ public class SftpFileService extends AbstractFileService implements IFileService
protected String decode(String s) throws SystemMessageException { protected String decode(String s) throws SystemMessageException {
if (fControlEncoding==null) { if (fControlEncoding==null) {
return s; return s;
} else if (fControlEncoding.equals(defaultEncoding)) { } else if (fControlEncoding.equals(fJSchChannelEncoding)) {
return s; return s;
} }
try { try {
byte[] bytes = s.getBytes(); //original bytes sent by SSH byte[] bytes = s.getBytes(fJSchChannelEncoding); // original
// bytes sent by
// SSH
return new String(bytes, fControlEncoding); return new String(bytes, fControlEncoding);
} catch(UnsupportedEncodingException e) { } catch(UnsupportedEncodingException e) {
throw makeSystemMessageException(e); throw makeSystemMessageException(e);
@ -260,7 +283,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
/** Regular expression pattern to know when Jsch needs quoting. */ /** Regular expression pattern to know when Jsch needs quoting. */
private static Pattern quoteForJschPattern = Pattern.compile("[*?\\\\]"); //$NON-NLS-1$ private static Pattern quoteForJschPattern = Pattern.compile("[*?\\\\]"); //$NON-NLS-1$
/** /**
* Quote characters '?' and '*' for Jsch because it would otherwise * Quote characters '?' and '*' for Jsch because it would otherwise
* use them as patterns for globbing. * use them as patterns for globbing.
@ -272,7 +295,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
StringBuffer buf = new StringBuffer(s.length()+8); StringBuffer buf = new StringBuffer(s.length()+8);
for(int i=0; i<s.length(); i++) { for(int i=0; i<s.length(); i++) {
char c = s.charAt(i); char c = s.charAt(i);
// if(c=='?' || c=='*' || c=='\\') { // if(c=='?' || c=='*' || c=='\\') {
if(c=='?' || c=='*') { if(c=='?' || c=='*') {
buf.append('\\'); buf.append('\\');
} }
@ -282,23 +305,23 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
return s; return s;
} }
public String getName() { public String getName() {
return SshServiceResources.SftpFileService_Name; return SshServiceResources.SftpFileService_Name;
} }
public String getDescription() { public String getDescription() {
return SshServiceResources.SftpFileService_Description; return SshServiceResources.SftpFileService_Description;
} }
public void connect() throws SystemMessageException { public void connect() throws SystemMessageException {
Activator.trace("SftpFileService.connecting..."); //$NON-NLS-1$ Activator.trace("SftpFileService.connecting..."); //$NON-NLS-1$
try { try {
Session session = fSessionProvider.getSession(); Session session = fSessionProvider.getSession();
Channel channel=session.openChannel("sftp"); //$NON-NLS-1$ Channel channel=session.openChannel("sftp"); //$NON-NLS-1$
channel.connect(); channel.connect();
fChannelSftp=(ChannelSftp)channel; fChannelSftp=(ChannelSftp)channel;
setControlEncoding(fSessionProvider.getControlEncoding()); setControlEncoding(fSessionProvider.getControlEncoding());
fUserHome = decode(fChannelSftp.pwd()); fUserHome = decode(fChannelSftp.pwd());
Activator.trace("SftpFileService.connected"); //$NON-NLS-1$ Activator.trace("SftpFileService.connected"); //$NON-NLS-1$
} catch(Exception e) { } catch(Exception e) {
@ -306,7 +329,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
throw makeSystemMessageException(e); throw makeSystemMessageException(e);
} }
} }
/** /**
* Check if the main ssh session is still connected. * Check if the main ssh session is still connected.
* Notify ConnectorService of lost session if necessary. * Notify ConnectorService of lost session if necessary.
@ -327,7 +350,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
return false; return false;
} }
} }
protected ChannelSftp getChannel(String task) throws SystemMessageException protected ChannelSftp getChannel(String task) throws SystemMessageException
{ {
Activator.trace(task); Activator.trace(task);
@ -347,7 +370,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
return fChannelSftp; return fChannelSftp;
} }
protected void progressTick(IProgressMonitor monitor, int ticks) throws RemoteFileCanceledException { protected void progressTick(IProgressMonitor monitor, int ticks) throws RemoteFileCanceledException {
if (monitor!=null) { if (monitor!=null) {
if (monitor.isCanceled()) { if (monitor.isCanceled()) {
@ -356,7 +379,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
monitor.worked(ticks); monitor.worked(ticks);
} }
} }
public void disconnect() { public void disconnect() {
//disconnect-service may be called after the session is already //disconnect-service may be called after the session is already
//disconnected (due to event handling). Therefore, don't try to //disconnected (due to event handling). Therefore, don't try to
@ -368,8 +391,8 @@ public class SftpFileService extends AbstractFileService implements IFileService
fDirChannelMutex.interruptAll(); fDirChannelMutex.interruptAll();
fChannelSftp = null; fChannelSftp = null;
} }
private SystemMessageException makeSystemMessageException(Exception e) { private SystemMessageException makeSystemMessageException(Exception e) {
if (e instanceof SystemMessageException) { if (e instanceof SystemMessageException) {
//dont wrap SystemMessageException again //dont wrap SystemMessageException again
@ -390,7 +413,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
return new RemoteFileIOException(e); return new RemoteFileIOException(e);
} }
/** /**
* Concatenate a parent directory with a file name to form a new proper path name. * Concatenate a parent directory with a file name to form a new proper path name.
* @param parentDir path name of the parent directory. * @param parentDir path name of the parent directory.
@ -408,11 +431,11 @@ public class SftpFileService extends AbstractFileService implements IFileService
path.append(fileName); path.append(fileName);
return path.toString(); return path.toString();
} }
public IHostFile getFile(String remoteParent, String fileName, IProgressMonitor monitor) throws SystemMessageException public IHostFile getFile(String remoteParent, String fileName, IProgressMonitor monitor) throws SystemMessageException
{ {
//getFile() must return a dummy even for non-existent files, //getFile() must return a dummy even for non-existent files,
//or the move() operation will fail. This is described in //or the move() operation will fail. This is described in
//the API docs. //the API docs.
SftpHostFile node = null; SftpHostFile node = null;
SftpATTRS attrs = null; SftpATTRS attrs = null;
@ -442,7 +465,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
return node; return node;
} }
public boolean isConnected() { public boolean isConnected() {
try { try {
return getChannel("SftpFileService.isConnected()").isConnected(); //$NON-NLS-1$ return getChannel("SftpFileService.isConnected()").isConnected(); //$NON-NLS-1$
@ -451,7 +474,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
return false; return false;
} }
protected IHostFile[] internalFetch(String parentPath, String fileFilter, int fileType, IProgressMonitor monitor) throws SystemMessageException protected IHostFile[] internalFetch(String parentPath, String fileFilter, int fileType, IProgressMonitor monitor) throws SystemMessageException
{ {
if (fileFilter == null) { if (fileFilter == null) {
@ -466,33 +489,33 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
List results = new ArrayList(); List results = new ArrayList();
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) { if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) {
boolean haveSubMonitor = false; boolean haveSubMonitor = false;
try { try {
Vector vv=getChannel("SftpFileService.internalFetch: "+parentPath).ls(recodeSafe(parentPath)); //$NON-NLS-1$ Vector vv=getChannel("SftpFileService.internalFetch: "+parentPath).ls(recodeSafe(parentPath)); //$NON-NLS-1$
progressTick(monitor, 40); progressTick(monitor, 40);
if (vv.size()>1 && monitor!=null) { if (vv.size()>1 && monitor!=null) {
monitor = new SubProgressMonitor(monitor, 40); monitor = new SubProgressMonitor(monitor, 40);
monitor.beginTask(null, vv.size()); monitor.beginTask(null, vv.size());
} }
for(int ii=0; ii<vv.size(); ii++) { for(int ii=0; ii<vv.size(); ii++) {
Object obj=vv.elementAt(ii); Object obj=vv.elementAt(ii);
if(obj instanceof ChannelSftp.LsEntry){ if(obj instanceof ChannelSftp.LsEntry){
ChannelSftp.LsEntry lsEntry = (ChannelSftp.LsEntry)obj; ChannelSftp.LsEntry lsEntry = (ChannelSftp.LsEntry)obj;
String fileName = decode(lsEntry.getFilename()); String fileName = decode(lsEntry.getFilename());
if (".".equals(fileName) || "..".equals(fileName)) { //$NON-NLS-1$ //$NON-NLS-2$ if (".".equals(fileName) || "..".equals(fileName)) { //$NON-NLS-1$ //$NON-NLS-2$
//don't show the trivial names //don't show the trivial names
continue; continue;
} }
if (filematcher.matches(fileName) || (lsEntry.getAttrs().isDir() && fileType!=IFileService.FILE_TYPE_FOLDERS)) { if (filematcher.matches(fileName) || (lsEntry.getAttrs().isDir() && fileType!=IFileService.FILE_TYPE_FOLDERS)) {
//get ALL directory names (unless looking for folders only) //get ALL directory names (unless looking for folders only)
SftpHostFile node = makeHostFile(parentPath, fileName, lsEntry.getAttrs()); SftpHostFile node = makeHostFile(parentPath, fileName, lsEntry.getAttrs());
progressTick(monitor, 1); progressTick(monitor, 1);
if (isRightType(fileType, node)) { if (isRightType(fileType, node)) {
results.add(node); results.add(node);
} }
} }
} }
} }
Activator.trace("SftpFileService.internalFetch <--"); //$NON-NLS-1$ Activator.trace("SftpFileService.internalFetch <--"); //$NON-NLS-1$
} catch(Exception e) { } catch(Exception e) {
//TODO throw new SystemMessageException. //TODO throw new SystemMessageException.
@ -505,7 +528,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
throw makeSystemMessageException(e); throw makeSystemMessageException(e);
} }
//TODO if not session connected, do we need to throw? //TODO if not session connected, do we need to throw?
//Probably not, since the session is going down anyways. //Probably not, since the session is going down anyways.
} finally { } finally {
fDirChannelMutex.release(); fDirChannelMutex.release();
if (haveSubMonitor) monitor.done(); else progressTick(monitor, 40); if (haveSubMonitor) monitor.done(); else progressTick(monitor, 40);
@ -533,7 +556,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
//Disadvantages of the cd/pwd approach: //Disadvantages of the cd/pwd approach:
// * _realpath() followed by _stat() might be one extra roundtrip compared to the readlink() approach // * _realpath() followed by _stat() might be one extra roundtrip compared to the readlink() approach
// * Immediate link target is not available, only the fully resolved link target (might be an advantage too!) // * Immediate link target is not available, only the fully resolved link target (might be an advantage too!)
// * -- but clients can also resolve the path with the // * -- but clients can also resolve the path with the
// * Immediate link target is not available for broken symbolic links // * Immediate link target is not available for broken symbolic links
getChannel("makeHostFile.chdir").cd(recode(concat(parentPath, fileName))); //$NON-NLS-1$ getChannel("makeHostFile.chdir").cd(recode(concat(parentPath, fileName))); //$NON-NLS-1$
linkTarget=decode(getChannel("makeHostFile.pwd").pwd()); //$NON-NLS-1$ linkTarget=decode(getChannel("makeHostFile.pwd").pwd()); //$NON-NLS-1$
@ -541,7 +564,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
if (linkTarget!=null && !linkTarget.equals(concat(parentPath, fileName))) { if (linkTarget!=null && !linkTarget.equals(concat(parentPath, fileName))) {
if (readlinkDone) { if (readlinkDone) {
//linkTarget may be a relative path name that needs to be resolved for stat() to work properly //linkTarget may be a relative path name that needs to be resolved for stat() to work properly
String curdir=decode(getChannel("makeHostFile.pwd").pwd()); //$NON-NLS-1$ String curdir=decode(getChannel("makeHostFile.pwd").pwd()); //$NON-NLS-1$
if (!parentPath.equals(curdir)) { if (!parentPath.equals(curdir)) {
getChannel("makeHostFile.chdir").cd(recode(parentPath)); //$NON-NLS-1$ getChannel("makeHostFile.chdir").cd(recode(parentPath)); //$NON-NLS-1$
@ -567,7 +590,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
} }
} }
SftpHostFile node = new SftpHostFile(parentPath, fileName, attrsTarget.isDir(), false, attrs.isLink(), 1000L * attrs.getMTime(), attrs.getSize()); SftpHostFile node = new SftpHostFile(parentPath, fileName, attrsTarget.isDir(), false, attrs.isLink(), 1000L * attrs.getMTime(), attrs.getSize());
if (linkTarget!=null) { if (linkTarget!=null) {
@ -596,19 +619,19 @@ public class SftpFileService extends AbstractFileService implements IFileService
if (attrs.getExtended()!=null) { if (attrs.getExtended()!=null) {
node.setExtendedData(attrs.getExtended()); node.setExtendedData(attrs.getExtended());
} }
// permissions // permissions
// TODO get the user and owner from the uid and gid // TODO get the user and owner from the uid and gid
HostFilePermissions permissions = new HostFilePermissions(perms, "" + attrs.getUId(), "" + attrs.getGId()); //$NON-NLS-1$ //$NON-NLS-2$ HostFilePermissions permissions = new HostFilePermissions(perms, "" + attrs.getUId(), "" + attrs.getGId()); //$NON-NLS-1$ //$NON-NLS-2$
node.setPermissions(permissions); node.setPermissions(permissions);
return node; return node;
} }
public String getSeparator() { public String getSeparator() {
return "/"; //$NON-NLS-1$ return "/"; //$NON-NLS-1$
} }
public boolean upload(File localFile, String remoteParent, String remoteFile, boolean isBinary, String srcEncoding, String hostEncoding, IProgressMonitor monitor) throws SystemMessageException public boolean upload(File localFile, String remoteParent, String remoteFile, boolean isBinary, String srcEncoding, String hostEncoding, IProgressMonitor monitor) throws SystemMessageException
{ {
String dst = remoteParent; String dst = remoteParent;
@ -625,10 +648,10 @@ public class SftpFileService extends AbstractFileService implements IFileService
SftpProgressMonitor sftpMonitor=new MyProgressMonitor(monitor); SftpProgressMonitor sftpMonitor=new MyProgressMonitor(monitor);
int mode=ChannelSftp.OVERWRITE; int mode=ChannelSftp.OVERWRITE;
dst = recodeSafe(dst); dst = recodeSafe(dst);
getChannel("SftpFileService.upload "+remoteFile); //check the session is healthy //$NON-NLS-1$ getChannel("SftpFileService.upload "+remoteFile); //check the session is healthy //$NON-NLS-1$
channel=(ChannelSftp)fSessionProvider.getSession().openChannel("sftp"); //$NON-NLS-1$ channel=(ChannelSftp)fSessionProvider.getSession().openChannel("sftp"); //$NON-NLS-1$
channel.connect(); channel.connect();
channel.put(localFile.getAbsolutePath(), dst, sftpMonitor, mode); channel.put(localFile.getAbsolutePath(), dst, sftpMonitor, mode);
Activator.trace("SftpFileService.upload "+remoteFile+ " ok"); //$NON-NLS-1$ //$NON-NLS-2$ Activator.trace("SftpFileService.upload "+remoteFile+ " ok"); //$NON-NLS-1$ //$NON-NLS-2$
if (monitor.isCanceled()) { if (monitor.isCanceled()) {
return false; return false;
@ -659,56 +682,56 @@ public class SftpFileService extends AbstractFileService implements IFileService
return true; return true;
} }
public static class MyProgressMonitor implements SftpProgressMonitor public static class MyProgressMonitor implements SftpProgressMonitor
{ {
private IProgressMonitor fMonitor; private IProgressMonitor fMonitor;
private double fWorkPercentFactor; private double fWorkPercentFactor;
private Long fMaxWorkKB; private Long fMaxWorkKB;
private long fWorkToDate; private long fWorkToDate;
public MyProgressMonitor(IProgressMonitor monitor) {
fMonitor = monitor;
}
public void init(int op, String src, String dest, long max){
fWorkPercentFactor = 1.0 / max;
fMaxWorkKB = new Long(max / 1024L);
fWorkToDate = 0;
String srcFile = new Path(src).lastSegment();
//String desc = ((op==SftpProgressMonitor.PUT)?
// "Uploading " : "Downloading ")+srcFile;
String desc = srcFile;
if (Activator.isTracingOn()) {
Activator.trace("Sftp-monitor: "+max+", "+desc); //$NON-NLS-1$ //$NON-NLS-2$
}
//TODO avoid cast from long to int
fMonitor.beginTask(desc, (int)max);
}
public boolean count(long count){
fWorkToDate += count;
Long workToDateKB = new Long(fWorkToDate / 1024L);
Double workPercent = new Double(fWorkPercentFactor * fWorkToDate);
String subDesc = MessageFormat.format(
SshServiceResources.SftpFileService_Msg_Progress,
new Object[] {
workToDateKB, fMaxWorkKB, workPercent
});
if (Activator.isTracingOn()) { public MyProgressMonitor(IProgressMonitor monitor) {
System.out.print('#'); fMonitor = monitor;
} }
fMonitor.subTask(subDesc); public void init(int op, String src, String dest, long max){
fMonitor.worked((int)count); fWorkPercentFactor = 1.0 / max;
return !(fMonitor.isCanceled()); fMaxWorkKB = new Long(max / 1024L);
} fWorkToDate = 0;
public void end(){ String srcFile = new Path(src).lastSegment();
if (Activator.isTracingOn()) { //String desc = ((op==SftpProgressMonitor.PUT)?
System.out.println(); // "Uploading " : "Downloading ")+srcFile;
System.out.println("Sftp-monitor <--"); //$NON-NLS-1$ String desc = srcFile;
System.out.flush(); if (Activator.isTracingOn()) {
} Activator.trace("Sftp-monitor: "+max+", "+desc); //$NON-NLS-1$ //$NON-NLS-2$
fMonitor.done(); }
} //TODO avoid cast from long to int
fMonitor.beginTask(desc, (int)max);
}
public boolean count(long count){
fWorkToDate += count;
Long workToDateKB = new Long(fWorkToDate / 1024L);
Double workPercent = new Double(fWorkPercentFactor * fWorkToDate);
String subDesc = MessageFormat.format(
SshServiceResources.SftpFileService_Msg_Progress,
new Object[] {
workToDateKB, fMaxWorkKB, workPercent
});
if (Activator.isTracingOn()) {
System.out.print('#');
}
fMonitor.subTask(subDesc);
fMonitor.worked((int)count);
return !(fMonitor.isCanceled());
}
public void end(){
if (Activator.isTracingOn()) {
System.out.println();
System.out.println("Sftp-monitor <--"); //$NON-NLS-1$
System.out.flush();
}
fMonitor.done();
}
} }
public boolean upload(InputStream stream, String remoteParent, String remoteFile, boolean isBinary, String hostEncoding, IProgressMonitor monitor) throws SystemMessageException public boolean upload(InputStream stream, String remoteParent, String remoteFile, boolean isBinary, String hostEncoding, IProgressMonitor monitor) throws SystemMessageException
@ -720,15 +743,15 @@ public class SftpFileService extends AbstractFileService implements IFileService
File tempFile = File.createTempFile("sftp", "temp"); //$NON-NLS-1$ //$NON-NLS-2$ File tempFile = File.createTempFile("sftp", "temp"); //$NON-NLS-1$ //$NON-NLS-2$
FileOutputStream os = new FileOutputStream(tempFile); FileOutputStream os = new FileOutputStream(tempFile);
BufferedOutputStream bos = new BufferedOutputStream(os); BufferedOutputStream bos = new BufferedOutputStream(os);
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
int readCount; int readCount;
while( (readCount = bis.read(buffer)) > 0) while( (readCount = bis.read(buffer)) > 0)
{ {
bos.write(buffer, 0, readCount); bos.write(buffer, 0, readCount);
} }
bos.close(); bos.close();
upload(tempFile, remoteParent, remoteFile, isBinary, "", hostEncoding, monitor); //$NON-NLS-1$ upload(tempFile, remoteParent, remoteFile, isBinary, "", hostEncoding, monitor); //$NON-NLS-1$
} }
catch (Exception e) { catch (Exception e) {
throw makeSystemMessageException(e); throw makeSystemMessageException(e);
@ -736,7 +759,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
return true; return true;
} }
public boolean download(String remoteParent, String remoteFile, File localFile, boolean isBinary, String hostEncoding, IProgressMonitor monitor) throws SystemMessageException public boolean download(String remoteParent, String remoteFile, File localFile, boolean isBinary, String hostEncoding, IProgressMonitor monitor) throws SystemMessageException
{ {
ChannelSftp channel = null; ChannelSftp channel = null;
@ -755,7 +778,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
MyProgressMonitor sftpMonitor = new MyProgressMonitor(monitor); MyProgressMonitor sftpMonitor = new MyProgressMonitor(monitor);
getChannel("SftpFileService.download "+remoteFile); //check the session is healthy //$NON-NLS-1$ getChannel("SftpFileService.download "+remoteFile); //check the session is healthy //$NON-NLS-1$
channel=(ChannelSftp)fSessionProvider.getSession().openChannel("sftp"); //$NON-NLS-1$ channel=(ChannelSftp)fSessionProvider.getSession().openChannel("sftp"); //$NON-NLS-1$
channel.connect(); channel.connect();
channel.get(remotePathRecoded, localFile.getAbsolutePath(), sftpMonitor, mode); channel.get(remotePathRecoded, localFile.getAbsolutePath(), sftpMonitor, mode);
Activator.trace("SftpFileService.download "+remoteFile+ " ok"); //$NON-NLS-1$ //$NON-NLS-2$ Activator.trace("SftpFileService.download "+remoteFile+ " ok"); //$NON-NLS-1$ //$NON-NLS-2$
if (monitor.isCanceled()) { if (monitor.isCanceled()) {
@ -778,7 +801,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
Activator.trace("SftpFileService.download "+remotePath+" failed: "+e.toString()); //$NON-NLS-1$ //$NON-NLS-2$ Activator.trace("SftpFileService.download "+remotePath+" failed: "+e.toString()); //$NON-NLS-1$ //$NON-NLS-2$
throw makeSystemMessageException(e); throw makeSystemMessageException(e);
//Note: In case of an exception, the caller needs to ensure that in case //Note: In case of an exception, the caller needs to ensure that in case
//we downloaded to a temp file, the temp file is deleted again, or a //we downloaded to a temp file, the temp file is deleted again, or a
//broken incorrect file might be synchronized back to the source, thus //broken incorrect file might be synchronized back to the source, thus
//destroying the original file!! //destroying the original file!!
//return false; //return false;
@ -790,12 +813,12 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
return true; return true;
} }
public IHostFile getUserHome() { public IHostFile getUserHome() {
//As per bug 204710, this may be called before we are connected //As per bug 204710, this may be called before we are connected
if (fUserHome!=null) { if (fUserHome!=null) {
int lastSlash = fUserHome.lastIndexOf('/'); int lastSlash = fUserHome.lastIndexOf('/');
String name = fUserHome.substring(lastSlash + 1); String name = fUserHome.substring(lastSlash + 1);
String parent = fUserHome.substring(0, lastSlash); String parent = fUserHome.substring(0, lastSlash);
try { try {
return getFile(parent, name, null); return getFile(parent, name, null);
@ -815,8 +838,8 @@ public class SftpFileService extends AbstractFileService implements IFileService
IHostFile root = new SftpHostFile("/", "/", true, true, false, 0, 0); //$NON-NLS-1$ //$NON-NLS-2$ IHostFile root = new SftpHostFile("/", "/", true, true, false, 0, 0); //$NON-NLS-1$ //$NON-NLS-2$
return new IHostFile[] { root }; return new IHostFile[] { root };
} }
public IHostFile createFile(String remoteParent, String fileName, IProgressMonitor monitor) throws SystemMessageException public IHostFile createFile(String remoteParent, String fileName, IProgressMonitor monitor) throws SystemMessageException
{ {
IHostFile result = null; IHostFile result = null;
String fullPath = concat(remoteParent, fileName); String fullPath = concat(remoteParent, fileName);
@ -875,7 +898,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
try { try {
attrs = getChannel("SftpFileService.delete").lstat(fullPathRecoded); //$NON-NLS-1$ attrs = getChannel("SftpFileService.delete").lstat(fullPathRecoded); //$NON-NLS-1$
} catch (SftpException e) { } catch (SftpException e) {
//bug 154419: test for dangling symbolic link //bug 154419: test for dangling symbolic link
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) { if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
//simply try to delete --> if it really doesnt exist, this will throw an exception //simply try to delete --> if it really doesnt exist, this will throw an exception
getChannel("SftpFileService.delete.rm").rm(fullPathRecoded); //$NON-NLS-1$ getChannel("SftpFileService.delete.rm").rm(fullPathRecoded); //$NON-NLS-1$
@ -935,7 +958,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
return ok; return ok;
} }
public boolean rename(String remoteParent, String oldName, String newName, IHostFile oldFile, IProgressMonitor monitor) throws SystemMessageException { public boolean rename(String remoteParent, String oldName, String newName, IHostFile oldFile, IProgressMonitor monitor) throws SystemMessageException {
// TODO dont know how to update // TODO dont know how to update
return rename(remoteParent, oldName, newName, monitor); return rename(remoteParent, oldName, newName, monitor);
@ -949,7 +972,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
return cancelRequested; return cancelRequested;
} }
public int runCommand(String command, IProgressMonitor monitor) throws SystemMessageException public int runCommand(String command, IProgressMonitor monitor) throws SystemMessageException
{ {
Activator.trace("SftpFileService.runCommand "+command); //$NON-NLS-1$ Activator.trace("SftpFileService.runCommand "+command); //$NON-NLS-1$
@ -1005,7 +1028,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
return result; return result;
} }
public boolean move(String srcParent, String srcName, String tgtParent, String tgtName, IProgressMonitor monitor) throws SystemMessageException public boolean move(String srcParent, String srcName, String tgtParent, String tgtName, IProgressMonitor monitor) throws SystemMessageException
{ {
// move is not supported by sftp directly. Use the ssh shell instead. // move is not supported by sftp directly. Use the ssh shell instead.
@ -1029,15 +1052,15 @@ public class SftpFileService extends AbstractFileService implements IFileService
int rv = runCommand("cp -Rp "+fullPathOld+' '+fullPathNew, monitor); //$NON-NLS-1$ int rv = runCommand("cp -Rp "+fullPathOld+' '+fullPathNew, monitor); //$NON-NLS-1$
return (rv==0); return (rv==0);
} }
public boolean copyBatch(String[] srcParents, String[] srcNames, String tgtParent, IProgressMonitor monitor) throws SystemMessageException public boolean copyBatch(String[] srcParents, String[] srcNames, String tgtParent, IProgressMonitor monitor) throws SystemMessageException
{ {
Activator.trace("SftpFileService.copyBatch "+srcNames); //$NON-NLS-1$ Activator.trace("SftpFileService.copyBatch "+srcNames); //$NON-NLS-1$
boolean ok = true; boolean ok = true;
for (int i = 0; i < srcParents.length; i++) for (int i = 0; i < srcParents.length; i++)
{ {
//TODO check what should happen if one file throws an Exception //TODO check what should happen if one file throws an Exception
//should the batch job continue? //should the batch job continue?
ok = ok && copy(srcParents[i], srcNames[i], tgtParent, srcNames[i], monitor); ok = ok && copy(srcParents[i], srcNames[i], tgtParent, srcNames[i], monitor);
} }
return ok; return ok;
@ -1050,10 +1073,10 @@ public class SftpFileService extends AbstractFileService implements IFileService
connect(); connect();
} }
catch (Exception e) catch (Exception e)
{ {
} }
} }
public void uninitService(IProgressMonitor monitor) { public void uninitService(IProgressMonitor monitor) {
Activator.trace("SftpFileService.uninitService"); //$NON-NLS-1$ Activator.trace("SftpFileService.uninitService"); //$NON-NLS-1$
disconnect(); disconnect();
@ -1065,8 +1088,8 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
public boolean setLastModified(String parent, String name, public boolean setLastModified(String parent, String name,
long timestamp, IProgressMonitor monitor) throws SystemMessageException long timestamp, IProgressMonitor monitor) throws SystemMessageException
{ {
boolean ok=false; boolean ok=false;
String path = concat(parent, name); String path = concat(parent, name);
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) { if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) {
@ -1082,7 +1105,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
} }
return ok; return ok;
} }
public boolean setReadOnly(String parent, String name, public boolean setReadOnly(String parent, String name,
boolean readOnly, IProgressMonitor monitor) throws SystemMessageException { boolean readOnly, IProgressMonitor monitor) throws SystemMessageException {
@ -1100,7 +1123,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
if (permNew != permOld) { if (permNew != permOld) {
//getChannel("SftpFileService.setReadOnly").chmod(permNew, path); //$NON-NLS-1$ //getChannel("SftpFileService.setReadOnly").chmod(permNew, path); //$NON-NLS-1$
attr.setPERMISSIONS(permNew); attr.setPERMISSIONS(permNew);
getChannel("SftpFileService.setReadOnly").setStat(recode(path), attr); //$NON-NLS-1$ ok=true; getChannel("SftpFileService.setReadOnly").setStat(recode(path), attr); //$NON-NLS-1$ ok=true;
Activator.trace("SftpFileService.setReadOnly ok"); //$NON-NLS-1$ Activator.trace("SftpFileService.setReadOnly ok"); //$NON-NLS-1$
} else { } else {
@ -1120,18 +1143,18 @@ public class SftpFileService extends AbstractFileService implements IFileService
/** /**
* Gets the input stream to access the contents of a remote file. * Gets the input stream to access the contents of a remote file.
* @since 2.0 * @since 2.0
* @see org.eclipse.rse.services.files.AbstractFileService#getInputStream(String, String, boolean, IProgressMonitor) * @see org.eclipse.rse.services.files.AbstractFileService#getInputStream(String, String, boolean, IProgressMonitor)
*/ */
public InputStream getInputStream(String remoteParent, String remoteFile, boolean isBinary, IProgressMonitor monitor) throws SystemMessageException { public InputStream getInputStream(String remoteParent, String remoteFile, boolean isBinary, IProgressMonitor monitor) throws SystemMessageException {
InputStream stream = null; InputStream stream = null;
String remotePath = concat(remoteParent, remoteFile); String remotePath = concat(remoteParent, remoteFile);
try { try {
String remotePathRecoded = recode(remotePath); String remotePathRecoded = recode(remotePath);
getChannel("SftpFileService.getInputStream " + remoteFile); //check the session is healthy //$NON-NLS-1$ getChannel("SftpFileService.getInputStream " + remoteFile); //check the session is healthy //$NON-NLS-1$
ChannelSftp channel = (ChannelSftp)fSessionProvider.getSession().openChannel("sftp"); //$NON-NLS-1$ ChannelSftp channel = (ChannelSftp)fSessionProvider.getSession().openChannel("sftp"); //$NON-NLS-1$
channel.connect(); channel.connect();
stream = new SftpBufferedInputStream(channel.get(remotePathRecoded), channel); stream = new SftpBufferedInputStream(channel.get(remotePathRecoded), channel);
Activator.trace("SftpFileService.getInputStream " + remoteFile + " ok"); //$NON-NLS-1$ //$NON-NLS-2$ Activator.trace("SftpFileService.getInputStream " + remoteFile + " ok"); //$NON-NLS-1$ //$NON-NLS-2$
} }
@ -1139,7 +1162,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
Activator.trace("SftpFileService.getInputStream " + remotePath + " failed: " + e.toString()); //$NON-NLS-1$ //$NON-NLS-2$ Activator.trace("SftpFileService.getInputStream " + remotePath + " failed: " + e.toString()); //$NON-NLS-1$ //$NON-NLS-2$
throw makeSystemMessageException(e); throw makeSystemMessageException(e);
} }
return stream; return stream;
} }
@ -1152,23 +1175,23 @@ public class SftpFileService extends AbstractFileService implements IFileService
int options = isBinary ? IFileService.NONE : IFileService.TEXT_MODE; int options = isBinary ? IFileService.NONE : IFileService.TEXT_MODE;
return getOutputStream(remoteParent, remoteFile, options, monitor); return getOutputStream(remoteParent, remoteFile, options, monitor);
} }
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.eclipse.rse.services.files.AbstractFileService#getOutputStream(java.lang.String, java.lang.String, boolean, int, org.eclipse.core.runtime.IProgressMonitor) * @see org.eclipse.rse.services.files.AbstractFileService#getOutputStream(java.lang.String, java.lang.String, boolean, int, org.eclipse.core.runtime.IProgressMonitor)
*/ */
public OutputStream getOutputStream(String remoteParent, String remoteFile, int options, IProgressMonitor monitor) throws SystemMessageException { public OutputStream getOutputStream(String remoteParent, String remoteFile, int options, IProgressMonitor monitor) throws SystemMessageException {
if (monitor == null) { if (monitor == null) {
monitor = new NullProgressMonitor(); monitor = new NullProgressMonitor();
} }
OutputStream stream = null; OutputStream stream = null;
String dst = remoteParent; String dst = remoteParent;
if (remoteFile!=null) { if (remoteFile!=null) {
dst = concat(remoteParent, remoteFile); dst = concat(remoteParent, remoteFile);
} }
try { try {
SftpProgressMonitor sftpMonitor = new MyProgressMonitor(monitor); SftpProgressMonitor sftpMonitor = new MyProgressMonitor(monitor);
int mode; int mode;
@ -1179,8 +1202,8 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
getChannel("SftpFileService.getOutputStream " + remoteFile); //check the session is healthy //$NON-NLS-1$ getChannel("SftpFileService.getOutputStream " + remoteFile); //check the session is healthy //$NON-NLS-1$
ChannelSftp channel = (ChannelSftp)fSessionProvider.getSession().openChannel("sftp"); //$NON-NLS-1$ ChannelSftp channel = (ChannelSftp)fSessionProvider.getSession().openChannel("sftp"); //$NON-NLS-1$
channel.connect(); channel.connect();
stream = new SftpBufferedOutputStream(channel.put(recodeSafe(dst), sftpMonitor, mode), channel); stream = new SftpBufferedOutputStream(channel.put(recodeSafe(dst), sftpMonitor, mode), channel);
Activator.trace("SftpFileService.getOutputStream " + remoteFile + " ok"); //$NON-NLS-1$ //$NON-NLS-2$ Activator.trace("SftpFileService.getOutputStream " + remoteFile + " ok"); //$NON-NLS-1$ //$NON-NLS-2$
} }
catch (Exception e) { catch (Exception e) {
@ -1199,7 +1222,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
*/ */
public IHostFilePermissions getFilePermissions(IHostFile file, public IHostFilePermissions getFilePermissions(IHostFile file,
IProgressMonitor monitor) throws SystemMessageException { IProgressMonitor monitor) throws SystemMessageException {
if (file instanceof IHostFilePermissionsContainer){ if (file instanceof IHostFilePermissionsContainer){
return ((IHostFilePermissionsContainer)file).getPermissions(); return ((IHostFilePermissionsContainer)file).getPermissions();
} }
return null; return null;
@ -1211,10 +1234,10 @@ public class SftpFileService extends AbstractFileService implements IFileService
*/ */
public void setFilePermissions(IHostFile file, public void setFilePermissions(IHostFile file,
IHostFilePermissions permissions, IProgressMonitor monitor) IHostFilePermissions permissions, IProgressMonitor monitor)
throws SystemMessageException { throws SystemMessageException {
return; return;
} }
public int getCapabilities(IHostFile file) { public int getCapabilities(IHostFile file) {
return IFilePermissionsService.FS_CAN_GET_ALL; return IFilePermissionsService.FS_CAN_GET_ALL;
} }