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

com.lithium.flow.shell.sshj.SshjDataIo Maven / Gradle / Ivy

/*
 * Copyright 2015 Lithium Technologies, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.lithium.flow.shell.sshj;

import static com.google.common.base.Preconditions.checkNotNull;

import com.lithium.flow.io.DataIo;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;

import javax.annotation.Nonnull;

import net.schmizz.sshj.sftp.RemoteFile;

/**
 * @author Matt Ayres
 */
public class SshjDataIo implements DataIo {
	private final RemoteFile file;
	private long fp;

	private byte[] b1 = new byte[1];
	private byte[] b2 = new byte[2];
	private byte[] b4 = new byte[4];
	private byte[] b8 = new byte[8];

	public SshjDataIo(@Nonnull RemoteFile file) {
		this.file = checkNotNull(file);
	}

	@Override
	public long getFilePointer() throws IOException {
		return fp;
	}

	@Override
	public void seek(long pos) throws IOException {
		fp = pos;
	}

	@Override
	public long length() throws IOException {
		return file.length();
	}

	@Override
	public void close() throws IOException {
		file.close();
	}

	@Override
	public void readFully(@Nonnull byte[] b) throws IOException {
		readFully(b, 0, b.length);
	}

	@Override
	public void readFully(@Nonnull byte[] b, int off, int len) throws IOException {
		int n = 0;
		while (n < len) {
			n += readFile(b, off + n, len - n);
		}
	}

	private int readFile(@Nonnull byte[] b) throws IOException {
		return readFile(b, 0, b.length);
	}

	private int readFile(@Nonnull byte[] b, int off, int len) throws IOException {
		int count = file.read(fp, b, off, len);
		if (count < 0) {
			throw new EOFException();
		}
		fp += count;
		return count;
	}

	@Override
	public int skipBytes(int n) throws IOException {
		long last = fp;
		fp = Math.min(fp + Math.max(n, 0), file.length());
		return (int) (last - fp);
	}

	@Override
	public boolean readBoolean() throws IOException {
		readFile(b1);
		return b1[0] != 0;
	}

	@Override
	public byte readByte() throws IOException {
		return (byte) readUnsignedByte();
	}

	@Override
	public int readUnsignedByte() throws IOException {
		readFile(b1);
		return b1[0] & 0xFF;
	}

	@Override
	public short readShort() throws IOException {
		return (short) readUnsignedShort();
	}


	@Override
	public int readUnsignedShort() throws IOException {
		readFile(b2);
		return b2[0] << 8 & 0xFF00 | b2[1] & 0xFF;
	}

	@Override
	public char readChar() throws IOException {
		readFile(b2);
		return (char) (b2[0] << 8 & 0xFF00 | b2[1] & 0xFF);
	}

	@Override
	public int readInt() throws IOException {
		readFile(b4);
		return b4[0] << 24 & 0xFF000000 | b4[1] << 16 & 0xFF0000 | b4[2] << 8 & 0xFF00 | b4[3] & 0xFF;
	}

	@Override
	public long readLong() throws IOException {
		readFile(b8);
		return (long) (b8[0] << 24 & 0xFF000000 | b8[1] << 16 & 0xFF0000 | b8[2] << 8 & 0xFF00 | b8[3] & 0xFF) << 32
				| (b8[4] << 24 & 0xFF000000L | b8[5] << 16 & 0xFF0000L | b8[6] << 8 & 0xFF00L | b8[7] & 0xFFL);
	}

	@Override
	public float readFloat() throws IOException {
		return Float.intBitsToFloat(readInt());
	}

	@Override
	public double readDouble() throws IOException {
		return Double.longBitsToDouble(readLong());
	}

	@Override
	public String readLine() throws IOException {
		StringBuilder input = new StringBuilder();
		int c = -1;
		boolean eol = false;

		while (!eol)
			switch (c = readUnsignedByte()) {
				case -1:
				case '\n':
					eol = true;
					break;
				case '\r':
					eol = true;
					long cur = getFilePointer();
					if (readUnsignedByte() != '\n') {
						seek(cur);
					}
					break;
				default:
					input.append((char) c);
					break;
			}

		if (c == -1 && input.length() == 0) {
			return null;
		}
		return input.toString();
	}

	@Override
	@Nonnull
	public String readUTF() throws IOException {
		return DataInputStream.readUTF(this);
	}

	@Override
	public void write(int b) throws IOException {
		b1[0] = (byte) b;
		write(b1);
	}

	@Override
	public void write(byte[] b) throws IOException {
		write(b, 0, b.length);
	}

	@Override
	public void write(byte[] b, int off, int len) throws IOException {
		if (off == 0) {
			file.write(fp, b, off, len);
		} else {
			// workaround for bug in RemoteFile where 'len - off' is sent instead of 'len'
			byte[] c = new byte[len];
			System.arraycopy(b, off, c, 0, len);
			file.write(fp, c, 0, len);
		}
		fp += len;
	}

	@Override
	public void writeBoolean(boolean v) throws IOException {
		write(v ? 1 : 0);
	}

	@Override
	public void writeByte(int v) throws IOException {
		write(v);
	}

	@Override
	public void writeShort(int v) throws IOException {
		b2[0] = (byte) (v >>> 8);
		b2[1] = (byte) v;
		write(b2, 0, 2);
	}

	@Override
	public void writeChar(int v) throws IOException {
		writeShort(v);
	}

	@Override
	public void writeInt(int v) throws IOException {
		b4[0] = (byte) (v >>> 24);
		b4[1] = (byte) (v >>> 16);
		b4[2] = (byte) (v >>> 8);
		b4[3] = (byte) v;
		write(b4, 0, 4);
	}

	@Override
	public void writeLong(long v) throws IOException {
		b8[0] = (byte) (v >>> 56);
		b8[1] = (byte) (v >>> 48);
		b8[2] = (byte) (v >>> 40);
		b8[3] = (byte) (v >>> 32);
		b8[4] = (byte) (v >>> 24);
		b8[5] = (byte) (v >>> 16);
		b8[6] = (byte) (v >>> 8);
		b8[7] = (byte) v;
		write(b8, 0, 8);
	}

	@Override
	public void writeFloat(float v) throws IOException {
		writeInt(Float.floatToIntBits(v));
	}

	@Override
	public void writeDouble(double v) throws IOException {
		writeLong(Double.doubleToLongBits(v));
	}

	@Override
	public void writeBytes(String s) throws IOException {
		write(s.getBytes());
	}

	@Override
	public void writeChars(String s) throws IOException {
		for (char c : s.toCharArray()) {
			writeChar(c);
		}
	}

	@Override
	public void writeUTF(String s) throws IOException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		new DataOutputStream(baos).writeUTF(s);
		write(baos.toByteArray());
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy