Lighter, more coherent interfaces by refactoring LocalFile into LocalSourceFile & LocalDestFile

This commit is contained in:
Shikhar Bhushan
2011-04-06 23:37:55 +01:00
parent a2c82de260
commit ce930c969b
13 changed files with 180 additions and 316 deletions

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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<FileSystemFile> getChildren()
throws IOException {
return getChildren(null);
}
@Override
public Iterable<FileSystemFile> 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));

View File

@@ -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();

View File

@@ -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<LocalFile> getChildren()
throws IOException {
return null;
}
@Override
public Iterable<LocalFile> 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");
}
}

View File

@@ -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<LocalFile> getChildren()
throws IOException {
return null;
}
@Override
public Iterable<LocalFile> 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<? extends LocalSourceFile> 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");
}
}

View File

@@ -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<? extends LocalFile> getChildren() throws IOException;
Iterable<? extends LocalFile> 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;
}
}

View File

@@ -17,6 +17,6 @@ package net.schmizz.sshj.xfer;
public interface LocalFileFilter {
boolean accept(LocalFile file);
boolean accept(LocalSourceFile file);
}

View File

@@ -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<? extends LocalSourceFile> 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;
}

View File

@@ -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<Arg> args = new LinkedList<Arg>();
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<perms> 0 <dirname>
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<perms> <size> <filename>
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<mtime> 0 <atime> 0
f.setLastModifiedTime(parseLong(tMsgParts[0].substring(1), "last modified time"));
f.setLastAccessedTime(parseLong(tMsgParts[2], "last access time"));

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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<Arg> args = new LinkedList<Arg>();
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);
}