/* * Copyright (C)2009 - SSHJ Contributors * * 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 net.schmizz.sshj.sftp; import java.io.*; public class RandomAccessRemoteFile implements DataInput, DataOutput { private final byte[] singleByte = new byte[1]; private final RemoteFile rf; private long fp; public RandomAccessRemoteFile(RemoteFile rf) { this.rf = rf; } public long getFilePointer() { return fp; } public void seek(long fp) { this.fp = fp; } public int read() throws IOException { return read(singleByte, 0, 1) == -1 ? -1 : singleByte[0]; } public int read(byte[] b) throws IOException { return read(b, 0, b.length); } public int read(byte[] b, int off, int len) throws IOException { final int count = rf.read(fp, b, off, len); fp += count; return count; } @Override public boolean readBoolean() throws IOException { final int ch = read(); if (ch < 0) throw new EOFException(); return (ch != 0); } @Override public byte readByte() throws IOException { final int ch = this.read(); if (ch < 0) throw new EOFException(); return (byte) (ch); } @Override public char readChar() throws IOException { final int ch1 = this.read(); final int ch2 = this.read(); if ((ch1 | ch2) < 0) throw new EOFException(); return (char) ((ch1 << 8) + ch2); } @Override public double readDouble() throws IOException { return Double.longBitsToDouble(readLong()); } @Override public float readFloat() throws IOException { return Float.intBitsToFloat(readInt()); } @Override public void readFully(byte[] b) throws IOException { readFully(b, 0, b.length); } @Override public void readFully(byte[] b, int off, int len) throws IOException { int n = 0; do { int count = read(b, off + n, len - n); if (count < 0) throw new EOFException(); n += count; } while (n < len); } @Override public int readInt() throws IOException { final int ch1 = read(); final int ch2 = read(); final int ch3 = read(); final int ch4 = read(); if ((ch1 | ch2 | ch3 | ch4) < 0) throw new EOFException(); return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4); } @Override public String readLine() throws IOException { StringBuffer input = new StringBuffer(); int c = -1; boolean eol = false; while (!eol) switch (c = read()) { case -1: case '\n': eol = true; break; case '\r': eol = true; long cur = getFilePointer(); if ((read()) != '\n') seek(cur); break; default: input.append((char) c); break; } if ((c == -1) && (input.length() == 0)) return null; return input.toString(); } @Override public long readLong() throws IOException { return ((long) (readInt()) << 32) + (readInt() & 0xFFFFFFFFL); } @Override public short readShort() throws IOException { final int ch1 = this.read(); final int ch2 = this.read(); if ((ch1 | ch2) < 0) throw new EOFException(); return (short) ((ch1 << 8) + ch2); } @Override public String readUTF() throws IOException { return DataInputStream.readUTF(this); } @Override public int readUnsignedByte() throws IOException { final int ch = this.read(); if (ch < 0) throw new EOFException(); return ch; } @Override public int readUnsignedShort() throws IOException { final int ch1 = this.read(); final int ch2 = this.read(); if ((ch1 | ch2) < 0) throw new EOFException(); return (ch1 << 8) + ch2; } @Override public int skipBytes(int n) throws IOException { if (n <= 0) return 0; final long pos = getFilePointer(); final long len = rf.length(); long newpos = pos + n; if (newpos > len) newpos = len; seek(newpos); /* return the actual number of bytes skipped */ return (int) (newpos - pos); } @Override public void write(int i) throws IOException { singleByte[0] = (byte) i; write(singleByte); } @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 { rf.write(fp, b, off, len); fp += (len - off); } @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 writeBytes(String s) throws IOException { final byte[] b = s.getBytes(); write(b, 0, b.length); } @Override public void writeChar(int v) throws IOException { write((v >>> 8) & 0xFF); write(v & 0xFF); } @Override public void writeChars(String s) throws IOException { final int clen = s.length(); final int blen = 2 * clen; final byte[] b = new byte[blen]; final char[] c = new char[clen]; s.getChars(0, clen, c, 0); for (int i = 0, j = 0; i < clen; i++) { b[j++] = (byte) (c[i] >>> 8); b[j++] = (byte) c[i]; } write(b, 0, blen); } @Override public void writeDouble(double v) throws IOException { writeLong(Double.doubleToLongBits(v)); } @Override public void writeFloat(float v) throws IOException { writeInt(Float.floatToIntBits(v)); } @Override public void writeInt(int v) throws IOException { write((v >>> 24) & 0xFF); write((v >>> 16) & 0xFF); write((v >>> 8) & 0xFF); write(v & 0xFF); } @Override public void writeLong(long v) throws IOException { write((int) (v >>> 56) & 0xFF); write((int) (v >>> 48) & 0xFF); write((int) (v >>> 40) & 0xFF); write((int) (v >>> 32) & 0xFF); write((int) (v >>> 24) & 0xFF); write((int) (v >>> 16) & 0xFF); write((int) (v >>> 8) & 0xFF); write((int) v & 0xFF); } @Override public void writeShort(int v) throws IOException { write((v >>> 8) & 0xFF); write(v & 0xFF); } @Override public void writeUTF(String str) throws IOException { final DataOutputStream dos = new DataOutputStream(rf.new RemoteFileOutputStream(fp)); try { dos.writeUTF(str); } finally { dos.close(); } fp += dos.size(); } }