Make sure nio2 is disabled on jdk < 7 while still supporting various commands 
correctly

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

Branch: refs/heads/master
Commit: d7c21f79990e17fcafa7df97c5eda7122189ecce
Parents: ca990bd
Author: Guillaume Nodet <[email protected]>
Authored: Mon Jul 22 20:25:15 2013 +0200
Committer: Guillaume Nodet <[email protected]>
Committed: Mon Jul 22 20:25:15 2013 +0200

----------------------------------------------------------------------
 .../file/nativefs/NativeFileSystemView.java     |  18 ++-
 .../common/file/nativefs/NativeSshFile.java     | 127 ++++------------
 .../common/file/nativefs/NativeSshFileNio.java  | 149 +++++++++++++++++++
 .../apache/sshd/server/sftp/SftpSubsystem.java  |  51 +++++--
 4 files changed, 233 insertions(+), 112 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d7c21f79/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 dbf07bc..a39c4c8 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
@@ -113,7 +113,23 @@ public class NativeFileSystemView implements 
FileSystemView {
                return System.getProperty("user.dir");
        }
 
+    static boolean isJava7;
+    static {
+        boolean j7 = false;
+        try {
+            
ClassLoader.getSystemClassLoader().loadClass("java.nio.file.Files");
+            j7 = true;
+        } catch (Throwable t) {
+            // Ignore
+        }
+        isJava7 = j7;
+    }
+
     public NativeSshFile createNativeSshFile(final String fileName2, final 
File fileObj, final String userName2) {
-               return new NativeSshFile(this, fileName2, fileObj, userName2);
+        if (isJava7) {
+            return new NativeSshFileNio(this, fileName2, fileObj, userName2);
+        } else {
+                   return new NativeSshFile(this, fileName2, fileObj, 
userName2);
+        }
        }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d7c21f79/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 2366706..53d573b 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
@@ -27,23 +27,13 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.RandomAccessFile;
 import java.lang.reflect.Method;
-import java.nio.file.Files;
-import java.nio.file.LinkOption;
-import java.nio.file.Path;
-import java.nio.file.attribute.FileTime;
-import java.nio.file.attribute.GroupPrincipal;
-import java.nio.file.attribute.PosixFilePermission;
-import java.nio.file.attribute.UserPrincipal;
-import java.nio.file.attribute.UserPrincipalLookupService;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.EnumSet;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.StringTokenizer;
 
 import org.apache.sshd.common.file.SshFile;
@@ -59,18 +49,18 @@ import org.slf4j.LoggerFactory;
  */
 public class NativeSshFile implements SshFile {
 
-    private static final Logger LOG = 
LoggerFactory.getLogger(NativeSshFile.class);
+    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 '/'.
-    private String fileName;
+    protected String fileName;
 
-    private File file;
+    protected File file;
 
-    private String userName;
+    protected String userName;
 
-       private final NativeFileSystemView nativeFileSystemView;
+    protected final NativeFileSystemView nativeFileSystemView;
 
     /**
      * Constructor, internal do not use directly.
@@ -606,90 +596,39 @@ public class NativeSshFile implements SshFile {
     }
 
     public Map<Attribute, Object> getAttributes(boolean followLinks) throws 
IOException {
-        Map<String, Object> a = Files.readAttributes(
-                file.toPath(),
-                
"unix:size,uid,owner,gid,group,isDirectory,isRegularFile,isSymbolicLink,permissions,creationTime,lastModifiedTime,lastAccessTime",
-                followLinks ? new LinkOption[0] : new LinkOption[] { 
LinkOption.NOFOLLOW_LINKS });
         Map<Attribute, Object> map = new HashMap<Attribute, Object>();
-        map.put(Attribute.Size, a.get("size"));
-        map.put(Attribute.Uid, a.get("uid"));
-        map.put(Attribute.Owner, ((UserPrincipal) a.get("owner")).getName());
-        map.put(Attribute.Gid, a.get("gid"));
-        map.put(Attribute.Group, ((GroupPrincipal) a.get("group")).getName());
-        map.put(Attribute.IsDirectory, a.get("isDirectory"));
-        map.put(Attribute.IsRegularFile, a.get("isRegularFile"));
-        map.put(Attribute.IsSymbolicLink, a.get("isSymbolicLink"));
-        map.put(Attribute.CreationTime, ((FileTime) 
a.get("creationTime")).toMillis());
-        map.put(Attribute.LastModifiedTime, ((FileTime) 
a.get("lastModifiedTime")).toMillis());
-        map.put(Attribute.LastAccessTime, ((FileTime) 
a.get("lastAccessTime")).toMillis());
-        map.put(Attribute.Permissions, fromPerms((Set<PosixFilePermission>) 
a.get("permissions")));
-        return map;
-    }
-
-    private EnumSet<Permission> fromPerms(Set<PosixFilePermission> perms) {
+        map.put(Attribute.Size, getSize());
+        map.put(Attribute.IsDirectory, isDirectory());
+        map.put(Attribute.IsRegularFile, isFile());
+        map.put(Attribute.IsSymbolicLink, false);
+        map.put(Attribute.LastModifiedTime, getLastModified());
+        map.put(Attribute.LastAccessTime, getLastModified());
+        map.put(Attribute.Owner, userName);
+        map.put(Attribute.Group, userName);
         EnumSet<Permission> p = EnumSet.noneOf(Permission.class);
-        for (PosixFilePermission perm : perms) {
-            switch (perm) {
-                case OWNER_READ:     p.add(Permission.UserRead); break;
-                case OWNER_WRITE:    p.add(Permission.UserWrite); break;
-                case OWNER_EXECUTE:  p.add(Permission.UserExecute); break;
-                case GROUP_READ:     p.add(Permission.GroupRead); break;
-                case GROUP_WRITE:    p.add(Permission.GroupWrite); break;
-                case GROUP_EXECUTE:  p.add(Permission.GroupExecute); break;
-                case OTHERS_READ:    p.add(Permission.OthersRead); break;
-                case OTHERS_WRITE:   p.add(Permission.OthersWrite); break;
-                case OTHERS_EXECUTE: p.add(Permission.OthersExecute); break;
-            }
+        if (isReadable()) {
+            p.add(Permission.UserRead);
+            p.add(Permission.GroupRead);
+            p.add(Permission.OthersRead);
         }
-        return p;
-    }
-
-    public void setAttributes(Map<Attribute, Object> attributes) throws 
IOException {
-        for (Attribute attribute : attributes.keySet()) {
-            String name = null;
-            Object value = attributes.get(attribute);
-            switch (attribute) {    
-                case Uid:              name = "unix:uid"; break;
-                case Owner:            name = "unix:owner"; value = 
toUser((String) value); break;
-                case Gid:              name = "unix:gid"; break;
-                case Group:            name = "unix:group"; value = 
toGroup((String) value); break;
-                case CreationTime:     name = "unix:creationTime"; value = 
FileTime.fromMillis((Long) value); break;
-                case LastModifiedTime: name = "unix:lastModifiedTime"; value = 
FileTime.fromMillis((Long) value); break;
-                case LastAccessTime:   name = "unix:lastAccessTime"; value = 
FileTime.fromMillis((Long) value); break;
-                case Permissions:      name = "unix:permissions"; value = 
toPerms((EnumSet<Permission>) value); break;
-            }
-            if (name != null && value != null) {
-                Files.setAttribute(file.toPath(), name, value, 
LinkOption.NOFOLLOW_LINKS);
-            }
+        if (isWritable()) {
+            p.add(Permission.UserWrite);
+            p.add(Permission.GroupWrite);
+            p.add(Permission.OthersWrite);
         }
+        if (isExecutable()) {
+            p.add(Permission.UserExecute);
+            p.add(Permission.GroupExecute);
+            p.add(Permission.OthersExecute);
+        }
+        map.put(Attribute.Permissions, p);
+        return map;
     }
 
-    private GroupPrincipal toGroup(String name) throws IOException {
-        UserPrincipalLookupService lookupService = 
file.toPath().getFileSystem().getUserPrincipalLookupService();
-        return lookupService.lookupPrincipalByGroupName(name);
-    }
-
-    private UserPrincipal toUser(String name) throws IOException {
-        UserPrincipalLookupService lookupService = 
file.toPath().getFileSystem().getUserPrincipalLookupService();
-        return lookupService.lookupPrincipalByName(name);
-    }
-
-    private Set<PosixFilePermission> toPerms(EnumSet<Permission> perms) {
-        Set<PosixFilePermission> set = new HashSet<PosixFilePermission>();
-        for (Permission p : perms) {
-            switch (p) {
-                case UserRead:      set.add(PosixFilePermission.OWNER_READ); 
break;
-                case UserWrite:     set.add(PosixFilePermission.OWNER_WRITE); 
break;
-                case UserExecute:   
set.add(PosixFilePermission.OWNER_EXECUTE); break;
-                case GroupRead:     set.add(PosixFilePermission.GROUP_READ); 
break;
-                case GroupWrite:    set.add(PosixFilePermission.GROUP_WRITE); 
break;
-                case GroupExecute:  
set.add(PosixFilePermission.GROUP_EXECUTE); break;
-                case OthersRead:    set.add(PosixFilePermission.OTHERS_READ); 
break;
-                case OthersWrite:   set.add(PosixFilePermission.OTHERS_WRITE); 
break;
-                case OthersExecute: 
set.add(PosixFilePermission.OTHERS_EXECUTE); break;
-            }
+    public void setAttributes(Map<Attribute, Object> attributes) throws 
IOException {
+        if (!attributes.isEmpty()) {
+            throw new UnsupportedOperationException();
         }
-        return set;
     }
 
     public Object getAttribute(Attribute attribute, boolean followLinks) 
throws IOException {
@@ -703,8 +642,6 @@ public class NativeSshFile implements SshFile {
     }
 
     public String readSymbolicLink() throws IOException {
-        Path path = file.toPath();
-        Path link = Files.readSymbolicLink(path);
-        return link.toString();
+        throw new UnsupportedOperationException();
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d7c21f79/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFileNio.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFileNio.java
 
b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFileNio.java
new file mode 100644
index 0000000..765410c
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFileNio.java
@@ -0,0 +1,149 @@
+/*
+ * 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.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.nio.file.attribute.FileTime;
+import java.nio.file.attribute.GroupPrincipal;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.UserPrincipal;
+import java.nio.file.attribute.UserPrincipalLookupService;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <strong>Internal class, do not use directly.</strong>
+ * 
+ * This class wraps native file object.
+ *
+ * @author <a href="http://mina.apache.org";>Apache MINA Project</a>
+ */
+public class NativeSshFileNio extends NativeSshFile {
+
+    /**
+     * Constructor, internal do not use directly.
+     * @param nativeFileSystemView
+     */
+    public NativeSshFileNio(NativeFileSystemView nativeFileSystemView, String 
fileName, File file, String userName) {
+        super(nativeFileSystemView, fileName, file, userName);
+    }
+
+    public Map<Attribute, Object> getAttributes(boolean followLinks) throws 
IOException {
+        Map<String, Object> a = Files.readAttributes(
+                file.toPath(),
+                
"unix:size,uid,owner,gid,group,isDirectory,isRegularFile,isSymbolicLink,permissions,creationTime,lastModifiedTime,lastAccessTime",
+                followLinks ? new LinkOption[0] : new LinkOption[] { 
LinkOption.NOFOLLOW_LINKS });
+        Map<Attribute, Object> map = new HashMap<Attribute, Object>();
+        map.put(Attribute.Size, a.get("size"));
+        map.put(Attribute.Uid, a.get("uid"));
+        map.put(Attribute.Owner, ((UserPrincipal) a.get("owner")).getName());
+        map.put(Attribute.Gid, a.get("gid"));
+        map.put(Attribute.Group, ((GroupPrincipal) a.get("group")).getName());
+        map.put(Attribute.IsDirectory, a.get("isDirectory"));
+        map.put(Attribute.IsRegularFile, a.get("isRegularFile"));
+        map.put(Attribute.IsSymbolicLink, a.get("isSymbolicLink"));
+        map.put(Attribute.CreationTime, ((FileTime) 
a.get("creationTime")).toMillis());
+        map.put(Attribute.LastModifiedTime, ((FileTime) 
a.get("lastModifiedTime")).toMillis());
+        map.put(Attribute.LastAccessTime, ((FileTime) 
a.get("lastAccessTime")).toMillis());
+        map.put(Attribute.Permissions, fromPerms((Set<PosixFilePermission>) 
a.get("permissions")));
+        return map;
+    }
+
+    public void setAttributes(Map<Attribute, Object> attributes) throws 
IOException {
+        for (Attribute attribute : attributes.keySet()) {
+            String name = null;
+            Object value = attributes.get(attribute);
+            switch (attribute) {    
+                case Uid:              name = "unix:uid"; break;
+                case Owner:            name = "unix:owner"; value = 
toUser((String) value); break;
+                case Gid:              name = "unix:gid"; break;
+                case Group:            name = "unix:group"; value = 
toGroup((String) value); break;
+                case CreationTime:     name = "unix:creationTime"; value = 
FileTime.fromMillis((Long) value); break;
+                case LastModifiedTime: name = "unix:lastModifiedTime"; value = 
FileTime.fromMillis((Long) value); break;
+                case LastAccessTime:   name = "unix:lastAccessTime"; value = 
FileTime.fromMillis((Long) value); break;
+                case Permissions:      name = "unix:permissions"; value = 
toPerms((EnumSet<Permission>) value); break;
+                case Size:             throw new 
UnsupportedOperationException("Can not set Size attribute");
+            }
+            if (name != null && value != null) {
+                Files.setAttribute(file.toPath(), name, value, 
LinkOption.NOFOLLOW_LINKS);
+            }
+        }
+    }
+
+    public String readSymbolicLink() throws IOException {
+        Path path = file.toPath();
+        Path link = Files.readSymbolicLink(path);
+        return link.toString();
+    }
+
+    private EnumSet<Permission> fromPerms(Set<PosixFilePermission> perms) {
+        EnumSet<Permission> p = EnumSet.noneOf(Permission.class);
+        for (PosixFilePermission perm : perms) {
+            switch (perm) {
+                case OWNER_READ:     p.add(Permission.UserRead); break;
+                case OWNER_WRITE:    p.add(Permission.UserWrite); break;
+                case OWNER_EXECUTE:  p.add(Permission.UserExecute); break;
+                case GROUP_READ:     p.add(Permission.GroupRead); break;
+                case GROUP_WRITE:    p.add(Permission.GroupWrite); break;
+                case GROUP_EXECUTE:  p.add(Permission.GroupExecute); break;
+                case OTHERS_READ:    p.add(Permission.OthersRead); break;
+                case OTHERS_WRITE:   p.add(Permission.OthersWrite); break;
+                case OTHERS_EXECUTE: p.add(Permission.OthersExecute); break;
+            }
+        }
+        return p;
+    }
+
+    private GroupPrincipal toGroup(String name) throws IOException {
+        UserPrincipalLookupService lookupService = 
file.toPath().getFileSystem().getUserPrincipalLookupService();
+        return lookupService.lookupPrincipalByGroupName(name);
+    }
+
+    private UserPrincipal toUser(String name) throws IOException {
+        UserPrincipalLookupService lookupService = 
file.toPath().getFileSystem().getUserPrincipalLookupService();
+        return lookupService.lookupPrincipalByName(name);
+    }
+
+    private Set<PosixFilePermission> toPerms(EnumSet<Permission> perms) {
+        Set<PosixFilePermission> set = new HashSet<PosixFilePermission>();
+        for (Permission p : perms) {
+            switch (p) {
+                case UserRead:      set.add(PosixFilePermission.OWNER_READ); 
break;
+                case UserWrite:     set.add(PosixFilePermission.OWNER_WRITE); 
break;
+                case UserExecute:   
set.add(PosixFilePermission.OWNER_EXECUTE); break;
+                case GroupRead:     set.add(PosixFilePermission.GROUP_READ); 
break;
+                case GroupWrite:    set.add(PosixFilePermission.GROUP_WRITE); 
break;
+                case GroupExecute:  
set.add(PosixFilePermission.GROUP_EXECUTE); break;
+                case OthersRead:    set.add(PosixFilePermission.OTHERS_READ); 
break;
+                case OthersWrite:   set.add(PosixFilePermission.OTHERS_WRITE); 
break;
+                case OthersExecute: 
set.add(PosixFilePermission.OTHERS_EXECUTE); break;
+            }
+        }
+        return set;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d7c21f79/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 c2c5b92..dbbae10 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
@@ -542,6 +542,8 @@ public class SftpSubsystem implements Command, Runnable, 
SessionAware, FileSyste
                     sendStatus(id, SSH_FX_NO_SUCH_FILE, e.getMessage());
                 } catch (IOException e) {
                     sendStatus(id, SSH_FX_FAILURE, e.getMessage());
+                } catch (UnsupportedOperationException e) {
+                    sendStatus(id, SSH_FX_FAILURE, "");
                 }
                 break;
             }
@@ -561,6 +563,8 @@ public class SftpSubsystem implements Command, Runnable, 
SessionAware, FileSyste
                     sendStatus(id, SSH_FX_NO_SUCH_FILE, e.getMessage());
                 } catch (IOException e) {
                     sendStatus(id, SSH_FX_FAILURE, e.getMessage());
+                } catch (UnsupportedOperationException e) {
+                    sendStatus(id, SSH_FX_FAILURE, e.getMessage());
                 }
                 break;
             }
@@ -754,6 +758,8 @@ public class SftpSubsystem implements Command, Runnable, 
SessionAware, FileSyste
                     SshFile f = resolveFile(path);
                     String l = f.readSymbolicLink();
                     sendLink(id, l);
+                } catch (UnsupportedOperationException e) {
+                    sendStatus(id, SSH_FX_OP_UNSUPPORTED, "Command " + type + 
" is unsupported or not implemented");
                 } catch (IOException e) {
                     sendStatus(id, SSH_FX_FAILURE, e.getMessage());
                 }
@@ -919,30 +925,43 @@ public class SftpSubsystem implements Command, Runnable, 
SessionAware, FileSyste
             throw new FileNotFoundException(file.getAbsolutePath());
         }
         Map<SshFile.Attribute, Object> attributes = 
file.getAttributes(followLinks);
-        boolean isReg = (Boolean) 
attributes.get(SshFile.Attribute.IsRegularFile);
-        boolean isDir = (Boolean) 
attributes.get(SshFile.Attribute.IsDirectory);
-        boolean isLnk = (Boolean) 
attributes.get(SshFile.Attribute.IsSymbolicLink);
-        int pf = getPermissions(attributes);
-        if (isReg || isLnk) {
-            buffer.putInt(SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_UIDGID | 
SSH_FILEXFER_ATTR_PERMISSIONS | SSH_FILEXFER_ATTR_ACMODTIME);
+        boolean isReg = getBool((Boolean) 
attributes.get(SshFile.Attribute.IsRegularFile));
+        boolean isDir = getBool((Boolean) 
attributes.get(SshFile.Attribute.IsDirectory));
+        boolean isLnk = getBool((Boolean) 
attributes.get(SshFile.Attribute.IsSymbolicLink));
+        int flags = 0;
+        if ((isReg || isLnk) && 
attributes.containsKey(SshFile.Attribute.Size)) {
+            flags |= SSH_FILEXFER_ATTR_SIZE;
+        }
+        if (attributes.containsKey(SshFile.Attribute.Uid) && 
attributes.containsKey(SshFile.Attribute.Gid)) {
+            flags |= SSH_FILEXFER_ATTR_UIDGID;
+        }
+        if (attributes.containsKey(SshFile.Attribute.Permissions)) {
+            flags |= SSH_FILEXFER_ATTR_PERMISSIONS;
+        }
+        if (attributes.containsKey(SshFile.Attribute.LastAccessTime) && 
attributes.containsKey(SshFile.Attribute.LastModifiedTime)) {
+            flags |= SSH_FILEXFER_ATTR_ACMODTIME;
+        }
+        buffer.putInt(flags);
+        if ((flags & SSH_FILEXFER_ATTR_SIZE) != 0) {
             buffer.putLong((Long) attributes.get(SshFile.Attribute.Size));
+        }
+        if ((flags & SSH_FILEXFER_ATTR_UIDGID) != 0) {
             buffer.putInt((Integer) attributes.get(SshFile.Attribute.Uid));
             buffer.putInt((Integer) attributes.get(SshFile.Attribute.Gid));
-            buffer.putInt(pf);
-            buffer.putInt(((Long) 
attributes.get(SshFile.Attribute.LastAccessTime)) / 1000);
-            buffer.putInt(((Long) 
attributes.get(SshFile.Attribute.LastModifiedTime)) / 1000);
-        } else if (isDir) {
-            buffer.putInt(SSH_FILEXFER_ATTR_UIDGID | 
SSH_FILEXFER_ATTR_PERMISSIONS | SSH_FILEXFER_ATTR_ACMODTIME);
-            buffer.putInt((Integer) attributes.get(SshFile.Attribute.Uid));
-            buffer.putInt((Integer) attributes.get(SshFile.Attribute.Gid));
-            buffer.putInt(pf);
+        }
+        if ((flags & SSH_FILEXFER_ATTR_PERMISSIONS) != 0) {
+            buffer.putInt(getPermissions(attributes));
+        }
+        if ((flags & SSH_FILEXFER_ATTR_ACMODTIME) != 0) {
             buffer.putInt(((Long) 
attributes.get(SshFile.Attribute.LastAccessTime)) / 1000);
             buffer.putInt(((Long) 
attributes.get(SshFile.Attribute.LastModifiedTime)) / 1000);
-        } else {
-            buffer.putInt(0);
         }
     }
 
+    protected boolean getBool(Boolean bool) {
+        return bool != null && bool;
+    }
+
     protected Map<SshFile.Attribute, Object> readAttrs(Buffer buffer) throws 
IOException {
         Map<SshFile.Attribute, Object> attrs = new HashMap<SshFile.Attribute, 
Object>();
         int flags = buffer.getInt();

Reply via email to