Remove inheritance coupling between SCP*Clients

Use delegation to SCPEngine instead of inheritance.
Remove methods using String path for source file.
This commit is contained in:
Cyril Ledru
2011-03-16 16:15:21 +08:00
committed by Shikhar Bhushan
parent 41ac277023
commit aa9f4e192f
4 changed files with 80 additions and 101 deletions

View File

@@ -15,37 +15,44 @@
*/ */
package net.schmizz.sshj.xfer.scp; package net.schmizz.sshj.xfer.scp;
import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.common.SSHException;
import net.schmizz.sshj.connection.channel.direct.SessionFactory;
import net.schmizz.sshj.xfer.FileTransferUtil;
import net.schmizz.sshj.xfer.ModeSetter;
import net.schmizz.sshj.xfer.TransferListener;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.common.SSHException;
import net.schmizz.sshj.connection.channel.direct.SessionFactory;
import net.schmizz.sshj.xfer.FileTransferUtil;
import net.schmizz.sshj.xfer.ModeSetter;
import net.schmizz.sshj.xfer.TransferListener;
import net.schmizz.sshj.xfer.scp.SCPEngine.Arg;
/** Support for uploading files over a connected link using SCP. */ /** Support for uploading files over a connected link using SCP. */
public final class SCPDownloadClient public final class SCPDownloadClient {
extends SCPEngine {
private final ModeSetter modeSetter; private final ModeSetter modeSetter;
private boolean recursive = true; private boolean recursive = true;
private SCPEngine engine;
SCPDownloadClient(SessionFactory host, TransferListener listener, ModeSetter modeSetter) { SCPDownloadClient(SessionFactory host, TransferListener listener, ModeSetter modeSetter) {
super(host, listener); engine = new SCPEngine(host, listener);
this.modeSetter = modeSetter; this.modeSetter = modeSetter;
} }
/** Download a file from {@code sourcePath} on the connected host to {@code targetPath} locally. */ /** Download a file from {@code sourcePath} on the connected host to {@code targetPath} locally. */
@Override
public synchronized int copy(String sourcePath, String targetPath) public synchronized int copy(String sourcePath, String targetPath)
throws IOException { throws IOException {
return super.copy(sourcePath, targetPath); engine.cleanSlate();
try {
startCopy(sourcePath, targetPath);
} finally {
engine.exit();
}
return engine.exitStatus;
} }
public boolean getRecursive() { public boolean getRecursive() {
@@ -56,17 +63,16 @@ public final class SCPDownloadClient
this.recursive = recursive; this.recursive = recursive;
} }
@Override
void startCopy(String sourcePath, String targetPath) void startCopy(String sourcePath, String targetPath)
throws IOException { throws IOException {
init(sourcePath); init(sourcePath);
signal("Start status OK"); engine.signal("Start status OK");
String msg = readMessage(true); String msg = engine.readMessage(true);
do do
process(null, msg, new File(targetPath)); process(null, msg, new File(targetPath));
while ((msg = readMessage(false)) != null); while ((msg = engine.readMessage(false)) != null);
} }
private void init(String source) private void init(String source)
@@ -78,7 +84,7 @@ public final class SCPDownloadClient
args.add(Arg.RECURSIVE); args.add(Arg.RECURSIVE);
if (modeSetter.preservesTimes()) if (modeSetter.preservesTimes())
args.add(Arg.PRESERVE_TIMES); args.add(Arg.PRESERVE_TIMES);
execSCPWith(args, source); engine.execSCPWith(args, source);
} }
private long parseLong(String longString, String valType) private long parseLong(String longString, String valType)
@@ -107,8 +113,8 @@ public final class SCPDownloadClient
switch (msg.charAt(0)) { switch (msg.charAt(0)) {
case 'T': case 'T':
signal("ACK: T"); engine.signal("ACK: T");
process(msg, readMessage(true), f); process(msg, engine.readMessage(true), f);
break; break;
case 'C': case 'C':
@@ -128,7 +134,7 @@ public final class SCPDownloadClient
default: default:
String err = "Unrecognized message: `" + msg + "`"; String err = "Unrecognized message: `" + msg + "`";
sendMessage((char) 2 + err); engine.sendMessage((char) 2 + err);
throw new SCPException(err); throw new SCPException(err);
} }
@@ -142,16 +148,16 @@ public final class SCPDownloadClient
final String dirname = dMsgParts[2]; final String dirname = dMsgParts[2];
if (length != 0) if (length != 0)
throw new IOException("Remote SCP command sent strange directory length: " + length); throw new IOException("Remote SCP command sent strange directory length: " + length);
listener.startedDir(dirname); engine.listener.startedDir(dirname);
{ {
f = FileTransferUtil.getTargetDirectory(f, dirname); f = FileTransferUtil.getTargetDirectory(f, dirname);
signal("ACK: D"); engine.signal("ACK: D");
do { do {
} while (!process(null, readMessage(), f)); } while (!process(null, engine.readMessage(), f));
setAttributes(f, parsePermissions(dMsgParts[0]), tMsg); setAttributes(f, parsePermissions(dMsgParts[0]), tMsg);
signal("ACK: E"); engine.signal("ACK: E");
} }
listener.finishedDir(); engine.listener.finishedDir();
} }
private void processFile(String cMsg, String tMsg, File f) private void processFile(String cMsg, String tMsg, File f)
@@ -159,21 +165,21 @@ public final class SCPDownloadClient
final String[] cMsgParts = tokenize(cMsg, 3); // C<perms> <size> <filename> final String[] cMsgParts = tokenize(cMsg, 3); // C<perms> <size> <filename>
final long length = parseLong(cMsgParts[1], "length"); final long length = parseLong(cMsgParts[1], "length");
final String filename = cMsgParts[2]; final String filename = cMsgParts[2];
listener.startedFile(filename, length); engine.listener.startedFile(filename, length);
{ {
f = FileTransferUtil.getTargetFile(f, filename); f = FileTransferUtil.getTargetFile(f, filename);
signal("Remote can start transfer"); engine.signal("Remote can start transfer");
final FileOutputStream fos = new FileOutputStream(f); final FileOutputStream fos = new FileOutputStream(f);
try { try {
transfer(scp.getInputStream(), fos, scp.getLocalMaxPacketSize(), length); engine.transfer(engine.scp.getInputStream(), fos, engine.scp.getLocalMaxPacketSize(), length);
} finally { } finally {
IOUtils.closeQuietly(fos); IOUtils.closeQuietly(fos);
} }
check("Remote agrees transfer done"); engine.check("Remote agrees transfer done");
setAttributes(f, parsePermissions(cMsgParts[0]), tMsg); setAttributes(f, parsePermissions(cMsgParts[0]), tMsg);
signal("Transfer done"); engine.signal("Transfer done");
} }
listener.finishedFile(); engine.listener.finishedFile();
} }
private void setAttributes(File f, int perms, String tMsg) private void setAttributes(File f, int perms, String tMsg)

View File

@@ -15,23 +15,22 @@
*/ */
package net.schmizz.sshj.xfer.scp; package net.schmizz.sshj.xfer.scp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import net.schmizz.sshj.common.IOUtils; import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.common.SSHException; import net.schmizz.sshj.common.SSHException;
import net.schmizz.sshj.connection.channel.direct.Session.Command; import net.schmizz.sshj.connection.channel.direct.Session.Command;
import net.schmizz.sshj.connection.channel.direct.SessionFactory; import net.schmizz.sshj.connection.channel.direct.SessionFactory;
import net.schmizz.sshj.xfer.TransferListener; import net.schmizz.sshj.xfer.TransferListener;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
/** @see <a href="http://blogs.sun.com/janp/entry/how_the_scp_protocol_works">SCP Protocol</a> */ /** @see <a href="http://blogs.sun.com/janp/entry/how_the_scp_protocol_works">SCP Protocol</a> */
abstract class SCPEngine { class SCPEngine {
static enum Arg { static enum Arg {
SOURCE('f'), SOURCE('f'),
@@ -70,17 +69,6 @@ abstract class SCPEngine {
this.listener = listener; this.listener = listener;
} }
public int copy(String sourcePath, String targetPath)
throws IOException {
cleanSlate();
try {
startCopy(sourcePath, targetPath);
} finally {
exit();
}
return exitStatus;
}
public int getExitStatus() { public int getExitStatus() {
return exitStatus; return exitStatus;
} }
@@ -173,9 +161,6 @@ abstract class SCPEngine {
scp.getOutputStream().flush(); scp.getOutputStream().flush();
} }
abstract void startCopy(String sourcePath, String targetPath)
throws IOException;
void transfer(InputStream in, OutputStream out, int bufSize, long len) void transfer(InputStream in, OutputStream out, int bufSize, long len)
throws IOException { throws IOException {
final byte[] buf = new byte[bufSize]; final byte[] buf = new byte[bufSize];

View File

@@ -19,6 +19,7 @@ import java.io.IOException;
import net.schmizz.sshj.connection.channel.direct.SessionFactory; import net.schmizz.sshj.connection.channel.direct.SessionFactory;
import net.schmizz.sshj.xfer.AbstractFileTransfer; import net.schmizz.sshj.xfer.AbstractFileTransfer;
import net.schmizz.sshj.xfer.FileSystemFile;
import net.schmizz.sshj.xfer.FileTransfer; import net.schmizz.sshj.xfer.FileTransfer;
import net.schmizz.sshj.xfer.LocalFile; import net.schmizz.sshj.xfer.LocalFile;
@@ -49,7 +50,7 @@ public class SCPFileTransfer
@Override @Override
public void upload(String localPath, String remotePath) public void upload(String localPath, String remotePath)
throws IOException { throws IOException {
newSCPUploadClient().copy(localPath, remotePath); newSCPUploadClient().copy(new FileSystemFile(localPath), remotePath);
} }
public void upload(LocalFile localFile, String remotePath) public void upload(LocalFile localFile, String remotePath)

View File

@@ -29,55 +29,42 @@ import net.schmizz.sshj.connection.channel.direct.SessionFactory;
import net.schmizz.sshj.xfer.LocalFile; import net.schmizz.sshj.xfer.LocalFile;
import net.schmizz.sshj.xfer.ModeGetter; import net.schmizz.sshj.xfer.ModeGetter;
import net.schmizz.sshj.xfer.TransferListener; import net.schmizz.sshj.xfer.TransferListener;
import net.schmizz.sshj.xfer.scp.SCPEngine.Arg;
/** Support for uploading files over a connected link using SCP. */ /** Support for uploading files over a connected link using SCP. */
public final class SCPUploadClient public final class SCPUploadClient {
extends SCPEngine {
private final ModeGetter modeGetter; private final ModeGetter modeGetter;
private FileFilter fileFilter; private FileFilter fileFilter;
SCPUploadClient(SessionFactory host, TransferListener listener, ModeGetter modeGetter) { private SCPEngine engine;
super(host, listener);
this.modeGetter = modeGetter;
}
/** Upload a file from {@code sourcePath} locally to {@code targetPath} on the remote host. */ SCPUploadClient(SessionFactory host, TransferListener listener, ModeGetter modeGetter) {
@Override engine = new SCPEngine(host, listener);
public synchronized int copy(String sourcePath, String targetPath) this.modeGetter = modeGetter;
throws IOException {
return super.copy(sourcePath, targetPath);
} }
/** Upload a local file from {@code localFile} to {@code targetPath} on the remote host. */ /** 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(LocalFile sourceFile, String remotePath)
throws IOException { throws IOException {
cleanSlate(); engine.cleanSlate();
try { try {
startCopy(sourceFile, remotePath); startCopy(sourceFile, remotePath);
} finally { } finally {
exit(); engine.exit();
} }
return exitStatus; return engine.exitStatus;
} }
public void setFileFilter(FileFilter fileFilter) { public void setFileFilter(FileFilter fileFilter) {
this.fileFilter = fileFilter; this.fileFilter = fileFilter;
} }
@Override private synchronized void startCopy(LocalFile sourceFile, String targetPath)
protected synchronized void startCopy(String sourcePath, String targetPath)
throws IOException {
init(targetPath);
check("Start status OK");
process(new File(sourcePath));
}
protected synchronized void startCopy(LocalFile sourceFile, String targetPath)
throws IOException { throws IOException {
init(targetPath); init(targetPath);
check("Start status OK"); engine.check("Start status OK");
process(sourceFile); process(sourceFile);
} }
@@ -96,19 +83,19 @@ public final class SCPUploadClient
args.add(Arg.RECURSIVE); args.add(Arg.RECURSIVE);
if (modeGetter.preservesTimes()) if (modeGetter.preservesTimes())
args.add(Arg.PRESERVE_TIMES); args.add(Arg.PRESERVE_TIMES);
execSCPWith(args, target); engine.execSCPWith(args, target);
} }
private void process(File f) private void process(File f)
throws IOException { throws IOException {
if (f.isDirectory()) { if (f.isDirectory()) {
listener.startedDir(f.getName()); engine.listener.startedDir(f.getName());
sendDirectory(f); sendDirectory(f);
listener.finishedDir(); engine.listener.finishedDir();
} else if (f.isFile()) { } else if (f.isFile()) {
listener.startedFile(f.getName(), f.length()); engine.listener.startedFile(f.getName(), f.length());
sendFile(f); sendFile(f);
listener.finishedFile(); engine.listener.finishedFile();
} else } else
throw new IOException(f + " is not a regular file or directory"); throw new IOException(f + " is not a regular file or directory");
} }
@@ -116,13 +103,13 @@ public final class SCPUploadClient
private void process(LocalFile f) private void process(LocalFile f)
throws IOException { throws IOException {
if (f.isDirectory()) { if (f.isDirectory()) {
listener.startedDir(f.getName()); engine.listener.startedDir(f.getName());
sendDirectory(f); sendDirectory(f);
listener.finishedDir(); engine.listener.finishedDir();
} else if (f.isFile()) { } else if (f.isFile()) {
listener.startedFile(f.getName(), f.length()); engine.listener.startedFile(f.getName(), f.length());
sendFile(f); sendFile(f);
listener.finishedFile(); engine.listener.finishedFile();
} else } else
throw new IOException(f + " is not a regular file or directory"); throw new IOException(f + " is not a regular file or directory");
} }
@@ -130,19 +117,19 @@ public final class SCPUploadClient
private void sendDirectory(File f) private void sendDirectory(File f)
throws IOException { throws IOException {
preserveTimeIfPossible(f); preserveTimeIfPossible(f);
sendMessage("D0" + getPermString(f) + " 0 " + f.getName()); engine.sendMessage("D0" + getPermString(f) + " 0 " + f.getName());
for (File child : getChildren(f)) for (File child : getChildren(f))
process(child); process(child);
sendMessage("E"); engine.sendMessage("E");
} }
private void sendDirectory(LocalFile f) private void sendDirectory(LocalFile f)
throws IOException { throws IOException {
preserveTimeIfPossible(f); preserveTimeIfPossible(f);
sendMessage("D0" + getPermString(f) + " 0 " + f.getName()); engine.sendMessage("D0" + getPermString(f) + " 0 " + f.getName());
for (LocalFile child : f.getChildren()) for (LocalFile child : f.getChildren())
process(child); process(child);
sendMessage("E"); engine.sendMessage("E");
} }
private void sendFile(File f) private void sendFile(File f)
@@ -150,10 +137,10 @@ public final class SCPUploadClient
preserveTimeIfPossible(f); preserveTimeIfPossible(f);
final InputStream src = new FileInputStream(f); final InputStream src = new FileInputStream(f);
try { try {
sendMessage("C0" + getPermString(f) + " " + f.length() + " " + f.getName()); engine.sendMessage("C0" + getPermString(f) + " " + f.length() + " " + f.getName());
transfer(src, scp.getOutputStream(), scp.getRemoteMaxPacketSize(), f.length()); engine.transfer(src, engine.scp.getOutputStream(), engine.scp.getRemoteMaxPacketSize(), f.length());
signal("Transfer done"); engine.signal("Transfer done");
check("Remote agrees transfer done"); engine.check("Remote agrees transfer done");
} finally { } finally {
IOUtils.closeQuietly(src); IOUtils.closeQuietly(src);
} }
@@ -164,10 +151,10 @@ public final class SCPUploadClient
preserveTimeIfPossible(f); preserveTimeIfPossible(f);
final InputStream src = f.stream(); final InputStream src = f.stream();
try { try {
sendMessage("C0" + getPermString(f) + " " + f.length() + " " + f.getName()); engine.sendMessage("C0" + getPermString(f) + " " + f.length() + " " + f.getName());
transfer(src, scp.getOutputStream(), scp.getRemoteMaxPacketSize(), f.length()); engine.transfer(src, engine.scp.getOutputStream(), engine.scp.getRemoteMaxPacketSize(), f.length());
signal("Transfer done"); engine.signal("Transfer done");
check("Remote agrees transfer done"); engine.check("Remote agrees transfer done");
} finally { } finally {
IOUtils.closeQuietly(src); IOUtils.closeQuietly(src);
} }
@@ -176,13 +163,13 @@ public final class SCPUploadClient
private void preserveTimeIfPossible(File f) private void preserveTimeIfPossible(File f)
throws IOException { throws IOException {
if (modeGetter.preservesTimes()) if (modeGetter.preservesTimes())
sendMessage("T" + modeGetter.getLastModifiedTime(f) + " 0 " + modeGetter.getLastAccessTime(f) + " 0"); engine.sendMessage("T" + modeGetter.getLastModifiedTime(f) + " 0 " + modeGetter.getLastAccessTime(f) + " 0");
} }
private void preserveTimeIfPossible(LocalFile f) private void preserveTimeIfPossible(LocalFile f)
throws IOException { throws IOException {
if (modeGetter.preservesTimes()) if (modeGetter.preservesTimes())
sendMessage("T" + modeGetter.getLastModifiedTime(f) + " 0 " + modeGetter.getLastAccessTime(f) + " 0"); engine.sendMessage("T" + modeGetter.getLastModifiedTime(f) + " 0 " + modeGetter.getLastAccessTime(f) + " 0");
} }
private String getPermString(File f) private String getPermString(File f)