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

net.schmizz.sshj.sftp.RemoteFile Maven / Gradle / Ivy

There is a newer version: 0.10.0
Show newest version
/*
 * Copyright 2010 Shikhar Bhushan
 *
 * 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 net.schmizz.sshj.sftp.Response.StatusCode;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class RemoteFile
        extends RemoteResource {

    public RemoteFile(Requester requester, String path, String handle) {
        super(requester, path, handle);
    }

    public RemoteFileInputStream getInputStream() {
        return new RemoteFileInputStream();
    }

    public RemoteFileOutputStream getOutputStream() {
        return new RemoteFileOutputStream();
    }

    public FileAttributes fetchAttributes()
            throws IOException {
        return requester.doRequest(newRequest(PacketType.FSTAT))
                .ensurePacketTypeIs(PacketType.ATTRS)
                .readFileAttributes();
    }

    public long length()
            throws IOException {
        return fetchAttributes().getSize();
    }

    public void setLength(long len)
            throws IOException {
        setAttributes(new FileAttributes.Builder().withSize(len).build());
    }

    public int read(long fileOffset, byte[] to, int offset, int len)
            throws IOException {
        Response res = requester.doRequest(newRequest(PacketType.READ).putUINT64(fileOffset).putInt(len));
        switch (res.getType()) {
            case DATA:
                int recvLen = res.readInt();
                System.arraycopy(res.array(), res.rpos(), to, offset, recvLen);
                return recvLen;

            case STATUS:
                res.ensureStatusIs(StatusCode.EOF);
                return -1;

            default:
                throw new SFTPException("Unexpected packet: " + res.getType());
        }
    }

    public void write(long fileOffset, byte[] data, int off, int len)
            throws IOException {
        requester.doRequest(newRequest(PacketType.WRITE)
                .putUINT64(fileOffset)
                .putInt(len - off)
                .putRawBytes(data, off, len)
        ).ensureStatusPacketIsOK();
    }

    public void setAttributes(FileAttributes attrs)
            throws IOException {
        requester.doRequest(newRequest(PacketType.FSETSTAT).putFileAttributes(attrs)).ensureStatusPacketIsOK();
    }

    public int getOutgoingPacketOverhead() {
        return 1 + // packet type
               4 + // request id
               4 + // next length
               handle.length() + // next
               8 + // file offset
               4 + // data length
               4; // packet length
    }

    public class RemoteFileOutputStream
            extends OutputStream {


        private final byte[] b = new byte[1];

        private long fileOffset;

        public RemoteFileOutputStream() {
            this(0);
        }

        public RemoteFileOutputStream(long fileOffset) {
            this.fileOffset = fileOffset;
        }

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

        @Override
        public void write(byte[] buf, int off, int len)
                throws IOException {
            RemoteFile.this.write(fileOffset, buf, off, len);
            fileOffset += len;
        }

    }

    public class RemoteFileInputStream
            extends InputStream {

        private final byte[] b = new byte[1];

        private long fileOffset;
        private long markPos;
        private long readLimit;

        public RemoteFileInputStream() {
            this(0);
        }

        public RemoteFileInputStream(int fileOffset) {
            this.fileOffset = fileOffset;
        }

        @Override
        public boolean markSupported() {
            return true;
        }

        @Override
        public void mark(int readLimit) {
            this.readLimit = readLimit;
            markPos = fileOffset;
        }

        @Override
        public void reset()
                throws IOException {
            fileOffset = markPos;
        }

        @Override
        public long skip(long n)
                throws IOException {
            return (this.fileOffset = Math.min(fileOffset + n, length()));
        }

        @Override
        public int read()
                throws IOException {
            return read(b, 0, 1) == -1 ? -1 : b[0] & 0xff;
        }

        @Override
        public int read(byte[] into, int off, int len)
                throws IOException {
            int read = RemoteFile.this.read(fileOffset, into, off, len);
            if (read != -1) {
                fileOffset += read;
                if (markPos != 0 && read > readLimit) // Invalidate mark position
                    markPos = 0;
            }
            return read;
        }

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy