Repository: mina-sshd
Updated Branches:
  refs/heads/master 3eefdb3f8 -> 2678bbfe6


[SSHD-548] Export some inner private classes as public static ones


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

Branch: refs/heads/master
Commit: 2678bbfe6f685239ebb1b148a80b3086715f236f
Parents: 3eefdb3
Author: Lyor Goldstein <[email protected]>
Authored: Tue Aug 4 14:36:06 2015 +0300
Committer: Lyor Goldstein <[email protected]>
Committed: Tue Aug 4 14:36:06 2015 +0300

----------------------------------------------------------------------
 .../sshd/client/channel/ChannelSubsystem.java   |  12 +
 .../subsystem/sftp/AbstractSftpClient.java      | 246 +------------------
 .../sshd/client/subsystem/sftp/SftpCommand.java |   1 +
 .../subsystem/sftp/SftpDirEntryIterator.java    | 157 ++++++++++++
 .../subsystem/sftp/SftpDirectoryStream.java     |  65 +++++
 .../client/subsystem/sftp/SftpFileSystem.java   |  25 +-
 .../subsystem/sftp/SftpFileSystemProvider.java  | 219 +----------------
 .../sftp/SftpInputStreamWithChannel.java        | 127 ++++++++++
 .../subsystem/sftp/SftpIterableDirEntry.java    |  64 +++++
 .../sftp/SftpOutputStreamWithChannel.java       | 124 ++++++++++
 .../client/subsystem/sftp/SftpPathIterator.java |  82 +++++++
 .../sftp/SftpPosixFileAttributeView.java        | 126 ++++++++++
 .../subsystem/sftp/SftpPosixFileAttributes.java | 111 +++++++++
 .../common/channel/ChannelRequestHandler.java   |   1 +
 .../org/apache/sshd/common/channel/PtyMode.java |   1 -
 .../sshd/common/forward/TcpipClientChannel.java |   5 +-
 .../ConnectionServiceRequestHandler.java        |   1 +
 .../apache/sshd/common/mac/BuiltinMacsTest.java |   1 -
 .../common/signature/BuiltinSignaturesTest.java |   1 -
 19 files changed, 897 insertions(+), 472 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java 
b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java
index 583c937..b4d8c8f 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java
@@ -35,10 +35,22 @@ public class ChannelSubsystem extends ChannelSession {
 
     private final String subsystem;
 
+    /**
+     * @param subsystem The subsystem name for the channel - never {@code 
null} or empty
+     */
     public ChannelSubsystem(String subsystem) {
         this.subsystem = ValidateUtils.checkNotNullAndNotEmpty(subsystem, 
"Subsystem may not be null/empty");
     }
 
+    /**
+     * The subsystem name
+     *
+     * @return The subsystem name for the channel - never {@code null} or empty
+     */
+    public final String getSubsystem() {
+        return subsystem;
+    }
+
     @Override
     protected void doOpen() throws IOException {
         log.debug("Send SSH_MSG_CHANNEL_REQUEST exec");

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java
 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java
index db7afc5..28aae10 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java
@@ -16,7 +16,6 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
 package org.apache.sshd.client.subsystem.sftp;
 
 import java.io.IOException;
@@ -27,7 +26,6 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
@@ -43,8 +41,6 @@ import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
-import org.apache.sshd.common.util.io.InputStreamWithChannel;
-import org.apache.sshd.common.util.io.OutputStreamWithChannel;
 import org.apache.sshd.common.util.logging.AbstractLoggingBean;
 
 import static 
org.apache.sshd.common.subsystem.sftp.SftpConstants.ACE4_APPEND_DATA;
@@ -373,7 +369,7 @@ public abstract class AbstractSftpClient extends 
AbstractLoggingBean implements
         int id = buffer.getInt();
         if (type == SSH_FXP_ATTRS) {
             return readAttributes(buffer);
-        }            
+        }
 
         if (type == SSH_FXP_STATUS) {
             int substatus = buffer.getInt();
@@ -424,7 +420,7 @@ public abstract class AbstractSftpClient extends 
AbstractLoggingBean implements
             }
             return name;
         }
-        
+
         if (type == SSH_FXP_STATUS) {
             int substatus = buffer.getInt();
             String msg = buffer.getString();
@@ -900,7 +896,7 @@ public abstract class AbstractSftpClient extends 
AbstractLoggingBean implements
                 if (log.isTraceEnabled()) {
                     log.trace("checkDir(id={})[{}] ({})[{}]: {}", 
Integer.valueOf(id), Integer.valueOf(i), name, longName, attrs);
                 }
-    
+
                 entries.add(new DirEntry(name, longName, attrs));
             }
             return entries;
@@ -1080,7 +1076,7 @@ public abstract class AbstractSftpClient extends 
AbstractLoggingBean implements
         if (!isOpen()) {
             throw new IOException("readDir(" + path + ") client is closed");
         }
-        return new DirEntryIterable(path);
+        return new SftpIterableDirEntry(this, path);
     }
 
     @Override
@@ -1093,7 +1089,7 @@ public abstract class AbstractSftpClient extends 
AbstractLoggingBean implements
             throw new IOException("read(" + path + ")[" + mode + "] size=" + 
bufferSize + ": client is closed");
         }
 
-        return new SftpInputStreamWithChannel(bufferSize, path, mode);
+        return new SftpInputStreamWithChannel(this, bufferSize, path, mode);
     }
 
     @Override
@@ -1106,236 +1102,6 @@ public abstract class AbstractSftpClient extends 
AbstractLoggingBean implements
             throw new IOException("write(" + path + ")[" + mode + "] size=" + 
bufferSize + ": client is closed");
         }
 
-        return new SftpOutputStreamWithChannel(bufferSize, path, mode);
-    }
-
-    private class DirEntryIterable implements Iterable<DirEntry> {
-
-        private final String path;
-
-        public DirEntryIterable(String path) {
-            this.path = path;
-        }
-
-        @Override
-        public Iterator<DirEntry> iterator() {
-            return new DirEntryIterator();
-        }
-
-        private class DirEntryIterator implements Iterator<DirEntry> {
-            private CloseableHandle handle;
-            private List<DirEntry> entries;
-            private int index;
-
-            public DirEntryIterator() {
-                open();
-                load();
-            }
-
-            @Override
-            public boolean hasNext() {
-                return (entries != null) && (index < entries.size());
-            }
-
-            @Override
-            public DirEntry next() {
-                DirEntry entry = entries.get(index++);
-                if (index >= entries.size()) {
-                    load();
-                }
-                return entry;
-            }
-
-            @SuppressWarnings("synthetic-access")
-            private void open() {
-                try {
-                    handle = openDir(path);
-                    if (log.isDebugEnabled()) {
-                        log.debug("readDir(" + path + ") handle=" + handle);
-                    }
-                } catch (IOException e) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("readDir(" + path + ") failed (" + 
e.getClass().getSimpleName() + ") to open dir: " + e.getMessage());
-                    }
-                    throw new RuntimeException(e);
-                }
-            }
-
-            @SuppressWarnings("synthetic-access")
-            private void load() {
-                try {
-                    entries = readDir(handle);
-                    index = 0;
-                    if (entries == null) {
-                        handle.close();
-                    }
-                } catch (IOException e) {
-                    entries = null;
-                    try {
-                        handle.close();
-                    } catch (IOException t) {
-                        if (log.isTraceEnabled()) {
-                            log.trace(t.getClass().getSimpleName() + " while 
close handle=" + handle
-                                    + " due to " + 
e.getClass().getSimpleName() + " [" + e.getMessage() + "]"
-                                    + ": " + t.getMessage());
-                        }
-                    }
-                    throw new RuntimeException(e);
-                }
-            }
-
-            @Override
-            public void remove() {
-                throw new UnsupportedOperationException("readDir(" + path + ") 
Iterator#remove() N/A");
-            }
-        }
-    }
-
-    private class SftpOutputStreamWithChannel extends OutputStreamWithChannel {
-        private final String path;
-        private byte[] bb;
-        private byte[] buffer;
-        private int index;
-        private CloseableHandle handle;
-        private long offset;
-
-        public SftpOutputStreamWithChannel(int bufferSize, String path, 
Collection<OpenMode> mode) throws IOException {
-            this.path = path;
-            bb = new byte[1];
-            buffer = new byte[bufferSize];
-            handle = AbstractSftpClient.this.open(path, mode);
-        }
-
-        @Override
-        public boolean isOpen() {
-            return (handle != null) && handle.isOpen();
-        }
-
-        @Override
-        public void write(int b) throws IOException {
-            bb[0] = (byte) b;
-            write(bb, 0, 1);
-        }
-
-        @Override
-        public void write(byte[] b, int off, int len) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("write(" + path + ")[len=" + len + "] 
stream is closed");
-            }
-
-            do {
-                int nb = Math.min(len, buffer.length - index);
-                System.arraycopy(b, off, buffer, index, nb);
-                index += nb;
-                if (index == buffer.length) {
-                    flush();
-                }
-                off += nb;
-                len -= nb;
-            } while (len > 0);
-        }
-
-        @Override
-        public void flush() throws IOException {
-            if (!isOpen()) {
-                throw new IOException("flush(" + path + ") stream is closed");
-            }
-
-            AbstractSftpClient.this.write(handle, offset, buffer, 0, index);
-            offset += index;
-            index = 0;
-        }
-
-        @Override
-        public void close() throws IOException {
-            if (isOpen()) {
-                try {
-                    try {
-                        if (index > 0) {
-                            flush();
-                        }
-                    } finally {
-                        handle.close();
-                    }
-                } finally {
-                    handle = null;
-                }
-            }
-        }
-    }
-
-    private class SftpInputStreamWithChannel extends InputStreamWithChannel {
-        private final String path;
-        private byte[] bb;
-        private byte[] buffer;
-        private int index;
-        private int available;
-        private CloseableHandle handle;
-        private long offset;
-
-        public SftpInputStreamWithChannel(int bufferSize, String path, 
Collection<OpenMode> mode) throws IOException {
-            this.path = path;
-            bb = new byte[1];
-            buffer = new byte[bufferSize];
-            handle = AbstractSftpClient.this.open(path, mode);
-        }
-
-        @Override
-        public boolean isOpen() {
-            return (handle != null) && handle.isOpen();
-        }
-
-        @Override
-        public int read() throws IOException {
-            int read = read(bb, 0, 1);
-            if (read > 0) {
-                return bb[0];
-            }
-
-            return read;
-        }
-
-        @Override
-        public int read(byte[] b, int off, int len) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("read(" + path + ") stream closed");
-            }
-
-            int idx = off;
-            while (len > 0) {
-                if (index >= available) {
-                    available = AbstractSftpClient.this.read(handle, offset, 
buffer, 0, buffer.length);
-                    if (available < 0) {
-                        if (idx == off) {
-                            return -1;
-                        } else {
-                            break;
-                        }
-                    }
-                    offset += available;
-                    index = 0;
-                }
-                if (index >= available) {
-                    break;
-                }
-                int nb = Math.min(len, available - index);
-                System.arraycopy(buffer, index, b, idx, nb);
-                index += nb;
-                idx += nb;
-                len -= nb;
-            }
-            return idx - off;
-        }
-
-        @Override
-        public void close() throws IOException {
-            if (isOpen()) {
-                try {
-                    handle.close();
-                } finally {
-                    handle = null;
-                }
-            }
-        }
+        return new SftpOutputStreamWithChannel(this, bufferSize, path, mode);
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
index d132fe3..ca0d294 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
@@ -53,6 +53,7 @@ public class SftpCommand implements Channel {
     private final Map<String, CommandExecutor> commandsMap;
     private String cwdRemote;
 
+    @SuppressWarnings("synthetic-access")
     public SftpCommand(SftpClient client) {
         this.client = ValidateUtils.checkNotNull(client, "No client");
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirEntryIterator.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirEntryIterator.java
 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirEntryIterator.java
new file mode 100644
index 0000000..b933f1f
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirEntryIterator.java
@@ -0,0 +1,157 @@
+/*
+ * 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.client.subsystem.sftp;
+
+import java.io.IOException;
+import java.nio.channels.Channel;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.sshd.client.subsystem.sftp.SftpClient.CloseableHandle;
+import org.apache.sshd.client.subsystem.sftp.SftpClient.DirEntry;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.logging.AbstractLoggingBean;
+
+/**
+ * Iterates over the available directory entries for a given path. <B>Note:</B>
+ * if the iteration is carried out until no more entries are available, then
+ * no need to close the iterator. Otherwise, it is recommended to close it so
+ * as to release the internal handle.
+ *
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class SftpDirEntryIterator extends AbstractLoggingBean implements 
Iterator<DirEntry>, Channel {
+    private final SftpClient client;
+    private final String dirPath;
+    private CloseableHandle dirHandle;
+    private List<DirEntry> dirEntries;
+    private int index;
+
+    /**
+     * @param client The {@link SftpClient} instance to use for the iteration
+     * @param path The remote directory path
+     */
+    public SftpDirEntryIterator(SftpClient client, String path) {
+        this.client = ValidateUtils.checkNotNull(client, "No SFTP client 
instance");
+        this.dirPath = path;
+        this.dirHandle = open(path);
+        this.dirEntries = load(dirHandle);
+    }
+
+    /**
+     * The client instance
+     *
+     * @return {@link SftpClient} instance used to access the remote file
+     */
+    public final SftpClient getClient() {
+        return client;
+    }
+
+    /**
+     * The remotely accessed directory path
+     *
+     * @return Remote directory path
+     */
+    public final String getPath() {
+        return dirPath;
+    }
+
+    @Override
+    public boolean hasNext() {
+        return (dirEntries != null) && (index < dirEntries.size());
+    }
+
+    @Override
+    public DirEntry next() {
+        DirEntry entry = dirEntries.get(index++);
+        if (index >= dirEntries.size()) {
+            index = 0;
+
+            try {
+                dirEntries = load(dirHandle);
+            } catch (RuntimeException e) {
+                dirEntries = null;
+                throw e;
+            }
+        }
+
+        return entry;
+    }
+
+    @Override
+    public boolean isOpen() {
+        return (dirHandle != null) && dirHandle.isOpen();
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (isOpen()) {
+            if (log.isDebugEnabled()) {
+                log.debug("close(" + getPath() + ") handle=" + dirHandle);
+            }
+            dirHandle.close();
+        }
+    }
+
+    protected CloseableHandle open(String path) {
+        try {
+            CloseableHandle handle = client.openDir(path);
+            if (log.isDebugEnabled()) {
+                log.debug("open(" + path + ") handle=" + handle);
+            }
+
+            return handle;
+        } catch (IOException e) {
+            if (log.isDebugEnabled()) {
+                log.debug("open(" + path + ") failed (" + 
e.getClass().getSimpleName() + ") to open dir: " + e.getMessage());
+            }
+            throw new RuntimeException(e);
+        }
+    }
+
+    protected List<DirEntry> load(CloseableHandle handle) {
+        try {
+            List<DirEntry> entries = client.readDir(handle);
+            if (entries == null) {
+                if (log.isTraceEnabled()) {
+                    log.trace("load(" + getPath() + ") exhausted all entries");
+                }
+                close();
+            }
+
+            return entries;
+        } catch (IOException e) {
+            try {
+                close();
+            } catch (IOException t) {
+                if (log.isTraceEnabled()) {
+                    log.trace(t.getClass().getSimpleName() + " while close 
handle=" + handle
+                            + " due to " + e.getClass().getSimpleName() + " [" 
+ e.getMessage() + "]"
+                            + ": " + t.getMessage());
+                }
+            }
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException("readDir(" + getPath() + ") 
Iterator#remove() N/A");
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirectoryStream.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirectoryStream.java
 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirectoryStream.java
new file mode 100644
index 0000000..3217ecb
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirectoryStream.java
@@ -0,0 +1,65 @@
+/*
+ * 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.client.subsystem.sftp;
+
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Path;
+import java.util.Iterator;
+
+/**
+ * Implements a remote {@link DirectoryStream}
+ *
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class SftpDirectoryStream implements DirectoryStream<Path> {
+    private final SftpClient sftp;
+    private final Iterable<SftpClient.DirEntry> iter;
+    private final SftpPath p;
+
+    /**
+     * @param path The remote {@link SftpPath}
+     * @throws IOException If failed to initialize the directory access handle
+     */
+    public SftpDirectoryStream(SftpPath path) throws IOException {
+        SftpFileSystem fs = path.getFileSystem();
+        p = path;
+        sftp = fs.getClient();
+        iter = sftp.readDir(path.toString());
+    }
+
+    /**
+     * Client instance used to access the remote directory
+     *
+     * @return The {@link SftpClient} instance used to access the remote 
directory
+     */
+    public final SftpClient getClient() {
+        return sftp;
+    }
+
+    @Override
+    public Iterator<Path> iterator() {
+        return new SftpPathIterator(p, iter);
+    }
+
+    @Override
+    public void close() throws IOException {
+        sftp.close();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java
 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java
index 444082c..576eda0 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java
@@ -32,6 +32,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Queue;
 import java.util.Set;
 import java.util.concurrent.LinkedBlockingQueue;
@@ -485,7 +486,10 @@ public class SftpFileSystem extends 
BaseFileSystem<SftpPath> {
         }
     }
 
-    protected static class DefaultUserPrincipalLookupService extends 
UserPrincipalLookupService {
+    public static class DefaultUserPrincipalLookupService extends 
UserPrincipalLookupService {
+        public DefaultUserPrincipalLookupService() {
+            super();
+        }
 
         @Override
         public UserPrincipal lookupPrincipalByName(String name) throws 
IOException {
@@ -498,19 +502,16 @@ public class SftpFileSystem extends 
BaseFileSystem<SftpPath> {
         }
     }
 
-    protected static class DefaultUserPrincipal implements UserPrincipal {
+    public static class DefaultUserPrincipal implements UserPrincipal {
 
         private final String name;
 
         public DefaultUserPrincipal(String name) {
-            if (name == null) {
-                throw new IllegalArgumentException("name is null");
-            }
-            this.name = name;
+            this.name = ValidateUtils.checkNotNull(name, "name is null");
         }
 
         @Override
-        public String getName() {
+        public final String getName() {
             return name;
         }
 
@@ -523,26 +524,24 @@ public class SftpFileSystem extends 
BaseFileSystem<SftpPath> {
                 return false;
             }
             DefaultUserPrincipal that = (DefaultUserPrincipal) o;
-            return name.equals(that.name);
+            return Objects.equals(this.getName(), that.getName());
         }
 
         @Override
         public int hashCode() {
-            return name.hashCode();
+            return Objects.hashCode(getName());
         }
 
         @Override
         public String toString() {
-            return name;
+            return getName();
         }
     }
 
-    protected static class DefaultGroupPrincipal extends DefaultUserPrincipal 
implements GroupPrincipal {
+    public static class DefaultGroupPrincipal extends DefaultUserPrincipal 
implements GroupPrincipal {
 
         public DefaultGroupPrincipal(String name) {
             super(name);
         }
-
     }
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemProvider.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemProvider.java
 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemProvider.java
index 87579c5..8b5eeab 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemProvider.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemProvider.java
@@ -60,9 +60,7 @@ import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.Map;
-import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
@@ -289,7 +287,7 @@ public class SftpFileSystemProvider extends 
FileSystemProvider {
             } else if (option == StandardOpenOption.SPARSE) {
                 /*
                  * As per the Javadoc:
-                 * 
+                 *
                  *      The option is ignored when the file system does not
                  *  support the creation of sparse files
                  */
@@ -309,7 +307,7 @@ public class SftpFileSystemProvider extends 
FileSystemProvider {
     @Override
     public DirectoryStream<Path> newDirectoryStream(Path dir, 
DirectoryStream.Filter<? super Path> filter) throws IOException {
         final SftpPath p = toSftpPath(dir);
-        return new PathDirectoryStream(p);
+        return new SftpDirectoryStream(p);
     }
 
     @Override
@@ -576,7 +574,7 @@ public class SftpFileSystemProvider extends 
FileSystemProvider {
     @Override
     public <V extends FileAttributeView> V getFileAttributeView(final Path 
path, Class<V> type, final LinkOption... options) {
         if (isSupportedFileAttributeView(type)) {
-            return type.cast(new SftpPosixFileAttributeView(path, options));
+            return type.cast(new SftpPosixFileAttributeView(this, path, 
options));
         } else {
             throw new UnsupportedOperationException("getFileAttributeView(" + 
path + ") view not supported: " + type.getSimpleName());
         }
@@ -728,7 +726,7 @@ public class SftpFileSystemProvider extends 
FileSystemProvider {
         }
     }
 
-    private SftpPath toSftpPath(Path path) {
+    protected SftpPath toSftpPath(Path path) {
         ValidateUtils.checkNotNull(path, "No path provided");
         if (!(path instanceof SftpPath)) {
             throw new ProviderMismatchException("Path is not SFTP: " + path);
@@ -960,213 +958,4 @@ public class SftpFileSystemProvider extends 
FileSystemProvider {
     public static URI createFileSystemURI(String host, int port, String 
username, String password) {
         return URI.create(SftpConstants.SFTP_SUBSYSTEM_NAME + "://" + username 
+ ":" + password + "@" + host + ":" + port + "/");
     }
-
-    private static class PathDirectoryStream implements DirectoryStream<Path> {
-        private final SftpFileSystem fs;
-        private final SftpClient sftp;
-        private final Iterable<SftpClient.DirEntry> iter;
-        private final SftpPath p;
-
-        public PathDirectoryStream(SftpPath p) throws IOException {
-            this.p = p;
-            fs = p.getFileSystem();
-            sftp = fs.getClient();
-            iter = sftp.readDir(p.toString());
-        }
-
-        @Override
-        public Iterator<Path> iterator() {
-            return new PathIterator();
-        }
-
-        @Override
-        public void close() throws IOException {
-            sftp.close();
-        }
-
-        private class PathIterator implements Iterator<Path> {
-            @SuppressWarnings("synthetic-access")
-            private final Iterator<SftpClient.DirEntry> it = (iter == null) ? 
null : iter.iterator();
-            private boolean dotIgnored;
-            private boolean dotdotIgnored;
-            private SftpClient.DirEntry curEntry = nextEntry();
-
-            @Override
-            public boolean hasNext() {
-                return curEntry != null;
-            }
-
-            @Override
-            public Path next() {
-                if (curEntry == null) {
-                    throw new NoSuchElementException("No next entry");
-                }
-
-                SftpClient.DirEntry entry = curEntry;
-                curEntry = nextEntry();
-                return p.resolve(entry.filename);
-            }
-
-            private SftpClient.DirEntry nextEntry() {
-                while ((it != null) && it.hasNext()) {
-                    SftpClient.DirEntry entry = it.next();
-                    String name = entry.filename;
-                    if (".".equals(name) && (!dotIgnored)) {
-                        dotIgnored = true;
-                    } else if ("..".equals(name) && (!dotdotIgnored)) {
-                        dotdotIgnored = true;
-                    } else {
-                        return entry;
-                    }
-                }
-
-                return null;
-            }
-
-            @Override
-            public void remove() {
-                throw new UnsupportedOperationException("newDirectoryStream(" 
+ p + ") Iterator#remove() N/A");
-            }
-        }
-    }
-
-    private class SftpPosixFileAttributeView implements PosixFileAttributeView 
{
-        private final Path path;
-        private final LinkOption[] options;
-
-        public SftpPosixFileAttributeView(Path path, LinkOption... options) {
-            this.path = path;
-            this.options = options;
-        }
-
-        @Override
-        public String name() {
-            return "view";
-        }
-
-        @SuppressWarnings("synthetic-access")
-        @Override
-        public PosixFileAttributes readAttributes() throws IOException {
-            SftpPath p = toSftpPath(path);
-            SftpFileSystem fs = p.getFileSystem();
-            final Attributes attributes;
-            try (SftpClient client = fs.getClient()) {
-                try {
-                    if (IoUtils.followLinks(options)) {
-                        attributes = client.stat(p.toString());
-                    } else {
-                        attributes = client.lstat(p.toString());
-                    }
-                } catch (SftpException e) {
-                    if (e.getStatus() == SftpConstants.SSH_FX_NO_SUCH_FILE) {
-                        throw new NoSuchFileException(p.toString());
-                    }
-                    throw e;
-                }
-            }
-            return new SftpPosixFileAttributes(attributes);
-        }
-
-        @Override
-        public void setTimes(FileTime lastModifiedTime, FileTime 
lastAccessTime, FileTime createTime) throws IOException {
-            if (lastModifiedTime != null) {
-                setAttribute(path, "lastModifiedTime", lastModifiedTime, 
options);
-            }
-            if (lastAccessTime != null) {
-                setAttribute(path, "lastAccessTime", lastAccessTime, options);
-            }
-            if (createTime != null) {
-                setAttribute(path, "createTime", createTime, options);
-            }
-        }
-
-        @Override
-        public void setPermissions(Set<PosixFilePermission> perms) throws 
IOException {
-            setAttribute(path, "permissions", perms, options);
-        }
-
-        @Override
-        public void setGroup(GroupPrincipal group) throws IOException {
-            setAttribute(path, "group", group, options);
-        }
-
-        @Override
-        public UserPrincipal getOwner() throws IOException {
-            return readAttributes().owner();
-        }
-
-        @Override
-        public void setOwner(UserPrincipal owner) throws IOException {
-            setAttribute(path, "owner", owner, options);
-        }
-
-        private class SftpPosixFileAttributes implements PosixFileAttributes {
-            private final Attributes attributes;
-
-            public SftpPosixFileAttributes(Attributes attributes) {
-                this.attributes = attributes;
-            }
-
-            @Override
-            public UserPrincipal owner() {
-                return attributes.owner != null ? new 
SftpFileSystem.DefaultGroupPrincipal(attributes.owner) : null;
-            }
-
-            @Override
-            public GroupPrincipal group() {
-                return attributes.group != null ? new 
SftpFileSystem.DefaultGroupPrincipal(attributes.group) : null;
-            }
-
-            @Override
-            public Set<PosixFilePermission> permissions() {
-                return permissionsToAttributes(attributes.perms);
-            }
-
-            @Override
-            public FileTime lastModifiedTime() {
-                return FileTime.from(attributes.mtime, TimeUnit.SECONDS);
-            }
-
-            @Override
-            public FileTime lastAccessTime() {
-                return FileTime.from(attributes.atime, TimeUnit.SECONDS);
-            }
-
-            @Override
-            public FileTime creationTime() {
-                return FileTime.from(attributes.ctime, TimeUnit.SECONDS);
-            }
-
-            @Override
-            public boolean isRegularFile() {
-                return attributes.isRegularFile();
-            }
-
-            @Override
-            public boolean isDirectory() {
-                return attributes.isDirectory();
-            }
-
-            @Override
-            public boolean isSymbolicLink() {
-                return attributes.isSymbolicLink();
-            }
-
-            @Override
-            public boolean isOther() {
-                return attributes.isOther();
-            }
-
-            @Override
-            public long size() {
-                return attributes.size;
-            }
-
-            @Override
-            public Object fileKey() {
-                // TODO
-                return null;
-            }
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpInputStreamWithChannel.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpInputStreamWithChannel.java
 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpInputStreamWithChannel.java
new file mode 100644
index 0000000..530b2e1
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpInputStreamWithChannel.java
@@ -0,0 +1,127 @@
+/*
+ * 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.client.subsystem.sftp;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import org.apache.sshd.client.subsystem.sftp.SftpClient.CloseableHandle;
+import org.apache.sshd.client.subsystem.sftp.SftpClient.OpenMode;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.io.InputStreamWithChannel;
+
+/**
+ * Implements an input stream for reading from a remote file
+ *
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class SftpInputStreamWithChannel extends InputStreamWithChannel {
+    private final SftpClient client;
+    private final String path;
+    private byte[] bb;
+    private byte[] buffer;
+    private int index;
+    private int available;
+    private CloseableHandle handle;
+    private long offset;
+
+    public SftpInputStreamWithChannel(SftpClient client, int bufferSize, 
String path, Collection<OpenMode> mode) throws IOException {
+        this.client = ValidateUtils.checkNotNull(client, "No SFTP client 
instance");
+        this.path = path;
+        bb = new byte[1];
+        buffer = new byte[bufferSize];
+        handle = client.open(path, mode);
+    }
+
+    /**
+     * The client instance
+     *
+     * @return {@link SftpClient} instance used to access the remote file
+     */
+    public final SftpClient getClient() {
+        return client;
+    }
+
+    /**
+     * The remotely accessed file path
+     *
+     * @return Remote file path
+     */
+    public final String getPath() {
+        return path;
+    }
+
+    @Override
+    public boolean isOpen() {
+        return (handle != null) && handle.isOpen();
+    }
+
+    @Override
+    public int read() throws IOException {
+        int read = read(bb, 0, 1);
+        if (read > 0) {
+            return bb[0];
+        }
+
+        return read;
+    }
+
+    @Override
+    public int read(byte[] b, int off, int len) throws IOException {
+        if (!isOpen()) {
+            throw new IOException("read(" + getPath() + ") stream closed");
+        }
+
+        int idx = off;
+        while (len > 0) {
+            if (index >= available) {
+                available = client.read(handle, offset, buffer, 0, 
buffer.length);
+                if (available < 0) {
+                    if (idx == off) {
+                        return -1;
+                    } else {
+                        break;
+                    }
+                }
+                offset += available;
+                index = 0;
+            }
+            if (index >= available) {
+                break;
+            }
+            int nb = Math.min(len, available - index);
+            System.arraycopy(buffer, index, b, idx, nb);
+            index += nb;
+            idx += nb;
+            len -= nb;
+        }
+        return idx - off;
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (isOpen()) {
+            try {
+                handle.close();
+            } finally {
+                handle = null;
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpIterableDirEntry.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpIterableDirEntry.java
 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpIterableDirEntry.java
new file mode 100644
index 0000000..7300da7
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpIterableDirEntry.java
@@ -0,0 +1,64 @@
+/*
+ * 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.client.subsystem.sftp;
+
+import org.apache.sshd.client.subsystem.sftp.SftpClient.DirEntry;
+
+/**
+ * Provides an {@link Iterable} implementation of the {@link DirEntry}-ies
+ * for a remote directory
+ *
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class SftpIterableDirEntry implements Iterable<DirEntry> {
+    private final SftpClient client;
+    private final String path;
+
+    /**
+     * @param client The {@link SftpClient} instance to use for the iteration
+     * @param path The remote directory path
+     */
+    public SftpIterableDirEntry(SftpClient client, String path) {
+        this.client = client;
+        this.path = path;
+    }
+
+    /**
+     * The client instance
+     *
+     * @return {@link SftpClient} instance used to access the remote file
+     */
+    public final SftpClient getClient() {
+        return client;
+    }
+
+    /**
+     * The remotely accessed directory path
+     *
+     * @return Remote directory path
+     */
+    public final String getPath() {
+        return path;
+    }
+
+    @Override
+    public SftpDirEntryIterator iterator() {
+        return new SftpDirEntryIterator(getClient(), getPath());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpOutputStreamWithChannel.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpOutputStreamWithChannel.java
 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpOutputStreamWithChannel.java
new file mode 100644
index 0000000..4cc6845
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpOutputStreamWithChannel.java
@@ -0,0 +1,124 @@
+/*
+ * 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.client.subsystem.sftp;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import org.apache.sshd.client.subsystem.sftp.SftpClient.CloseableHandle;
+import org.apache.sshd.client.subsystem.sftp.SftpClient.OpenMode;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.io.OutputStreamWithChannel;
+
+/**
+ * Implements an output stream for a given remote file
+ *
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class SftpOutputStreamWithChannel extends OutputStreamWithChannel {
+    private final SftpClient client;
+    private final String path;
+    private final byte[] bb =  new byte[1];
+    private final byte[] buffer;
+    private int index;
+    private CloseableHandle handle;
+    private long offset;
+
+    public SftpOutputStreamWithChannel(SftpClient client, int bufferSize, 
String path, Collection<OpenMode> mode) throws IOException {
+        this.client = ValidateUtils.checkNotNull(client, "No SFTP client 
instance");
+        this.path = path;
+        buffer = new byte[bufferSize];
+        handle = client.open(path, mode);
+    }
+
+    /**
+     * The client instance
+     *
+     * @return {@link SftpClient} instance used to access the remote file
+     */
+    public final SftpClient getClient() {
+        return client;
+    }
+
+    /**
+     * The remotely accessed file path
+     *
+     * @return Remote file path
+     */
+    public final String getPath() {
+        return path;
+    }
+
+    @Override
+    public boolean isOpen() {
+        return (handle != null) && handle.isOpen();
+    }
+
+    @Override
+    public void write(int b) throws IOException {
+        bb[0] = (byte) b;
+        write(bb, 0, 1);
+    }
+
+    @Override
+    public void write(byte[] b, int off, int len) throws IOException {
+        if (!isOpen()) {
+            throw new IOException("write(" + getPath() + ")[len=" + len + "] 
stream is closed");
+        }
+
+        do {
+            int nb = Math.min(len, buffer.length - index);
+            System.arraycopy(b, off, buffer, index, nb);
+            index += nb;
+            if (index == buffer.length) {
+                flush();
+            }
+            off += nb;
+            len -= nb;
+        } while (len > 0);
+    }
+
+    @Override
+    public void flush() throws IOException {
+        if (!isOpen()) {
+            throw new IOException("flush(" + getPath() + ") stream is closed");
+        }
+
+        client.write(handle, offset, buffer, 0, index);
+        offset += index;
+        index = 0;
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (isOpen()) {
+            try {
+                try {
+                    if (index > 0) {
+                        flush();
+                    }
+                } finally {
+                    handle.close();
+                }
+            } finally {
+                handle = null;
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPathIterator.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPathIterator.java
 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPathIterator.java
new file mode 100644
index 0000000..ad6bb71
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPathIterator.java
@@ -0,0 +1,82 @@
+/*
+ * 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.client.subsystem.sftp;
+
+import java.nio.file.Path;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class SftpPathIterator implements Iterator<Path> {
+    private final SftpPath p;
+    private final Iterator<? extends SftpClient.DirEntry> it;
+    private boolean dotIgnored;
+    private boolean dotdotIgnored;
+    private SftpClient.DirEntry curEntry;
+
+    public SftpPathIterator(SftpPath path, Iterable<? extends 
SftpClient.DirEntry> iter) {
+        this(path, (iter == null) ? null : iter.iterator());
+    }
+
+    public SftpPathIterator(SftpPath path, Iterator<? extends 
SftpClient.DirEntry> iter) {
+        p = path;
+        it = iter;
+        curEntry = nextEntry();
+    }
+
+    @Override
+    public boolean hasNext() {
+        return curEntry != null;
+    }
+
+    @Override
+    public Path next() {
+        if (curEntry == null) {
+            throw new NoSuchElementException("No next entry");
+        }
+
+        SftpClient.DirEntry entry = curEntry;
+        curEntry = nextEntry();
+        return p.resolve(entry.filename);
+    }
+
+    private SftpClient.DirEntry nextEntry() {
+        while ((it != null) && it.hasNext()) {
+            SftpClient.DirEntry entry = it.next();
+            String name = entry.filename;
+            if (".".equals(name) && (!dotIgnored)) {
+                dotIgnored = true;
+            } else if ("..".equals(name) && (!dotdotIgnored)) {
+                dotdotIgnored = true;
+            } else {
+                return entry;
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException("newDirectoryStream(" + p + ") 
Iterator#remove() N/A");
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPosixFileAttributeView.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPosixFileAttributeView.java
 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPosixFileAttributeView.java
new file mode 100644
index 0000000..6c7cef4
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPosixFileAttributeView.java
@@ -0,0 +1,126 @@
+/*
+ * 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.client.subsystem.sftp;
+
+import java.io.IOException;
+import java.nio.file.LinkOption;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.attribute.FileTime;
+import java.nio.file.attribute.GroupPrincipal;
+import java.nio.file.attribute.PosixFileAttributeView;
+import java.nio.file.attribute.PosixFileAttributes;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.UserPrincipal;
+import java.util.Set;
+
+import org.apache.sshd.client.subsystem.sftp.SftpClient.Attributes;
+import org.apache.sshd.common.subsystem.sftp.SftpConstants;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.io.IoUtils;
+
+/**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class SftpPosixFileAttributeView implements PosixFileAttributeView {
+    private final SftpFileSystemProvider provider;
+    private final Path path;
+    private final LinkOption[] options;
+
+    public SftpPosixFileAttributeView(SftpFileSystemProvider provider, Path 
path, LinkOption... options) {
+        this.provider = ValidateUtils.checkNotNull(provider, "No file system 
provider instance");
+        this.path = path;
+        this.options = options;
+    }
+
+    @Override
+    public String name() {
+        return "view";
+    }
+
+    /**
+     * @return The underlying {@link SftpFileSystemProvider} used to
+     * provide the view functionality
+     */
+    public final SftpFileSystemProvider provider() {
+        return provider;
+    }
+
+    /**
+     * @return The referenced view {@link Path}
+     */
+    public final Path getPath() {
+        return path;
+    }
+
+    @Override
+    public PosixFileAttributes readAttributes() throws IOException {
+        SftpPath p = provider.toSftpPath(path);
+        SftpFileSystem fs = p.getFileSystem();
+        final Attributes attributes;
+        try (SftpClient client = fs.getClient()) {
+            try {
+                if (IoUtils.followLinks(options)) {
+                    attributes = client.stat(p.toString());
+                } else {
+                    attributes = client.lstat(p.toString());
+                }
+            } catch (SftpException e) {
+                if (e.getStatus() == SftpConstants.SSH_FX_NO_SUCH_FILE) {
+                    throw new NoSuchFileException(p.toString());
+                }
+                throw e;
+            }
+        }
+        return new SftpPosixFileAttributes(path, attributes);
+    }
+
+    @Override
+    public void setTimes(FileTime lastModifiedTime, FileTime lastAccessTime, 
FileTime createTime) throws IOException {
+        if (lastModifiedTime != null) {
+            provider.setAttribute(path, "lastModifiedTime", lastModifiedTime, 
options);
+        }
+        if (lastAccessTime != null) {
+            provider.setAttribute(path, "lastAccessTime", lastAccessTime, 
options);
+        }
+        if (createTime != null) {
+            provider.setAttribute(path, "createTime", createTime, options);
+        }
+    }
+
+    @Override
+    public void setPermissions(Set<PosixFilePermission> perms) throws 
IOException {
+        provider.setAttribute(path, "permissions", perms, options);
+    }
+
+    @Override
+    public void setGroup(GroupPrincipal group) throws IOException {
+        provider.setAttribute(path, "group", group, options);
+    }
+
+    @Override
+    public UserPrincipal getOwner() throws IOException {
+        return readAttributes().owner();
+    }
+
+    @Override
+    public void setOwner(UserPrincipal owner) throws IOException {
+        provider.setAttribute(path, "owner", owner, options);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPosixFileAttributes.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPosixFileAttributes.java
 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPosixFileAttributes.java
new file mode 100644
index 0000000..9790b01
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPosixFileAttributes.java
@@ -0,0 +1,111 @@
+/*
+ * 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.client.subsystem.sftp;
+
+import java.nio.file.Path;
+import java.nio.file.attribute.FileTime;
+import java.nio.file.attribute.GroupPrincipal;
+import java.nio.file.attribute.PosixFileAttributes;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.UserPrincipal;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.sshd.client.subsystem.sftp.SftpClient.Attributes;
+
+/**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class SftpPosixFileAttributes implements PosixFileAttributes {
+    private final Path path;
+    private final Attributes attributes;
+
+    public SftpPosixFileAttributes(Path path, Attributes attributes) {
+        this.path = path;
+        this.attributes = attributes;
+    }
+
+    /**
+     * @return The referenced attributes file {@link Path}
+     */
+    public final Path getPath() {
+        return path;
+    }
+
+    @Override
+    public UserPrincipal owner() {
+        return attributes.owner != null ? new 
SftpFileSystem.DefaultGroupPrincipal(attributes.owner) : null;
+    }
+
+    @Override
+    public GroupPrincipal group() {
+        return attributes.group != null ? new 
SftpFileSystem.DefaultGroupPrincipal(attributes.group) : null;
+    }
+
+    @Override
+    public Set<PosixFilePermission> permissions() {
+        return 
SftpFileSystemProvider.permissionsToAttributes(attributes.perms);
+    }
+
+    @Override
+    public FileTime lastModifiedTime() {
+        return FileTime.from(attributes.mtime, TimeUnit.SECONDS);
+    }
+
+    @Override
+    public FileTime lastAccessTime() {
+        return FileTime.from(attributes.atime, TimeUnit.SECONDS);
+    }
+
+    @Override
+    public FileTime creationTime() {
+        return FileTime.from(attributes.ctime, TimeUnit.SECONDS);
+    }
+
+    @Override
+    public boolean isRegularFile() {
+        return attributes.isRegularFile();
+    }
+
+    @Override
+    public boolean isDirectory() {
+        return attributes.isDirectory();
+    }
+
+    @Override
+    public boolean isSymbolicLink() {
+        return attributes.isSymbolicLink();
+    }
+
+    @Override
+    public boolean isOther() {
+        return attributes.isOther();
+    }
+
+    @Override
+    public long size() {
+        return attributes.size;
+    }
+
+    @Override
+    public Object fileKey() {
+        // TODO consider implementing this
+        return null;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelRequestHandler.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelRequestHandler.java
 
b/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelRequestHandler.java
index e7d5e65..8210c23 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelRequestHandler.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelRequestHandler.java
@@ -36,6 +36,7 @@ public interface ChannelRequestHandler extends 
RequestHandler<Channel> {
             }
         };
 
+    @Override
     Result process(Channel channel, String request, boolean wantReply, Buffer 
buffer) throws Exception;
 
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/common/channel/PtyMode.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/channel/PtyMode.java 
b/sshd-core/src/main/java/org/apache/sshd/common/channel/PtyMode.java
index b0ec6db..fd81ee0 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/PtyMode.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/PtyMode.java
@@ -19,7 +19,6 @@
 package org.apache.sshd.common.channel;
 
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Map;
 
 /**

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java
 
b/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java
index 8d8a729..2cc657f 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java
@@ -40,7 +40,10 @@ import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
  */
 public class TcpipClientChannel extends AbstractClientChannel {
 
-    public enum Type {
+    /**
+     * Type of channel being created
+     */
+    public static enum Type {
         Direct,
         Forwarded
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionServiceRequestHandler.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionServiceRequestHandler.java
 
b/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionServiceRequestHandler.java
index 9749345..39ef956 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionServiceRequestHandler.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionServiceRequestHandler.java
@@ -31,6 +31,7 @@ public interface ConnectionServiceRequestHandler extends 
RequestHandler<Connecti
     // required because of generics issues
     Transformer<ConnectionServiceRequestHandler, 
RequestHandler<ConnectionService>> SVC2HNDLR = Transformer.Utils.identity();
 
+    @Override
     Result process(ConnectionService service, String request, boolean 
wantReply, Buffer buffer) throws Exception;
 
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/test/java/org/apache/sshd/common/mac/BuiltinMacsTest.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/test/java/org/apache/sshd/common/mac/BuiltinMacsTest.java 
b/sshd-core/src/test/java/org/apache/sshd/common/mac/BuiltinMacsTest.java
index b2933e9..9c8fbc4 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/mac/BuiltinMacsTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/mac/BuiltinMacsTest.java
@@ -28,7 +28,6 @@ import java.util.List;
 import java.util.Random;
 import java.util.Set;
 
-import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.NamedResource;
 import org.apache.sshd.common.mac.BuiltinMacs.ParseResult;
 import org.apache.sshd.common.util.GenericUtils;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2678bbfe/sshd-core/src/test/java/org/apache/sshd/common/signature/BuiltinSignaturesTest.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/test/java/org/apache/sshd/common/signature/BuiltinSignaturesTest.java
 
b/sshd-core/src/test/java/org/apache/sshd/common/signature/BuiltinSignaturesTest.java
index 7592b93..b2b89a1 100644
--- 
a/sshd-core/src/test/java/org/apache/sshd/common/signature/BuiltinSignaturesTest.java
+++ 
b/sshd-core/src/test/java/org/apache/sshd/common/signature/BuiltinSignaturesTest.java
@@ -25,7 +25,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Random;
 
-import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.NamedResource;
 import org.apache.sshd.common.signature.BuiltinSignatures.ParseResult;
 import org.apache.sshd.common.util.GenericUtils;

Reply via email to