com.sshtools.sftp.SftpFileInputStream Maven / Gradle / Ivy
The newest version!
/**
* Copyright 2003-2016 SSHTOOLS Limited. All Rights Reserved.
*
* For product documentation visit https://www.sshtools.com/
*
* This file is part of J2SSH Maverick.
*
* J2SSH Maverick is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* J2SSH Maverick is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with J2SSH Maverick. If not, see .
*/
package com.sshtools.sftp;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;
import com.sshtools.ssh.SshException;
import com.sshtools.ssh.SshIOException;
import com.sshtools.util.UnsignedInteger32;
/**
*
* An InputStream to read the contents of a remote file.
*
*
*
*
* // Create an SshClient forcing SSH2 connectivity.
* SshConnector con = SshConnector.getInstance();
* con.setSupportedVersions(SshConnector.SSH2);
*
* // Connect and authenticate an SshClient
* Ssh2Client ssh = (Ssh2Client) con.connect(....);
* ....
*
* SftpClient sftp=new SftpClient(ssh);
*
* //read file as input stream
* InputStream in = sftp.getInputStream("streamTest");
*
* // Read the data
* int read;
* while((read = in.read()) > -1){
* //do something with data
* }
*
* // Close the file and the stream
* in.close();
*
* @author Lee David Painter
*/
public class SftpFileInputStream extends InputStream {
SftpFile file;
SftpSubsystemChannel sftp;
long position;
Vector outstandingRequests = new Vector();
SftpMessage currentMessage;
int currentMessageRemaining;
boolean isEOF = false;
/**
*
* @param file
* @throws SftpStatusException
* @throws SshException
*/
public SftpFileInputStream(SftpFile file) throws SftpStatusException,
SshException {
this(file, 0);
}
/**
* Creates a new SftpFileInputStream object.
*
* @param file
* @param position
* at which to start reading
* @throws SftpStatusException
* @throws SshException
*/
public SftpFileInputStream(SftpFile file, long position)
throws SftpStatusException, SshException {
if (file.getHandle() == null) {
throw new SftpStatusException(SftpStatusException.INVALID_HANDLE,
"The file does not have a valid handle!");
}
if (file.getSFTPChannel() == null) {
throw new SshException(
"The file is not attached to an SFTP subsystem!",
SshException.BAD_API_USAGE);
}
this.file = file;
this.position = position;
this.sftp = file.getSFTPChannel();
try {
bufferNextMessage();
} catch (IOException e) {
throw new SshException(e);
}
}
/*
* (non-Javadoc)
*
* @see java.io.InputStream#read(byte[], int, int)
*/
public int read(byte[] buffer, int offset, int len) throws IOException {
try {
if (isEOF && currentMessageRemaining == 0) {
return -1;
}
int read = 0;
int wantsLength = len;
while (read < wantsLength && !isEOF) {
if (currentMessage == null || currentMessageRemaining == 0) {
bufferNextMessage();
if (isEOF && read == 0) {
return -1;
}
}
if (currentMessage == null)
throw new IOException(
"Failed to obtain file data or status from the SFTP server!");
int count = Math.min(currentMessageRemaining, len);
System.arraycopy(currentMessage.array(),
currentMessage.getPosition(), buffer, offset, count);
currentMessageRemaining -= count;
currentMessage.skip(count);
if (currentMessageRemaining == 0) {
bufferNextMessage();
}
read += count;
len -= count;
offset += count;
}
return read;
} catch (SshException ex) {
throw new SshIOException(ex);
} catch (SftpStatusException ex) {
throw new IOException(ex.getMessage());
}
}
private void bufferNextMessage() throws SshException, IOException,
SftpStatusException {
bufferMoreData();
UnsignedInteger32 requestid = (UnsignedInteger32) outstandingRequests
.elementAt(0);
currentMessage = sftp.getResponse(requestid);
outstandingRequests.removeElementAt(0);
if (currentMessage.getType() == SftpSubsystemChannel.SSH_FXP_DATA) {
currentMessageRemaining = (int) currentMessage.readInt();
} else if (currentMessage.getType() == SftpSubsystemChannel.SSH_FXP_STATUS) {
int status = (int) currentMessage.readInt();
if (status == SftpStatusException.SSH_FX_EOF) {
isEOF = true;
return;
}
if (sftp.getVersion() >= 3) {
String desc = currentMessage.readString().trim();
throw new IOException(desc);
}
throw new IOException("Unexpected status " + status);
} else {
close();
throw new IOException(
"The server responded with an unexpected SFTP protocol message! type="
+ currentMessage.getType());
}
}
private void bufferMoreData() throws SftpStatusException, SshException {
while (outstandingRequests.size() < 100) {
outstandingRequests.addElement(sftp.postReadRequest(
file.getHandle(), position, 32768));
position += 32768;
}
}
public int available() {
return currentMessageRemaining;
}
/**
*
*/
public int read() throws java.io.IOException {
byte[] b = new byte[1];
if (read(b) == 1) {
int val = (b[0] & 0xFF);
return val;
}
return -1;
}
/**
* Closes the SFTP file handle.
*/
public void close() throws IOException {
try {
file.close();
UnsignedInteger32 requestid;
while (outstandingRequests.size() > 0) {
requestid = (UnsignedInteger32) outstandingRequests
.elementAt(0);
outstandingRequests.removeElementAt(0);
sftp.getResponse(requestid);
}
} catch (SshException ex) {
throw new SshIOException(ex);
} catch (SftpStatusException ex) {
throw new IOException(ex.getMessage());
}
}
/**
* This method will only be available in J2SE builds
*/
// J2SE protected void finalize() throws IOException {
// J2SE if (file.getHandle() != null) {
// J2SE close();
// J2SE }
// J2SE }
}