You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by gn...@apache.org on 2014/04/08 13:03:48 UTC
[1/2] git commit: [SSHD-310] Better file system abstraction to
support multiple roots
Repository: mina-sshd
Updated Branches:
refs/heads/master 83c1fc118 -> 441bdb919
[SSHD-310] Better file system abstraction to support multiple roots
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/61ebb206
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/61ebb206
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/61ebb206
Branch: refs/heads/master
Commit: 61ebb2063a75991d6f5c6e0ff7b2d56343bf2ec3
Parents: 83c1fc1
Author: Guillaume Nodet <gn...@apache.org>
Authored: Tue Apr 8 13:02:19 2014 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Tue Apr 8 13:03:22 2014 +0200
----------------------------------------------------------------------
.../apache/sshd/common/file/FileSystemView.java | 9 +
.../file/nativefs/NativeFileSystemView.java | 336 +++++++++++++++++--
.../common/file/nativefs/NativeSshFile.java | 67 ++--
.../virtualfs/VirtualFileSystemFactory.java | 8 +-
.../file/virtualfs/VirtualFileSystemView.java | 63 ----
.../apache/sshd/server/sftp/SftpSubsystem.java | 2 +-
.../file/nativefs/NativeFileSystemViewTest.java | 115 +++++++
.../common/file/nativefs/NativeSshFileTest.java | 10 +-
8 files changed, 472 insertions(+), 138 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/61ebb206/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemView.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemView.java b/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemView.java
index 0730341..e2de5d5 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemView.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemView.java
@@ -41,4 +41,13 @@ public interface FileSystemView {
*/
SshFile getFile(SshFile baseDir, String file);
+ /**
+ * Return a view of this file system which has a single root
+ * and uses '/' as a file separator.
+ * If the file system has multiple roots, they are mapped
+ * to directories inside that single root.
+ * @return a normalized file system view
+ */
+ FileSystemView getNormalizedView();
+
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/61ebb206/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemView.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemView.java b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemView.java
index 69bc2d2..9816b1e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemView.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemView.java
@@ -20,12 +20,21 @@
package org.apache.sshd.common.file.nativefs;
import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
import org.apache.sshd.common.file.FileSystemView;
import org.apache.sshd.common.file.SshFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static org.apache.sshd.common.file.nativefs.NativeSshFile.normalizeSeparateChar;
+
/**
* <strong>Internal class, do not use directly.</strong>
*
@@ -36,22 +45,25 @@ import org.slf4j.LoggerFactory;
*/
public class NativeFileSystemView implements FileSystemView {
- private final Logger LOG = LoggerFactory
- .getLogger(NativeFileSystemView.class);
+ private final Logger LOG = LoggerFactory.getLogger(NativeFileSystemView.class);
+
+ private Map<String, String> roots;
// the first and the last character will always be '/'
- // It is always with respect to the root directory.
- private String currDir;
+ // It is always with respect to one of the roots.
+ private String current;
private String userName;
+ private char separator;
+
private boolean caseInsensitive = false;
/**
* Constructor - internal do not use directly, use {@link NativeFileSystemFactory} instead
*/
- protected NativeFileSystemView(String userName) {
+ public NativeFileSystemView(String userName) {
this(userName, false);
}
@@ -59,28 +71,89 @@ public class NativeFileSystemView implements FileSystemView {
* Constructor - internal do not use directly, use {@link NativeFileSystemFactory} instead
*/
public NativeFileSystemView(String userName, boolean caseInsensitive) {
+ this(userName, getAllRoots(), System.getProperty("user.dir"), File.separatorChar, caseInsensitive);
+ }
+
+ /**
+ * Constructor - internal do not use directly, use {@link NativeFileSystemFactory} instead
+ */
+ public NativeFileSystemView(String userName, Map<String, String> roots, String current) {
+ this(userName, roots, current, File.separatorChar, false);
+ }
+
+ /**
+ * Constructor - internal do not use directly, use {@link NativeFileSystemFactory} instead
+ *
+ * @param userName the user name
+ * @param roots known root mapping, key is the virtual root name, value is the physical file
+ * @param current the virtual current dir
+ */
+ public NativeFileSystemView(String userName, Map<String, String> roots, String current, char separator, boolean caseInsensitive) {
if (userName == null) {
throw new IllegalArgumentException("user can not be null");
}
+ // Normalize roots
+ Map<String, String> verRoots = new LinkedHashMap<String, String>();
+ for (String r : roots.keySet()) {
+ String virtual = appendSlash(normalizeSeparateChar(r));
+ String physical = appendSlash(normalizeSeparateChar(roots.get(r)));
+ verRoots.put(virtual, physical);
+ }
+ // add last '/' if necessary
+ current = appendSlash(normalizeSeparateChar(current));
+ // Verify the current dir is relative to a known root
+ String root = null;
+ for (String r : verRoots.keySet()) {
+ if (current.startsWith(r)) {
+ root = r;
+ break;
+ }
+ }
+ if (root == null) {
+ throw new IllegalArgumentException("Current dir " + current + " does not start from a known root: " + new ArrayList<String>(verRoots.keySet()));
+ }
+ this.separator = separator;
this.caseInsensitive = caseInsensitive;
-
- currDir = getVirtualUserDir();
+ this.roots = verRoots;
+ this.current = current;
this.userName = userName;
+ LOG.debug("Native filesystem view created for user \"{}\" with current dir \"{}\"", userName, this.current);
+ }
- // add last '/' if necessary
- LOG.debug("Native filesystem view created for user \"{}\" with root \"{}\"", userName, currDir);
+ private String appendSlash(String path) {
+ return path.endsWith("/") ? path : path + "/";
+ }
+
+ private static Map<String, String> getAllRoots() {
+ Map<String, String> roots = new LinkedHashMap<String, String>();
+ if (isWindows) {
+ for (File file : File.listRoots()) {
+ if (file.exists()) {
+ String root = file.toString();
+ String name = root.substring(0, root.length() - 1);
+ roots.put(name, root);
+ }
+ }
+ } else {
+ roots.put("/", "/");
+ }
+ return roots;
}
public String getUserName() {
return userName;
}
+ public char getSeparator() {
+ return separator;
+ }
+
/**
* Get file object.
*/
public SshFile getFile(String file) {
- return getFile(currDir, file);
+ return getFile(current, file);
}
public SshFile getFile(SshFile baseDir, String file) {
@@ -88,35 +161,48 @@ public class NativeFileSystemView implements FileSystemView {
}
protected SshFile getFile(String dir, String file) {
+ dir = appendSlash(normalizeSeparateChar(dir));
+ file = normalizeSeparateChar(file);
+ // Compute root + non rooted absolute file
+ String root = null;
+ if (roots.size() > 1 && file.startsWith("/")) {
+ file = file.substring(1);
+ }
+ for (String r : roots.keySet()) {
+ if (!file.isEmpty() && r.equals(file + "/")) {
+ file += "/";
+ }
+ if (file.startsWith(r)) {
+ root = r;
+ file = "/" + file.substring(r.length());
+ break;
+ }
+ }
+ if (root == null) {
+ // file is relative to dir
+ file = dir + file;
+ for (String r : roots.keySet()) {
+ if (file.startsWith(r)) {
+ root = r;
+ file = "/" + file.substring(r.length());
+ break;
+ }
+ }
+ }
+ if (root == null) {
+ throw new IllegalStateException("Could not find root dir for file(" + dir + ", " + file + ")");
+ }
+ // Physical root
+ String physicalRoot = roots.get(root);
// get actual file object
- String physicalName = NativeSshFile.getPhysicalName(getPhysicalUserDir(),
- dir, file, caseInsensitive);
+ String physicalName = NativeSshFile.getPhysicalName(physicalRoot, "/", file, caseInsensitive);
File fileObj = new File(physicalName);
// strip the root directory and return
- String userFileName = physicalName.substring(getPhysicalUserDir().length() - 1);
+ String userFileName = root + physicalName.substring(physicalRoot.length());
return createNativeSshFile(userFileName, fileObj, userName);
}
- /**
- * Returns the physical user directory, for accessing the according files or directories.
- *
- * @return The physical user directory.
- */
- public String getPhysicalUserDir() {
- return "/";
- }
-
- /**
- * Returns the virtual user directory.
- * The will be shown in sftp client. It is relative to the physical user directory.
- *
- * @return The virtual user directory.
- */
- public String getVirtualUserDir() {
- return System.getProperty("user.dir");
- }
-
static boolean isJava7;
static boolean isWindows;
static {
@@ -139,11 +225,191 @@ public class NativeFileSystemView implements FileSystemView {
isWindows = win;
}
- public NativeSshFile createNativeSshFile(final String fileName2, final File fileObj, final String userName2) {
+ public NativeSshFile createNativeSshFile(String name, File file, String userName) {
+ name = deNormalizeSeparateChar(name);
if (isJava7 && !isWindows) {
- return new NativeSshFileNio(this, fileName2, fileObj, userName2);
+ return new NativeSshFileNio(this, name, file, userName);
} else {
- return new NativeSshFile(this, fileName2, fileObj, userName2);
+ return new NativeSshFile(this, name, file, userName);
}
}
+
+ /**
+ * Normalize separate character. Separate character should be '/' always.
+ */
+ public final String deNormalizeSeparateChar(final String pathName) {
+ return pathName.replace('/', separator);
+ }
+
+ public FileSystemView getNormalizedView() {
+ if (roots.size() == 1 && roots.containsKey("/") && separator == '/') {
+ return this;
+ }
+ return new NativeFileSystemView(userName, roots, current, '/', caseInsensitive) {
+ public SshFile getFile(String file) {
+ return getFile(reroot(current), file);
+ }
+
+ public SshFile getFile(SshFile baseDir, String file) {
+ return getFile(baseDir.getAbsolutePath(), file);
+ }
+
+ public FileSystemView getNormalizedView() {
+ return this;
+ }
+
+ protected String reroot(String file) {
+ file = appendSlash(file);
+ for (String r : roots.keySet()) {
+ if (file.startsWith(r)) {
+ return "/" + normalizeRoot(r) + file.substring(r.length());
+ }
+ }
+ throw new IllegalArgumentException();
+ }
+
+ protected SshFile getFile(String dir, String file) {
+ dir = appendSlash(normalizeSeparateChar(dir));
+ file = normalizeSeparateChar(file);
+ // Compute root + non rooted absolute file
+ if (!file.startsWith("/")) {
+ file = dir + file;
+ }
+ // get actual file object
+ String userFileName = NativeSshFile.getPhysicalName("/", "/", file, caseInsensitive);
+ if (userFileName.equals("/")) {
+ return new RootFile();
+ }
+ int idx = userFileName.indexOf("/", 1);
+ if (idx < 0) {
+ String root = userFileName + "/";
+ String physRoot = null;
+ for (String r : roots.keySet()) {
+ if (normalizeRoot(r).equals(root)) {
+ physRoot = roots.get(r);
+ break;
+ }
+ }
+ if (physRoot == null) {
+ throw new IllegalArgumentException("Unknown root " + userFileName);
+ }
+ File fileObj = new File(physRoot);
+ userFileName = normalizeSeparateChar(userFileName);
+ return createNativeSshFile(userFileName, fileObj, userName);
+ } else {
+ String root = userFileName.substring(1, idx) + "/";
+ String physRoot = null;
+ for (String r : roots.keySet()) {
+ if (normalizeRoot(r).equals(root)) {
+ physRoot = roots.get(r);
+ break;
+ }
+ }
+ if (physRoot == null) {
+ throw new IllegalArgumentException("Unknown root " + userFileName);
+ }
+ File fileObj = new File(physRoot + userFileName.substring(idx + 1));
+ userFileName = normalizeSeparateChar(userFileName);
+ return createNativeSshFile(userFileName, fileObj, userName);
+ }
+ }
+ };
+ }
+
+ protected static String normalizeRoot(String root) {
+ return root.replace(":", "");
+ }
+
+ class RootFile implements SshFile {
+ public String getAbsolutePath() {
+ return "/";
+ }
+ public String getName() {
+ return "/";
+ }
+ public Map<Attribute, Object> getAttributes(boolean followLinks) throws IOException {
+ return null;
+ }
+ public void setAttributes(Map<Attribute, Object> attributes) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+ public Object getAttribute(Attribute attribute, boolean followLinks) throws IOException {
+ return null;
+ }
+ public void setAttribute(Attribute attribute, Object value) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+ public String readSymbolicLink() throws IOException {
+ return null;
+ }
+ public void createSymbolicLink(SshFile destination) throws IOException {
+ }
+ public String getOwner() {
+ return null;
+ }
+ public boolean isDirectory() {
+ return true;
+ }
+ public boolean isFile() {
+ return false;
+ }
+ public boolean doesExist() {
+ return true;
+ }
+ public boolean isReadable() {
+ return true;
+ }
+ public boolean isWritable() {
+ return false;
+ }
+ public boolean isExecutable() {
+ return false;
+ }
+ public boolean isRemovable() {
+ return false;
+ }
+ public SshFile getParentFile() {
+ return null;
+ }
+ public long getLastModified() {
+ return 0;
+ }
+ public boolean setLastModified(long time) {
+ return false;
+ }
+ public long getSize() {
+ return 0;
+ }
+ public boolean mkdir() {
+ return false;
+ }
+ public boolean delete() {
+ return false;
+ }
+ public boolean create() throws IOException {
+ return false;
+ }
+ public void truncate() throws IOException {
+ }
+ public boolean move(SshFile destination) {
+ return false;
+ }
+ public List<SshFile> listSshFiles() {
+ List<SshFile> list = new ArrayList<SshFile>();
+ for (String root : roots.keySet()) {
+ String display = normalizeRoot(root);
+ display = "/" + display.substring(display.length() - 1);
+ list.add(createNativeSshFile(display, new File(roots.get(root)), userName));
+ }
+ return list;
+ }
+ public OutputStream createOutputStream(long offset) throws IOException {
+ return null;
+ }
+ public InputStream createInputStream(long offset) throws IOException {
+ return null;
+ }
+ public void handleClose() throws IOException {
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/61ebb206/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFile.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFile.java b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFile.java
index ee2626c..0ece66c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFile.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFile.java
@@ -52,8 +52,7 @@ public class NativeSshFile implements SshFile {
protected static final Logger LOG = LoggerFactory.getLogger(NativeSshFile.class);
// the file name with respect to the user root.
- // The path separator character will be '/' and
- // it will always begin with '/'.
+ // The path separator character will be '/'.
protected String fileName;
protected File file;
@@ -78,8 +77,6 @@ public class NativeSshFile implements SshFile {
if (fileName.length() == 0) {
throw new IllegalArgumentException("fileName can not be empty");
- } else if (fileName.charAt(0) != '/') {
- throw new IllegalArgumentException("fileName must be an absolute path");
}
this.fileName = fileName;
@@ -96,10 +93,12 @@ public class NativeSshFile implements SshFile {
*/
public String getAbsolutePath() {
+ char separator = nativeFileSystemView.getSeparator();
+
// strip the last '/' if necessary
String fullName = fileName;
int filelen = fullName.length();
- if ((filelen != 1) && (fullName.charAt(filelen - 1) == '/')) {
+ if (fileName.indexOf(separator) != filelen - 1 && (fullName.charAt(filelen - 1) == separator)) {
fullName = fullName.substring(0, filelen - 1);
}
@@ -111,20 +110,22 @@ public class NativeSshFile implements SshFile {
*/
public String getName() {
+ char separator = nativeFileSystemView.getSeparator();
+
// root - the short name will be '/'
- if (fileName.equals("/")) {
- return "/";
+ if (fileName.indexOf(separator) == fileName.length() - 1) {
+ return fileName;
}
// strip the last '/'
String shortName = fileName;
int filelen = fileName.length();
- if (shortName.charAt(filelen - 1) == '/') {
+ if (shortName.charAt(filelen - 1) == separator) {
shortName = shortName.substring(0, filelen - 1);
}
// return from the last '/'
- int slashIndex = shortName.lastIndexOf('/');
+ int slashIndex = shortName.lastIndexOf(separator);
if (slashIndex != -1) {
shortName = shortName.substring(slashIndex + 1);
}
@@ -234,8 +235,10 @@ public class NativeSshFile implements SshFile {
*/
public boolean isRemovable() {
+ char separator = nativeFileSystemView.getSeparator();
+
// root cannot be deleted
- if ("/".equals(fileName)) {
+ if (fileName.indexOf(separator) == fileName.length() - 1) {
return false;
}
@@ -251,12 +254,16 @@ public class NativeSshFile implements SshFile {
// }
// In order to maintain consistency, when possible we delete the last '/' character in the String
- int indexOfSlash = fullName.lastIndexOf('/');
+ int indexOfSlash = fullName.lastIndexOf(separator);
String parentFullName;
if (indexOfSlash == 0) {
parentFullName = "/";
} else {
- parentFullName = fullName.substring(0, indexOfSlash);
+ if (fullName.indexOf(separator) == indexOfSlash) {
+ parentFullName = fullName.substring(0, indexOfSlash + 1);
+ } else {
+ parentFullName = fullName.substring(0, indexOfSlash);
+ }
}
// we check if the parent FileObject is writable.
@@ -266,12 +273,19 @@ public class NativeSshFile implements SshFile {
}
public SshFile getParentFile() {
- int indexOfSlash = getAbsolutePath().lastIndexOf('/');
+ char separator = nativeFileSystemView.getSeparator();
+
+ String path = getAbsolutePath();
+ int indexOfSlash = path.lastIndexOf(separator);
String parentFullName;
if (indexOfSlash == 0) {
parentFullName = "/";
} else {
- parentFullName = getAbsolutePath().substring(0, indexOfSlash);
+ if (path.indexOf(separator) == indexOfSlash) {
+ parentFullName = path.substring(0, indexOfSlash + 1);
+ } else {
+ parentFullName = path.substring(0, indexOfSlash);
+ }
}
// we check if the parent FileObject is writable.
@@ -363,10 +377,12 @@ public class NativeSshFile implements SshFile {
}
});
+ char separator = nativeFileSystemView.getSeparator();
+
// get the virtual name of the base directory
String virtualFileStr = getAbsolutePath();
- if (virtualFileStr.charAt(virtualFileStr.length() - 1) != '/') {
- virtualFileStr += '/';
+ if (virtualFileStr.charAt(virtualFileStr.length() - 1) != separator) {
+ virtualFileStr += separator;
}
// now return all the files under the directory
@@ -448,20 +464,10 @@ public class NativeSshFile implements SshFile {
* Normalize separate character. Separate character should be '/' always.
*/
public final static String normalizeSeparateChar(final String pathName) {
- String normalizedPathName = pathName.replace(File.separatorChar, '/');
- normalizedPathName = normalizedPathName.replace('\\', '/');
+ String normalizedPathName = pathName.replace('\\', '/');
return normalizedPathName;
}
- public final static String normalizePath(final String pathName) {
- // Support windows drive as
- if (pathName.matches("[A-Z]:\\\\.*")) {
- return "/" + normalizeSeparateChar(pathName);
- } else {
- return normalizeSeparateChar(pathName);
- }
- }
-
/**
* Get the physical canonical file name. It works like
* File.getCanonicalPath().
@@ -477,11 +483,6 @@ public class NativeSshFile implements SshFile {
* will never be null.
*/
public final static String getPhysicalName(final String rootDir,
- final String currDir, final String fileName) {
- return getPhysicalName(rootDir, currDir, fileName, false);
- }
-
- public final static String getPhysicalName(final String rootDir,
final String currDir, final String fileName,
final boolean caseInsensitive) {
@@ -491,7 +492,7 @@ public class NativeSshFile implements SshFile {
normalizedRootDir += '/';
}
- String normalizedFileName = normalizePath(fileName);
+ String normalizedFileName = normalizeSeparateChar(fileName);
String resArg;
String normalizedCurrDir = currDir;
if (normalizedFileName.charAt(0) != '/') {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/61ebb206/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemFactory.java
index 4c99b52..052d864 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemFactory.java
@@ -18,12 +18,14 @@
*/
package org.apache.sshd.common.file.virtualfs;
+import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.sshd.common.Session;
import org.apache.sshd.common.file.FileSystemFactory;
import org.apache.sshd.common.file.FileSystemView;
+import org.apache.sshd.common.file.nativefs.NativeFileSystemView;
/**
* SSHd file system factory to reduce the visibility to a physical folder.
@@ -68,8 +70,10 @@ public class VirtualFileSystemFactory implements FileSystemFactory {
}
public FileSystemView createFileSystemView(Session session) {
- return new VirtualFileSystemView(session.getUsername(),
- computeRootDir(session.getUsername()));
+ String dir = computeRootDir(session.getUsername());
+ Map<String, String> roots = new HashMap<String, String>();
+ roots.put("/", dir);
+ return new NativeFileSystemView(session.getUsername(), roots, "/");
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/61ebb206/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemView.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemView.java b/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemView.java
deleted file mode 100644
index 0c96cf8..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemView.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 org.apache.sshd.common.file.virtualfs;
-
-import java.io.File;
-
-import org.apache.sshd.common.file.SshFile;
-import org.apache.sshd.common.file.nativefs.NativeFileSystemView;
-import org.apache.sshd.common.file.nativefs.NativeSshFile;
-
-/**
- * Virtual file system view reduced to a physical folder
- */
-public class VirtualFileSystemView extends NativeFileSystemView {
-
- private String location;
-
- public VirtualFileSystemView(String username, String location) {
- super(username);
- if (location.endsWith("/")) {
- location = location.substring(0, location.length() - 1);
- }
- this.location = location;
- }
-
- @Override
- public String getVirtualUserDir() {
- return "/";
- }
-
- @Override
- public String getPhysicalUserDir() {
- return location;
- }
-
- @Override
- protected SshFile getFile(String dir, String file) {
- // get actual file object
- String location = getPhysicalUserDir();
- String physicalName = NativeSshFile.getPhysicalName(location, dir, file, false);
- File fileObj = new File(physicalName);
- // strip the root directory and return
- String karafFileName = physicalName.substring(location.length());
- return createNativeSshFile(karafFileName, fileObj, getUserName());
- }
-
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/61ebb206/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java b/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java
index df56bd4..bb244b2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java
@@ -1094,7 +1094,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
}
private SshFile resolveFile(String path) {
- return this.root.getFile(path);
+ return this.root.getNormalizedView().getFile(path);
}
private final static String[] MONTHS = { "Jan", "Feb", "Mar", "Apr", "May",
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/61ebb206/sshd-core/src/test/java/org/apache/sshd/common/file/nativefs/NativeFileSystemViewTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/file/nativefs/NativeFileSystemViewTest.java b/sshd-core/src/test/java/org/apache/sshd/common/file/nativefs/NativeFileSystemViewTest.java
new file mode 100644
index 0000000..a77d950
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/common/file/nativefs/NativeFileSystemViewTest.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.sshd.common.file.nativefs;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sshd.common.file.FileSystemView;
+import org.apache.sshd.common.file.SshFile;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+public class NativeFileSystemViewTest {
+
+ @Test
+ public void testResolveWithVirtualRoots() throws Exception {
+
+ Map<String, String> roots = new HashMap<String, String>();
+ roots.put("A:", "/fs/rootA");
+ roots.put("Z:", "/fs/rootZ");
+ String current = "Z:/git";
+ NativeFileSystemView view = new NativeFileSystemView("user", roots, current, '/', false);
+
+ assertEquals("Z:/git/foo/bar", view.getFile("foo/bar").getAbsolutePath());
+ assertEquals("Z:/foo/bar", view.getFile("../foo/bar").getAbsolutePath());
+ assertEquals("A:/temp", view.getFile("A:/./a/../temp").getAbsolutePath());
+ assertEquals("A:/temp", view.getFile("A:/../../temp").getAbsolutePath());
+
+ FileSystemView normView = view.getNormalizedView();
+
+ assertEquals("/Z/git/foo/bar", normView.getFile("foo/bar").getAbsolutePath());
+ assertEquals("/Z/foo/bar", normView.getFile("../foo/bar").getAbsolutePath());
+ assertEquals("/A/temp", normView.getFile("/A/./a/../temp").getAbsolutePath());
+ assertEquals("/Z/temp", normView.getFile("/A/../Z/temp").getAbsolutePath());
+ }
+
+ @Test
+ public void testResolveWithVirtualRootsWithBackslash() throws Exception {
+
+ Map<String, String> roots = new HashMap<String, String>();
+ roots.put("A:", "/fs/rootA");
+ roots.put("Z:", "/fs/rootZ");
+ String current = "Z:/git";
+ NativeFileSystemView view = new NativeFileSystemView("user", roots, current, '\\', false);
+
+ assertEquals("Z:\\git\\foo\\bar", view.getFile("/Z:/git/foo/bar").getAbsolutePath());
+ assertEquals("Z:\\git\\foo\\bar", view.getFile("foo/bar").getAbsolutePath());
+ assertEquals("Z:\\git\\foo", view.getFile("foo/bar").getParentFile().getAbsolutePath());
+ assertEquals("Z:\\git", view.getFile("foo/bar").getParentFile().getParentFile().getAbsolutePath());
+ assertEquals("Z:\\", view.getFile("foo/bar").getParentFile().getParentFile().getParentFile().getAbsolutePath());
+ assertFalse(view.getFile("foo/bar").getParentFile().getParentFile().getParentFile().isRemovable());
+ assertEquals("Z:\\foo\\bar", view.getFile("../foo/bar").getAbsolutePath());
+ assertEquals("A:\\temp", view.getFile("A:/./a/../temp").getAbsolutePath());
+ assertEquals("A:\\temp", view.getFile("A:/../../temp").getAbsolutePath());
+
+ FileSystemView normView = view.getNormalizedView();
+
+ assertEquals("/Z/git/foo/bar", normView.getFile("foo/bar").getAbsolutePath());
+ assertEquals("/Z/git/foo", normView.getFile("foo/bar").getParentFile().getAbsolutePath());
+ assertEquals("/Z/foo/bar", normView.getFile("../foo/bar").getAbsolutePath());
+ assertEquals("/A/temp", normView.getFile("/A/./a/../temp").getAbsolutePath());
+ assertEquals("/Z/temp", normView.getFile("/A/../Z/temp").getAbsolutePath());
+ }
+
+ @Test
+ public void testResolveWithPhysicalRoots() throws Exception {
+
+ Map<String, String> roots = new HashMap<String, String>();
+ roots.put("V:", "A:/bar");
+ roots.put("X:", "B:");
+ String current = "X:/git";
+ NativeFileSystemView view = new NativeFileSystemView("user", roots, current, '/', false);
+
+ assertEquals("X:/git/foo/bar", view.getFile("foo/bar").getAbsolutePath());
+
+ assertEquals("X:/foo/bar", view.getFile("X:/foo/bar").getAbsolutePath());
+ assertEquals(new File("B:/foo/bar").toString(), ((NativeSshFile) view.getFile("X:/foo/bar")).getNativeFile().toString());
+
+ assertEquals("X:/foo/bar", view.getFile("../foo/bar").getAbsolutePath());
+ assertEquals(new File("B:/foo/bar").toString(), ((NativeSshFile) view.getFile("../foo/bar")).getNativeFile().toString());
+
+ assertEquals("V:/temp", view.getFile("V:/./a/../temp").getAbsolutePath());
+
+ assertEquals("V:/temp", view.getFile("V:/../../temp").getAbsolutePath());
+ assertEquals(new File("A:/bar/temp").toString(), ((NativeSshFile) view.getFile("V:/../../temp")).getNativeFile().toString());
+
+ assertEquals("X:/", view.getFile("..").getAbsolutePath());
+
+ SshFile cur = view.getFile(".");
+ assertEquals("X:/git", cur.getAbsolutePath());
+ cur = view.getFile(cur, "..");
+ assertEquals("X:/", cur.getAbsolutePath());
+
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/61ebb206/sshd-core/src/test/java/org/apache/sshd/common/file/nativefs/NativeSshFileTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/file/nativefs/NativeSshFileTest.java b/sshd-core/src/test/java/org/apache/sshd/common/file/nativefs/NativeSshFileTest.java
index 0d6f77c..7ff2787 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/file/nativefs/NativeSshFileTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/file/nativefs/NativeSshFileTest.java
@@ -27,10 +27,12 @@ public class NativeSshFileTest extends BaseTest {
@Test
public void testResolve() {
- assertEquals("/Z:/git/mina-sshd/sshd-core/target/scp/remote/out.txt",
- NativeSshFile.getPhysicalName("/", "Z:\\git\\mina-sshd\\sshd-core", "Z:\\git\\mina-sshd\\sshd-core\\target\\scp\\remote\\out.txt", false));
- assertEquals("/Z:/git/mina-sshd/sshd-core/target/scp/remote/out.txt",
- NativeSshFile.getPhysicalName("/", "Z:\\git\\mina-sshd\\sshd-core", "/Z:/git/mina-sshd/sshd-core/target/scp/remote/out.txt", false));
+ assertEquals("Z:/git/mina-sshd/sshd-core/target/scp/remote/out.txt",
+ NativeSshFile.getPhysicalName("Z:\\git/", "Z:\\git\\mina-sshd\\sshd-core", "\\mina-sshd\\sshd-core\\target\\scp\\remote\\out.txt", false));
+ assertEquals("Z:/git/mina-sshd/sshd-core/target/scp/remote/out.txt",
+ NativeSshFile.getPhysicalName("Z:/", "Z:\\git\\mina-sshd\\sshd-core", "\\git\\mina-sshd\\sshd-core\\target\\scp\\remote\\out.txt", false));
+ assertEquals("Z:/git/mina-sshd/sshd-core/target/scp/remote/out.txt",
+ NativeSshFile.getPhysicalName("Z:/", "Z:\\git\\mina-sshd\\sshd-core", "/git/mina-sshd/sshd-core/target/scp/remote/out.txt", false));
assertEquals("/bar", NativeSshFile.getPhysicalName("/", "/foo", "/bar", false));
assertEquals("/bar", NativeSshFile.getPhysicalName("/", "/", "/bar", false));
[2/2] git commit: Improve tests on slow machines and on windows
Posted by gn...@apache.org.
Improve tests on slow machines and on windows
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/441bdb91
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/441bdb91
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/441bdb91
Branch: refs/heads/master
Commit: 441bdb91915ede93670487c21bf80ee7e9571272
Parents: 61ebb20
Author: Guillaume Nodet <gn...@apache.org>
Authored: Tue Apr 8 13:03:37 2014 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Tue Apr 8 13:03:37 2014 +0200
----------------------------------------------------------------------
sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java | 6 +++---
sshd-core/src/test/java/org/apache/sshd/ServerTest.java | 4 ++--
sshd-core/src/test/java/org/apache/sshd/SftpTest.java | 5 +++++
.../src/test/java/org/apache/sshd/SinglePublicKeyAuthTest.java | 1 +
4 files changed, 11 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/441bdb91/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java b/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
index a652d42..3a5c496 100644
--- a/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
@@ -45,9 +45,9 @@ public class KeepAliveTest extends BaseTest {
private SshServer sshd;
private int port;
- private int heartbeat = 1000;
- private int timeout = 2000;
- private int wait = 4000;
+ private int heartbeat = 2000;
+ private int timeout = 4000;
+ private int wait = 8000;
@Before
public void setUp() throws Exception {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/441bdb91/sshd-core/src/test/java/org/apache/sshd/ServerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/ServerTest.java b/sshd-core/src/test/java/org/apache/sshd/ServerTest.java
index 4f4e496..e79fe23 100644
--- a/sshd-core/src/test/java/org/apache/sshd/ServerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/ServerTest.java
@@ -132,12 +132,12 @@ public class ServerTest extends BaseTest {
@Test
public void testAuthenticationTimeout() throws Exception {
- sshd.getProperties().put(SshServer.AUTH_TIMEOUT, "1000");
+ sshd.getProperties().put(SshServer.AUTH_TIMEOUT, "5000");
client = SshClient.setUpDefaultClient();
client.start();
ClientSession s = client.connect("localhost", port).await().getSession();
- int res = s.waitFor(ClientSession.CLOSED, 5000);
+ int res = s.waitFor(ClientSession.CLOSED, 10000);
assertEquals("Session should be closed", ClientSession.CLOSED | ClientSession.WAIT_AUTH, res);
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/441bdb91/sshd-core/src/test/java/org/apache/sshd/SftpTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/SftpTest.java b/sshd-core/src/test/java/org/apache/sshd/SftpTest.java
index 256fa85..7d3a95e 100644
--- a/sshd-core/src/test/java/org/apache/sshd/SftpTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/SftpTest.java
@@ -237,6 +237,11 @@ public class SftpTest extends BaseTest {
@Test
public void testCreateSymbolicLink() throws Exception {
+ // Do not execute on windows as the file system does not support symlinks
+ if (System.getProperty("os.name").toLowerCase().contains("win")) {
+ return;
+ }
+
File root = new File("target/sftp");
String unixPath = "target/sftp/out.txt";
String linkUnixPath = "target/sftp/link.txt";
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/441bdb91/sshd-core/src/test/java/org/apache/sshd/SinglePublicKeyAuthTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/SinglePublicKeyAuthTest.java b/sshd-core/src/test/java/org/apache/sshd/SinglePublicKeyAuthTest.java
index 29efe15..43fb8bf 100644
--- a/sshd-core/src/test/java/org/apache/sshd/SinglePublicKeyAuthTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/SinglePublicKeyAuthTest.java
@@ -107,6 +107,7 @@ public class SinglePublicKeyAuthTest extends BaseTest {
assertEquals(1, count.get(KeyUtils.getFingerPrint(pairRsaBad.getPublic())).get());
assertEquals(1, count.get(KeyUtils.getFingerPrint(pairRsa.getPublic())).get());
client.close(false).await();
+ Thread.sleep(100);
assertTrue(auth.getCache().isEmpty());
}