From ce930c969b9af00388012835c597a84870cfc966 Mon Sep 17 00:00:00 2001 From: Shikhar Bhushan Date: Wed, 6 Apr 2011 23:37:55 +0100 Subject: [PATCH] Lighter, more coherent interfaces by refactoring LocalFile into LocalSourceFile & LocalDestFile --- .../net/schmizz/sshj/sftp/SFTPClient.java | 7 +- .../schmizz/sshj/sftp/SFTPFileTransfer.java | 41 +++---- .../net/schmizz/sshj/xfer/FileSystemFile.java | 20 ++-- .../net/schmizz/sshj/xfer/FileTransfer.java | 4 +- .../schmizz/sshj/xfer/InMemoryDestFile.java | 102 +++--------------- .../schmizz/sshj/xfer/InMemorySourceFile.java | 92 ++-------------- .../{LocalFile.java => LocalDestFile.java} | 73 ++++--------- .../schmizz/sshj/xfer/LocalFileFilter.java | 2 +- .../schmizz/sshj/xfer/LocalSourceFile.java | 68 ++++++++++++ .../sshj/xfer/scp/SCPDownloadClient.java | 27 +++-- .../net/schmizz/sshj/xfer/scp/SCPEngine.java | 23 ++-- .../sshj/xfer/scp/SCPFileTransfer.java | 7 +- .../sshj/xfer/scp/SCPUploadClient.java | 30 +++--- 13 files changed, 180 insertions(+), 316 deletions(-) rename src/main/java/net/schmizz/sshj/xfer/{LocalFile.java => LocalDestFile.java} (51%) create mode 100644 src/main/java/net/schmizz/sshj/xfer/LocalSourceFile.java diff --git a/src/main/java/net/schmizz/sshj/sftp/SFTPClient.java b/src/main/java/net/schmizz/sshj/sftp/SFTPClient.java index d3f9e5a6..b7f68775 100644 --- a/src/main/java/net/schmizz/sshj/sftp/SFTPClient.java +++ b/src/main/java/net/schmizz/sshj/sftp/SFTPClient.java @@ -16,7 +16,8 @@ package net.schmizz.sshj.sftp; import net.schmizz.sshj.xfer.FilePermission; -import net.schmizz.sshj.xfer.LocalFile; +import net.schmizz.sshj.xfer.LocalDestFile; +import net.schmizz.sshj.xfer.LocalSourceFile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -239,12 +240,12 @@ public class SFTPClient xfer.upload(source, dest); } - public void get(String source, LocalFile dest) + public void get(String source, LocalDestFile dest) throws IOException { xfer.download(source, dest); } - public void put(LocalFile source, String dest) + public void put(LocalSourceFile source, String dest) throws IOException { xfer.upload(source, dest); } diff --git a/src/main/java/net/schmizz/sshj/sftp/SFTPFileTransfer.java b/src/main/java/net/schmizz/sshj/sftp/SFTPFileTransfer.java index bc17b2d3..0960e1a7 100644 --- a/src/main/java/net/schmizz/sshj/sftp/SFTPFileTransfer.java +++ b/src/main/java/net/schmizz/sshj/sftp/SFTPFileTransfer.java @@ -20,8 +20,9 @@ import net.schmizz.sshj.sftp.Response.StatusCode; import net.schmizz.sshj.xfer.AbstractFileTransfer; import net.schmizz.sshj.xfer.FileSystemFile; import net.schmizz.sshj.xfer.FileTransfer; -import net.schmizz.sshj.xfer.LocalFile; +import net.schmizz.sshj.xfer.LocalDestFile; import net.schmizz.sshj.xfer.LocalFileFilter; +import net.schmizz.sshj.xfer.LocalSourceFile; import net.schmizz.sshj.xfer.TransferListener; import java.io.IOException; @@ -57,13 +58,13 @@ public class SFTPFileTransfer } @Override - public void upload(LocalFile localFile, String remotePath) + public void upload(LocalSourceFile localFile, String remotePath) throws IOException { new Uploader().upload(localFile, remotePath); } @Override - public void download(String source, LocalFile dest) + public void download(String source, LocalDestFile dest) throws IOException { final PathComponents pathComponents = pathHelper.getComponents(source); final FileAttributes attributes = engine.stat(source); @@ -90,9 +91,9 @@ public class SFTPFileTransfer private final TransferListener listener = getTransferListener(); - private void download(final RemoteResourceInfo remote, final LocalFile local) + private void download(final RemoteResourceInfo remote, final LocalDestFile local) throws IOException { - final LocalFile adjustedFile; + final LocalDestFile adjustedFile; switch (remote.getAttributes().getType()) { case DIRECTORY: listener.startedDir(remote.getName()); @@ -114,9 +115,9 @@ public class SFTPFileTransfer } - private LocalFile downloadDir(final RemoteResourceInfo remote, final LocalFile local) + private LocalDestFile downloadDir(final RemoteResourceInfo remote, final LocalDestFile local) throws IOException { - final LocalFile adjusted = local.getTargetDirectory(remote.getName()); + final LocalDestFile adjusted = local.getTargetDirectory(remote.getName()); final RemoteDirectory rd = engine.openDir(remote.getPath()); try { for (RemoteResourceInfo rri : rd.scan(getDownloadFilter())) @@ -127,9 +128,9 @@ public class SFTPFileTransfer return adjusted; } - private LocalFile downloadFile(final RemoteResourceInfo remote, final LocalFile local) + private LocalDestFile downloadFile(final RemoteResourceInfo remote, final LocalDestFile local) throws IOException { - final LocalFile adjusted = local.getTargetFile(remote.getName()); + final LocalDestFile adjusted = local.getTargetFile(remote.getName()); final RemoteFile rf = engine.open(remote.getPath()); try { final OutputStream os = adjusted.getOutputStream(); @@ -145,11 +146,11 @@ public class SFTPFileTransfer return adjusted; } - private void copyAttributes(final RemoteResourceInfo remote, final LocalFile local) + private void copyAttributes(final RemoteResourceInfo remote, final LocalDestFile local) throws IOException { final FileAttributes attrs = remote.getAttributes(); local.setPermissions(attrs.getMode().getPermissionsMask()); - if (local.preservesTimes() && attrs.has(FileAttributes.Flag.ACMODTIME)) { + if (attrs.has(FileAttributes.Flag.ACMODTIME)) { local.setLastAccessedTime(attrs.getAtime()); local.setLastModifiedTime(attrs.getMtime()); } @@ -161,7 +162,7 @@ public class SFTPFileTransfer private final TransferListener listener = getTransferListener(); - private void upload(LocalFile local, String remote) + private void upload(LocalSourceFile local, String remote) throws IOException { final String adjustedPath; if (local.isDirectory()) { @@ -169,7 +170,7 @@ public class SFTPFileTransfer adjustedPath = uploadDir(local, remote); listener.finishedDir(); } else if (local.isFile()) { - listener.startedFile(local.getName(), local.length()); + listener.startedFile(local.getName(), local.getLength()); adjustedPath = uploadFile(local, remote); listener.finishedFile(); } else @@ -177,15 +178,15 @@ public class SFTPFileTransfer engine.setAttributes(adjustedPath, getAttributes(local)); } - private String uploadDir(LocalFile local, String remote) + private String uploadDir(LocalSourceFile local, String remote) throws IOException { final String adjusted = prepareDir(local, remote); - for (LocalFile f : local.getChildren(getUploadFilter())) + for (LocalSourceFile f : local.getChildren(getUploadFilter())) upload(f, adjusted); return adjusted; } - private String uploadFile(LocalFile local, String remote) + private String uploadFile(LocalSourceFile local, String remote) throws IOException { final String adjusted = prepareFile(local, remote); final RemoteFile rf = engine.open(adjusted, EnumSet.of(OpenMode.WRITE, @@ -205,7 +206,7 @@ public class SFTPFileTransfer return adjusted; } - private String prepareDir(LocalFile local, String remote) + private String prepareDir(LocalSourceFile local, String remote) throws IOException { final FileAttributes attrs; try { @@ -231,7 +232,7 @@ public class SFTPFileTransfer throw new IOException(attrs.getMode().getType() + " file already exists at " + remote); } - private String prepareFile(LocalFile local, String remote) + private String prepareFile(LocalSourceFile local, String remote) throws IOException { final FileAttributes attrs; try { @@ -253,10 +254,10 @@ public class SFTPFileTransfer } } - private FileAttributes getAttributes(LocalFile local) + private FileAttributes getAttributes(LocalSourceFile local) throws IOException { final FileAttributes.Builder builder = new FileAttributes.Builder().withPermissions(local.getPermissions()); - if (local.preservesTimes()) + if (local.providesAtimeMtime()) builder.withAtimeMtime(local.getLastAccessTime(), local.getLastModifiedTime()); return builder.build(); } diff --git a/src/main/java/net/schmizz/sshj/xfer/FileSystemFile.java b/src/main/java/net/schmizz/sshj/xfer/FileSystemFile.java index 32f0442d..cd3ee1bb 100644 --- a/src/main/java/net/schmizz/sshj/xfer/FileSystemFile.java +++ b/src/main/java/net/schmizz/sshj/xfer/FileSystemFile.java @@ -31,7 +31,7 @@ import java.util.List; import java.util.Map; public class FileSystemFile - implements LocalFile { + implements LocalSourceFile, LocalDestFile { protected final Logger log = LoggerFactory.getLogger(getClass()); @@ -65,7 +65,7 @@ public class FileSystemFile } @Override - public long length() { + public long getLength() { return file.length(); } @@ -81,12 +81,6 @@ public class FileSystemFile return new FileOutputStream(file); } - @Override - public Iterable getChildren() - throws IOException { - return getChildren(null); - } - @Override public Iterable getChildren(final LocalFileFilter filter) throws IOException { @@ -111,6 +105,11 @@ public class FileSystemFile return children; } + @Override + public boolean providesAtimeMtime() { + return true; + } + @Override public long getLastAccessTime() throws IOException { @@ -160,11 +159,6 @@ public class FileSystemFile log.warn("Could not set permissions for {} to {}", file, Integer.toString(perms, 16)); } - @Override - public boolean preservesTimes() { - return true; - } - @Override public FileSystemFile getChild(String name) { return new FileSystemFile(new File(file, name)); diff --git a/src/main/java/net/schmizz/sshj/xfer/FileTransfer.java b/src/main/java/net/schmizz/sshj/xfer/FileTransfer.java index 6f1f5b3b..61d4e2cb 100644 --- a/src/main/java/net/schmizz/sshj/xfer/FileTransfer.java +++ b/src/main/java/net/schmizz/sshj/xfer/FileTransfer.java @@ -25,10 +25,10 @@ public interface FileTransfer { void download(String remotePath, String localPath) throws IOException; - void upload(LocalFile localFile, String remotePath) + void upload(LocalSourceFile localFile, String remotePath) throws IOException; - void download(String remotePath, LocalFile localFile) + void download(String remotePath, LocalDestFile localFile) throws IOException; TransferListener getTransferListener(); diff --git a/src/main/java/net/schmizz/sshj/xfer/InMemoryDestFile.java b/src/main/java/net/schmizz/sshj/xfer/InMemoryDestFile.java index 10fe9795..1d9d80f9 100644 --- a/src/main/java/net/schmizz/sshj/xfer/InMemoryDestFile.java +++ b/src/main/java/net/schmizz/sshj/xfer/InMemoryDestFile.java @@ -19,123 +19,45 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -public class InMemoryDestFile - implements LocalFile { +public abstract class InMemoryDestFile + implements LocalDestFile { protected final Logger log = LoggerFactory.getLogger(getClass()); - protected final String filename; - protected final OutputStream outStream; - - public InMemoryDestFile(String filename, OutputStream outStream) { - this.filename = filename; - this.outStream = outStream; - } - @Override - public String getName() { - return filename; - } - - @Override - public LocalFile getTargetFile(String filename) + public InMemoryDestFile getTargetFile(String filename) throws IOException { - if (filename.equals(this.filename)) - return this; - else - throw new IOException("Filename mismatch"); - } - - @Override - public boolean isFile() { - return true; - } - - @Override - public boolean isDirectory() { - return false; - } - - @Override - public OutputStream getOutputStream() - throws IOException { - return outStream; - } - - // Everything else is unimplemented - - @Override - public long length() { - return 0; - } - - @Override - public InputStream getInputStream() - throws IOException { - return null; - } - - @Override - public Iterable getChildren() - throws IOException { - return null; - } - - @Override - public Iterable getChildren(LocalFileFilter filter) - throws IOException { - return null; - } - - @Override - public long getLastAccessTime() - throws IOException { - return 0; - } - - @Override - public long getLastModifiedTime() - throws IOException { - return 0; - } - - @Override - public int getPermissions() - throws IOException { - return 0; + return this; } @Override public void setLastAccessedTime(long t) throws IOException { + log.info("atime = {}", t); } @Override public void setLastModifiedTime(long t) throws IOException { + log.info("mtime = {}", t); } @Override public void setPermissions(int perms) throws IOException { + log.info("permissions = {}", Integer.toOctalString(perms)); } @Override - public boolean preservesTimes() { - return false; + public LocalDestFile getTargetDirectory(String dirname) + throws IOException { + throw new AssertionError("Unimplemented"); } @Override - public LocalFile getChild(String name) { - return null; - } - - @Override - public LocalFile getTargetDirectory(String dirname) { - return null; + public LocalDestFile getChild(String name) { + throw new AssertionError("Unimplemented"); } } diff --git a/src/main/java/net/schmizz/sshj/xfer/InMemorySourceFile.java b/src/main/java/net/schmizz/sshj/xfer/InMemorySourceFile.java index 1d9b1152..5047fb42 100644 --- a/src/main/java/net/schmizz/sshj/xfer/InMemorySourceFile.java +++ b/src/main/java/net/schmizz/sshj/xfer/InMemorySourceFile.java @@ -19,38 +19,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -public class InMemorySourceFile - implements LocalFile { +public abstract class InMemorySourceFile + implements LocalSourceFile { protected final Logger log = LoggerFactory.getLogger(getClass()); - protected final String filename; - protected final long length; - protected final InputStream inStream; - - public InMemorySourceFile(String filename, long length, InputStream inStream) { - this.filename = filename; - this.length = length; - this.inStream = inStream; - } - - @Override - public String getName() { - return filename; - } - - @Override - public LocalFile getTargetFile(String filename) - throws IOException { - if (filename.equals(this.filename)) - return this; - else - throw new IOException("Filename mismatch"); - } - @Override public boolean isFile() { return true; @@ -61,83 +35,33 @@ public class InMemorySourceFile return false; } - @Override - public long length() { - return length; - } - - @Override - public InputStream getInputStream() - throws IOException { - return inStream; - } - @Override public int getPermissions() throws IOException { return 0644; } - // Everything else is unimplemented - @Override - public OutputStream getOutputStream() - throws IOException { - return null; - } - - @Override - public Iterable getChildren() - throws IOException { - return null; - } - - @Override - public Iterable getChildren(LocalFileFilter filter) - throws IOException { - return null; + public boolean providesAtimeMtime() { + return false; } @Override public long getLastAccessTime() throws IOException { - return 0; + throw new AssertionError("Unimplemented"); } @Override public long getLastModifiedTime() throws IOException { - return 0; + throw new AssertionError("Unimplemented"); } @Override - public void setLastAccessedTime(long t) + public Iterable getChildren(LocalFileFilter filter) throws IOException { - } - - @Override - public void setLastModifiedTime(long t) - throws IOException { - } - - @Override - public void setPermissions(int perms) - throws IOException { - } - - @Override - public boolean preservesTimes() { - return false; - } - - @Override - public LocalFile getChild(String name) { - return null; - } - - @Override - public LocalFile getTargetDirectory(String dirname) { - return null; + throw new AssertionError("Unimplemented"); } } diff --git a/src/main/java/net/schmizz/sshj/xfer/LocalFile.java b/src/main/java/net/schmizz/sshj/xfer/LocalDestFile.java similarity index 51% rename from src/main/java/net/schmizz/sshj/xfer/LocalFile.java rename to src/main/java/net/schmizz/sshj/xfer/LocalDestFile.java index cbc15868..7515afb9 100644 --- a/src/main/java/net/schmizz/sshj/xfer/LocalFile.java +++ b/src/main/java/net/schmizz/sshj/xfer/LocalDestFile.java @@ -16,57 +16,41 @@ package net.schmizz.sshj.xfer; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; -// TODO Document all methods properly +public interface LocalDestFile { -public interface LocalFile { + OutputStream getOutputStream() + throws IOException; - String getName(); - - boolean isFile(); - - boolean isDirectory(); - - long length(); - - InputStream getInputStream() throws IOException; - - OutputStream getOutputStream() throws IOException; - - Iterable getChildren() throws IOException; - - Iterable getChildren(LocalFileFilter filter) throws IOException; + /** @return A child file/directory of this directory with given {@code name}. */ + LocalDestFile getChild(String name); /** - * Returns last access time for the underlying file. - * - * @return time in seconds since Unix epoch - * - * @throws IOException + * Allows caller to express intent that caller expects to write to file with {@code filename}. Based on this + * information, an implementation may return an alternate file to write to, which should be respected by the + * caller. */ - long getLastAccessTime() + LocalDestFile getTargetFile(String filename) throws IOException; /** - * Returns last access time for the underlying file. - * - * @return time in seconds since Unix epoch - * - * @throws IOException + * Allows caller to express intent that caller expects to write to directory with {@code dirname}. Based on this + * information, an implementation may return an alternate directory to write to, which should be respected by the + * caller. */ - long getLastModifiedTime() + LocalDestFile getTargetDirectory(String dirname) throws IOException; /** - * Returns the permissions for the underlying file + * Set the permissions for the underlying file. * - * @return permissions in octal format, e.g. 0644 + * @param f the file + * @param perms permissions e.g. 0644 * * @throws IOException */ - int getPermissions() + void setPermissions(int perms) throws IOException; /** @@ -90,25 +74,4 @@ public interface LocalFile { void setLastModifiedTime(long t) throws IOException; - /** - * Set the permissions for the underlying file. - * - * @param f the file - * @param perms permissions in octal format, e.g. 0644 - * - * @throws IOException - */ - void setPermissions(int perms) - throws IOException; - - /** @return whether this implementation is interested in preserving mtime and atime. */ - boolean preservesTimes(); - - /** @return A child file of this directory having {@code name} as filename */ - LocalFile getChild(String name); - - LocalFile getTargetFile(String filename) throws IOException; - - LocalFile getTargetDirectory(String dirname) throws IOException; - -} \ No newline at end of file +} diff --git a/src/main/java/net/schmizz/sshj/xfer/LocalFileFilter.java b/src/main/java/net/schmizz/sshj/xfer/LocalFileFilter.java index 7cf75a87..138b9dd1 100644 --- a/src/main/java/net/schmizz/sshj/xfer/LocalFileFilter.java +++ b/src/main/java/net/schmizz/sshj/xfer/LocalFileFilter.java @@ -17,6 +17,6 @@ package net.schmizz.sshj.xfer; public interface LocalFileFilter { - boolean accept(LocalFile file); + boolean accept(LocalSourceFile file); } diff --git a/src/main/java/net/schmizz/sshj/xfer/LocalSourceFile.java b/src/main/java/net/schmizz/sshj/xfer/LocalSourceFile.java new file mode 100644 index 00000000..9078a4ae --- /dev/null +++ b/src/main/java/net/schmizz/sshj/xfer/LocalSourceFile.java @@ -0,0 +1,68 @@ +/* + * Copyright 2011 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.xfer; + +import java.io.IOException; +import java.io.InputStream; + +public interface LocalSourceFile { + + String getName(); + + long getLength(); + + InputStream getInputStream() + throws IOException; + + /** + * Returns the permissions for the underlying file + * + * @return permissions e.g. 0644 + * + * @throws IOException + */ + int getPermissions() throws IOException; + + boolean isFile(); + + boolean isDirectory(); + + Iterable getChildren(LocalFileFilter filter) + throws IOException; + + boolean providesAtimeMtime(); + + /** + * Returns last access time for the underlying file. + * + * @return time in seconds since Unix epoch + * + * @throws IOException + */ + long getLastAccessTime() + throws IOException; + + /** + * Returns last access time for the underlying file. + * + * @return time in seconds since Unix epoch + * + * @throws IOException + */ + long getLastModifiedTime() + throws IOException; + +} diff --git a/src/main/java/net/schmizz/sshj/xfer/scp/SCPDownloadClient.java b/src/main/java/net/schmizz/sshj/xfer/scp/SCPDownloadClient.java index 31d3974e..ebc18abc 100644 --- a/src/main/java/net/schmizz/sshj/xfer/scp/SCPDownloadClient.java +++ b/src/main/java/net/schmizz/sshj/xfer/scp/SCPDownloadClient.java @@ -21,7 +21,7 @@ import java.util.LinkedList; import java.util.List; import net.schmizz.sshj.common.IOUtils; -import net.schmizz.sshj.xfer.LocalFile; +import net.schmizz.sshj.xfer.LocalDestFile; import net.schmizz.sshj.xfer.scp.SCPEngine.Arg; /** Support for uploading files over a connected link using SCP. */ @@ -36,7 +36,7 @@ public final class SCPDownloadClient { } /** Download a file from {@code sourcePath} on the connected host to {@code targetPath} locally. */ - public synchronized int copy(String sourcePath, LocalFile targetFile) + public synchronized int copy(String sourcePath, LocalDestFile targetFile) throws IOException { engine.cleanSlate(); try { @@ -55,15 +55,14 @@ public final class SCPDownloadClient { this.recursive = recursive; } - void startCopy(String sourcePath, LocalFile targetFile) + void startCopy(String sourcePath, LocalDestFile targetFile) throws IOException { List args = new LinkedList(); args.add(Arg.SOURCE); args.add(Arg.QUIET); + args.add(Arg.PRESERVE_TIMES); if (recursive) args.add(Arg.RECURSIVE); - if (targetFile.preservesTimes()) - args.add(Arg.PRESERVE_TIMES); engine.execSCPWith(args, sourcePath); engine.signal("Start status OK"); @@ -92,7 +91,7 @@ public final class SCPDownloadClient { return Integer.parseInt(cmd.substring(1), 8); } - private boolean process(String bufferedTMsg, String msg, LocalFile f) + private boolean process(String bufferedTMsg, String msg, LocalDestFile f) throws IOException { if (msg.length() < 1) throw new SCPException("Could not parse message `" + msg + "`"); @@ -128,7 +127,7 @@ public final class SCPDownloadClient { return false; } - private void processDirectory(String dMsg, String tMsg, LocalFile f) + private void processDirectory(String dMsg, String tMsg, LocalDestFile f) throws IOException { final String[] dMsgParts = tokenize(dMsg, 3); // D 0 final long length = parseLong(dMsgParts[1], "dir length"); @@ -147,20 +146,20 @@ public final class SCPDownloadClient { engine.finishedDir(); } - private void processFile(String cMsg, String tMsg, LocalFile f) + private void processFile(String cMsg, String tMsg, LocalDestFile f) throws IOException { final String[] cMsgParts = tokenize(cMsg, 3); // C final long length = parseLong(cMsgParts[1], "length"); final String filename = cMsgParts[2]; - engine.startedFile(length, filename); + engine.startedFile(filename, length); { f = f.getTargetFile(filename); engine.signal("Remote can start transfer"); - final OutputStream os = f.getOutputStream(); + final OutputStream dest = f.getOutputStream(); try { - engine.transferFromRemote(length, os); + engine.transferFromRemote(dest, length); } finally { - IOUtils.closeQuietly(os); + IOUtils.closeQuietly(dest); } engine.check("Remote agrees transfer done"); setAttributes(f, parsePermissions(cMsgParts[0]), tMsg); @@ -169,10 +168,10 @@ public final class SCPDownloadClient { engine.finishedFile(); } - private void setAttributes(LocalFile f, int perms, String tMsg) + private void setAttributes(LocalDestFile f, int perms, String tMsg) throws IOException { f.setPermissions(perms); - if (tMsg != null && f.preservesTimes()) { + if (tMsg != null) { String[] tMsgParts = tokenize(tMsg, 4); // e.g. T 0 0 f.setLastModifiedTime(parseLong(tMsgParts[0].substring(1), "last modified time")); f.setLastAccessedTime(parseLong(tMsgParts[2], "last access time")); diff --git a/src/main/java/net/schmizz/sshj/xfer/scp/SCPEngine.java b/src/main/java/net/schmizz/sshj/xfer/scp/SCPEngine.java index 9091b75b..baba2795 100644 --- a/src/main/java/net/schmizz/sshj/xfer/scp/SCPEngine.java +++ b/src/main/java/net/schmizz/sshj/xfer/scp/SCPEngine.java @@ -24,7 +24,6 @@ import net.schmizz.sshj.common.IOUtils; import net.schmizz.sshj.common.SSHException; import net.schmizz.sshj.connection.channel.direct.Session.Command; import net.schmizz.sshj.connection.channel.direct.SessionFactory; -import net.schmizz.sshj.xfer.LocalFile; import net.schmizz.sshj.xfer.TransferListener; import org.slf4j.Logger; @@ -160,15 +159,15 @@ class SCPEngine { scp.getOutputStream().write(0); scp.getOutputStream().flush(); } - - void transferToRemote(LocalFile f, final InputStream src) + + void transferToRemote(final InputStream src, final long length) throws IOException { - transfer(src, scp.getOutputStream(), scp.getRemoteMaxPacketSize(), f.length()); + transfer(src, scp.getOutputStream(), scp.getRemoteMaxPacketSize(), length); } - - void transferFromRemote(final long length, final OutputStream os) + + void transferFromRemote(final OutputStream dest, final long length) throws IOException { - transfer(scp.getInputStream(), os, scp.getLocalMaxPacketSize(), length); + transfer(scp.getInputStream(), dest, scp.getLocalMaxPacketSize(), length); } private void transfer(InputStream in, OutputStream out, int bufSize, long len) @@ -198,22 +197,14 @@ class SCPEngine { listener.startedDir(dirname); } - void startedDir(LocalFile f) { - listener.startedDir(f.getName()); - } - void finishedDir() { listener.finishedDir(); } - void startedFile(final long length, final String filename) { + void startedFile(final String filename, final long length) { listener.startedFile(filename, length); } - void startedFile(LocalFile f) { - listener.startedFile(f.getName(), f.length()); - } - void finishedFile() { listener.finishedFile(); } diff --git a/src/main/java/net/schmizz/sshj/xfer/scp/SCPFileTransfer.java b/src/main/java/net/schmizz/sshj/xfer/scp/SCPFileTransfer.java index c3487f2e..17b1760e 100644 --- a/src/main/java/net/schmizz/sshj/xfer/scp/SCPFileTransfer.java +++ b/src/main/java/net/schmizz/sshj/xfer/scp/SCPFileTransfer.java @@ -21,7 +21,8 @@ import net.schmizz.sshj.connection.channel.direct.SessionFactory; import net.schmizz.sshj.xfer.AbstractFileTransfer; import net.schmizz.sshj.xfer.FileSystemFile; import net.schmizz.sshj.xfer.FileTransfer; -import net.schmizz.sshj.xfer.LocalFile; +import net.schmizz.sshj.xfer.LocalDestFile; +import net.schmizz.sshj.xfer.LocalSourceFile; public class SCPFileTransfer extends AbstractFileTransfer @@ -58,13 +59,13 @@ public class SCPFileTransfer } @Override - public void download(String remotePath, LocalFile localFile) + public void download(String remotePath, LocalDestFile localFile) throws IOException { newSCPDownloadClient().copy(remotePath, localFile); } @Override - public void upload(LocalFile localFile, String remotePath) + public void upload(LocalSourceFile localFile, String remotePath) throws IOException { newSCPUploadClient().copy(localFile, remotePath); } diff --git a/src/main/java/net/schmizz/sshj/xfer/scp/SCPUploadClient.java b/src/main/java/net/schmizz/sshj/xfer/scp/SCPUploadClient.java index 5b3b9fcf..a7cd87ed 100644 --- a/src/main/java/net/schmizz/sshj/xfer/scp/SCPUploadClient.java +++ b/src/main/java/net/schmizz/sshj/xfer/scp/SCPUploadClient.java @@ -16,7 +16,7 @@ package net.schmizz.sshj.xfer.scp; import net.schmizz.sshj.common.IOUtils; -import net.schmizz.sshj.xfer.LocalFile; +import net.schmizz.sshj.xfer.LocalSourceFile; import net.schmizz.sshj.xfer.scp.SCPEngine.Arg; import java.io.IOException; @@ -34,7 +34,7 @@ public final class SCPUploadClient { } /** Upload a local file from {@code localFile} to {@code targetPath} on the remote host. */ - public synchronized int copy(LocalFile sourceFile, String remotePath) + public synchronized int copy(LocalSourceFile sourceFile, String remotePath) throws IOException { engine.cleanSlate(); try { @@ -45,48 +45,48 @@ public final class SCPUploadClient { return engine.getExitStatus(); } - private synchronized void startCopy(LocalFile sourceFile, String targetPath) + private synchronized void startCopy(LocalSourceFile sourceFile, String targetPath) throws IOException { List args = new LinkedList(); args.add(Arg.SINK); args.add(Arg.RECURSIVE); - if (sourceFile.preservesTimes()) + if (sourceFile.providesAtimeMtime()) args.add(Arg.PRESERVE_TIMES); engine.execSCPWith(args, targetPath); engine.check("Start status OK"); process(sourceFile); } - private void process(LocalFile f) + private void process(LocalSourceFile f) throws IOException { if (f.isDirectory()) { - engine.startedDir(f); + engine.startedDir(f.getName()); sendDirectory(f); engine.finishedDir(); } else if (f.isFile()) { - engine.startedFile(f); + engine.startedFile(f.getName(), f.getLength()); sendFile(f); engine.finishedFile(); } else throw new IOException(f + " is not a regular file or directory"); } - private void sendDirectory(LocalFile f) + private void sendDirectory(LocalSourceFile f) throws IOException { preserveTimeIfPossible(f); engine.sendMessage("D0" + getPermString(f) + " 0 " + f.getName()); - for (LocalFile child : f.getChildren()) + for (LocalSourceFile child : f.getChildren(null)) process(child); engine.sendMessage("E"); } - private void sendFile(LocalFile f) + private void sendFile(LocalSourceFile f) throws IOException { preserveTimeIfPossible(f); final InputStream src = f.getInputStream(); try { - engine.sendMessage("C0" + getPermString(f) + " " + f.length() + " " + f.getName()); - engine.transferToRemote(f, src); + engine.sendMessage("C0" + getPermString(f) + " " + f.getLength() + " " + f.getName()); + engine.transferToRemote(src, f.getLength()); engine.signal("Transfer done"); engine.check("Remote agrees transfer done"); } finally { @@ -94,13 +94,13 @@ public final class SCPUploadClient { } } - private void preserveTimeIfPossible(LocalFile f) + private void preserveTimeIfPossible(LocalSourceFile f) throws IOException { - if (f.preservesTimes()) + if (f.providesAtimeMtime()) engine.sendMessage("T" + f.getLastModifiedTime() + " 0 " + f.getLastAccessTime() + " 0"); } - private String getPermString(LocalFile f) + private String getPermString(LocalSourceFile f) throws IOException { return Integer.toOctalString(f.getPermissions() & 07777); }