blob: c6c82b4ff9506ede9f9627fec30b32481d642da6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014 CohesionForce 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:
* CohesionForce Inc - initial API and implementation
*******************************************************************************/
package org.eclipse.ecf.internal.provider.filetransfer.scp;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.Session;
import java.io.*;
import java.net.*;
import java.util.*;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.ecf.core.identity.IDFactory;
import org.eclipse.ecf.core.security.IConnectContext;
import org.eclipse.ecf.core.util.Proxy;
import org.eclipse.ecf.filetransfer.IRemoteFile;
import org.eclipse.ecf.filetransfer.IRemoteFileSystemListener;
import org.eclipse.ecf.filetransfer.identity.*;
import org.eclipse.ecf.provider.filetransfer.browse.AbstractFileSystemBrowser;
import org.eclipse.ecf.provider.filetransfer.browse.URLRemoteFile;
import org.eclipse.ecf.provider.filetransfer.identity.FileTransferNamespace;
/**
* The ScpFileSystemBrowser uses the JCraft JSch package to run remote commands
* using SSH to list files in a directory.
*
*/
public class ScpFileSystemBrowser extends AbstractFileSystemBrowser implements
IScpFileTransfer {
protected InputStream inputStream;
protected OutputStream outputStream;
protected ScpUtil scpUtil;
protected ChannelExec channel;
protected String username;
protected static final String SCP_EXEC = System.getProperty(
"org.eclipse.ecf.filetransfer.scp.filebrowse.exec", "exec"); //$NON-NLS-1$
protected static final String LS_START_COMMAND = System.getProperty(
"org.eclipse.ecf.filetransfer.scp.filebrowse.lscommand.start",
"IFS=\"$(printf '\n\t\')\"; shopt -s dotglob; for file in "); //$NON-NLS-1$; //$NON-NLS-1$
protected static final String LS_END_COMMAND = System.getProperty(
"org.eclipse.ecf.filetransfer.scp.filebrowse.lscommand.end",
"/*; do stat --format='%F|%s|%Y|%n' $file; done "); //$NON-NLS-1$; //$NON-NLS-1$
/**
* Constructor for creating a ScpFileSystemBrowser.
*
* @param directoryOrFileID
* - ID of the remote location to browse
* @param listener
* - will be called asynchronously with events resulting from
* file browsing.
* @param url
* - URL of the parent directory to browse.
* @param connectContext
* - contains username/password to use for the ssh connection
* @param proxy
* - proxy to be used if set.
*/
public ScpFileSystemBrowser(IFileID directoryOrFileID,
IRemoteFileSystemListener listener, URL url,
IConnectContext connectContext, Proxy proxy) {
super(directoryOrFileID, listener, url, connectContext, proxy);
username = directoryOrFile.getUserInfo();
}
/**
* Method called from super class to build the list of remote files.
*/
protected void runRequest() throws Exception {
scpUtil = new ScpUtil(this);
final Session s = scpUtil.getSession();
s.connect();
if (s.isConnected()) {
final String targetFileName = scpUtil
.trimTargetFile(directoryOrFile.getPath());
final String command = LS_START_COMMAND + targetFileName
+ LS_END_COMMAND;
channel = (ChannelExec) s.openChannel(SCP_EXEC);
channel.setCommand(command);
final OutputStream outs = channel.getOutputStream();
inputStream = channel.getInputStream();
channel.connect();
setOutputStream(outs);
BufferedReader reader = new BufferedReader(new InputStreamReader(
inputStream));
String line = reader.readLine();
ArrayList strings = new ArrayList();
while (line != null) {
strings.add(line);
line = reader.readLine();
}
List remoteFilesList = new ArrayList();
for (int i = 0; i < strings.size(); i++) {
try {
remoteFilesList.add(createRemoteFile((String) strings
.get(i)));
} catch (Exception e) {
Activator
.getDefault()
.log(new Status(
IStatus.ERROR,
Activator.PLUGIN_ID,
IStatus.ERROR,
"SCPFileBrowser could not convert string '" + ((String) strings.get(i)) + "' to FileID", e)); //$NON-NLS-1$
}
}
remoteFiles = (IRemoteFile[]) remoteFilesList
.toArray(new IRemoteFile[remoteFilesList.size()]);
}
}
private IRemoteFile createRemoteFile(String string)
throws URISyntaxException, FileCreateException, SecurityException {
URLRemoteFile file = null;
IFileID id = null;
String[] parts = string.split("\\|");
// Check to see if this string can be parsed
if (parts.length < 4) {
id = FileIDFactory.getDefault().createFileID(
IDFactory.getDefault().getNamespaceByName(
FileTransferNamespace.PROTOCOL), "scp://unknown");
file = new URLRemoteFile(0, 0, id);
} else {
// Build the filename back up, since the filename may also contain
// "|"
// characters
StringBuilder builder = new StringBuilder("scp://");
for (int i = 3; i < parts.length; i++) {
builder.append(parts[i]);
// Put the | back into the name
if (i > 3 && i < parts.length - 1) {
builder.append("|");
}
}
// If it's a directory, then make sure it ends with /
if (parts[0].equals("directory")
&& !builder.toString().endsWith("/")) {
builder.append("/");
} else if (!parts[0].equals("directory")
&& builder.toString().endsWith("/")) {
builder.deleteCharAt(builder.length() - 1);
}
String originalName = builder.toString();
String formatedName = originalName.replace(" ", "%20");
URI uri = new URI(formatedName);
// Create the FileID
id = FileIDFactory.getDefault().createFileID(
IDFactory.getDefault().getNamespaceByName(
FileTransferNamespace.PROTOCOL),
new Object[] { uri });
long size = Long.parseLong(parts[1]);
long modification = Long.parseLong(parts[2]);
file = new URLRemoteFile(modification, size, id);
}
return file;
}
protected void cleanUp() {
super.cleanUp();
if (channel != null) {
channel.disconnect();
channel = null;
}
if (scpUtil != null) {
scpUtil.dispose();
scpUtil = null;
}
try {
if (inputStream != null)
inputStream.close();
} catch (final IOException e) {
Activator.getDefault().log(
new Status(IStatus.ERROR, Activator.PLUGIN_ID,
IStatus.ERROR, "cleanup", e)); //$NON-NLS-1$
}
try {
if (outputStream != null)
outputStream.close();
} catch (final IOException e) {
Activator.getDefault().log(
new Status(IStatus.ERROR, Activator.PLUGIN_ID,
IStatus.ERROR, "cleanup", e)); //$NON-NLS-1$
}
inputStream = null;
outputStream = null;
}
protected void setupProxy(Proxy proxy) {
this.proxy = proxy;
this.setupProxies();
}
protected void setInputStream(InputStream ins) {
inputStream = ins;
}
protected void setOutputStream(OutputStream outs) {
outputStream = outs;
}
public IConnectContext getConnectContext() {
return connectContext;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Proxy getProxy() {
return proxy;
}
public URL getTargetURL() {
return directoryOrFile;
}
public Map getOptions() {
return null;
}
}