diff --git a/src/main/java/net/schmizz/sshj/sftp/PathComponents.java b/src/main/java/net/schmizz/sshj/sftp/PathComponents.java index b639ff2a..0634366f 100644 --- a/src/main/java/net/schmizz/sshj/sftp/PathComponents.java +++ b/src/main/java/net/schmizz/sshj/sftp/PathComponents.java @@ -17,23 +17,23 @@ package net.schmizz.sshj.sftp; public class PathComponents { - public static String adjustForParent(String parent, String path) { - return (path.startsWith("/")) ? path // Absolute path, nothing to adjust - : (parent + (parent.endsWith("/") ? "" : "/") + path); // Relative path + static String adjustForParent(String parent, String path, String pathSep) { + return (path.startsWith(pathSep)) ? path // Absolute path, nothing to adjust + : (parent + (parent.endsWith(pathSep) ? "" : pathSep) + path); // Relative path } - private static String trimFinalSlash(String path) { - return path.endsWith("/") ? path.substring(0, path.length() - 1) : path; + static String trimTrailingSeparator(String somePath, String pathSep) { + return somePath.endsWith(pathSep) ? somePath.substring(0, somePath.length() - pathSep.length()) : somePath; } private final String parent; private final String name; private final String path; - public PathComponents(String parent, String name) { + public PathComponents(String parent, String name, String pathSep) { this.parent = parent; this.name = name; - this.path = adjustForParent(parent, name); + this.path = trimTrailingSeparator(adjustForParent(parent, name, pathSep), pathSep); } public String getParent() { @@ -50,17 +50,12 @@ public class PathComponents { @Override public boolean equals(Object o) { - if (o instanceof PathComponents) { - final PathComponents that = (PathComponents) o; - return (trimFinalSlash(path).equals(trimFinalSlash(that.path))); - } - - return false; + return this == o || ((o instanceof PathComponents) && path.equals(((PathComponents) o).path)); } @Override public int hashCode() { - return trimFinalSlash(path).hashCode(); + return path.hashCode(); } @Override diff --git a/src/main/java/net/schmizz/sshj/sftp/PathHelper.java b/src/main/java/net/schmizz/sshj/sftp/PathHelper.java index 447e4259..08d3d878 100644 --- a/src/main/java/net/schmizz/sshj/sftp/PathHelper.java +++ b/src/main/java/net/schmizz/sshj/sftp/PathHelper.java @@ -19,16 +19,32 @@ import java.io.IOException; public class PathHelper { - public static final String DEFAULT_SEPARATOR = "/"; + public static final String DEFAULT_PATH_SEPARATOR = "/"; private final SFTPEngine engine; - private final String separator; + private final String pathSep; private String dotDir; - public PathHelper(SFTPEngine engine, String separator) { + public PathHelper(SFTPEngine engine, String pathSep) { 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) @@ -36,21 +52,21 @@ public class PathHelper { if (path.isEmpty() || path.equals(".")) 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("..")) return getComponents(canon(path)); 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("..")) return getComponents(canon(path)); else { final String parent = path.substring(0, lastSlash); - return new PathComponents(parent, name); + return getComponents(parent, name); } } diff --git a/src/main/java/net/schmizz/sshj/sftp/RemoteDirectory.java b/src/main/java/net/schmizz/sshj/sftp/RemoteDirectory.java index 46ab26ab..56fad605 100644 --- a/src/main/java/net/schmizz/sshj/sftp/RemoteDirectory.java +++ b/src/main/java/net/schmizz/sshj/sftp/RemoteDirectory.java @@ -42,7 +42,8 @@ public class RemoteDirectory final String name = res.readString(); res.readString(); // long name - IGNORED - shdve never been in the protocol 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))) rri.add(inf); } diff --git a/src/main/java/net/schmizz/sshj/sftp/RemoteResourceInfo.java b/src/main/java/net/schmizz/sshj/sftp/RemoteResourceInfo.java index f53d5fb0..2714abe9 100644 --- a/src/main/java/net/schmizz/sshj/sftp/RemoteResourceInfo.java +++ b/src/main/java/net/schmizz/sshj/sftp/RemoteResourceInfo.java @@ -20,10 +20,6 @@ public class RemoteResourceInfo { private final PathComponents comps; private final FileAttributes attrs; - public RemoteResourceInfo(String parent, String name, FileAttributes attrs) { - this(new PathComponents(parent, name), attrs); - } - public RemoteResourceInfo(PathComponents comps, FileAttributes attrs) { this.comps = comps; this.attrs = attrs; diff --git a/src/main/java/net/schmizz/sshj/sftp/Requester.java b/src/main/java/net/schmizz/sshj/sftp/Requester.java index a11b02f7..0cfc73c2 100644 --- a/src/main/java/net/schmizz/sshj/sftp/Requester.java +++ b/src/main/java/net/schmizz/sshj/sftp/Requester.java @@ -19,6 +19,8 @@ import java.io.IOException; public interface Requester { + PathHelper getPathHelper(); + Request newRequest(PacketType type); Response doRequest(Request req) diff --git a/src/main/java/net/schmizz/sshj/sftp/SFTPClient.java b/src/main/java/net/schmizz/sshj/sftp/SFTPClient.java index 65cbdde9..c23a99ca 100644 --- a/src/main/java/net/schmizz/sshj/sftp/SFTPClient.java +++ b/src/main/java/net/schmizz/sshj/sftp/SFTPClient.java @@ -35,18 +35,12 @@ public class SFTPClient /** Logger */ protected final Logger log = LoggerFactory.getLogger(getClass()); - private final SFTPEngine engine; - private final SFTPFileTransfer xfer; - private final PathHelper pathHelper; + protected final SFTPEngine engine; + protected final SFTPFileTransfer xfer; public SFTPClient(SFTPEngine engine) { - this(engine, PathHelper.DEFAULT_SEPARATOR); - } - - public SFTPClient(SFTPEngine engine, String separator) { this.engine = engine; - this.pathHelper = new PathHelper(engine, separator); - this.xfer = new SFTPFileTransfer(engine, pathHelper); + this.xfer = new SFTPFileTransfer(engine); } public SFTPEngine getSFTPEngine() { @@ -96,8 +90,8 @@ public class SFTPClient public void mkdirs(String path) throws IOException { final Deque dirsToMake = new LinkedList(); - for (PathComponents current = pathHelper.getComponents(path); ; current = pathHelper - .getComponents(current.getParent())) { + for (PathComponents current = engine.getPathHelper().getComponents(path); ; + current = engine.getPathHelper().getComponents(current.getParent())) { final FileAttributes attrs = statExistence(current.getPath()); if (attrs == null) { dirsToMake.push(current.getPath()); diff --git a/src/main/java/net/schmizz/sshj/sftp/SFTPEngine.java b/src/main/java/net/schmizz/sshj/sftp/SFTPEngine.java index 8fca0092..09784bc4 100644 --- a/src/main/java/net/schmizz/sshj/sftp/SFTPEngine.java +++ b/src/main/java/net/schmizz/sshj/sftp/SFTPEngine.java @@ -41,6 +41,8 @@ public class SFTPEngine protected volatile int timeout = DEFAULT_TIMEOUT; + protected final PathHelper pathHelper; + protected final Subsystem sub; protected final PacketReader reader; protected final OutputStream out; @@ -51,9 +53,14 @@ public class SFTPEngine public SFTPEngine(SessionFactory ssh) throws SSHException { + this(ssh, PathHelper.DEFAULT_PATH_SEPARATOR); + } + + public SFTPEngine(SessionFactory ssh, String pathSep) throws SSHException { sub = ssh.startSession().startSubsystem("sftp"); out = sub.getOutputStream(); reader = new PacketReader(this); + pathHelper = new PathHelper(this, pathSep); } public SFTPEngine init() @@ -91,6 +98,11 @@ public class SFTPEngine return newRequest(PacketType.EXTENDED).putString(reqName); } + @Override + public PathHelper getPathHelper() { + return pathHelper; + } + @Override public synchronized Request newRequest(PacketType type) { return new Request(type, reqID = reqID + 1 & 0xffffffffL); diff --git a/src/main/java/net/schmizz/sshj/sftp/SFTPFileTransfer.java b/src/main/java/net/schmizz/sshj/sftp/SFTPFileTransfer.java index e7ef7786..589642f2 100644 --- a/src/main/java/net/schmizz/sshj/sftp/SFTPFileTransfer.java +++ b/src/main/java/net/schmizz/sshj/sftp/SFTPFileTransfer.java @@ -35,20 +35,12 @@ public class SFTPFileTransfer implements FileTransfer { private final SFTPEngine engine; - private final PathHelper pathHelper; private volatile LocalFileFilter uploadFilter; private volatile RemoteResourceFilter downloadFilter; - public SFTPFileTransfer(SFTPEngine engine, PathHelper pathHelper) { - this.engine = engine; - this.pathHelper = pathHelper; - } - - @Deprecated public SFTPFileTransfer(SFTPEngine engine) { this.engine = engine; - this.pathHelper = new PathHelper(engine, PathHelper.DEFAULT_SEPARATOR); } @Override @@ -72,7 +64,7 @@ public class SFTPFileTransfer @Override public void download(String source, LocalDestFile dest) throws IOException { - final PathComponents pathComponents = pathHelper.getComponents(source); + final PathComponents pathComponents = engine.getPathHelper().getComponents(source); final FileAttributes attributes = engine.stat(source); new Downloader().download(new RemoteResourceInfo(pathComponents, attributes), dest); } @@ -233,12 +225,12 @@ public class SFTPFileTransfer } 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); return remote; } else { 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 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) { 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; } else { log.debug("probeFile: {} is a {} file that will be replaced", remote, attrs.getMode().getType()); diff --git a/src/main/java/net/schmizz/sshj/sftp/StatefulSFTPClient.java b/src/main/java/net/schmizz/sshj/sftp/StatefulSFTPClient.java index cd3da309..9013ec61 100644 --- a/src/main/java/net/schmizz/sshj/sftp/StatefulSFTPClient.java +++ b/src/main/java/net/schmizz/sshj/sftp/StatefulSFTPClient.java @@ -32,7 +32,7 @@ public class StatefulSFTPClient } private synchronized String cwdify(String path) { - return PathComponents.adjustForParent(cwd, path); + return engine.getPathHelper().adjustForParent(cwd, path); } public synchronized void cd(String dirname)