All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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 }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy