http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a6e2bf9e/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystemFactory.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystemFactory.java
 
b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystemFactory.java
new file mode 100644
index 0000000..98c0205
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystemFactory.java
@@ -0,0 +1,139 @@
+/*
+ * 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.server.subsystem.sftp;
+
+import java.util.concurrent.ExecutorService;
+
+import org.apache.sshd.common.subsystem.sftp.SftpConstants;
+import org.apache.sshd.common.util.ObjectBuilder;
+import org.apache.sshd.common.util.threads.ExecutorServiceConfigurer;
+import org.apache.sshd.server.Command;
+import org.apache.sshd.server.subsystem.SubsystemFactory;
+
+/**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class SftpSubsystemFactory implements SubsystemFactory, Cloneable, 
ExecutorServiceConfigurer {
+    public static final String NAME = SftpConstants.SFTP_SUBSYSTEM_NAME;
+    public static final UnsupportedAttributePolicy DEFAULT_POLICY = 
UnsupportedAttributePolicy.Warn;
+
+    public static class Builder implements ObjectBuilder<SftpSubsystemFactory> 
{
+        private final SftpSubsystemFactory factory = new 
SftpSubsystemFactory();
+
+        public Builder() {
+            super();
+        }
+
+        public Builder withExecutorService(ExecutorService service) {
+            factory.setExecutorService(service);
+            return this;
+        }
+
+        public Builder withShutdownOnExit(boolean shutdown) {
+            factory.setShutdownOnExit(shutdown);
+            return this;
+        }
+
+        public Builder 
withUnsupportedAttributePolicy(UnsupportedAttributePolicy p) {
+            factory.setUnsupportedAttributePolicy(p);
+            return this;
+        }
+
+        @Override
+        public SftpSubsystemFactory build() {
+            // return a clone so that each invocation returns a different 
instance - avoid shared instances
+            return factory.clone();
+        }
+    }
+
+    private ExecutorService executors;
+    private boolean shutdownExecutor;
+    private UnsupportedAttributePolicy policy = DEFAULT_POLICY;
+
+    public SftpSubsystemFactory() {
+        super();
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public ExecutorService getExecutorService() {
+        return executors;
+    }
+
+    /**
+     * @param service The {@link ExecutorService} to be used by the {@link 
SftpSubsystem}
+     *                command when starting execution. If {@code null} then a 
single-threaded ad-hoc service is used.
+     */
+    @Override
+    public void setExecutorService(ExecutorService service) {
+        executors = service;
+    }
+
+    @Override
+    public boolean isShutdownOnExit() {
+        return shutdownExecutor;
+    }
+
+    /**
+     * @param shutdownOnExit If {@code true} the {@link 
ExecutorService#shutdownNow()}
+     *                       will be called when subsystem terminates - unless 
it is the ad-hoc service, which
+     *                       will be shutdown regardless
+     */
+    @Override
+    public void setShutdownOnExit(boolean shutdownOnExit) {
+        shutdownExecutor = shutdownOnExit;
+    }
+
+    public UnsupportedAttributePolicy getUnsupportedAttributePolicy() {
+        return policy;
+    }
+
+    /**
+     * @param p The {@link UnsupportedAttributePolicy} to use if failed to 
access
+     *          some local file attributes
+     */
+    public void setUnsupportedAttributePolicy(UnsupportedAttributePolicy p) {
+        if (p == null) {
+            throw new IllegalArgumentException("No policy provided");
+        }
+
+        policy = p;
+    }
+
+    @Override
+    public Command create() {
+        return new SftpSubsystem(getExecutorService(), isShutdownOnExit(), 
getUnsupportedAttributePolicy());
+    }
+
+    @Override
+    public SftpSubsystemFactory clone() {
+        try {
+            return getClass().cast(super.clone());  // shallow clone is good 
enough
+        } catch (CloneNotSupportedException e) {
+            throw new UnsupportedOperationException("Unexpected clone 
exception", e);   // unexpected since we implement cloneable
+        }
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a6e2bf9e/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/UnsupportedAttributePolicy.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/UnsupportedAttributePolicy.java
 
b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/UnsupportedAttributePolicy.java
new file mode 100644
index 0000000..87a0c01
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/UnsupportedAttributePolicy.java
@@ -0,0 +1,36 @@
+/*
+ * 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.server.subsystem.sftp;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public enum UnsupportedAttributePolicy {
+    Ignore,
+    Warn,
+    ThrowException;
+
+    public static final Set<UnsupportedAttributePolicy> VALUES =
+            
Collections.unmodifiableSet(EnumSet.allOf(UnsupportedAttributePolicy.class));
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a6e2bf9e/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java 
b/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
index 96f69b8..4ec4891 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
@@ -70,7 +70,7 @@ import org.apache.sshd.common.keyprovider.KeyPairProvider;
 import org.apache.sshd.common.session.AbstractSession;
 import org.apache.sshd.common.session.ConnectionService;
 import org.apache.sshd.common.session.Session;
-import org.apache.sshd.common.sftp.SftpConstants;
+import org.apache.sshd.common.subsystem.sftp.SftpConstants;
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.Transformer;
 import org.apache.sshd.common.util.buffer.Buffer;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a6e2bf9e/sshd-core/src/test/java/org/apache/sshd/client/sftp/DefaultCloseableHandleTest.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/test/java/org/apache/sshd/client/sftp/DefaultCloseableHandleTest.java
 
b/sshd-core/src/test/java/org/apache/sshd/client/sftp/DefaultCloseableHandleTest.java
deleted file mode 100644
index 22f1a70..0000000
--- 
a/sshd-core/src/test/java/org/apache/sshd/client/sftp/DefaultCloseableHandleTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.sshd.client.sftp;
-
-import java.io.IOException;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.sshd.client.sftp.SftpClient.CloseableHandle;
-import org.apache.sshd.client.sftp.SftpClient.Handle;
-import org.apache.sshd.util.BaseTestSupport;
-import org.junit.FixMethodOrder;
-import org.junit.Test;
-import org.junit.runners.MethodSorters;
-import org.mockito.Matchers;
-import org.mockito.Mockito;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-/**
- * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
- */
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-public class DefaultCloseableHandleTest extends BaseTestSupport {
-    public DefaultCloseableHandleTest() {
-        super();
-    }
-
-    @Test
-    public void testChannelBehavior() throws IOException {
-        final String id = getCurrentTestName();
-        SftpClient client = Mockito.mock(SftpClient.class);
-        Mockito.doAnswer(new Answer<Void>() {
-                @Override
-                public Void answer(InvocationOnMock invocation) throws 
Throwable {
-                    Object[] args = invocation.getArguments();
-                    Handle handle = (Handle) args[0];
-                    assertEquals("Mismatched closing handle", id, handle.id);
-                    return null;
-                }
-            }).when(client).close(Matchers.any(Handle.class));
-
-        CloseableHandle handle = new DefaultCloseableHandle(client, id);
-        try {
-            assertTrue("Handle not initially open", handle.isOpen());
-        } finally {
-            handle.close();
-        }
-        assertFalse("Handle not marked as closed", handle.isOpen());
-        // make sure close was called
-        Mockito.verify(client).close(handle);
-    }
-
-    @Test
-    public void testCloseIdempotent() throws IOException {
-        SftpClient client = Mockito.mock(SftpClient.class);
-        final AtomicBoolean closeCalled = new AtomicBoolean(false);
-        Mockito.doAnswer(new Answer<Void>() {
-                @Override
-                public Void answer(InvocationOnMock invocation) throws 
Throwable {
-                    Object[] args = invocation.getArguments();
-                    assertFalse("Close already called on handle=" + args[0], 
closeCalled.getAndSet(true));
-                    return null;
-                }
-            }).when(client).close(Matchers.any(Handle.class));
-
-        CloseableHandle handle = new DefaultCloseableHandle(client, 
getCurrentTestName());
-        for (int index=0; index < Byte.SIZE; index++) {
-            handle.close();
-        }
-        
-        assertTrue("Close method not called", closeCalled.get());
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a6e2bf9e/sshd-core/src/test/java/org/apache/sshd/client/sftp/SftpFileSystemTest.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/test/java/org/apache/sshd/client/sftp/SftpFileSystemTest.java 
b/sshd-core/src/test/java/org/apache/sshd/client/sftp/SftpFileSystemTest.java
deleted file mode 100644
index cbe27a8..0000000
--- 
a/sshd-core/src/test/java/org/apache/sshd/client/sftp/SftpFileSystemTest.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.sshd.client.sftp;
-
-import java.io.IOException;
-import java.net.URI;
-import java.nio.channels.FileChannel;
-import java.nio.channels.FileLock;
-import java.nio.channels.OverlappingFileLockException;
-import java.nio.file.DirectoryStream;
-import java.nio.file.FileAlreadyExistsException;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.LinkOption;
-import java.nio.file.NoSuchFileException;
-import java.nio.file.Path;
-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.Collections;
-import java.util.Map;
-import java.util.TreeMap;
-
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.file.FileSystemFactory;
-import org.apache.sshd.common.file.root.RootedFileSystemProvider;
-import org.apache.sshd.common.session.Session;
-import org.apache.sshd.common.sftp.SftpConstants;
-import org.apache.sshd.common.util.OsUtils;
-import org.apache.sshd.common.util.io.IoUtils;
-import org.apache.sshd.server.Command;
-import org.apache.sshd.server.SshServer;
-import org.apache.sshd.server.command.ScpCommandFactory;
-import org.apache.sshd.server.sftp.SftpSubsystemFactory;
-import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
-import org.apache.sshd.util.Utils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.FixMethodOrder;
-import org.junit.Test;
-import org.junit.runners.MethodSorters;
-
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-public class SftpFileSystemTest extends BaseTestSupport {
-
-    private SshServer sshd;
-    private int port;
-    private final FileSystemFactory fileSystemFactory;
-
-    public SftpFileSystemTest() throws IOException {
-        Path targetPath = detectTargetFolder().toPath();
-        Path parentPath = targetPath.getParent();
-        final FileSystem fileSystem = new 
RootedFileSystemProvider().newFileSystem(parentPath, 
Collections.<String,Object>emptyMap());
-        fileSystemFactory = new FileSystemFactory() {
-            @Override
-            public FileSystem createFileSystem(Session session) throws 
IOException {
-                return fileSystem;
-            }
-        };
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        sshd = SshServer.setUpDefaultServer();
-        sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
-        sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new 
SftpSubsystemFactory()));
-        sshd.setCommandFactory(new ScpCommandFactory());
-        sshd.setShellFactory(new EchoShellFactory());
-        sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
-        sshd.setFileSystemFactory(fileSystemFactory);
-        sshd.start();
-        port = sshd.getPort();
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        if (sshd != null) {
-            sshd.stop(true);
-        }
-    }
-
-    @Test
-    public void testFileSystem() throws IOException {
-        Path targetPath = detectTargetFolder().toPath();
-        Path lclSftp = Utils.resolve(targetPath, 
SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), 
getCurrentTestName());
-        Utils.deleteRecursive(lclSftp);
-
-        try(FileSystem fs = FileSystems.newFileSystem(
-                URI.create("sftp://"; + getCurrentTestName() + ":" + 
getCurrentTestName() + "@localhost:" + port + "/"),
-                new TreeMap<String,Object>() {
-                    private static final long serialVersionUID = 1L;    // 
we're not serializing it
-                
-                    {
-                        put(SftpFileSystemProvider.READ_BUFFER_PROP_NAME, 
Integer.valueOf(IoUtils.DEFAULT_COPY_SIZE));
-                        put(SftpFileSystemProvider.WRITE_BUFFER_PROP_NAME, 
Integer.valueOf(IoUtils.DEFAULT_COPY_SIZE));
-                    }
-            })) {
-
-            Iterable<Path> rootDirs = fs.getRootDirectories();
-            for (Path root : rootDirs) {
-                String  rootName = root.toString();
-                try (DirectoryStream<Path> ds = 
Files.newDirectoryStream(root)) {
-                    for (Path child : ds) {
-                        
System.out.append('\t').append('[').append(rootName).append("] 
").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().normalize();
-            System.out.append("CWD: ").println(current);
-
-            Path parentPath = targetPath.getParent();
-            Path clientFolder = lclSftp.resolve("client");
-            String remFile1Path = Utils.resolveRelativeRemotePath(parentPath, 
clientFolder.resolve(getCurrentTestName() + "-1.txt"));
-            Path file1 = fs.getPath(remFile1Path);
-            Files.createDirectories(file1.getParent());
-
-            String  expected="Hello world: " + getCurrentTestName();
-            {
-                Files.write(file1, expected.getBytes());
-                String buf = new String(Files.readAllBytes(file1));
-                assertEquals("Mismatched read test data", expected, buf);
-            }
-    
-            String remFile2Path = Utils.resolveRelativeRemotePath(parentPath, 
clientFolder.resolve(getCurrentTestName() + "-2.txt"));
-            Path file2 = fs.getPath(remFile2Path);
-            String remFile3Path = Utils.resolveRelativeRemotePath(parentPath, 
clientFolder.resolve(getCurrentTestName() + "-3.txt"));
-            Path file3 = fs.getPath(remFile3Path);
-            try {
-                Files.move(file2, file3);
-                fail("Unexpected success in moving " + file2 + " => " + file3);
-            } catch (NoSuchFileException e) {
-                // expected
-            }
-
-            Files.write(file2, "h".getBytes());
-            try {
-                Files.move(file1, file2);
-                fail("Unexpected success in moving " + file1 + " => " + file2);
-            } catch (FileAlreadyExistsException e) {
-                // expected
-            }
-            Files.move(file1, file2, StandardCopyOption.REPLACE_EXISTING);
-            Files.move(file2, file1);
-    
-            Map<String, Object> attrs = Files.readAttributes(file1, "*");
-            System.out.append(file1.toString()).append(" attributes: 
").println(attrs);
-    
-            // TODO: symbolic links only work for absolute files
-    //        Path link = fs.getPath("target/sftp/client/test2.txt");
-    //        Files.createSymbolicLink(link, link.relativize(file));
-    //        assertTrue(Files.isSymbolicLink(link));
-    //        assertEquals("test.txt", 
Files.readSymbolicLink(link).toString());
-    
-            // 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(remFile2Path);
-                Path linkParent = link.getParent();
-                Path relPath = linkParent.relativize(file1);
-                Files.createSymbolicLink(link, relPath);
-                assertTrue("Not a symbolic link: " + link, 
Files.isSymbolicLink(link));
-
-                Path symLink = Files.readSymbolicLink(link);
-                assertEquals("mismatched symbolic link name", 
relPath.toString(), symLink.toString());
-                Files.delete(link);
-            }
-    
-            attrs = Files.readAttributes(file1, "*", 
LinkOption.NOFOLLOW_LINKS);
-            System.out.append(file1.toString()).append(" no-follow attributes: 
").println(attrs);
-    
-            assertEquals("Mismatched symlink data", expected, new 
String(Files.readAllBytes(file1)));
-    
-            try (FileChannel channel = FileChannel.open(file1)) {
-                try (FileLock lock = channel.lock()) {
-                    System.out.println("Locked " + lock.toString());
-    
-                    try (FileChannel channel2 = FileChannel.open(file1)) {
-                        try (FileLock lock2 = channel2.lock()) {
-                            System.out.println("Locked " + lock2.toString());
-                            fail("Unexpected success in re-locking " + file1);
-                        } catch (OverlappingFileLockException e) {
-                            // expected
-                        }
-                    }
-                }
-            }
-    
-            Files.delete(file1);
-        }
-    }
-
-    @Test
-    public void testAttributes() throws IOException {
-        Path targetPath = detectTargetFolder().toPath();
-        Path lclSftp = Utils.resolve(targetPath, 
SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), 
getCurrentTestName());
-        Utils.deleteRecursive(lclSftp);
-
-        try(FileSystem fs = FileSystems.newFileSystem(
-                URI.create("sftp://"; + getCurrentTestName() + ":" + 
getCurrentTestName() + "@localhost:" + port + "/"),
-                new TreeMap<String,Object>() {
-                    private static final long serialVersionUID = 1L;    // 
we're not serializing it
-                
-                    {
-                        put(SftpFileSystemProvider.READ_BUFFER_PROP_NAME, 
Integer.valueOf(SftpClient.MIN_READ_BUFFER_SIZE));
-                        put(SftpFileSystemProvider.WRITE_BUFFER_PROP_NAME, 
Integer.valueOf(SftpClient.MIN_WRITE_BUFFER_SIZE));
-                    }
-            })) {
-
-            Path parentPath = targetPath.getParent();
-            Path clientFolder = lclSftp.resolve("client");
-            String remFilePath = Utils.resolveRelativeRemotePath(parentPath, 
clientFolder.resolve(getCurrentTestName() + ".txt"));
-            Path file = fs.getPath(remFilePath);
-            Files.createDirectories(file.getParent());
-            Files.write(file, (getCurrentTestName() + "\n").getBytes());
-    
-            Map<String, Object> attrs = Files.readAttributes(file, "posix:*");
-            assertNotNull("NO attributes read for " + file, attrs);
-    
-            Files.setAttribute(file, "basic:size", Long.valueOf(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
-    public void testRootFileSystem() throws IOException {
-        Path targetPath = detectTargetFolder().toPath();
-        Path rootNative = targetPath.resolve("root").toAbsolutePath();
-        Utils.deleteRecursive(rootNative);
-        Files.createDirectories(rootNative);
-
-        try(FileSystem fs = FileSystems.newFileSystem(URI.create("root:" + 
rootNative.toUri().toString() + "!/"), null)) {
-            Path dir = Files.createDirectories(fs.getPath("test/foo"));
-            System.out.println("Created " + dir);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a6e2bf9e/sshd-core/src/test/java/org/apache/sshd/client/sftp/SftpTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/sftp/SftpTest.java 
b/sshd-core/src/test/java/org/apache/sshd/client/sftp/SftpTest.java
deleted file mode 100644
index ad6f603..0000000
--- a/sshd-core/src/test/java/org/apache/sshd/client/sftp/SftpTest.java
+++ /dev/null
@@ -1,651 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.sshd.client.sftp;
-
-import static 
org.apache.sshd.common.sftp.SftpConstants.SSH_FX_FILE_ALREADY_EXISTS;
-import static org.apache.sshd.common.sftp.SftpConstants.SSH_FX_NO_SUCH_FILE;
-import static org.apache.sshd.common.sftp.SftpConstants.S_IRUSR;
-import static org.apache.sshd.common.sftp.SftpConstants.S_IWUSR;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URI;
-import java.nio.file.FileSystem;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.Random;
-import java.util.Vector;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.sshd.client.SshClient;
-import org.apache.sshd.client.session.ClientSession;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.file.FileSystemFactory;
-import org.apache.sshd.common.file.root.RootedFileSystemProvider;
-import org.apache.sshd.common.session.Session;
-import org.apache.sshd.common.sftp.SftpConstants;
-import org.apache.sshd.common.util.OsUtils;
-import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
-import org.apache.sshd.common.util.io.IoUtils;
-import org.apache.sshd.server.Command;
-import org.apache.sshd.server.SshServer;
-import org.apache.sshd.server.command.ScpCommandFactory;
-import org.apache.sshd.server.sftp.SftpSubsystemFactory;
-import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
-import org.apache.sshd.util.JSchLogger;
-import org.apache.sshd.util.SimpleUserInfo;
-import org.apache.sshd.util.Utils;
-import org.junit.After;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.FixMethodOrder;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runners.MethodSorters;
-
-import com.jcraft.jsch.ChannelSftp;
-import com.jcraft.jsch.JSch;
-import com.jcraft.jsch.SftpException;
-
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-public class SftpTest extends BaseTestSupport {
-
-    private SshServer sshd;
-    private int port;
-    private com.jcraft.jsch.Session session;
-    private final FileSystemFactory fileSystemFactory;
-
-    public SftpTest() throws IOException {
-        Path targetPath = detectTargetFolder().toPath();
-        Path parentPath = targetPath.getParent();
-        final FileSystem fileSystem = new 
RootedFileSystemProvider().newFileSystem(parentPath, 
Collections.<String,Object>emptyMap());
-        fileSystemFactory = new FileSystemFactory() {
-            @Override
-            public FileSystem createFileSystem(Session session) throws 
IOException {
-                return fileSystem;
-            }
-        };
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        sshd = SshServer.setUpDefaultServer();
-        sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
-        sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new 
SftpSubsystemFactory()));
-        sshd.setCommandFactory(new ScpCommandFactory());
-        sshd.setShellFactory(new EchoShellFactory());
-        sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
-        sshd.setFileSystemFactory(fileSystemFactory);
-        sshd.start();
-        port = sshd.getPort();
-
-        JSchLogger.init();
-        JSch sch = new JSch();
-        session = sch.getSession("sshd", "localhost", port);
-        session.setUserInfo(new SimpleUserInfo("sshd"));
-        session.connect();
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        if (session != null) {
-            session.disconnect();
-        }
-        
-        if (sshd != null) {
-            sshd.stop(true);
-        }
-    }
-
-    @Test
-    @Ignore
-    public void testExternal() throws Exception {
-        System.out.println("SFTP subsystem available on port " + port);
-        Thread.sleep(5 * 60000);
-    }
-
-    @Test
-    public void testOpen() throws Exception {
-        try(SshClient client = SshClient.setUpDefaultClient()) {
-            client.start();
-            
-            try (ClientSession session = client.connect(getCurrentTestName(), 
"localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                Path targetPath = detectTargetFolder().toPath();
-                Path parentPath = targetPath.getParent();
-                Path lclSftp = Utils.resolve(targetPath, 
SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), 
getCurrentTestName());
-                Path clientFolder = lclSftp.resolve("client");
-                Path testFile = clientFolder.resolve(getCurrentTestName() + 
".txt");
-                String file = Utils.resolveRelativeRemotePath(parentPath, 
testFile);
-
-                File javaFile = testFile.toFile();
-                assertHierarchyTargetFolderExists(javaFile.getParentFile());
-                javaFile.createNewFile();
-                javaFile.setWritable(false, false);
-                javaFile.setReadable(false, false);
-        
-                try (SftpClient sftp = session.createSftpClient()) {
-                    boolean    isWindows = OsUtils.isWin32();
-            
-                    try(SftpClient.CloseableHandle h = sftp.open(file, 
EnumSet.of(SftpClient.OpenMode.Read))) {
-                        // NOTE: on Windows files are always readable
-                        // see 
https://svn.apache.org/repos/asf/harmony/enhanced/java/branches/java6/classlib/modules/luni/src/test/api/windows/org/apache/harmony/luni/tests/java/io/WinFileTest.java
-                        assertTrue("Empty read should have failed on " + file, 
isWindows);
-                    } catch (IOException e) {
-                        if (isWindows) {
-                            throw e;
-                        }
-                    }
-            
-                    try(SftpClient.CloseableHandle h = sftp.open(file, 
EnumSet.of(SftpClient.OpenMode.Write))) {
-                        fail("Empty write should have failed on " + file);
-                    } catch (IOException e) {
-                        // ok
-                    }
-    
-                    try(SftpClient.CloseableHandle h = sftp.open(file, 
EnumSet.of(SftpClient.OpenMode.Truncate))) {
-                        // NOTE: on Windows files are always readable
-                        assertTrue("Empty truncate should have failed on " + 
file, isWindows);
-                    } catch (IOException e) {
-                        // ok
-                    }
-    
-                    // NOTE: on Windows files are always readable
-                    int        perms=sftp.stat(file).perms;
-                    int        permsMask=S_IWUSR | (isWindows ? 0 : S_IRUSR);
-                    assertEquals("Mismatched permissions for " + file + ": 0x" 
+ Integer.toHexString(perms), 0, (perms & permsMask));
-            
-                    javaFile.setWritable(true, false);
-            
-                    try(SftpClient.CloseableHandle h = sftp.open(file, 
EnumSet.of(SftpClient.OpenMode.Truncate, SftpClient.OpenMode.Write))) {
-                        // OK should succeed
-                        assertTrue("Handle not marked as open for file=" + 
file, h.isOpen());
-                    }
-            
-                    byte[] d = "0123456789\n".getBytes();
-                    try(SftpClient.CloseableHandle h = sftp.open(file, 
EnumSet.of(SftpClient.OpenMode.Write))) {
-                        sftp.write(h, 0, d, 0, d.length);
-                        sftp.write(h, d.length, d, 0, d.length);
-                    }
-
-                    try(SftpClient.CloseableHandle h = sftp.open(file, 
EnumSet.of(SftpClient.OpenMode.Write))) {
-                        sftp.write(h, d.length * 2, d, 0, d.length);
-                    }
-
-                    try(SftpClient.CloseableHandle h = sftp.open(file, 
EnumSet.of(SftpClient.OpenMode.Write))) {
-                        sftp.write(h, 3, "-".getBytes(), 0, 1);
-                    }
-
-                    try(SftpClient.CloseableHandle h = sftp.open(file, 
EnumSet.of(SftpClient.OpenMode.Read))) {
-                        // NOTE: on Windows files are always readable
-                        assertTrue("Data read should have failed on " + file, 
isWindows);
-                    } catch (IOException e) {
-                        if (isWindows) {
-                            throw e;
-                        }
-                    }
-            
-                    javaFile.setReadable(true, false);
-            
-                    byte[] buf = new byte[3];
-                    try(SftpClient.CloseableHandle h = sftp.open(file, 
EnumSet.of(SftpClient.OpenMode.Read))) {
-                        int l = sftp.read(h, 2l, buf, 0, 3);
-                        assertEquals("Mismatched read data", "2-4", new 
String(buf, 0, l));
-                    }
-                }
-            } finally {
-                client.stop();
-            }
-        }
-    }
-
-    @Test
-    public void testClient() throws Exception {
-        try(SshClient client = SshClient.setUpDefaultClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), 
"localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                Path targetPath = detectTargetFolder().toPath();
-                Path lclSftp = Utils.resolve(targetPath, 
SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), 
getCurrentTestName());
-                Utils.deleteRecursive(lclSftp);
-                Files.createDirectories(lclSftp);
-
-                Path parentPath = targetPath.getParent();
-                Path clientFolder = lclSftp.resolve("client");
-                String dir = Utils.resolveRelativeRemotePath(parentPath, 
clientFolder);
-                String file = dir + "/" + getCurrentTestName() + ".txt";
-
-                try (SftpClient sftp = session.createSftpClient()) {
-                    sftp.mkdir(dir);
-            
-                    try(SftpClient.CloseableHandle h = sftp.open(file, 
EnumSet.of(SftpClient.OpenMode.Write, SftpClient.OpenMode.Create))) {
-                        byte[] d = "0123456789\n".getBytes();
-                        sftp.write(h, 0, d, 0, d.length);
-                        sftp.write(h, d.length, d, 0, d.length);
-                
-                        SftpClient.Attributes attrs = sftp.stat(h);
-                        assertNotNull("No handle attributes", attrs);
-                    }            
-            
-                    try(SftpClient.CloseableHandle h = sftp.openDir(dir)) {
-                        SftpClient.DirEntry[] dirEntries = sftp.readDir(h);
-                        assertNotNull("No dir entries", dirEntries);
-                        assertEquals("Mismatced number of dir entries", 1, 
dirEntries.length);
-                        assertNull("Unexpected entry read", sftp.readDir(h));
-                    }
-            
-                    sftp.remove(file);
-    
-                    byte[] workBuf = new byte[IoUtils.DEFAULT_COPY_SIZE * 
Short.SIZE];
-                    new Random(System.currentTimeMillis()).nextBytes(workBuf);
-                    try (OutputStream os = sftp.write(file)) {
-                        os.write(workBuf);
-                    }
-            
-                    try (InputStream is = sftp.read(file, 
IoUtils.DEFAULT_COPY_SIZE)) {
-                        int readLen = is.read(workBuf);
-                        assertEquals("Mismatched read data length", 
workBuf.length, readLen);
-        
-                        int i = is.read();
-                        assertEquals("Unexpected read past EOF", -1, i);
-                    }
-        
-                    SftpClient.Attributes attributes = sftp.stat(file);
-                    assertTrue("Test file not detected as regular", 
attributes.isRegularFile());
-            
-                    attributes = sftp.stat(dir);
-                    assertTrue("Test directory not reported as such", 
attributes.isDirectory());
-            
-                    int nb = 0;
-                    for (SftpClient.DirEntry entry : sftp.readDir(dir)) {
-                        assertNotNull("Unexpected null entry", entry);
-                        nb++;
-                    }
-                    assertEquals("Mismatched read dir entries", 1, nb);
-            
-                    sftp.remove(file);
-            
-                    sftp.rmdir(dir);
-                }
-            } finally {
-                client.stop();
-            }
-        }
-    }
-
-    /**
-     * this test is meant to test out write's logic, to ensure that internal 
chunking (based on Buffer.MAX_LEN) is
-     * functioning properly. To do this, we write a variety of file sizes, 
both smaller and larger than Buffer.MAX_LEN.
-     * in addition, this test ensures that improper arguments passed in get 
caught with an IllegalArgumentException
-     * @throws Exception upon any uncaught exception or failure
-     */
-    @Test
-    public void testWriteChunking() throws Exception {
-        try(SshClient client = SshClient.setUpDefaultClient()) {
-            client.start();
-            
-            try (ClientSession session = client.connect(getCurrentTestName(), 
"localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-        
-                Path targetPath = detectTargetFolder().toPath();
-                Path lclSftp = Utils.resolve(targetPath, 
SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), 
getCurrentTestName());
-                Utils.deleteRecursive(lclSftp);
-                Files.createDirectories(lclSftp);
-
-                Path parentPath = targetPath.getParent();
-                Path clientFolder = lclSftp.resolve("client");
-                String dir = Utils.resolveRelativeRemotePath(parentPath, 
clientFolder);
-        
-                try(SftpClient sftp = session.createSftpClient()) {
-                    sftp.mkdir(dir);
-            
-                    uploadAndVerifyFile(sftp, clientFolder, dir, 0, 
"emptyFile.txt");
-                    uploadAndVerifyFile(sftp, clientFolder, dir, 1000, 
"smallFile.txt");
-                    uploadAndVerifyFile(sftp, clientFolder, dir, 
ByteArrayBuffer.MAX_LEN - 1, "bufferMaxLenMinusOneFile.txt");
-                    uploadAndVerifyFile(sftp, clientFolder, dir, 
ByteArrayBuffer.MAX_LEN, "bufferMaxLenFile.txt");
-                    // were chunking not implemented, these would fail. these 
sizes should invoke our internal chunking mechanism
-                    uploadAndVerifyFile(sftp, clientFolder, dir, 
ByteArrayBuffer.MAX_LEN + 1, "bufferMaxLenPlusOneFile.txt");
-                    uploadAndVerifyFile(sftp, clientFolder, dir, (int)(1.5 * 
ByteArrayBuffer.MAX_LEN), "1point5BufferMaxLenFile.txt");
-                    uploadAndVerifyFile(sftp, clientFolder, dir, (2 * 
ByteArrayBuffer.MAX_LEN) - 1, "2TimesBufferMaxLenMinusOneFile.txt");
-                    uploadAndVerifyFile(sftp, clientFolder, dir, 2 * 
ByteArrayBuffer.MAX_LEN, "2TimesBufferMaxLenFile.txt");
-                    uploadAndVerifyFile(sftp, clientFolder, dir, (2 * 
ByteArrayBuffer.MAX_LEN) + 1, "2TimesBufferMaxLenPlusOneFile.txt");
-                    uploadAndVerifyFile(sftp, clientFolder, dir, 200000, 
"largerFile.txt");
-            
-                    // test erroneous calls that check for negative values
-                    Path invalidPath = 
clientFolder.resolve(getCurrentTestName() + "-invalid");
-                    testInvalidParams(sftp, invalidPath, 
Utils.resolveRelativeRemotePath(parentPath, invalidPath));
-            
-                    // cleanup
-                    sftp.rmdir(dir);
-                }
-            } finally {
-                client.stop();
-            }
-        }
-    }
-
-    private void testInvalidParams(SftpClient sftp, Path file, String 
filePath) throws Exception {
-        // generate random file and upload it
-        String randomData = randomString(5);
-        byte[] randomBytes = randomData.getBytes();
-        try(SftpClient.CloseableHandle handle = sftp.open(filePath, 
EnumSet.of(SftpClient.OpenMode.Write, SftpClient.OpenMode.Create))) {
-            try {
-                sftp.write(handle, -1, randomBytes, 0, 0);
-                fail("should not have been able to write file with invalid 
file offset for " + filePath);
-            } catch (IllegalArgumentException e) {
-                // expected
-            }
-            try {
-                sftp.write(handle, 0, randomBytes, -1, 0);
-                fail("should not have been able to write file with invalid 
source offset for " + filePath);
-            } catch (IllegalArgumentException e) {
-                // expected
-            }
-            try {
-                sftp.write(handle, 0, randomBytes, 0, -1);
-                fail("should not have been able to write file with invalid 
length for " + filePath);
-            } catch (IllegalArgumentException e) {
-                // expected
-            }
-            try {
-                sftp.write(handle, 0, randomBytes, 0, randomBytes.length + 1);
-                fail("should not have been able to write file with length 
bigger than array itself (no offset) for " + filePath);
-            } catch (IllegalArgumentException e) {
-                // expected
-            }
-            try {
-                sftp.write(handle, 0, randomBytes, randomBytes.length, 1);
-                fail("should not have been able to write file with length 
bigger than array itself (with offset) for " + filePath);
-            } catch (IllegalArgumentException e) {
-                // expected
-            }
-        }
-
-        sftp.remove(filePath);
-        assertFalse("File should not be there: " + file.toString(), 
Files.exists(file));
-    }
-
-    private void uploadAndVerifyFile(SftpClient sftp, Path clientFolder, 
String remoteDir, int size, String filename) throws Exception {
-        // generate random file and upload it
-        String remotePath = remoteDir + "/" + filename;
-        String randomData = randomString(size);
-        try(SftpClient.CloseableHandle handle = sftp.open(remotePath, 
EnumSet.of(SftpClient.OpenMode.Write, SftpClient.OpenMode.Create))) {
-            sftp.write(handle, 0, randomData.getBytes(), 0, 
randomData.length());
-        }
-
-        // verify results
-        Path resultPath = clientFolder.resolve(filename);
-        assertTrue("File should exist on disk: " + resultPath, 
Files.exists(resultPath));
-        assertTrue("Mismatched file contents: " + resultPath, 
randomData.equals(readFile(remotePath)));
-
-        // cleanup
-        sftp.remove(remotePath);
-        assertFalse("File should have been removed: " + resultPath, 
Files.exists(resultPath));
-    }
-
-    @Test
-    public void testSftp() throws Exception {
-        String d = getCurrentTestName() + "\n";
-
-        Path targetPath = detectTargetFolder().toPath();
-        Path lclSftp = Utils.resolve(targetPath, 
SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), 
getCurrentTestName());
-        Utils.deleteRecursive(lclSftp);
-        Files.createDirectories(lclSftp);
-
-        Path target = lclSftp.resolve(getCurrentTestName() + ".txt");
-        String remotePath = 
Utils.resolveRelativeRemotePath(targetPath.getParent(), target);
-
-        final int NUM_ITERATIONS=10;
-        StringBuilder   sb = new StringBuilder(d.length() * NUM_ITERATIONS * 
NUM_ITERATIONS);
-        for (int j = 1; j <= NUM_ITERATIONS; j++) {
-            if (sb.length() > 0) {
-                sb.setLength(0);
-            }
-
-            for (int i = 0; i < j; i++) {
-                sb.append(d);
-            }
-
-            sendFile(remotePath, sb.toString());
-            assertFileLength(target, sb.length(), 5000);
-            Files.delete(target);
-        }
-    }
-
-    @Test
-    public void testReadWriteWithOffset() throws Exception {
-        Path targetPath = detectTargetFolder().toPath();
-        Path lclSftp = Utils.resolve(targetPath, 
SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), 
getCurrentTestName());
-        Utils.deleteRecursive(lclSftp);
-        Files.createDirectories(lclSftp);
-
-        Path localPath = lclSftp.resolve(getCurrentTestName() + ".txt");
-        String remotePath = 
Utils.resolveRelativeRemotePath(targetPath.getParent(), localPath);
-        String data = getCurrentTestName();
-        String extraData = "@" + getClass().getSimpleName();
-        int appendOffset = -5;
-
-        ChannelSftp c = (ChannelSftp) 
session.openChannel(SftpConstants.SFTP_SUBSYSTEM_NAME);
-        c.connect();
-        try {
-            c.put(new ByteArrayInputStream(data.getBytes()), remotePath);
-    
-            assertTrue("Remote file not created after initial write: " + 
localPath, Files.exists(localPath));
-            assertEquals("Mismatched data read from " + remotePath, data, 
readFile(remotePath));
-    
-            try(OutputStream os = c.put(remotePath, null, ChannelSftp.APPEND, 
appendOffset)) {
-                os.write(extraData.getBytes());
-            }
-        } finally {
-            c.disconnect();
-        }
-
-        assertTrue("Remote file not created after data update: " + localPath, 
Files.exists(localPath));
-        
-        String expected = data.substring(0, data.length() + appendOffset) + 
extraData;
-        String actual = readFile(remotePath);
-        assertEquals("Mismatched final file data in " + remotePath, expected, 
actual);
-    }
-
-    @Test
-    public void testReadDir() throws Exception {
-        ChannelSftp c = (ChannelSftp) 
session.openChannel(SftpConstants.SFTP_SUBSYSTEM_NAME);
-        c.connect();
-        try {
-            URI url = 
getClass().getClassLoader().getResource(SshClient.class.getName().replace('.', 
'/') + ".class").toURI();
-            URI base = new 
File(System.getProperty("user.dir")).getAbsoluteFile().toURI();
-            String path = new File(base.relativize(url).getPath()).getParent() 
+ "/";
-            path = path.replace('\\', '/');
-            Vector<?> res = c.ls(path);
-            for (Object f : res) {
-                System.out.println(f.toString());
-            }
-        } finally {
-            c.disconnect();
-        }
-    }
-
-    @Test
-    public void testRealPath() throws Exception {
-        ChannelSftp c = (ChannelSftp) 
session.openChannel(SftpConstants.SFTP_SUBSYSTEM_NAME);
-        c.connect();
-
-        try {
-            URI url = 
getClass().getClassLoader().getResource(SshClient.class.getName().replace('.', 
'/') + ".class").toURI();
-            URI base = new 
File(System.getProperty("user.dir")).getAbsoluteFile().toURI();
-            String path = new File(base.relativize(url).getPath()).getParent() 
+ "/";
-            path = path.replace('\\', '/');
-            String real = c.realpath(path);
-            System.out.println(real);
-            try {
-                real = c.realpath(path + "/foobar");
-                System.out.println(real);
-                fail("Expected SftpException");
-            } catch (SftpException e) {
-                // ok
-            }
-        } finally {
-            c.disconnect();
-        }
-    }
-
-    @Test
-    public void testRename() throws Exception {
-        try(SshClient client = SshClient.setUpDefaultClient()) {
-            client.start();
-            
-            try (ClientSession session = client.connect(getCurrentTestName(), 
"localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-        
-                Path targetPath = detectTargetFolder().toPath();
-                Path lclSftp = Utils.resolve(targetPath, 
SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), 
getCurrentTestName());
-                Utils.deleteRecursive(lclSftp);
-                Files.createDirectories(lclSftp);
-
-                Path parentPath = targetPath.getParent();
-                Path clientFolder = 
assertHierarchyTargetFolderExists(lclSftp.resolve("client"));
-        
-                try(SftpClient sftp = session.createSftpClient()) {
-                    Path file1 = clientFolder.resolve(getCurrentTestName() + 
"-1.txt");
-                    String file1Path = 
Utils.resolveRelativeRemotePath(parentPath, file1);
-                    try (OutputStream os = sftp.write(file1Path, 
SftpClient.MIN_WRITE_BUFFER_SIZE)) {
-                        os.write((getCurrentTestName() + "\n").getBytes());
-                    }
-
-                    Path file2 = clientFolder.resolve(getCurrentTestName() + 
"-2.txt");
-                    String file2Path = 
Utils.resolveRelativeRemotePath(parentPath, file2);
-                    Path file3 = clientFolder.resolve(getCurrentTestName() + 
"-3.txt");
-                    String file3Path = 
Utils.resolveRelativeRemotePath(parentPath, file3);
-                    try {
-                        sftp.rename(file2Path, file3Path);
-                        fail("Unxpected rename success of " + file2Path + " => 
" + file3Path);
-                    } catch (org.apache.sshd.client.SftpException e) {
-                        assertEquals("Mismatched status for failed rename of " 
+ file2Path + " => " + file3Path, SSH_FX_NO_SUCH_FILE, e.getStatus());
-                    }
-            
-                    try (OutputStream os = sftp.write(file2Path, 
SftpClient.MIN_WRITE_BUFFER_SIZE)) {
-                        os.write("H".getBytes());
-                    }
-            
-                    try {
-                        sftp.rename(file1Path, file2Path);
-                        fail("Unxpected rename success of " + file1Path + " => 
" + file2Path);
-                    } catch (org.apache.sshd.client.SftpException e) {
-                        assertEquals("Mismatched status for failed rename of " 
+ file1Path + " => " + file2Path, SSH_FX_FILE_ALREADY_EXISTS, e.getStatus());
-                    }
-
-                    sftp.rename(file1Path, file2Path, 
SftpClient.CopyMode.Overwrite);
-                }
-            } finally {
-                client.stop();
-            }
-        }
-    }
-
-    @Test
-    public void testCreateSymbolicLink() throws Exception {
-        // Do not execute on windows as the file system does not support 
symlinks
-        Assume.assumeTrue("Skip non-Unix O/S", OsUtils.isUNIX());
-
-        Path targetPath = detectTargetFolder().toPath();
-        Path lclSftp = Utils.resolve(targetPath, 
SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), 
getCurrentTestName());
-        Utils.deleteRecursive(lclSftp);
-        Files.createDirectories(lclSftp);
-
-        Path parentPath = targetPath.getParent();
-        Path sourcePath = lclSftp.resolve(getCurrentTestName() + ".txt");
-        String remSrcPath = Utils.resolveRelativeRemotePath(parentPath, 
sourcePath);
-        Path linkPath = lclSftp.resolve("link-" + sourcePath.getFileName());
-        String remLinkPath = Utils.resolveRelativeRemotePath(parentPath, 
linkPath);
-
-        String data = getCurrentTestName();
-        ChannelSftp c = (ChannelSftp) 
session.openChannel(SftpConstants.SFTP_SUBSYSTEM_NAME);
-        c.connect();
-        try {
-            c.put(new ByteArrayInputStream(data.getBytes()), remSrcPath);
-    
-            assertTrue("Source file not created: " + sourcePath, 
Files.exists(sourcePath));
-            assertEquals("Mismatched stored data in " + remSrcPath, data, 
readFile(remSrcPath));
-    
-            c.symlink(remSrcPath, remLinkPath);
-    
-            assertTrue("Symlink not created: " + linkPath, 
Files.exists(linkPath));
-            assertEquals("Mismatche link data in " + remLinkPath, data, 
readFile(remLinkPath));
-    
-            String str1 = c.readlink(remLinkPath);
-            String str2 = c.realpath(remSrcPath);
-            assertEquals("Mismatched link vs. real path", str1, str2);
-        } finally {
-            c.disconnect();
-        }
-    }
-
-    protected String readFile(String path) throws Exception {
-        ChannelSftp c = (ChannelSftp) 
session.openChannel(SftpConstants.SFTP_SUBSYSTEM_NAME);
-        c.connect();
-        
-        try(ByteArrayOutputStream bos = new ByteArrayOutputStream();
-            InputStream is = c.get(path)) {
-
-            byte[] buffer = new byte[256];
-            int count;
-            while (-1 != (count = is.read(buffer))) {
-                bos.write(buffer, 0, count);
-            }
-
-            return bos.toString();
-        } finally {
-            c.disconnect();
-        }
-    }
-
-    protected void sendFile(String path, String data) throws Exception {
-        ChannelSftp c = (ChannelSftp) 
session.openChannel(SftpConstants.SFTP_SUBSYSTEM_NAME);
-        c.connect();
-        try {
-            c.put(new ByteArrayInputStream(data.getBytes()), path);
-        } finally {
-            c.disconnect();
-        }
-    }
-
-    private String randomString(int size) {
-        StringBuilder sb = new StringBuilder(size);
-        for (int i = 0; i < size; i++) {
-            sb.append((char) ((i % 10) + '0'));
-        }
-        return sb.toString();
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a6e2bf9e/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/DefaultCloseableHandleTest.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/DefaultCloseableHandleTest.java
 
b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/DefaultCloseableHandleTest.java
new file mode 100644
index 0000000..8dbab78
--- /dev/null
+++ 
b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/DefaultCloseableHandleTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.concurrent.atomic.AtomicBoolean;
+
+import org.apache.sshd.client.subsystem.sftp.DefaultCloseableHandle;
+import org.apache.sshd.client.subsystem.sftp.SftpClient;
+import org.apache.sshd.client.subsystem.sftp.SftpClient.CloseableHandle;
+import org.apache.sshd.client.subsystem.sftp.SftpClient.Handle;
+import org.apache.sshd.util.BaseTestSupport;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class DefaultCloseableHandleTest extends BaseTestSupport {
+    public DefaultCloseableHandleTest() {
+        super();
+    }
+
+    @Test
+    public void testChannelBehavior() throws IOException {
+        final String id = getCurrentTestName();
+        SftpClient client = Mockito.mock(SftpClient.class);
+        Mockito.doAnswer(new Answer<Void>() {
+                @Override
+                public Void answer(InvocationOnMock invocation) throws 
Throwable {
+                    Object[] args = invocation.getArguments();
+                    Handle handle = (Handle) args[0];
+                    assertEquals("Mismatched closing handle", id, handle.id);
+                    return null;
+                }
+            }).when(client).close(Matchers.any(Handle.class));
+
+        CloseableHandle handle = new DefaultCloseableHandle(client, id);
+        try {
+            assertTrue("Handle not initially open", handle.isOpen());
+        } finally {
+            handle.close();
+        }
+        assertFalse("Handle not marked as closed", handle.isOpen());
+        // make sure close was called
+        Mockito.verify(client).close(handle);
+    }
+
+    @Test
+    public void testCloseIdempotent() throws IOException {
+        SftpClient client = Mockito.mock(SftpClient.class);
+        final AtomicBoolean closeCalled = new AtomicBoolean(false);
+        Mockito.doAnswer(new Answer<Void>() {
+                @Override
+                public Void answer(InvocationOnMock invocation) throws 
Throwable {
+                    Object[] args = invocation.getArguments();
+                    assertFalse("Close already called on handle=" + args[0], 
closeCalled.getAndSet(true));
+                    return null;
+                }
+            }).when(client).close(Matchers.any(Handle.class));
+
+        CloseableHandle handle = new DefaultCloseableHandle(client, 
getCurrentTestName());
+        for (int index=0; index < Byte.SIZE; index++) {
+            handle.close();
+        }
+        
+        assertTrue("Close method not called", closeCalled.get());
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a6e2bf9e/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemTest.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemTest.java
 
b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemTest.java
new file mode 100644
index 0000000..fe3a123
--- /dev/null
+++ 
b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemTest.java
@@ -0,0 +1,288 @@
+/*
+ * 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.net.URI;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.OverlappingFileLockException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileAlreadyExistsException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+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.Collections;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.sshd.client.subsystem.sftp.SftpClient;
+import org.apache.sshd.client.subsystem.sftp.SftpFileSystemProvider;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.file.FileSystemFactory;
+import org.apache.sshd.common.file.root.RootedFileSystemProvider;
+import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.subsystem.sftp.SftpConstants;
+import org.apache.sshd.common.util.OsUtils;
+import org.apache.sshd.common.util.io.IoUtils;
+import org.apache.sshd.server.Command;
+import org.apache.sshd.server.SshServer;
+import org.apache.sshd.server.command.ScpCommandFactory;
+import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
+import org.apache.sshd.util.BaseTestSupport;
+import org.apache.sshd.util.BogusPasswordAuthenticator;
+import org.apache.sshd.util.EchoShellFactory;
+import org.apache.sshd.util.Utils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class SftpFileSystemTest extends BaseTestSupport {
+
+    private SshServer sshd;
+    private int port;
+    private final FileSystemFactory fileSystemFactory;
+
+    public SftpFileSystemTest() throws IOException {
+        Path targetPath = detectTargetFolder().toPath();
+        Path parentPath = targetPath.getParent();
+        final FileSystem fileSystem = new 
RootedFileSystemProvider().newFileSystem(parentPath, 
Collections.<String,Object>emptyMap());
+        fileSystemFactory = new FileSystemFactory() {
+            @Override
+            public FileSystem createFileSystem(Session session) throws 
IOException {
+                return fileSystem;
+            }
+        };
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        sshd = SshServer.setUpDefaultServer();
+        sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
+        sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new 
SftpSubsystemFactory()));
+        sshd.setCommandFactory(new ScpCommandFactory());
+        sshd.setShellFactory(new EchoShellFactory());
+        sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
+        sshd.setFileSystemFactory(fileSystemFactory);
+        sshd.start();
+        port = sshd.getPort();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        if (sshd != null) {
+            sshd.stop(true);
+        }
+    }
+
+    @Test
+    public void testFileSystem() throws IOException {
+        Path targetPath = detectTargetFolder().toPath();
+        Path lclSftp = Utils.resolve(targetPath, 
SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), 
getCurrentTestName());
+        Utils.deleteRecursive(lclSftp);
+
+        try(FileSystem fs = FileSystems.newFileSystem(
+                URI.create("sftp://"; + getCurrentTestName() + ":" + 
getCurrentTestName() + "@localhost:" + port + "/"),
+                new TreeMap<String,Object>() {
+                    private static final long serialVersionUID = 1L;    // 
we're not serializing it
+                
+                    {
+                        put(SftpFileSystemProvider.READ_BUFFER_PROP_NAME, 
Integer.valueOf(IoUtils.DEFAULT_COPY_SIZE));
+                        put(SftpFileSystemProvider.WRITE_BUFFER_PROP_NAME, 
Integer.valueOf(IoUtils.DEFAULT_COPY_SIZE));
+                    }
+            })) {
+
+            Iterable<Path> rootDirs = fs.getRootDirectories();
+            for (Path root : rootDirs) {
+                String  rootName = root.toString();
+                try (DirectoryStream<Path> ds = 
Files.newDirectoryStream(root)) {
+                    for (Path child : ds) {
+                        
System.out.append('\t').append('[').append(rootName).append("] 
").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().normalize();
+            System.out.append("CWD: ").println(current);
+
+            Path parentPath = targetPath.getParent();
+            Path clientFolder = lclSftp.resolve("client");
+            String remFile1Path = Utils.resolveRelativeRemotePath(parentPath, 
clientFolder.resolve(getCurrentTestName() + "-1.txt"));
+            Path file1 = fs.getPath(remFile1Path);
+            Files.createDirectories(file1.getParent());
+
+            String  expected="Hello world: " + getCurrentTestName();
+            {
+                Files.write(file1, expected.getBytes());
+                String buf = new String(Files.readAllBytes(file1));
+                assertEquals("Mismatched read test data", expected, buf);
+            }
+    
+            String remFile2Path = Utils.resolveRelativeRemotePath(parentPath, 
clientFolder.resolve(getCurrentTestName() + "-2.txt"));
+            Path file2 = fs.getPath(remFile2Path);
+            String remFile3Path = Utils.resolveRelativeRemotePath(parentPath, 
clientFolder.resolve(getCurrentTestName() + "-3.txt"));
+            Path file3 = fs.getPath(remFile3Path);
+            try {
+                Files.move(file2, file3);
+                fail("Unexpected success in moving " + file2 + " => " + file3);
+            } catch (NoSuchFileException e) {
+                // expected
+            }
+
+            Files.write(file2, "h".getBytes());
+            try {
+                Files.move(file1, file2);
+                fail("Unexpected success in moving " + file1 + " => " + file2);
+            } catch (FileAlreadyExistsException e) {
+                // expected
+            }
+            Files.move(file1, file2, StandardCopyOption.REPLACE_EXISTING);
+            Files.move(file2, file1);
+    
+            Map<String, Object> attrs = Files.readAttributes(file1, "*");
+            System.out.append(file1.toString()).append(" attributes: 
").println(attrs);
+    
+            // TODO: symbolic links only work for absolute files
+    //        Path link = fs.getPath("target/sftp/client/test2.txt");
+    //        Files.createSymbolicLink(link, link.relativize(file));
+    //        assertTrue(Files.isSymbolicLink(link));
+    //        assertEquals("test.txt", 
Files.readSymbolicLink(link).toString());
+    
+            // 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(remFile2Path);
+                Path linkParent = link.getParent();
+                Path relPath = linkParent.relativize(file1);
+                Files.createSymbolicLink(link, relPath);
+                assertTrue("Not a symbolic link: " + link, 
Files.isSymbolicLink(link));
+
+                Path symLink = Files.readSymbolicLink(link);
+                assertEquals("mismatched symbolic link name", 
relPath.toString(), symLink.toString());
+                Files.delete(link);
+            }
+    
+            attrs = Files.readAttributes(file1, "*", 
LinkOption.NOFOLLOW_LINKS);
+            System.out.append(file1.toString()).append(" no-follow attributes: 
").println(attrs);
+    
+            assertEquals("Mismatched symlink data", expected, new 
String(Files.readAllBytes(file1)));
+    
+            try (FileChannel channel = FileChannel.open(file1)) {
+                try (FileLock lock = channel.lock()) {
+                    System.out.println("Locked " + lock.toString());
+    
+                    try (FileChannel channel2 = FileChannel.open(file1)) {
+                        try (FileLock lock2 = channel2.lock()) {
+                            System.out.println("Locked " + lock2.toString());
+                            fail("Unexpected success in re-locking " + file1);
+                        } catch (OverlappingFileLockException e) {
+                            // expected
+                        }
+                    }
+                }
+            }
+    
+            Files.delete(file1);
+        }
+    }
+
+    @Test
+    public void testAttributes() throws IOException {
+        Path targetPath = detectTargetFolder().toPath();
+        Path lclSftp = Utils.resolve(targetPath, 
SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), 
getCurrentTestName());
+        Utils.deleteRecursive(lclSftp);
+
+        try(FileSystem fs = FileSystems.newFileSystem(
+                URI.create("sftp://"; + getCurrentTestName() + ":" + 
getCurrentTestName() + "@localhost:" + port + "/"),
+                new TreeMap<String,Object>() {
+                    private static final long serialVersionUID = 1L;    // 
we're not serializing it
+                
+                    {
+                        put(SftpFileSystemProvider.READ_BUFFER_PROP_NAME, 
Integer.valueOf(SftpClient.MIN_READ_BUFFER_SIZE));
+                        put(SftpFileSystemProvider.WRITE_BUFFER_PROP_NAME, 
Integer.valueOf(SftpClient.MIN_WRITE_BUFFER_SIZE));
+                    }
+            })) {
+
+            Path parentPath = targetPath.getParent();
+            Path clientFolder = lclSftp.resolve("client");
+            String remFilePath = Utils.resolveRelativeRemotePath(parentPath, 
clientFolder.resolve(getCurrentTestName() + ".txt"));
+            Path file = fs.getPath(remFilePath);
+            Files.createDirectories(file.getParent());
+            Files.write(file, (getCurrentTestName() + "\n").getBytes());
+    
+            Map<String, Object> attrs = Files.readAttributes(file, "posix:*");
+            assertNotNull("NO attributes read for " + file, attrs);
+    
+            Files.setAttribute(file, "basic:size", Long.valueOf(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
+    public void testRootFileSystem() throws IOException {
+        Path targetPath = detectTargetFolder().toPath();
+        Path rootNative = targetPath.resolve("root").toAbsolutePath();
+        Utils.deleteRecursive(rootNative);
+        Files.createDirectories(rootNative);
+
+        try(FileSystem fs = FileSystems.newFileSystem(URI.create("root:" + 
rootNative.toUri().toString() + "!/"), null)) {
+            Path dir = Files.createDirectories(fs.getPath("test/foo"));
+            System.out.println("Created " + dir);
+        }
+    }
+}

Reply via email to