blob: 81d0e0e8640b18aa0228955701711e31d70d9111 [file] [log] [blame]
/****************************************************************************
* Copyright (c) 2007 Composent, 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:
* Composent, Inc. - initial API and implementation
*****************************************************************************/
package org.eclipse.ecf.internal.provider.filetransfer.scp;
import com.jcraft.jsch.*;
import java.io.*;
import java.net.URL;
import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.ecf.core.security.IConnectContext;
import org.eclipse.ecf.core.util.Proxy;
import org.eclipse.ecf.filetransfer.IFileTransferPausable;
import org.eclipse.ecf.filetransfer.IncomingFileTransferException;
import org.eclipse.ecf.provider.filetransfer.retrieve.AbstractRetrieveFileTransfer;
import org.eclipse.osgi.util.NLS;
/**
*
*/
public class ScpRetrieveFileTransfer extends AbstractRetrieveFileTransfer implements IScpFileTransfer {
private static final String SCP_COMMAND = "scp -f "; //$NON-NLS-1$
private static final String SCP_EXEC = "exec"; //$NON-NLS-1$
String username;
Channel channel;
OutputStream responseStream;
private ScpUtil scpUtil;
/* (non-Javadoc)
* @see org.eclipse.ecf.provider.filetransfer.retrieve.AbstractRetrieveFileTransfer#doPause()
*/
protected boolean doPause() {
return false;
}
/* (non-Javadoc)
* @see org.eclipse.ecf.provider.filetransfer.retrieve.AbstractRetrieveFileTransfer#doResume()
*/
protected boolean doResume() {
return false;
}
public URL getTargetURL() {
return getRemoteFileURL();
}
public Map getOptions() {
return options;
}
/* (non-Javadoc)
* @see org.eclipse.ecf.provider.filetransfer.outgoing.AbstractOutgoingFileTransfer#openStreams()
*/
protected void openStreams() throws IncomingFileTransferException {
try {
// Set input stream from local file
final URL url = getRemoteFileURL();
this.username = url.getUserInfo();
scpUtil = new ScpUtil(this);
final Session s = scpUtil.getSession();
s.connect();
final String command = SCP_COMMAND + scpUtil.trimTargetFile(url.getPath());
channel = s.openChannel(SCP_EXEC);
((ChannelExec) channel).setCommand(command);
channel.connect();
final InputStream ins = channel.getInputStream();
responseStream = channel.getOutputStream();
scpUtil.sendZeroToStream(responseStream);
// read and set filesize
final int c = ins.read();
if (c != 'C')
throw new IOException(Messages.ScpRetrieveFileTransfer_EXCEPTION_SCP_PROTOCOL);
// read '0644 '
final byte[] buf = new byte[1024];
ins.read(buf, 0, 5);
setFileLength(readFileSize(ins, buf));
readFileName(ins, buf);
// set input stream for reading rest of file
setInputStream(ins);
scpUtil.sendZeroToStream(responseStream);
fireReceiveStartEvent();
} catch (final Exception e) {
channel = null;
username = null;
throw new IncomingFileTransferException(NLS.bind(Messages.ScpRetrieveFileTransfer_EXCEPTION_CONNECTING, getRemoteFileURL().toString()), e);
}
}
/* (non-Javadoc)
* @see org.eclipse.ecf.provider.filetransfer.retrieve.AbstractRetrieveFileTransfer#handleReceivedData(byte[], int, double, org.eclipse.core.runtime.IProgressMonitor)
*/
protected void handleReceivedData(byte[] buf, int bytes, double factor, IProgressMonitor monitor) throws IOException {
if (bytes == -1) {
done = true;
} else {
int fileBytes = bytes;
if ((bytesReceived + bytes) > fileLength) {
fileBytes = (int) (fileLength - bytesReceived);
}
bytesReceived += fileBytes;
localFileContents.write(buf, 0, fileBytes);
fireTransferReceiveDataEvent();
monitor.worked((int) Math.round(factor * fileBytes));
if (fileBytes != bytes) {
scpUtil.checkAck(buf[fileBytes], remoteFileContents);
done = true;
}
}
}
private long readFileSize(InputStream ins, byte[] buf) throws IOException {
long filesize = 0L;
while (true) {
if (ins.read(buf, 0, 1) < 0) {
throw new IOException(Messages.ScpRetrieveFileTransfer_EXCEPTION_ERROR_READING_FILE);
}
if (buf[0] == ' ')
break;
filesize = filesize * 10L + (buf[0] - '0');
}
return filesize;
}
private String readFileName(InputStream ins, byte[] buf) throws IOException {
String file = null;
for (int i = 0;; i++) {
ins.read(buf, i, 1);
if (buf[i] == (byte) 0x0a) {
file = new String(buf, 0, i);
break;
}
}
return file;
}
/* (non-Javadoc)
* @see org.eclipse.ecf.provider.filetransfer.outgoing.AbstractOutgoingFileTransfer#hardClose()
*/
protected void hardClose() {
try {
if (remoteFileContents != null && scpUtil != null) {
scpUtil.sendZeroToStream(responseStream);
scpUtil.dispose();
scpUtil = null;
remoteFileContents = null;
responseStream = null;
}
} catch (final IOException e) {
exception = e;
} finally {
super.hardClose();
channel = null;
username = null;
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ecf.provider.filetransfer.retrieve.AbstractRetrieveFileTransfer#getAdapter(java.lang.Class)
*/
public Object getAdapter(Class adapter) {
if (adapter == null)
return null;
if (adapter.equals(IFileTransferPausable.class))
return null;
return super.getAdapter(adapter);
}
/* (non-Javadoc)
* @see org.eclipse.ecf.provider.filetransfer.retrieve.AbstractRetrieveFileTransfer#setupProxy(org.eclipse.ecf.core.util.Proxy)
*/
protected void setupProxy(Proxy proxy) {
this.proxy = proxy;
}
/* (non-Javadoc)
* @see org.eclipse.ecf.provider.filetransfer.scp.IScpFileTransfer#getConnectContext()
*/
public IConnectContext getConnectContext() {
return connectContext;
}
/* (non-Javadoc)
* @see org.eclipse.ecf.provider.filetransfer.scp.IScpFileTransfer#getUsername()
*/
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
/* (non-Javadoc)
* @see org.eclipse.ecf.provider.filetransfer.scp.IScpFileTransfer#promptPassphrase()
*/
public boolean promptPassphrase() {
// XXX TODO
//return (keyFile != null);
return false;
}
public Proxy getProxy() {
return this.proxy;
}
}