blob: aa552348c263a395d00736e5a30d6da47246a63d [file] [log] [blame]
package org.eclipse.remote.internal.jsch.core.commands;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.osgi.util.NLS;
import org.eclipse.remote.core.exception.RemoteConnectionException;
import org.eclipse.remote.internal.jsch.core.JSchConnection;
import org.eclipse.remote.internal.jsch.core.messages.Messages;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
/**
* The JSch implementation does not support multiple streams open on a single channel, so we must create a new channel for each
* subsequent stream. This has the problem that there are usually only a limited number of channels that can be opened
* simultaneously, so it is possible that this call will fail unless the open streams are closed first.
*
* This code will use the initial (command) channel first, or if that is already being used, will open a new stream. It must be
* careful not to close the command stream as other threads may still be using it.
*/
public class GetInputStreamCommand extends AbstractRemoteCommand<InputStream> {
private final IPath fRemotePath;
private static ChannelSftp commandChannel;
private ChannelSftp thisChannel;
public GetInputStreamCommand(JSchConnection connection, IPath path) {
super(connection);
fRemotePath = path;
}
@Override
public InputStream getResult(IProgressMonitor monitor) throws RemoteConnectionException {
final SubMonitor subMon = SubMonitor.convert(monitor, 10);
final SftpCallable<InputStream> c = new SftpCallable<InputStream>() {
private ChannelSftp newChannel() throws IOException {
synchronized (GetInputStreamCommand.class) {
if (commandChannel != null) {
try {
thisChannel = getConnection().newSftpChannel();
return thisChannel;
} catch (RemoteConnectionException e) {
throw new IOException(e.getMessage());
}
}
thisChannel = commandChannel = getChannel();
return commandChannel;
}
}
@Override
public InputStream call() throws JSchException, SftpException, IOException {
return newChannel().get(fRemotePath.toString(), new CommandProgressMonitor(
NLS.bind(Messages.GetInputStreamCommand_Receiving, fRemotePath.toString()), getProgressMonitor()));
}
};
try {
final InputStream stream = c.getResult(subMon.newChild(10));
return new InputStream() {
@Override
public int read() throws IOException {
return stream.read();
}
/*
* (non-Javadoc)
*
* @see java.io.InputStream#close()
*/
@Override
public void close() throws IOException {
stream.close();
synchronized (GetInputStreamCommand.class) {
if (thisChannel != commandChannel) {
thisChannel.disconnect();
} else {
commandChannel = null;
}
}
}
/*
* (non-Javadoc)
*
* @see java.io.InputStream#read(byte[])
*/
@Override
public int read(byte[] b) throws IOException {
return stream.read(b);
}
/*
* (non-Javadoc)
*
* @see java.io.InputStream#read(byte[], int, int)
*/
@Override
public int read(byte[] b, int off, int len) throws IOException {
return stream.read(b, off, len);
}
/*
* (non-Javadoc)
*
* @see java.io.InputStream#skip(long)
*/
@Override
public long skip(long n) throws IOException {
return stream.skip(n);
}
/*
* (non-Javadoc)
*
* @see java.io.InputStream#available()
*/
@Override
public int available() throws IOException {
return stream.available();
}
/*
* (non-Javadoc)
*
* @see java.io.InputStream#mark(int)
*/
@Override
public synchronized void mark(int readlimit) {
stream.mark(readlimit);
}
/*
* (non-Javadoc)
*
* @see java.io.InputStream#reset()
*/
@Override
public synchronized void reset() throws IOException {
stream.reset();
}
/*
* (non-Javadoc)
*
* @see java.io.InputStream#markSupported()
*/
@Override
public boolean markSupported() {
return stream.markSupported();
}
};
} catch (SftpException e) {
throw new RemoteConnectionException(e.getMessage());
}
}
}