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

View File

@@ -15,23 +15,22 @@
*/
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.SSHException;
import net.schmizz.sshj.connection.channel.direct.Session.Command;
import net.schmizz.sshj.connection.channel.direct.SessionFactory;
import net.schmizz.sshj.xfer.TransferListener;
import org.slf4j.Logger;
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> */
abstract class SCPEngine {
class SCPEngine {
static enum Arg {
SOURCE('f'),
@@ -70,17 +69,6 @@ abstract class SCPEngine {
this.listener = listener;
}
public int copy(String sourcePath, String targetPath)
throws IOException {
cleanSlate();
try {
startCopy(sourcePath, targetPath);
} finally {
exit();
}
return exitStatus;
}
public int getExitStatus() {
return exitStatus;
}
@@ -173,9 +161,6 @@ abstract class SCPEngine {
scp.getOutputStream().flush();
}
abstract void startCopy(String sourcePath, String targetPath)
throws IOException;
void transfer(InputStream in, OutputStream out, int bufSize, long len)
throws IOException {
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.xfer.AbstractFileTransfer;
import net.schmizz.sshj.xfer.FileSystemFile;
import net.schmizz.sshj.xfer.FileTransfer;
import net.schmizz.sshj.xfer.LocalFile;
@@ -49,7 +50,7 @@ public class SCPFileTransfer
@Override
public void upload(String localPath, String remotePath)
throws IOException {
newSCPUploadClient().copy(localPath, remotePath);
newSCPUploadClient().copy(new FileSystemFile(localPath), 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.ModeGetter;
import net.schmizz.sshj.xfer.TransferListener;
import net.schmizz.sshj.xfer.scp.SCPEngine.Arg;
/** Support for uploading files over a connected link using SCP. */
public final class SCPUploadClient
extends SCPEngine {
public final class SCPUploadClient {
private final ModeGetter modeGetter;
private FileFilter fileFilter;
SCPUploadClient(SessionFactory host, TransferListener listener, ModeGetter modeGetter) {
super(host, listener);
this.modeGetter = modeGetter;
}
private SCPEngine engine;
/** Upload a file from {@code sourcePath} locally to {@code targetPath} on the remote host. */
@Override
public synchronized int copy(String sourcePath, String targetPath)
throws IOException {
return super.copy(sourcePath, targetPath);
SCPUploadClient(SessionFactory host, TransferListener listener, ModeGetter modeGetter) {
engine = new SCPEngine(host, listener);
this.modeGetter = modeGetter;
}
/** Upload a local file from {@code localFile} to {@code targetPath} on the remote host. */
public synchronized int copy(LocalFile sourceFile, String remotePath)
throws IOException {
cleanSlate();
engine.cleanSlate();
try {
startCopy(sourceFile, remotePath);
} finally {
exit();
engine.exit();
}
return exitStatus;
return engine.exitStatus;
}
public void setFileFilter(FileFilter fileFilter) {
this.fileFilter = fileFilter;
}
@Override
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)
private synchronized void startCopy(LocalFile sourceFile, String targetPath)
throws IOException {
init(targetPath);
check("Start status OK");
engine.check("Start status OK");
process(sourceFile);
}
@@ -96,19 +83,19 @@ public final class SCPUploadClient
args.add(Arg.RECURSIVE);
if (modeGetter.preservesTimes())
args.add(Arg.PRESERVE_TIMES);
execSCPWith(args, target);
engine.execSCPWith(args, target);
}
private void process(File f)
throws IOException {
if (f.isDirectory()) {
listener.startedDir(f.getName());
engine.listener.startedDir(f.getName());
sendDirectory(f);
listener.finishedDir();
engine.listener.finishedDir();
} else if (f.isFile()) {
listener.startedFile(f.getName(), f.length());
engine.listener.startedFile(f.getName(), f.length());
sendFile(f);
listener.finishedFile();
engine.listener.finishedFile();
} else
throw new IOException(f + " is not a regular file or directory");
}
@@ -116,13 +103,13 @@ public final class SCPUploadClient
private void process(LocalFile f)
throws IOException {
if (f.isDirectory()) {
listener.startedDir(f.getName());
engine.listener.startedDir(f.getName());
sendDirectory(f);
listener.finishedDir();
engine.listener.finishedDir();
} else if (f.isFile()) {
listener.startedFile(f.getName(), f.length());
engine.listener.startedFile(f.getName(), f.length());
sendFile(f);
listener.finishedFile();
engine.listener.finishedFile();
} else
throw new IOException(f + " is not a regular file or directory");
}
@@ -130,19 +117,19 @@ public final class SCPUploadClient
private void sendDirectory(File f)
throws IOException {
preserveTimeIfPossible(f);
sendMessage("D0" + getPermString(f) + " 0 " + f.getName());
engine.sendMessage("D0" + getPermString(f) + " 0 " + f.getName());
for (File child : getChildren(f))
process(child);
sendMessage("E");
engine.sendMessage("E");
}
private void sendDirectory(LocalFile f)
throws IOException {
preserveTimeIfPossible(f);
sendMessage("D0" + getPermString(f) + " 0 " + f.getName());
engine.sendMessage("D0" + getPermString(f) + " 0 " + f.getName());
for (LocalFile child : f.getChildren())
process(child);
sendMessage("E");
engine.sendMessage("E");
}
private void sendFile(File f)
@@ -150,10 +137,10 @@ public final class SCPUploadClient
preserveTimeIfPossible(f);
final InputStream src = new FileInputStream(f);
try {
sendMessage("C0" + getPermString(f) + " " + f.length() + " " + f.getName());
transfer(src, scp.getOutputStream(), scp.getRemoteMaxPacketSize(), f.length());
signal("Transfer done");
check("Remote agrees transfer done");
engine.sendMessage("C0" + getPermString(f) + " " + f.length() + " " + f.getName());
engine.transfer(src, engine.scp.getOutputStream(), engine.scp.getRemoteMaxPacketSize(), f.length());
engine.signal("Transfer done");
engine.check("Remote agrees transfer done");
} finally {
IOUtils.closeQuietly(src);
}
@@ -164,10 +151,10 @@ public final class SCPUploadClient
preserveTimeIfPossible(f);
final InputStream src = f.stream();
try {
sendMessage("C0" + getPermString(f) + " " + f.length() + " " + f.getName());
transfer(src, scp.getOutputStream(), scp.getRemoteMaxPacketSize(), f.length());
signal("Transfer done");
check("Remote agrees transfer done");
engine.sendMessage("C0" + getPermString(f) + " " + f.length() + " " + f.getName());
engine.transfer(src, engine.scp.getOutputStream(), engine.scp.getRemoteMaxPacketSize(), f.length());
engine.signal("Transfer done");
engine.check("Remote agrees transfer done");
} finally {
IOUtils.closeQuietly(src);
}
@@ -176,13 +163,13 @@ public final class SCPUploadClient
private void preserveTimeIfPossible(File f)
throws IOException {
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)
throws IOException {
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)