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 2015/02/28 14:32:52 UTC

[2/3] mina-sshd git commit: [SSHD-421] Add smart handling of UserPrincipalLookupService lookup failures

[SSHD-421] Add smart handling of UserPrincipalLookupService lookup failures

Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/c062c6f6
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/c062c6f6
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/c062c6f6

Branch: refs/heads/master
Commit: c062c6f6eb52be72b136dcb46e0c2eeb7d3983d1
Parents: c0a58db
Author: Guillaume Nodet <gn...@apache.org>
Authored: Sat Feb 28 14:20:05 2015 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Sat Feb 28 14:20:05 2015 +0100

----------------------------------------------------------------------
 .../apache/sshd/server/sftp/SftpSubsystem.java  | 52 ++++++++++---
 .../org/apache/sshd/SftpFileSystemTest.java     | 78 ++++++++++++++------
 2 files changed, 99 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c062c6f6/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 b78315c..7f7375c 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
@@ -45,6 +45,7 @@ import java.nio.file.OpenOption;
 import java.nio.file.Path;
 import java.nio.file.StandardCopyOption;
 import java.nio.file.StandardOpenOption;
+import java.nio.file.attribute.AclEntry;
 import java.nio.file.attribute.AclEntryFlag;
 import java.nio.file.attribute.AclEntryPermission;
 import java.nio.file.attribute.AclEntryType;
@@ -55,7 +56,8 @@ import java.nio.file.attribute.PosixFilePermission;
 import java.nio.file.attribute.PosixFilePermissions;
 import java.nio.file.attribute.UserPrincipal;
 import java.nio.file.attribute.UserPrincipalLookupService;
-import java.nio.file.attribute.AclEntry;
+import java.nio.file.attribute.UserPrincipalNotFoundException;
+import java.security.Principal;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collection;
@@ -398,6 +400,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         }
 
         public void close() throws IOException {
+            // ignored
         }
     }
 
@@ -1741,8 +1744,8 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
             String view = null;
             Object value = attributes.get(attribute);
             switch (attribute) {
-            case "size":             {
-                long newSize = (Long) value;
+            case "size": {
+                long newSize = ((Number) value).longValue();
                 try (FileChannel channel = FileChannel.open(file, StandardOpenOption.WRITE)) {
                     channel.truncate(newSize);
                 }
@@ -1757,7 +1760,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
             case "lastModifiedTime": view = "basic"; break;
             case "lastAccessTime":   view = "basic"; break;
             }
-            if (view != null) {
+            if (view != null && value != null) {
                 try {
                     Files.setAttribute(file, view + ":" + attribute, value, LinkOption.NOFOLLOW_LINKS);
                 } catch (UnsupportedOperationException e) {
@@ -1789,15 +1792,46 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         }
     }
 
-
     private GroupPrincipal toGroup(Path file, GroupPrincipal name) throws IOException {
-        UserPrincipalLookupService lookupService = file.getFileSystem().getUserPrincipalLookupService();
-        return lookupService.lookupPrincipalByGroupName(name.toString());
+        String groupName = name.toString();
+        FileSystem fileSystem = file.getFileSystem();
+        UserPrincipalLookupService lookupService = fileSystem.getUserPrincipalLookupService();
+        try {
+            return lookupService.lookupPrincipalByGroupName(groupName);
+        } catch (UserPrincipalNotFoundException e) {
+            handleUserPrincipalLookupServiceException(GroupPrincipal.class, groupName, e);
+            return null;
+        }
     }
 
     private UserPrincipal toUser(Path file, UserPrincipal name) throws IOException {
-        UserPrincipalLookupService lookupService = file.getFileSystem().getUserPrincipalLookupService();
-        return lookupService.lookupPrincipalByName(name.toString());
+        String username = name.toString();
+        FileSystem fileSystem = file.getFileSystem();
+        UserPrincipalLookupService lookupService = fileSystem.getUserPrincipalLookupService();
+        try {
+            return lookupService.lookupPrincipalByName(username);
+        } catch (UserPrincipalNotFoundException e) {
+            handleUserPrincipalLookupServiceException(UserPrincipal.class, username, e);
+            return null;
+        }
+    }
+
+    private void handleUserPrincipalLookupServiceException(Class<? extends Principal> principalType, String name, IOException e) throws IOException {
+        /* According to Javadoc:
+         * 
+         *      "Where an implementation does not support any notion of group
+         *      or user then this method always throws UserPrincipalNotFoundException."
+         */
+        switch (unsupportedAttributePolicy) {
+        case Ignore:
+            break;
+        case Warn:
+            log.warn("handleUserPrincipalLookupServiceException(" + principalType.getSimpleName() + "[" + name + "])"
+                   + " failed (" + e.getClass().getSimpleName() + "): " + e.getMessage());
+            break;
+        case ThrowException:
+            throw e;
+        }
     }
 
     private Set<PosixFilePermission> permissionsToAttributes(int perms) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c062c6f6/sshd-core/src/test/java/org/apache/sshd/SftpFileSystemTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/SftpFileSystemTest.java b/sshd-core/src/test/java/org/apache/sshd/SftpFileSystemTest.java
index 8ad1e0b..f550045 100644
--- a/sshd-core/src/test/java/org/apache/sshd/SftpFileSystemTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/SftpFileSystemTest.java
@@ -35,11 +35,15 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
 import java.nio.file.attribute.FileTime;
+import java.nio.file.attribute.GroupPrincipal;
 import java.nio.file.attribute.PosixFilePermissions;
+import java.nio.file.attribute.UserPrincipalLookupService;
+import java.nio.file.attribute.UserPrincipalNotFoundException;
 import java.util.Arrays;
 import java.util.Map;
 
 import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.util.OsUtils;
 import org.apache.sshd.server.Command;
 import org.apache.sshd.server.command.ScpCommandFactory;
 import org.apache.sshd.server.sftp.SftpSubsystem;
@@ -84,12 +88,24 @@ public class SftpFileSystemTest extends BaseTest {
         String uri = "sftp://x:x@localhost:" + port + "/";
 
         FileSystem fs = FileSystems.newFileSystem(URI.create(uri), null);
-        Path root = fs.getRootDirectories().iterator().next();
-        try (DirectoryStream<Path> ds = Files.newDirectoryStream(root)) {
-            for (Path child : ds) {
-                System.out.println(child);
+        Iterable<Path> rootDirs = fs.getRootDirectories();
+        for (Path root : rootDirs) {
+            try (DirectoryStream<Path> ds = Files.newDirectoryStream(root)) {
+                for (Path child : ds) {
+                    System.out.println(child);
+                }
+            } catch(IOException | RuntimeException e) {
+                // TODO on Windows one might get share problems for *.sys files
+                // e.g. "C:\hiberfil.sys: The process cannot access the file because it is being used by another process"
+                // for now, Windows is less of a target so we are lenient with it
+                if (OsUtils.isWin32()) {
+                    System.err.println(e.getClass().getSimpleName() + " while accessing children of root=" + root + ": " + e.getMessage());
+                } else {
+                    throw e;
+                }
             }
         }
+
         Path current = fs.getPath(".").toRealPath();
         Path file = fs.getPath("target/sftp/client/test.txt");
         Files.createDirectories(file.getParent());
@@ -124,11 +140,14 @@ public class SftpFileSystemTest extends BaseTest {
 //        assertTrue(Files.isSymbolicLink(link));
 //        assertEquals("test.txt", Files.readSymbolicLink(link).toString());
 
-        Path link = fs.getPath("target/sftp/client/test2.txt");
-        Files.createSymbolicLink(link, link.getParent().relativize(file));
-        assertTrue(Files.isSymbolicLink(link));
-        assertEquals("test.txt", Files.readSymbolicLink(link).toString());
-        Files.delete(link);
+        // TODO there are many issues with Windows and symbolic links - for now they are of a lesser interest
+        if (OsUtils.isUNIX()) {
+            Path link = fs.getPath("target/sftp/client/test2.txt");
+            Files.createSymbolicLink(link, link.getParent().relativize(file));
+            assertTrue("Not a symbolic link: " + link, Files.isSymbolicLink(link));
+            assertEquals("test.txt", Files.readSymbolicLink(link).toString());
+            Files.delete(link);
+        }
 
         attrs = Files.readAttributes(file, "*", LinkOption.NOFOLLOW_LINKS);
         System.out.println(attrs);
@@ -161,19 +180,34 @@ public class SftpFileSystemTest extends BaseTest {
     public void testAttributes() throws Exception {
         Utils.deleteRecursive(new File("target/sftp"));
 
-        FileSystem fs = FileSystems.newFileSystem(URI.create("sftp://x:x@localhost:" + port + "/"), null);
-        Path file = fs.getPath("target/sftp/client/test.txt");
-        Files.createDirectories(file.getParent());
-        Files.write(file, "Hello world\n".getBytes());
-
-        Map<String, Object> attrs = Files.readAttributes(file, "posix:*");
-
-        Files.setAttribute(file, "basic:size", 2l);
-        Files.setAttribute(file, "posix:permissions", PosixFilePermissions.fromString("rwxr-----"));
-        Files.setAttribute(file, "basic:lastModifiedTime", FileTime.fromMillis(100000l));
-        Files.setAttribute(file, "posix:group", file.getFileSystem().getUserPrincipalLookupService().lookupPrincipalByGroupName("everyone"));
-
-        fs.close();
+        try (FileSystem fs = FileSystems.newFileSystem(URI.create("sftp://x:x@localhost:" + port + "/"), null)) {
+            Path file = fs.getPath("target/sftp/client/test.txt");
+            Files.createDirectories(file.getParent());
+            Files.write(file, "Hello world\n".getBytes());
+    
+            Map<String, Object> attrs = Files.readAttributes(file, "posix:*");
+    
+            Files.setAttribute(file, "basic:size", 2l);
+            Files.setAttribute(file, "posix:permissions", PosixFilePermissions.fromString("rwxr-----"));
+            Files.setAttribute(file, "basic:lastModifiedTime", FileTime.fromMillis(100000l));
+
+            FileSystem fileSystem = file.getFileSystem();
+            try {
+                UserPrincipalLookupService userLookupService = fileSystem.getUserPrincipalLookupService();
+                GroupPrincipal group = userLookupService.lookupPrincipalByGroupName("everyone");
+                Files.setAttribute(file, "posix:group", group);
+            } catch (UserPrincipalNotFoundException e) {
+                // Also, according to the Javadoc:
+                //      "Where an implementation does not support any notion of
+                //       group then this method always throws UserPrincipalNotFoundException."
+                // Therefore we are lenient with this exception for Windows
+                if (OsUtils.isWin32()) {
+                    System.err.println(e.getClass().getSimpleName() + ": " + e.getMessage());
+                } else {
+                    throw e;
+                }
+            }
+        }
     }
 
     @Test