sftp reformat

This commit is contained in:
Shikhar Bhushan
2010-03-01 23:41:19 +01:00
parent 8ec5055615
commit 5335c282dc
17 changed files with 341 additions and 180 deletions

View File

@@ -27,7 +27,11 @@ public final class FileAttributes {
public static enum Flag {
SIZE(0x00000001), UIDGID(0x00000002), MODE(0x00000004), ACMODTIME(0x00000008), EXTENDED(0x80000000);
SIZE(0x00000001),
UIDGID(0x00000002),
MODE(0x00000004),
ACMODTIME(0x00000008),
EXTENDED(0x80000000);
private final int flag;

View File

@@ -24,7 +24,8 @@ import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class PacketReader extends Thread {
public class PacketReader
extends Thread {
/** Logger */
private final Logger log = LoggerFactory.getLogger(getClass());
@@ -39,7 +40,8 @@ public class PacketReader extends Thread {
setName("sftp reader");
}
private void readIntoBuffer(byte[] buf, int off, int len) throws IOException {
private void readIntoBuffer(byte[] buf, int off, int len)
throws IOException {
int count = 0;
int read = 0;
while (count < len && ((read = in.read(buf, off + count, len - count)) != -1))
@@ -48,17 +50,18 @@ public class PacketReader extends Thread {
throw new SFTPException("EOF while reading packet");
}
private int getPacketLength() throws IOException {
private int getPacketLength()
throws IOException {
readIntoBuffer(lenBuf, 0, lenBuf.length);
return (int) (lenBuf[0] << 24 & 0xff000000L
| lenBuf[1] << 16 & 0x00ff0000L
| lenBuf[2] << 8 & 0x0000ff00L
| lenBuf[3] & 0x000000ffL
);
| lenBuf[1] << 16 & 0x00ff0000L
| lenBuf[2] << 8 & 0x0000ff00L
| lenBuf[3] & 0x000000ffL);
}
public SFTPPacket<Response> readPacket() throws IOException {
public SFTPPacket<Response> readPacket()
throws IOException {
int len = getPacketLength();
packet.rpos(0);
@@ -85,13 +88,14 @@ public class PacketReader extends Thread {
}
}
public void handle() throws SFTPException {
public void handle()
throws SFTPException {
Response resp = new Response(packet);
Future<Response, SFTPException> future = futures.remove(resp.getRequestID());
log.debug("Received {} packet", resp.getType());
if (future == null)
throw new SFTPException("Received [" + resp.readType() + "] response for request-id " + resp.getRequestID()
+ ", no such request was made");
+ ", no such request was made");
else
future.set(resp);
}

View File

@@ -19,7 +19,7 @@ class PathComponents {
public static String adjustForParent(String parent, String path) {
return (path.startsWith("/")) ? path // Absolute path, nothing to adjust
: (parent + (parent.endsWith("/") ? "" : "/") + path); // Relative path
: (parent + (parent.endsWith("/") ? "" : "/") + path); // Relative path
}
private static String trimFinalSlash(String path) {

View File

@@ -26,7 +26,8 @@ class PathHelper {
this.sftp = sftp;
}
public PathComponents getComponents(String path) throws IOException {
public PathComponents getComponents(String path)
throws IOException {
if (path.isEmpty() || path.equals("."))
return getComponents(getDotDir());
@@ -48,11 +49,13 @@ class PathHelper {
}
}
private String getDotDir() throws IOException {
private String getDotDir()
throws IOException {
return (dotDir != null) ? dotDir : (dotDir = canon("."));
}
private String canon(String path) throws IOException {
private String canon(String path)
throws IOException {
return sftp.canonicalize(path);
}

View File

@@ -22,7 +22,8 @@ import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
public class RandomAccessRemoteFile implements DataInput, DataOutput {
public class RandomAccessRemoteFile
implements DataInput, DataOutput {
private final byte[] singleByte = new byte[1];
@@ -43,35 +44,41 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
this.fp = fp;
}
public int read() throws IOException {
public int read()
throws IOException {
return read(singleByte, 0, 1) == -1 ? -1 : singleByte[0];
}
public int read(byte[] b) throws IOException {
public int read(byte[] b)
throws IOException {
return read(b, 0, b.length);
}
public int read(byte[] b, int off, int len) throws IOException {
public int read(byte[] b, int off, int len)
throws IOException {
final int count = rf.read(fp, b, off, len);
fp += count;
return count;
}
public boolean readBoolean() throws IOException {
public boolean readBoolean()
throws IOException {
final int ch = read();
if (ch < 0)
throw new EOFException();
return (ch != 0);
}
public byte readByte() throws IOException {
public byte readByte()
throws IOException {
final int ch = this.read();
if (ch < 0)
throw new EOFException();
return (byte) (ch);
}
public char readChar() throws IOException {
public char readChar()
throws IOException {
final int ch1 = this.read();
final int ch2 = this.read();
if ((ch1 | ch2) < 0)
@@ -79,19 +86,23 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
return (char) ((ch1 << 8) + ch2);
}
public double readDouble() throws IOException {
public double readDouble()
throws IOException {
return Double.longBitsToDouble(readLong());
}
public float readFloat() throws IOException {
public float readFloat()
throws IOException {
return Float.intBitsToFloat(readInt());
}
public void readFully(byte[] b) throws IOException {
public void readFully(byte[] b)
throws IOException {
readFully(b, 0, b.length);
}
public void readFully(byte[] b, int off, int len) throws IOException {
public void readFully(byte[] b, int off, int len)
throws IOException {
int n = 0;
do {
int count = read(b, off + n, len - n);
@@ -101,7 +112,8 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
} while (n < len);
}
public int readInt() throws IOException {
public int readInt()
throws IOException {
final int ch1 = read();
final int ch2 = read();
final int ch3 = read();
@@ -111,7 +123,8 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4);
}
public String readLine() throws IOException {
public String readLine()
throws IOException {
StringBuffer input = new StringBuffer();
int c = -1;
boolean eol = false;
@@ -138,11 +151,13 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
return input.toString();
}
public long readLong() throws IOException {
public long readLong()
throws IOException {
return ((long) (readInt()) << 32) + (readInt() & 0xFFFFFFFFL);
}
public short readShort() throws IOException {
public short readShort()
throws IOException {
final int ch1 = this.read();
final int ch2 = this.read();
if ((ch1 | ch2) < 0)
@@ -150,18 +165,21 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
return (short) ((ch1 << 8) + ch2);
}
public String readUTF() throws IOException {
public String readUTF()
throws IOException {
return DataInputStream.readUTF(this);
}
public int readUnsignedByte() throws IOException {
public int readUnsignedByte()
throws IOException {
final int ch = this.read();
if (ch < 0)
throw new EOFException();
return ch;
}
public int readUnsignedShort() throws IOException {
public int readUnsignedShort()
throws IOException {
final int ch1 = this.read();
final int ch2 = this.read();
if ((ch1 | ch2) < 0)
@@ -169,7 +187,8 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
return (ch1 << 8) + ch2;
}
public int skipBytes(int n) throws IOException {
public int skipBytes(int n)
throws IOException {
if (n <= 0)
return 0;
final long pos = getFilePointer();
@@ -183,39 +202,47 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
return (int) (newpos - pos);
}
public void write(int i) throws IOException {
public void write(int i)
throws IOException {
singleByte[0] = (byte) i;
write(singleByte);
}
public void write(byte[] b) throws IOException {
public void write(byte[] b)
throws IOException {
write(b, 0, b.length);
}
public void write(byte[] b, int off, int len) throws IOException {
public void write(byte[] b, int off, int len)
throws IOException {
rf.write(fp, b, off, len);
fp += (len - off);
}
public void writeBoolean(boolean v) throws IOException {
public void writeBoolean(boolean v)
throws IOException {
write(v ? 1 : 0);
}
public void writeByte(int v) throws IOException {
public void writeByte(int v)
throws IOException {
write(v);
}
public void writeBytes(String s) throws IOException {
public void writeBytes(String s)
throws IOException {
final byte[] b = s.getBytes();
write(b, 0, b.length);
}
public void writeChar(int v) throws IOException {
public void writeChar(int v)
throws IOException {
write((v >>> 8) & 0xFF);
write(v & 0xFF);
}
public void writeChars(String s) throws IOException {
public void writeChars(String s)
throws IOException {
final int clen = s.length();
final int blen = 2 * clen;
final byte[] b = new byte[blen];
@@ -228,22 +255,26 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
write(b, 0, blen);
}
public void writeDouble(double v) throws IOException {
public void writeDouble(double v)
throws IOException {
writeLong(Double.doubleToLongBits(v));
}
public void writeFloat(float v) throws IOException {
public void writeFloat(float v)
throws IOException {
writeInt(Float.floatToIntBits(v));
}
public void writeInt(int v) throws IOException {
public void writeInt(int v)
throws IOException {
write((v >>> 24) & 0xFF);
write((v >>> 16) & 0xFF);
write((v >>> 8) & 0xFF);
write(v & 0xFF);
}
public void writeLong(long v) throws IOException {
public void writeLong(long v)
throws IOException {
write((int) (v >>> 56) & 0xFF);
write((int) (v >>> 48) & 0xFF);
write((int) (v >>> 40) & 0xFF);
@@ -254,12 +285,14 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
write((int) v & 0xFF);
}
public void writeShort(int v) throws IOException {
public void writeShort(int v)
throws IOException {
write((v >>> 8) & 0xFF);
write(v & 0xFF);
}
public void writeUTF(String str) throws IOException {
public void writeUTF(String str)
throws IOException {
final DataOutputStream dos = new DataOutputStream(rf.new RemoteFileOutputStream(fp));
try {
dos.writeUTF(str);

View File

@@ -21,13 +21,15 @@ import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
public class RemoteDirectory extends RemoteResource {
public class RemoteDirectory
extends RemoteResource {
public RemoteDirectory(Requester requester, String path, String handle) {
super(requester, path, handle);
}
public List<RemoteResourceInfo> scan(RemoteResourceFilter filter) throws IOException {
public List<RemoteResourceInfo> scan(RemoteResourceFilter filter)
throws IOException {
List<RemoteResourceInfo> rri = new LinkedList<RemoteResourceInfo>();
loop:
for (; ;) {

View File

@@ -21,7 +21,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class RemoteFile extends RemoteResource {
public class RemoteFile
extends RemoteResource {
public RemoteFile(Requester requester, String path, String handle) {
super(requester, path, handle);
@@ -35,21 +36,25 @@ public class RemoteFile extends RemoteResource {
return new RemoteFileOutputStream();
}
public FileAttributes fetchAttributes() throws IOException {
public FileAttributes fetchAttributes()
throws IOException {
return requester.doRequest(newRequest(PacketType.FSTAT)) //
.ensurePacketTypeIs(PacketType.ATTRS) //
.readFileAttributes();
}
public long length() throws IOException {
public long length()
throws IOException {
return fetchAttributes().getSize();
}
public void setLength(long len) throws IOException {
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 {
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:
@@ -66,30 +71,33 @@ public class RemoteFile extends RemoteResource {
}
}
public void write(long fileOffset, byte[] data, int off, int len) throws IOException {
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) //
newRequest(PacketType.WRITE) //
.putUINT64(fileOffset) //
.putInt(len - off) //
.putRawBytes(data, off, len) //
).ensureStatusPacketIsOK();
}
public void setAttributes(FileAttributes attrs) throws IOException {
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
4 + // request id
4 + // next length
handle.length() + // next
8 + // file offset
4 + // data length
4; // packet length
}
public class RemoteFileOutputStream extends OutputStream {
public class RemoteFileOutputStream
extends OutputStream {
private final byte[] b = new byte[1];
@@ -105,20 +113,23 @@ public class RemoteFile extends RemoteResource {
}
@Override
public void write(int w) throws IOException {
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 {
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 {
public class RemoteFileInputStream
extends InputStream {
private final byte[] b = new byte[1];
@@ -146,22 +157,26 @@ public class RemoteFile extends RemoteResource {
}
@Override
public void reset() throws IOException {
public void reset()
throws IOException {
fileOffset = markPos;
}
@Override
public long skip(long n) throws IOException {
public long skip(long n)
throws IOException {
return (this.fileOffset = Math.min(fileOffset + n, length()));
}
@Override
public int read() throws IOException {
public int read()
throws IOException {
return read(b, 0, 1) == -1 ? -1 : b[0];
}
@Override
public int read(byte[] into, int off, int len) throws IOException {
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;

View File

@@ -21,7 +21,8 @@ import org.slf4j.LoggerFactory;
import java.io.Closeable;
import java.io.IOException;
abstract class RemoteResource implements Closeable {
abstract class RemoteResource
implements Closeable {
/** Logger */
protected final Logger log = LoggerFactory.getLogger(getClass());
@@ -44,7 +45,8 @@ abstract class RemoteResource implements Closeable {
return requester.newRequest(type).putString(handle);
}
public void close() throws IOException {
public void close()
throws IOException {
log.info("Closing `{}`", this);
requester.doRequest(newRequest(PacketType.CLOSE)).ensureStatusPacketIsOK();
}

View File

@@ -17,7 +17,8 @@ package net.schmizz.sshj.sftp;
import net.schmizz.concurrent.Future;
public class Request extends SFTPPacket<Request> {
public class Request
extends SFTPPacket<Request> {
private final PacketType type;
private final long reqID;

View File

@@ -21,6 +21,7 @@ public interface Requester {
Request newRequest(PacketType type);
Response doRequest(Request req) throws IOException;
Response doRequest(Request req)
throws IOException;
}

View File

@@ -17,7 +17,8 @@ package net.schmizz.sshj.sftp;
import net.schmizz.sshj.common.Buffer;
public class Response extends SFTPPacket<Response> {
public class Response
extends SFTPPacket<Response> {
public static enum StatusCode {
UNKNOWN(-1),
@@ -67,7 +68,8 @@ public class Response extends SFTPPacket<Response> {
return StatusCode.fromInt(readInt());
}
public Response ensurePacketTypeIs(PacketType pt) throws SFTPException {
public Response ensurePacketTypeIs(PacketType pt)
throws SFTPException {
if (getType() != pt)
if (getType() == PacketType.STATUS)
throw new SFTPException(readStatusCode(), readString());
@@ -76,11 +78,13 @@ public class Response extends SFTPPacket<Response> {
return this;
}
public Response ensureStatusPacketIsOK() throws SFTPException {
public Response ensureStatusPacketIsOK()
throws SFTPException {
return ensurePacketTypeIs(PacketType.STATUS).ensureStatusIs(StatusCode.OK);
}
public Response ensureStatusIs(StatusCode acceptable) throws SFTPException {
public Response ensureStatusIs(StatusCode acceptable)
throws SFTPException {
StatusCode sc = readStatusCode();
if (sc != acceptable)
throw new SFTPException(sc, readString());

View File

@@ -33,7 +33,8 @@ public class SFTPClient {
private final SFTPEngine sftp;
private final SFTPFileTransfer xfer;
public SFTPClient(SessionFactory ssh) throws IOException {
public SFTPClient(SessionFactory ssh)
throws IOException {
this.sftp = new SFTPEngine(ssh).init();
this.xfer = new SFTPFileTransfer(sftp);
}
@@ -46,11 +47,13 @@ public class SFTPClient {
return xfer;
}
public List<RemoteResourceInfo> ls(String path) throws IOException {
public List<RemoteResourceInfo> ls(String path)
throws IOException {
return ls(path, null);
}
public List<RemoteResourceInfo> ls(String path, RemoteResourceFilter filter) throws IOException {
public List<RemoteResourceInfo> ls(String path, RemoteResourceFilter filter)
throws IOException {
final RemoteDirectory dir = sftp.openDir(path);
try {
return dir.scan(filter);
@@ -59,36 +62,44 @@ public class SFTPClient {
}
}
public RemoteFile open(String filename, Set<OpenMode> mode, FileAttributes attrs) throws IOException {
public RemoteFile open(String filename, Set<OpenMode> mode, FileAttributes attrs)
throws IOException {
log.debug("Opening `{}`", filename);
return sftp.open(filename, mode, attrs);
}
public RemoteFile open(String filename, Set<OpenMode> mode) throws IOException {
public RemoteFile open(String filename, Set<OpenMode> mode)
throws IOException {
return open(filename, mode, new FileAttributes());
}
public RemoteFile open(String filename) throws IOException {
public RemoteFile open(String filename)
throws IOException {
return open(filename, EnumSet.of(OpenMode.READ));
}
public void mkdir(String dirname) throws IOException {
public void mkdir(String dirname)
throws IOException {
sftp.makeDir(dirname);
}
public void rename(String oldpath, String newpath) throws IOException {
public void rename(String oldpath, String newpath)
throws IOException {
sftp.rename(oldpath, newpath);
}
public void rm(String filename) throws IOException {
public void rm(String filename)
throws IOException {
sftp.remove(filename);
}
public void rmdir(String dirname) throws IOException {
public void rmdir(String dirname)
throws IOException {
sftp.removeDir(dirname);
}
public void symlink(String linkpath, String targetpath) throws IOException {
public void symlink(String linkpath, String targetpath)
throws IOException {
sftp.symlink(linkpath, targetpath);
}
@@ -96,79 +107,98 @@ public class SFTPClient {
return sftp.getOperativeProtocolVersion();
}
public void setattr(String path, FileAttributes attrs) throws IOException {
public void setattr(String path, FileAttributes attrs)
throws IOException {
sftp.setAttributes(path, attrs);
}
public int uid(String path) throws IOException {
public int uid(String path)
throws IOException {
return stat(path).getUID();
}
public int gid(String path) throws IOException {
public int gid(String path)
throws IOException {
return stat(path).getGID();
}
public long atime(String path) throws IOException {
public long atime(String path)
throws IOException {
return stat(path).getAtime();
}
public long mtime(String path) throws IOException {
public long mtime(String path)
throws IOException {
return stat(path).getMtime();
}
public Set<FilePermission> perms(String path) throws IOException {
public Set<FilePermission> perms(String path)
throws IOException {
return stat(path).getPermissions();
}
public FileMode mode(String path) throws IOException {
public FileMode mode(String path)
throws IOException {
return stat(path).getMode();
}
public FileMode.Type type(String path) throws IOException {
public FileMode.Type type(String path)
throws IOException {
return stat(path).getType();
}
public String readlink(String path) throws IOException {
public String readlink(String path)
throws IOException {
return sftp.readLink(path);
}
public FileAttributes stat(String path) throws IOException {
public FileAttributes stat(String path)
throws IOException {
return sftp.stat(path);
}
public FileAttributes lstat(String path) throws IOException {
public FileAttributes lstat(String path)
throws IOException {
return sftp.lstat(path);
}
public void chown(String path, int uid) throws IOException {
public void chown(String path, int uid)
throws IOException {
setattr(path, new FileAttributes.Builder().withUIDGID(uid, gid(path)).build());
}
public void chmod(String path, int perms) throws IOException {
public void chmod(String path, int perms)
throws IOException {
setattr(path, new FileAttributes.Builder().withPermissions(perms).build());
}
public void chgrp(String path, int gid) throws IOException {
public void chgrp(String path, int gid)
throws IOException {
setattr(path, new FileAttributes.Builder().withUIDGID(uid(path), gid).build());
}
public void truncate(String path, long size) throws IOException {
public void truncate(String path, long size)
throws IOException {
setattr(path, new FileAttributes.Builder().withSize(size).build());
}
public String canonicalize(String path) throws IOException {
public String canonicalize(String path)
throws IOException {
return sftp.canonicalize(path);
}
public long size(String path) throws IOException {
public long size(String path)
throws IOException {
return stat(path).getSize();
}
public void get(String source, String dest) throws IOException {
public void get(String source, String dest)
throws IOException {
xfer.download(source, dest);
}
public void put(String source, String dest) throws IOException {
public void put(String source, String dest)
throws IOException {
xfer.upload(source, dest);
}

View File

@@ -29,7 +29,8 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
public class SFTPEngine implements Requester {
public class SFTPEngine
implements Requester {
/** Logger */
private final Logger log = LoggerFactory.getLogger(getClass());
@@ -48,7 +49,8 @@ public class SFTPEngine implements Requester {
private int negotiatedVersion;
private final Map<String, String> serverExtensions = new HashMap<String, String>();
public SFTPEngine(SessionFactory ssh) throws SSHException {
public SFTPEngine(SessionFactory ssh)
throws SSHException {
sub = ssh.startSession().startSubsystem("sftp");
out = sub.getOutputStream();
reader = new PacketReader(sub.getInputStream());
@@ -58,7 +60,8 @@ public class SFTPEngine implements Requester {
return sub;
}
public SFTPEngine init() throws IOException {
public SFTPEngine init()
throws IOException {
transmit(new SFTPPacket<Request>(PacketType.INIT).putInt(PROTOCOL_VERSION));
final SFTPPacket<Response> response = reader.readPacket();
@@ -88,14 +91,16 @@ public class SFTPEngine implements Requester {
return new Request(type, reqID = reqID + 1 & 0xffffffffL);
}
public Response doRequest(Request req) throws IOException {
public Response doRequest(Request req)
throws IOException {
reader.expectResponseTo(req);
log.debug("Sending {}", req);
transmit(req);
return req.getResponseFuture().get(timeout, TimeUnit.SECONDS);
}
private synchronized void transmit(SFTPPacket<Request> payload) throws IOException {
private synchronized void transmit(SFTPPacket<Request> payload)
throws IOException {
final int len = payload.available();
out.write((len >>> 24) & 0xff);
out.write((len >>> 16) & 0xff);
@@ -105,7 +110,8 @@ public class SFTPEngine implements Requester {
out.flush();
}
public RemoteFile open(String path, Set<OpenMode> modes, FileAttributes fa) throws IOException {
public RemoteFile open(String path, Set<OpenMode> modes, FileAttributes fa)
throws IOException {
final String handle = doRequest(
newRequest(PacketType.OPEN).putString(path).putInt(OpenMode.toMask(modes)).putFileAttributes(fa)
@@ -113,90 +119,106 @@ public class SFTPEngine implements Requester {
return new RemoteFile(this, path, handle);
}
public RemoteFile open(String filename, Set<OpenMode> modes) throws IOException {
public RemoteFile open(String filename, Set<OpenMode> modes)
throws IOException {
return open(filename, modes, new FileAttributes());
}
public RemoteFile open(String filename) throws IOException {
public RemoteFile open(String filename)
throws IOException {
return open(filename, EnumSet.of(OpenMode.READ));
}
public RemoteDirectory openDir(String path) throws IOException {
public RemoteDirectory openDir(String path)
throws IOException {
final String handle = doRequest(
newRequest(PacketType.OPENDIR).putString(path)
).ensurePacketTypeIs(PacketType.HANDLE).readString();
return new RemoteDirectory(this, path, handle);
}
public void setAttributes(String path, FileAttributes attrs) throws IOException {
public void setAttributes(String path, FileAttributes attrs)
throws IOException {
doRequest(
newRequest(PacketType.SETSTAT).putString(path).putFileAttributes(attrs)
).ensureStatusPacketIsOK();
}
public String readLink(String path) throws IOException {
public String readLink(String path)
throws IOException {
return readSingleName(
doRequest(
newRequest(PacketType.READLINK).putString(path)
));
}
public void makeDir(String path, FileAttributes attrs) throws IOException {
public void makeDir(String path, FileAttributes attrs)
throws IOException {
doRequest(
newRequest(PacketType.MKDIR).putString(path).putFileAttributes(attrs)
).ensureStatusPacketIsOK();
}
public void makeDir(String path) throws IOException {
public void makeDir(String path)
throws IOException {
makeDir(path, new FileAttributes());
}
public void symlink(String linkpath, String targetpath) throws IOException {
public void symlink(String linkpath, String targetpath)
throws IOException {
doRequest(
newRequest(PacketType.SYMLINK).putString(linkpath).putString(targetpath)
).ensureStatusPacketIsOK();
}
public void remove(String filename) throws IOException {
public void remove(String filename)
throws IOException {
doRequest(
newRequest(PacketType.REMOVE).putString(filename)
).ensureStatusPacketIsOK();
}
public void removeDir(String path) throws IOException {
public void removeDir(String path)
throws IOException {
doRequest(
newRequest(PacketType.RMDIR).putString(path)
).ensureStatusIs(Response.StatusCode.OK);
}
private FileAttributes stat(PacketType pt, String path) throws IOException {
private FileAttributes stat(PacketType pt, String path)
throws IOException {
return doRequest(newRequest(pt).putString(path))
.ensurePacketTypeIs(PacketType.ATTRS)
.readFileAttributes();
}
public FileAttributes stat(String path) throws IOException {
public FileAttributes stat(String path)
throws IOException {
return stat(PacketType.STAT, path);
}
public FileAttributes lstat(String path) throws IOException {
public FileAttributes lstat(String path)
throws IOException {
return stat(PacketType.LSTAT, path);
}
public void rename(String oldPath, String newPath) throws IOException {
public void rename(String oldPath, String newPath)
throws IOException {
doRequest(
newRequest(PacketType.RENAME).putString(oldPath).putString(newPath)
).ensureStatusPacketIsOK();
}
public String canonicalize(String path) throws IOException {
public String canonicalize(String path)
throws IOException {
return readSingleName(
doRequest(
newRequest(PacketType.REALPATH).putString(path)
));
}
private static String readSingleName(Response res) throws IOException {
private static String readSingleName(Response res)
throws IOException {
res.ensurePacketTypeIs(PacketType.NAME);
if (res.readInt() == 1)
return res.readString();

View File

@@ -20,7 +20,8 @@ import net.schmizz.sshj.common.DisconnectReason;
import net.schmizz.sshj.common.SSHException;
import net.schmizz.sshj.sftp.Response.StatusCode;
public class SFTPException extends SSHException {
public class SFTPException
extends SSHException {
public static final ExceptionChainer<SFTPException> chainer = new ExceptionChainer<SFTPException>() {

View File

@@ -30,7 +30,9 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.util.EnumSet;
public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransfer {
public class SFTPFileTransfer
extends AbstractFileTransfer
implements FileTransfer {
private final SFTPEngine sftp;
private final PathHelper pathHelper;
@@ -55,11 +57,13 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
this.pathHelper = new PathHelper(sftp);
}
public void upload(String source, String dest) throws IOException {
public void upload(String source, String dest)
throws IOException {
new Uploader(getModeGetter(), getUploadFilter()).upload(new File(source), dest);
}
public void download(String source, String dest) throws IOException {
public void download(String source, String dest)
throws IOException {
PathComponents src = pathHelper.getComponents(source);
new Downloader(getModeSetter(), getDownloadFilter()).download(new RemoteResourceInfo(src.getParent(), src
.getName(), sftp.stat(source)), new File(dest));
@@ -91,7 +95,8 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
this.filter = filter;
}
private void setAttributes(RemoteResourceInfo remote, File local) throws IOException {
private void setAttributes(RemoteResourceInfo remote, File local)
throws IOException {
final FileAttributes attrs = remote.getAttributes();
modeSetter.setPermissions(local, attrs.getMode().getPermissionsMask());
if (modeSetter.preservesTimes() && attrs.has(FileAttributes.Flag.ACMODTIME)) {
@@ -100,7 +105,8 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
}
}
private void downloadFile(RemoteResourceInfo remote, File local) throws IOException {
private void downloadFile(RemoteResourceInfo remote, File local)
throws IOException {
local = FileTransferUtil.getTargetFile(local, remote.getName());
setAttributes(remote, local);
RemoteFile rf = sftp.open(remote.getPath());
@@ -117,7 +123,8 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
}
}
private void downloadDir(RemoteResourceInfo remote, File local) throws IOException {
private void downloadDir(RemoteResourceInfo remote, File local)
throws IOException {
local = FileTransferUtil.getTargetDirectory(local, remote.getName());
setAttributes(remote, local);
final RemoteDirectory rd = sftp.openDir(remote.getPath());
@@ -126,7 +133,8 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
rd.close();
}
void download(RemoteResourceInfo remote, File local) throws IOException {
void download(RemoteResourceInfo remote, File local)
throws IOException {
log.info("Downloading [{}] to [{}]", remote, local);
if (remote.isDirectory())
downloadDir(remote, local);
@@ -147,7 +155,8 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
this.filter = filter;
}
public FileAttributes getAttributes(File local) throws IOException {
public FileAttributes getAttributes(File local)
throws IOException {
FileAttributes.Builder builder = new FileAttributes.Builder().withPermissions(modeGetter
.getPermissions(local));
if (modeGetter.preservesTimes())
@@ -156,17 +165,19 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
}
// tread carefully
private void setAttributes(FileAttributes current, File local, String remote) throws IOException {
private void setAttributes(FileAttributes current, File local, String remote)
throws IOException {
final FileAttributes attrs = getAttributes(local);
// TODO whoaaa.. simplify?
if (!(current != null
&& current.getMode().getPermissionsMask() == attrs.getMode().getPermissionsMask()
&& (!modeGetter.preservesTimes() || (attrs.getAtime() == current.getAtime() && attrs.getMtime() == current
.getMtime()))))
&& current.getMode().getPermissionsMask() == attrs.getMode().getPermissionsMask()
&& (!modeGetter.preservesTimes()
|| (attrs.getAtime() == current.getAtime() && attrs.getMtime() == current.getMtime()))))
sftp.setAttributes(remote, attrs);
}
private String prepareDir(File local, String remote) throws IOException {
private String prepareDir(File local, String remote)
throws IOException {
FileAttributes attrs;
try {
attrs = sftp.stat(remote);
@@ -192,7 +203,8 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
throw new IOException(attrs.getMode().getType() + " file already exists at " + remote);
}
private String prepareFile(File local, String remote) throws IOException {
private String prepareFile(File local, String remote)
throws IOException {
FileAttributes attrs;
try {
attrs = sftp.stat(remote);
@@ -213,22 +225,24 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
}
}
private void uploadDir(File local, String remote) throws IOException {
private void uploadDir(File local, String remote)
throws IOException {
final String adjusted = prepareDir(local, remote);
for (File f : local.listFiles(filter))
upload(f, adjusted);
}
private void uploadFile(File local, String remote) throws IOException {
private void uploadFile(File local, String remote)
throws IOException {
final String adjusted = prepareFile(local, remote);
final RemoteFile rf = sftp.open(adjusted, EnumSet.of(OpenMode.WRITE, OpenMode.CREAT, OpenMode.TRUNC),
getAttributes(local));
getAttributes(local));
try {
final FileInputStream fis = new FileInputStream(local);
try {
StreamCopier.copy(fis, //
rf.getOutputStream(), sftp.getSubsystem().getRemoteMaxPacketSize()
- rf.getOutgoingPacketOverhead(), false);
rf.getOutputStream(), sftp.getSubsystem().getRemoteMaxPacketSize()
- rf.getOutgoingPacketOverhead(), false);
} finally {
fis.close();
}
@@ -237,7 +251,8 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
}
}
void upload(File local, String remote) throws IOException {
void upload(File local, String remote)
throws IOException {
log.info("Uploading [{}] to [{}]", local, remote);
if (local.isDirectory())
uploadDir(local, remote);

View File

@@ -17,7 +17,8 @@ package net.schmizz.sshj.sftp;
import net.schmizz.sshj.common.Buffer;
public class SFTPPacket<T extends SFTPPacket<T>> extends Buffer<T> {
public class SFTPPacket<T extends SFTPPacket<T>>
extends Buffer<T> {
public SFTPPacket() {
super();

View File

@@ -21,11 +21,13 @@ import java.io.IOException;
import java.util.List;
import java.util.Set;
public class StatefulSFTPClient extends SFTPClient {
public class StatefulSFTPClient
extends SFTPClient {
private String cwd;
public StatefulSFTPClient(SessionFactory ssh) throws IOException {
public StatefulSFTPClient(SessionFactory ssh)
throws IOException {
super(ssh);
this.cwd = getSFTPEngine().canonicalize(".");
log.info("Start dir = " + cwd);
@@ -40,25 +42,30 @@ public class StatefulSFTPClient extends SFTPClient {
log.info("CWD = " + cwd);
}
public synchronized List<RemoteResourceInfo> ls() throws IOException {
public synchronized List<RemoteResourceInfo> ls()
throws IOException {
return ls(cwd, null);
}
public synchronized List<RemoteResourceInfo> ls(RemoteResourceFilter filter) throws IOException {
public synchronized List<RemoteResourceInfo> ls(RemoteResourceFilter filter)
throws IOException {
return ls(cwd, filter);
}
public synchronized String pwd() throws IOException {
public synchronized String pwd()
throws IOException {
return super.canonicalize(cwd);
}
@Override
public List<RemoteResourceInfo> ls(String path) throws IOException {
public List<RemoteResourceInfo> ls(String path)
throws IOException {
return ls(path, null);
}
@Override
public List<RemoteResourceInfo> ls(String path, RemoteResourceFilter filter) throws IOException {
public List<RemoteResourceInfo> ls(String path, RemoteResourceFilter filter)
throws IOException {
final RemoteDirectory dir = getSFTPEngine().openDir(cwdify(path));
try {
return dir.scan(filter);
@@ -68,82 +75,98 @@ public class StatefulSFTPClient extends SFTPClient {
}
@Override
public RemoteFile open(String filename, Set<OpenMode> mode, FileAttributes attrs) throws IOException {
public RemoteFile open(String filename, Set<OpenMode> mode, FileAttributes attrs)
throws IOException {
return super.open(cwdify(filename), mode, attrs);
}
@Override
public RemoteFile open(String filename, Set<OpenMode> mode) throws IOException {
public RemoteFile open(String filename, Set<OpenMode> mode)
throws IOException {
return super.open(cwdify(filename), mode);
}
@Override
public RemoteFile open(String filename) throws IOException {
public RemoteFile open(String filename)
throws IOException {
return super.open(cwdify(filename));
}
@Override
public void mkdir(String dirname) throws IOException {
public void mkdir(String dirname)
throws IOException {
super.mkdir(cwdify(dirname));
}
@Override
public void rename(String oldpath, String newpath) throws IOException {
public void rename(String oldpath, String newpath)
throws IOException {
super.rename(cwdify(oldpath), cwdify(newpath));
}
@Override
public void rm(String filename) throws IOException {
public void rm(String filename)
throws IOException {
super.rm(cwdify(filename));
}
@Override
public void rmdir(String dirname) throws IOException {
public void rmdir(String dirname)
throws IOException {
super.rmdir(cwdify(dirname));
}
@Override
public void symlink(String linkpath, String targetpath) throws IOException {
public void symlink(String linkpath, String targetpath)
throws IOException {
super.symlink(cwdify(linkpath), cwdify(targetpath));
}
@Override
public void setattr(String path, FileAttributes attrs) throws IOException {
public void setattr(String path, FileAttributes attrs)
throws IOException {
super.setattr(cwdify(path), attrs);
}
@Override
public String readlink(String path) throws IOException {
public String readlink(String path)
throws IOException {
return super.readlink(cwdify(path));
}
@Override
public FileAttributes stat(String path) throws IOException {
public FileAttributes stat(String path)
throws IOException {
return super.stat(cwdify(path));
}
@Override
public FileAttributes lstat(String path) throws IOException {
public FileAttributes lstat(String path)
throws IOException {
return super.lstat(cwdify(path));
}
@Override
public void truncate(String path, long size) throws IOException {
public void truncate(String path, long size)
throws IOException {
super.truncate(cwdify(path), size);
}
@Override
public String canonicalize(String path) throws IOException {
public String canonicalize(String path)
throws IOException {
return super.canonicalize(cwdify(path));
}
@Override
public void get(String source, String dest) throws IOException {
public void get(String source, String dest)
throws IOException {
super.get(cwdify(source), dest);
}
@Override
public void put(String source, String dest) throws IOException {
public void put(String source, String dest)
throws IOException {
super.get(source, cwdify(dest));
}