From bb9193b33309396b7c53745c20dd2bbb325b8ecd Mon Sep 17 00:00:00 2001 From: Shikhar Bhushan Date: Fri, 12 Mar 2010 17:45:37 +0100 Subject: [PATCH] * sftp / include file type information when uploading * misc. sftp cleanups --- .../net/schmizz/sshj/sftp/FileAttributes.java | 12 +- .../java/net/schmizz/sshj/sftp/FileMode.java | 4 +- .../schmizz/sshj/sftp/SFTPFileTransfer.java | 205 ++++++++---------- 3 files changed, 102 insertions(+), 119 deletions(-) diff --git a/src/main/java/net/schmizz/sshj/sftp/FileAttributes.java b/src/main/java/net/schmizz/sshj/sftp/FileAttributes.java index 48b31c79..8b0c9f1b 100644 --- a/src/main/java/net/schmizz/sshj/sftp/FileAttributes.java +++ b/src/main/java/net/schmizz/sshj/sftp/FileAttributes.java @@ -178,13 +178,19 @@ public final class FileAttributes { public Builder withPermissions(Set perms) { mask |= Flag.MODE.get(); - this.mode = new FileMode(FilePermission.toMask(perms)); + this.mode = new FileMode((mode != null ? mode.getTypeMask() : 0) | FilePermission.toMask(perms)); return this; } public Builder withPermissions(int perms) { mask |= Flag.MODE.get(); - this.mode = new FileMode(perms); + this.mode = new FileMode((mode != null ? mode.getTypeMask() : 0) | perms); + return this; + } + + public Builder withType(FileMode.Type type) { + mask |= Flag.MODE.get(); + this.mode = new FileMode(type.toMask() | (mode != null ? mode.getPermissionsMask() : 0)); return this; } @@ -208,7 +214,7 @@ public final class FileAttributes { @Override public String toString() { - StringBuilder sb = new StringBuilder("["); + final StringBuilder sb = new StringBuilder("["); if (has(Flag.SIZE)) sb.append("size=").append(size).append(";"); diff --git a/src/main/java/net/schmizz/sshj/sftp/FileMode.java b/src/main/java/net/schmizz/sshj/sftp/FileMode.java index eee1db9e..e14da98b 100644 --- a/src/main/java/net/schmizz/sshj/sftp/FileMode.java +++ b/src/main/java/net/schmizz/sshj/sftp/FileMode.java @@ -53,8 +53,8 @@ public class FileMode { return UNKNOWN; } - public static int toMask(Type t) { - return t.val; + public int toMask() { + return val; } } diff --git a/src/main/java/net/schmizz/sshj/sftp/SFTPFileTransfer.java b/src/main/java/net/schmizz/sshj/sftp/SFTPFileTransfer.java index a277baac..861c76e2 100644 --- a/src/main/java/net/schmizz/sshj/sftp/SFTPFileTransfer.java +++ b/src/main/java/net/schmizz/sshj/sftp/SFTPFileTransfer.java @@ -20,8 +20,6 @@ import net.schmizz.sshj.sftp.Response.StatusCode; import net.schmizz.sshj.xfer.AbstractFileTransfer; import net.schmizz.sshj.xfer.FileTransfer; import net.schmizz.sshj.xfer.FileTransferUtil; -import net.schmizz.sshj.xfer.ModeGetter; -import net.schmizz.sshj.xfer.ModeSetter; import java.io.File; import java.io.FileFilter; @@ -59,15 +57,14 @@ public class SFTPFileTransfer public void upload(String source, String dest) throws IOException { - new Uploader(getModeGetter(), getUploadFilter()).upload(new File(source), dest); + new Uploader().upload(new File(source), dest); } public void download(String source, String dest) throws IOException { final PathComponents pathComponents = pathHelper.getComponents(source); final FileAttributes attributes = sftp.stat(source); - new Downloader(getModeSetter(), getDownloadFilter()) - .download(new RemoteResourceInfo(pathComponents, attributes), new File(dest)); + new Downloader().download(new RemoteResourceInfo(pathComponents, attributes), new File(dest)); } public void setUploadFilter(FileFilter uploadFilter) { @@ -88,31 +85,23 @@ public class SFTPFileTransfer private class Downloader { - private final ModeSetter modeSetter; - private final RemoteResourceFilter filter; - - Downloader(ModeSetter modeSetter, RemoteResourceFilter filter) { - this.modeSetter = modeSetter; - this.filter = filter; - } - - private void setAttributes(RemoteResourceInfo remote, File local) + private void setAttributes(final RemoteResourceInfo remote, final File local) throws IOException { final FileAttributes attrs = remote.getAttributes(); - modeSetter.setPermissions(local, attrs.getMode().getPermissionsMask()); - if (modeSetter.preservesTimes() && attrs.has(FileAttributes.Flag.ACMODTIME)) { - modeSetter.setLastAccessedTime(local, attrs.getAtime()); - modeSetter.setLastModifiedTime(local, attrs.getMtime()); + getModeSetter().setPermissions(local, attrs.getMode().getPermissionsMask()); + if (getModeSetter().preservesTimes() && attrs.has(FileAttributes.Flag.ACMODTIME)) { + getModeSetter().setLastAccessedTime(local, attrs.getAtime()); + getModeSetter().setLastModifiedTime(local, attrs.getMtime()); } } - private void downloadFile(RemoteResourceInfo remote, File local) + private void downloadFile(final RemoteResourceInfo remote, final File local) throws IOException { - local = FileTransferUtil.getTargetFile(local, remote.getName()); - setAttributes(remote, local); - RemoteFile rf = sftp.open(remote.getPath()); + final File adjusted = FileTransferUtil.getTargetFile(local, remote.getName()); + setAttributes(remote, adjusted); + final RemoteFile rf = sftp.open(remote.getPath()); try { - final FileOutputStream fos = new FileOutputStream(local); + final FileOutputStream fos = new FileOutputStream(adjusted); try { StreamCopier.copy(rf.getInputStream(), fos, sftp.getSubsystem() .getLocalMaxPacketSize(), false); @@ -124,119 +113,54 @@ public class SFTPFileTransfer } } - private void downloadDir(RemoteResourceInfo remote, File local) + private void downloadDir(final RemoteResourceInfo remote, final File local) throws IOException { - local = FileTransferUtil.getTargetDirectory(local, remote.getName()); - setAttributes(remote, local); + final File adjusted = FileTransferUtil.getTargetDirectory(local, remote.getName()); + setAttributes(remote, adjusted); final RemoteDirectory rd = sftp.openDir(remote.getPath()); - for (RemoteResourceInfo rri : rd.scan(filter)) - download(rri, new File(local.getPath(), rri.getName())); - rd.close(); + try { + for (RemoteResourceInfo rri : rd.scan(getDownloadFilter())) + download(rri, new File(adjusted.getPath(), rri.getName())); + } finally { + rd.close(); + } } - void download(RemoteResourceInfo remote, File local) + void download(final RemoteResourceInfo remote, final File local) throws IOException { log.info("Downloading [{}] to [{}]", remote, local); switch (remote.getAttributes().getType()) { case DIRECTORY: downloadDir(remote, local); break; - case UNKNOWN: // ... BS servers like wodFTPD + case UNKNOWN: log.warn("Server did not supply information about the type of file at `{}` -- assuming it is a regular file!"); case REGULAR: downloadFile(remote, local); break; default: throw new IOException(remote + " is not a regular file or directory"); - } } } private class Uploader { - private final ModeGetter modeGetter; - private final FileFilter filter; - - Uploader(ModeGetter modeGetter, FileFilter filter) { - this.modeGetter = modeGetter; - this.filter = filter; - } - - public FileAttributes getAttributes(File local) + void upload(File local, String remote) throws IOException { - FileAttributes.Builder builder = new FileAttributes.Builder().withPermissions(modeGetter - .getPermissions(local)); - if (modeGetter.preservesTimes()) - builder.withAtimeMtime(modeGetter.getLastAccessTime(local), modeGetter.getLastModifiedTime(local)); - return builder.build(); - } - - // tread carefully - 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())))) - sftp.setAttributes(remote, attrs); - } - - private String prepareDir(File local, String remote) - throws IOException { - FileAttributes attrs; - try { - attrs = sftp.stat(remote); - } catch (SFTPException e) { - if (e.getStatusCode() == StatusCode.NO_SUCH_FILE) { - log.debug("probeDir: {} does not exist, creating", remote); - sftp.makeDir(remote, getAttributes(local)); - return remote; - } else - throw e; - } - - if (attrs.getMode().getType() == FileMode.Type.DIRECTORY) - if (pathHelper.getComponents(remote).getName().equals(local.getName())) { - log.debug("probeDir: {} already exists", remote); - setAttributes(attrs, local, remote); - return remote; - } else { - log.debug("probeDir: {} already exists, path adjusted for {}", remote, local.getName()); - return prepareDir(local, PathComponents.adjustForParent(remote, local.getName())); - } + log.info("Uploading [{}] to [{}]", local, remote); + if (local.isDirectory()) + uploadDir(local, remote); + else if (local.isFile()) + uploadFile(local, remote); else - throw new IOException(attrs.getMode().getType() + " file already exists at " + remote); - } - - private String prepareFile(File local, String remote) - throws IOException { - FileAttributes attrs; - try { - attrs = sftp.stat(remote); - } catch (SFTPException e) { - if (e.getStatusCode() == StatusCode.NO_SUCH_FILE) { - log.debug("probeFile: {} does not exist", remote); - return remote; - } else - throw e; - } - if (attrs.getMode().getType() == FileMode.Type.DIRECTORY) { - log.debug("probeFile: {} was directory, path adjusted for {}", remote, local.getName()); - remote = PathComponents.adjustForParent(remote, local.getName()); - return remote; - } else { - log.debug("probeFile: {} is a {} file that will be replaced", remote, attrs.getMode().getType()); - return remote; - } + throw new IOException(local + " is not a file or directory"); } private void uploadDir(File local, String remote) throws IOException { final String adjusted = prepareDir(local, remote); - for (File f : local.listFiles(filter)) + for (File f : local.listFiles(getUploadFilter())) upload(f, adjusted); } @@ -258,16 +182,69 @@ public class SFTPFileTransfer } } - void upload(File local, String remote) + private String prepareDir(File local, String remote) throws IOException { - log.info("Uploading [{}] to [{}]", local, remote); - if (local.isDirectory()) - uploadDir(local, remote); - else if (local.isFile()) - uploadFile(local, remote); + final FileAttributes attrs; + try { + attrs = sftp.stat(remote); + } catch (SFTPException e) { + if (e.getStatusCode() == StatusCode.NO_SUCH_FILE) { + log.debug("probeDir: {} does not exist, creating", remote); + sftp.makeDir(remote, getAttributes(local)); + return remote; + } else + throw e; + } + + if (attrs.getMode().getType() == FileMode.Type.DIRECTORY) + if (pathHelper.getComponents(remote).getName().equals(local.getName())) { + log.debug("probeDir: {} already exists", remote); + final FileAttributes localAttrs = getAttributes(local); + if (attrs.getMode().getMask() != localAttrs.getMode().getMask() + || (getModeGetter().preservesTimes() + && (attrs.getAtime() != attrs.getAtime() || attrs.getMtime() != localAttrs.getMtime()))) + sftp.setAttributes(remote, localAttrs); + return remote; + } else { + log.debug("probeDir: {} already exists, path adjusted for {}", remote, local.getName()); + return prepareDir(local, PathComponents.adjustForParent(remote, local.getName())); + } else - throw new IOException(local + " is not a file or directory"); + throw new IOException(attrs.getMode().getType() + " file already exists at " + remote); } + + private String prepareFile(File local, String remote) + throws IOException { + final FileAttributes attrs; + try { + attrs = sftp.stat(remote); + } catch (SFTPException e) { + if (e.getStatusCode() == StatusCode.NO_SUCH_FILE) { + log.debug("probeFile: {} does not exist", remote); + return remote; + } else + throw e; + } + if (attrs.getMode().getType() == FileMode.Type.DIRECTORY) { + log.debug("probeFile: {} was directory, path adjusted for {}", remote, local.getName()); + remote = PathComponents.adjustForParent(remote, local.getName()); + return remote; + } else { + log.debug("probeFile: {} is a {} file that will be replaced", remote, attrs.getMode().getType()); + return remote; + } + } + + private FileAttributes getAttributes(File local) + throws IOException { + final FileAttributes.Builder builder = new FileAttributes.Builder() + .withType(local.isDirectory() ? FileMode.Type.DIRECTORY : FileMode.Type.REGULAR) + .withPermissions(getModeGetter().getPermissions(local)); + if (getModeGetter().preservesTimes()) + builder.withAtimeMtime(getModeGetter().getLastAccessTime(local), getModeGetter().getLastModifiedTime(local)); + return builder.build(); + } + } }