mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-08 16:18:05 +03:00
SFTPEngine carries the instance of PathHelper
This commit is contained in:
@@ -17,23 +17,23 @@ package net.schmizz.sshj.sftp;
|
|||||||
|
|
||||||
public class PathComponents {
|
public class PathComponents {
|
||||||
|
|
||||||
public static String adjustForParent(String parent, String path) {
|
static String adjustForParent(String parent, String path, String pathSep) {
|
||||||
return (path.startsWith("/")) ? path // Absolute path, nothing to adjust
|
return (path.startsWith(pathSep)) ? path // Absolute path, nothing to adjust
|
||||||
: (parent + (parent.endsWith("/") ? "" : "/") + path); // Relative path
|
: (parent + (parent.endsWith(pathSep) ? "" : pathSep) + path); // Relative path
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String trimFinalSlash(String path) {
|
static String trimTrailingSeparator(String somePath, String pathSep) {
|
||||||
return path.endsWith("/") ? path.substring(0, path.length() - 1) : path;
|
return somePath.endsWith(pathSep) ? somePath.substring(0, somePath.length() - pathSep.length()) : somePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String parent;
|
private final String parent;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String path;
|
private final String path;
|
||||||
|
|
||||||
public PathComponents(String parent, String name) {
|
public PathComponents(String parent, String name, String pathSep) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.path = adjustForParent(parent, name);
|
this.path = trimTrailingSeparator(adjustForParent(parent, name, pathSep), pathSep);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getParent() {
|
public String getParent() {
|
||||||
@@ -50,17 +50,12 @@ public class PathComponents {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (o instanceof PathComponents) {
|
return this == o || ((o instanceof PathComponents) && path.equals(((PathComponents) o).path));
|
||||||
final PathComponents that = (PathComponents) o;
|
|
||||||
return (trimFinalSlash(path).equals(trimFinalSlash(that.path)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return trimFinalSlash(path).hashCode();
|
return path.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -19,16 +19,32 @@ import java.io.IOException;
|
|||||||
|
|
||||||
public class PathHelper {
|
public class PathHelper {
|
||||||
|
|
||||||
public static final String DEFAULT_SEPARATOR = "/";
|
public static final String DEFAULT_PATH_SEPARATOR = "/";
|
||||||
|
|
||||||
private final SFTPEngine engine;
|
private final SFTPEngine engine;
|
||||||
private final String separator;
|
private final String pathSep;
|
||||||
|
|
||||||
private String dotDir;
|
private String dotDir;
|
||||||
|
|
||||||
public PathHelper(SFTPEngine engine, String separator) {
|
public PathHelper(SFTPEngine engine, String pathSep) {
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
this.separator = separator;
|
this.pathSep = pathSep;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String adjustForParent(String parent, String path) {
|
||||||
|
return PathComponents.adjustForParent(parent, path, pathSep);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String trimTrailingSeparator(String path) {
|
||||||
|
return PathComponents.trimTrailingSeparator(path, pathSep);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPathSeparator() {
|
||||||
|
return pathSep;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PathComponents getComponents(String parent, String name) {
|
||||||
|
return new PathComponents(parent, name, pathSep);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PathComponents getComponents(String path)
|
public PathComponents getComponents(String path)
|
||||||
@@ -36,21 +52,21 @@ public class PathHelper {
|
|||||||
if (path.isEmpty() || path.equals("."))
|
if (path.isEmpty() || path.equals("."))
|
||||||
return getComponents(getDotDir());
|
return getComponents(getDotDir());
|
||||||
|
|
||||||
final int lastSlash = path.lastIndexOf(separator);
|
final int lastSlash = path.lastIndexOf(pathSep);
|
||||||
|
|
||||||
if (lastSlash == -1)
|
if (lastSlash == -1) // Relative path
|
||||||
if (path.equals(".."))
|
if (path.equals(".."))
|
||||||
return getComponents(canon(path));
|
return getComponents(canon(path));
|
||||||
else
|
else
|
||||||
return new PathComponents(getDotDir(), path);
|
return getComponents(getDotDir(), path);
|
||||||
|
|
||||||
final String name = path.substring(lastSlash + 1);
|
final String name = path.substring(lastSlash + pathSep.length());
|
||||||
|
|
||||||
if (name.equals(".") || name.equals(".."))
|
if (name.equals(".") || name.equals(".."))
|
||||||
return getComponents(canon(path));
|
return getComponents(canon(path));
|
||||||
else {
|
else {
|
||||||
final String parent = path.substring(0, lastSlash);
|
final String parent = path.substring(0, lastSlash);
|
||||||
return new PathComponents(parent, name);
|
return getComponents(parent, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ public class RemoteDirectory
|
|||||||
final String name = res.readString();
|
final String name = res.readString();
|
||||||
res.readString(); // long name - IGNORED - shdve never been in the protocol
|
res.readString(); // long name - IGNORED - shdve never been in the protocol
|
||||||
final FileAttributes attrs = res.readFileAttributes();
|
final FileAttributes attrs = res.readFileAttributes();
|
||||||
RemoteResourceInfo inf = new RemoteResourceInfo(path, name, attrs);
|
final PathComponents comps = requester.getPathHelper().getComponents(path, name);
|
||||||
|
final RemoteResourceInfo inf = new RemoteResourceInfo(comps, attrs);
|
||||||
if (!(name.equals(".") || name.equals("..")) && (filter == null || filter.accept(inf)))
|
if (!(name.equals(".") || name.equals("..")) && (filter == null || filter.accept(inf)))
|
||||||
rri.add(inf);
|
rri.add(inf);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,6 @@ public class RemoteResourceInfo {
|
|||||||
private final PathComponents comps;
|
private final PathComponents comps;
|
||||||
private final FileAttributes attrs;
|
private final FileAttributes attrs;
|
||||||
|
|
||||||
public RemoteResourceInfo(String parent, String name, FileAttributes attrs) {
|
|
||||||
this(new PathComponents(parent, name), attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RemoteResourceInfo(PathComponents comps, FileAttributes attrs) {
|
public RemoteResourceInfo(PathComponents comps, FileAttributes attrs) {
|
||||||
this.comps = comps;
|
this.comps = comps;
|
||||||
this.attrs = attrs;
|
this.attrs = attrs;
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ import java.io.IOException;
|
|||||||
|
|
||||||
public interface Requester {
|
public interface Requester {
|
||||||
|
|
||||||
|
PathHelper getPathHelper();
|
||||||
|
|
||||||
Request newRequest(PacketType type);
|
Request newRequest(PacketType type);
|
||||||
|
|
||||||
Response doRequest(Request req)
|
Response doRequest(Request req)
|
||||||
|
|||||||
@@ -35,18 +35,12 @@ public class SFTPClient
|
|||||||
/** Logger */
|
/** Logger */
|
||||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
private final SFTPEngine engine;
|
protected final SFTPEngine engine;
|
||||||
private final SFTPFileTransfer xfer;
|
protected final SFTPFileTransfer xfer;
|
||||||
private final PathHelper pathHelper;
|
|
||||||
|
|
||||||
public SFTPClient(SFTPEngine engine) {
|
public SFTPClient(SFTPEngine engine) {
|
||||||
this(engine, PathHelper.DEFAULT_SEPARATOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SFTPClient(SFTPEngine engine, String separator) {
|
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
this.pathHelper = new PathHelper(engine, separator);
|
this.xfer = new SFTPFileTransfer(engine);
|
||||||
this.xfer = new SFTPFileTransfer(engine, pathHelper);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SFTPEngine getSFTPEngine() {
|
public SFTPEngine getSFTPEngine() {
|
||||||
@@ -96,8 +90,8 @@ public class SFTPClient
|
|||||||
public void mkdirs(String path)
|
public void mkdirs(String path)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final Deque<String> dirsToMake = new LinkedList<String>();
|
final Deque<String> dirsToMake = new LinkedList<String>();
|
||||||
for (PathComponents current = pathHelper.getComponents(path); ; current = pathHelper
|
for (PathComponents current = engine.getPathHelper().getComponents(path); ;
|
||||||
.getComponents(current.getParent())) {
|
current = engine.getPathHelper().getComponents(current.getParent())) {
|
||||||
final FileAttributes attrs = statExistence(current.getPath());
|
final FileAttributes attrs = statExistence(current.getPath());
|
||||||
if (attrs == null) {
|
if (attrs == null) {
|
||||||
dirsToMake.push(current.getPath());
|
dirsToMake.push(current.getPath());
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ public class SFTPEngine
|
|||||||
|
|
||||||
protected volatile int timeout = DEFAULT_TIMEOUT;
|
protected volatile int timeout = DEFAULT_TIMEOUT;
|
||||||
|
|
||||||
|
protected final PathHelper pathHelper;
|
||||||
|
|
||||||
protected final Subsystem sub;
|
protected final Subsystem sub;
|
||||||
protected final PacketReader reader;
|
protected final PacketReader reader;
|
||||||
protected final OutputStream out;
|
protected final OutputStream out;
|
||||||
@@ -51,9 +53,14 @@ public class SFTPEngine
|
|||||||
|
|
||||||
public SFTPEngine(SessionFactory ssh)
|
public SFTPEngine(SessionFactory ssh)
|
||||||
throws SSHException {
|
throws SSHException {
|
||||||
|
this(ssh, PathHelper.DEFAULT_PATH_SEPARATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SFTPEngine(SessionFactory ssh, String pathSep) throws SSHException {
|
||||||
sub = ssh.startSession().startSubsystem("sftp");
|
sub = ssh.startSession().startSubsystem("sftp");
|
||||||
out = sub.getOutputStream();
|
out = sub.getOutputStream();
|
||||||
reader = new PacketReader(this);
|
reader = new PacketReader(this);
|
||||||
|
pathHelper = new PathHelper(this, pathSep);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SFTPEngine init()
|
public SFTPEngine init()
|
||||||
@@ -91,6 +98,11 @@ public class SFTPEngine
|
|||||||
return newRequest(PacketType.EXTENDED).putString(reqName);
|
return newRequest(PacketType.EXTENDED).putString(reqName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PathHelper getPathHelper() {
|
||||||
|
return pathHelper;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Request newRequest(PacketType type) {
|
public synchronized Request newRequest(PacketType type) {
|
||||||
return new Request(type, reqID = reqID + 1 & 0xffffffffL);
|
return new Request(type, reqID = reqID + 1 & 0xffffffffL);
|
||||||
|
|||||||
@@ -35,20 +35,12 @@ public class SFTPFileTransfer
|
|||||||
implements FileTransfer {
|
implements FileTransfer {
|
||||||
|
|
||||||
private final SFTPEngine engine;
|
private final SFTPEngine engine;
|
||||||
private final PathHelper pathHelper;
|
|
||||||
|
|
||||||
private volatile LocalFileFilter uploadFilter;
|
private volatile LocalFileFilter uploadFilter;
|
||||||
private volatile RemoteResourceFilter downloadFilter;
|
private volatile RemoteResourceFilter downloadFilter;
|
||||||
|
|
||||||
public SFTPFileTransfer(SFTPEngine engine, PathHelper pathHelper) {
|
|
||||||
this.engine = engine;
|
|
||||||
this.pathHelper = pathHelper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public SFTPFileTransfer(SFTPEngine engine) {
|
public SFTPFileTransfer(SFTPEngine engine) {
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
this.pathHelper = new PathHelper(engine, PathHelper.DEFAULT_SEPARATOR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -72,7 +64,7 @@ public class SFTPFileTransfer
|
|||||||
@Override
|
@Override
|
||||||
public void download(String source, LocalDestFile dest)
|
public void download(String source, LocalDestFile dest)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final PathComponents pathComponents = pathHelper.getComponents(source);
|
final PathComponents pathComponents = engine.getPathHelper().getComponents(source);
|
||||||
final FileAttributes attributes = engine.stat(source);
|
final FileAttributes attributes = engine.stat(source);
|
||||||
new Downloader().download(new RemoteResourceInfo(pathComponents, attributes), dest);
|
new Downloader().download(new RemoteResourceInfo(pathComponents, attributes), dest);
|
||||||
}
|
}
|
||||||
@@ -233,12 +225,12 @@ public class SFTPFileTransfer
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (attrs.getMode().getType() == FileMode.Type.DIRECTORY)
|
if (attrs.getMode().getType() == FileMode.Type.DIRECTORY)
|
||||||
if (pathHelper.getComponents(remote).getName().equals(local.getName())) {
|
if (engine.getPathHelper().getComponents(remote).getName().equals(local.getName())) {
|
||||||
log.debug("probeDir: {} already exists", remote);
|
log.debug("probeDir: {} already exists", remote);
|
||||||
return remote;
|
return remote;
|
||||||
} else {
|
} else {
|
||||||
log.debug("probeDir: {} already exists, path adjusted for {}", remote, local.getName());
|
log.debug("probeDir: {} already exists, path adjusted for {}", remote, local.getName());
|
||||||
return prepareDir(local, PathComponents.adjustForParent(remote, local.getName()));
|
return prepareDir(local, engine.getPathHelper().adjustForParent(remote, local.getName()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw new IOException(attrs.getMode().getType() + " file already exists at " + remote);
|
throw new IOException(attrs.getMode().getType() + " file already exists at " + remote);
|
||||||
@@ -258,7 +250,7 @@ public class SFTPFileTransfer
|
|||||||
}
|
}
|
||||||
if (attrs.getMode().getType() == FileMode.Type.DIRECTORY) {
|
if (attrs.getMode().getType() == FileMode.Type.DIRECTORY) {
|
||||||
log.debug("probeFile: {} was directory, path adjusted for {}", remote, local.getName());
|
log.debug("probeFile: {} was directory, path adjusted for {}", remote, local.getName());
|
||||||
remote = PathComponents.adjustForParent(remote, local.getName());
|
remote = engine.getPathHelper().adjustForParent(remote, local.getName());
|
||||||
return remote;
|
return remote;
|
||||||
} else {
|
} else {
|
||||||
log.debug("probeFile: {} is a {} file that will be replaced", remote, attrs.getMode().getType());
|
log.debug("probeFile: {} is a {} file that will be replaced", remote, attrs.getMode().getType());
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class StatefulSFTPClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
private synchronized String cwdify(String path) {
|
private synchronized String cwdify(String path) {
|
||||||
return PathComponents.adjustForParent(cwd, path);
|
return engine.getPathHelper().adjustForParent(cwd, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void cd(String dirname)
|
public synchronized void cd(String dirname)
|
||||||
|
|||||||
Reference in New Issue
Block a user